v2 refactor: @devrev/airsync-sdk (rename, state/adapter split, emit-from-return)#208
Draft
radovanjorgic wants to merge 22 commits into
Draft
v2 refactor: @devrev/airsync-sdk (rename, state/adapter split, emit-from-return)#208radovanjorgic wants to merge 22 commits into
radovanjorgic wants to merge 22 commits into
Conversation
Self-contained plan for the v2 rebuild: branch strategy, 12-commit sequence, hard rules, and baked-in reference data (enum old->new tables, deprecated-file list, connector import surface). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Package identity change for the v2 AirSync rebrand. Scoped to package identity only: - package.json name, version (2.0.0-beta.0), description - package-lock.json (regenerated) - README install command - release workflow references Deferred to later commits: README Airdrop->AirSync prose (C2), the api-extractor report filename + config under backwards-compatibility (C8, test/report territory). Ref: V2_PROGRESS.md C0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the entire src/deprecated/ tree (Adapter, DemoExtractor, HTTPClient, deprecated Uploader, demo metadata) and its four barrel re-exports from src/index.ts. These were unused by production code and any of the inspectable connectors (zero live references). Add tsconfig.build.json that extends tsconfig.json and excludes test files (**/*.test.ts, src/tests). Point the 'build' script at it so 'npm run build' compiles only shippable source. This keeps the build green across subsequent v2 commits even while the test suite (run separately via ts-jest) lags behind the rename/contract changes until it is fixed in Phase 2. BREAKING CHANGE: removed deprecated exports Adapter, DemoExtractor, HTTPClient, and the legacy Uploader from the public API. Ref: V2_PROGRESS.md C1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d prose Rename the public types AirdropEvent -> AirSyncEvent and AirdropMessage -> AirSyncMessage across all production code (no back-compat alias), and update stale 'ADaaS'/'Airdrop' branding in comments and JSDoc to 'AirSync'. Left untouched (platform contracts): the /internal/airdrop.* API route strings, the AIRDROP_* mapping enum members and their 'airdrop_*' values, and the external_system_type: 'ADaaS' string literal. BREAKING CHANGE: AirdropEvent and AirdropMessage are renamed to AirSyncEvent and AirSyncMessage. Connectors must update their imports and type references. Ref: V2_PROGRESS.md C2 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The backend now sends and accepts only the new event-type values, so the old->new translation indirection and the deprecated enum members are no longer needed. - Delete deprecated members from EventType and ExtractorEventType (the EXTRACTION_* values) and the typo/plural dupes from LoaderEventType (DataLoadingDelay, AttachmentsLoading*), keeping only the new members. - Delete src/common/event-type-translation.ts and its test. - Rewire the four callers to use event types directly with no translation: process-task.ts, spawn.ts (incoming), control-protocol.ts emit() and worker-adapter.ts emit() (outgoing). - Drop the now-dead old-member case arms in spawn.helpers.ts (return values unchanged). Behavior is unchanged: translation was identity for new values, which are now the only values on the wire. BREAKING CHANGE: removed deprecated enum members. Connectors must use the new event-type members (e.g. EventType.StartExtractingMetadata instead of EventType.ExtractionMetadataStart; LoaderEventType.DataLoadingDelayed instead of DataLoadingDelay). Ref: V2_PROGRESS.md C3 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tate Structural split of the monolithic State class into a shared abstract BaseState plus mode-specific ExtractionState and LoadingState subclasses. The on-disk state shape is unchanged: still the flat AdapterState = ConnectorState & SdkState (the connector/SDK envelope split comes in a later commit). - base-state.ts: abstract BaseState owns the shared lifecycle (init, fetch, postState) and installInitialDomainMappingIfNeeded, extracted from the old createAdapterState factory. - extraction-state.ts: ExtractionState seeds extractionSdkState and adds resolveExtractionWindow (time-value resolution, pending-boundary reuse, lastSyncStarted, window validation); createExtractionState factory. - loading-state.ts: LoadingState seeds loadingSdkState; createLoadingState factory. - state.ts: thin module re-exporting the classes/factories; createAdapterState is now a dispatcher selecting the mode-specific state by event_context.mode. - Consumers (types/workers.ts, worker-adapter.ts) reference BaseState. Behavior is preserved. Loading mode previously ran extraction-window code that was inert for loading events (no matching event types, no pending boundaries in loadingSdkState); routing it to LoadingState only drops those inert log lines. Ref: V2_PROGRESS.md C4a Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gin/v2) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Separate connector-owned state from SDK bookkeeping on disk. State is now
persisted as a v2 envelope { connectorState, sdkState } instead of a single
flat blob that merged both, so SDK internals stay encapsulated and can never
collide with connector keys.
- state.interfaces.ts: add AdapterStateEnvelope and V1_SDK_STATE_KEYS (the
union of the SDK-owned initial-state keys); mark the flat AdapterState
deprecated. SdkState stays a single combined interface (narrowing into
per-mode variants is deferred to the adapter split).
- base-state.ts: hold _connectorState and _sdkState separately; the state
getter/setter now exposes connector state only; add an sdkState getter/setter
for SDK internals; init() routes fetched state through a normalizeFetchedState()
migration shim; postState() persists the envelope.
- Migration shim: a v2 envelope is used as-is; a legacy flat v1 blob is split
by V1_SDK_STATE_KEYS (SDK keys to sdkState, the rest to connectorState);
a half-envelope or non-object fails loud. Existing syncs migrate on first read.
- extraction-state.ts: resolve the extraction window against sdkState.
- worker-adapter.ts: adapter.state now returns ConnectorState; add an
adapter.sdkState getter; all internal SDK-field access goes through sdkState.
- attachments-streaming-pool.ts: read toDevRev via adapter.sdkState.
BREAKING CHANGE: adapter.state no longer exposes SDK bookkeeping fields
(lastSyncStarted, workersOldest, toDevRev, fromDevRev, snapInVersionId, ...).
Connector state is now disjoint from SDK state. Persisted v1 state is migrated
automatically on read.
Ref: V2_PROGRESS.md C4b
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the monolithic WorkerAdapter with a BaseAdapter holding the shared state access and the emit() control-protocol flow as a template method, plus ExtractionAdapter and LoadingAdapter subclasses that own their mode-specific surface. - base-adapter.ts: abstract BaseAdapter owns event/options/isTimeout/ hasWorkerEmitted, adapterState, uploader, state/sdkState/extractionScope accessors, postState(), and emit(). emit() is a template method with three hooks: beforeEmit (pre-emit work), buildEmitPayload (mode payload extras), afterEmit (post-emit cleanup). - extraction-adapter.ts: ExtractionAdapter owns repos, artifacts, attachment streaming/processing. beforeEmit uploads repos and updates extraction boundaries (incl. lastSuccessfulSyncStarted promotion); buildEmitPayload adds artifacts; afterEmit clears them. An override emit() handles the inline external-sync-unit upload before delegating to BaseAdapter.emit(). - loading-adapter.ts: LoadingAdapter owns mappers, loader reports, item and attachment loading. buildEmitPayload adds reports + processed_files. - worker-adapter.helpers.ts moved to adapters/loading-adapter.helpers.ts (loader-only). Old worker-adapter.ts removed. - WorkerAdapter is now a type alias ExtractionAdapter | LoadingAdapter. processTask builds the concrete adapter from the event's sync mode and passes it to task/onTimeout. Attachment processor types and the streaming pool are typed to ExtractionAdapter. Behavior is preserved: emit() runs the same steps in the same order, the mode-specific payloads are unchanged, and the extraction-boundary bookkeeping is identical. The emit(eventType, data) signature is kept; the emit-from-return contract change is a separate commit. BREAKING CHANGE: WorkerAdapter is no longer a constructable class. Extraction tasks receive an ExtractionAdapter and loading tasks a LoadingAdapter; the methods available are scoped to the worker's mode. Ref: V2_PROGRESS.md C5 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Connectors now signal how a phase ended by RETURNING a TaskResult from their
task/onTimeout callbacks; the SDK maps that status to the phase-appropriate
platform event and emits it exactly once. Connectors never call emit directly.
- types/workers.ts: add TaskResult ({status: 'success'|'progress'|'delay'
(+delaySeconds)|'error' (+error)}) and TaskStatus. ProcessTaskInterface.task
now returns Promise<TaskResult>; onTimeout is optional and also returns
Promise<TaskResult>. TaskAdapterInterface is generic over the adapter. The
WorkerAdapter union alias is removed.
- spawn.helpers.ts: add getEventTypeForResult + EVENT_PHASE_MAP, mapping each
incoming EventType + status to the outgoing event. Resumable phases (data/
attachment extraction, data/attachment loading) honour every status; non-
resumable phases (ESU, metadata, state deletions) only have done/error, so
a progress/delay there is illegal and emits an error with a descriptive msg.
- base-adapter.ts: emit() is now protected (SDK-internal). New public
emitFromResult(result) — the driver-invoked bridge that picks the event from
the mapping and emits with the right payload. State is still saved before
emit for non-stateless events.
- extraction-adapter.ts: streamAttachments returns a TaskResult (timeout ->
progress, pool error/delay -> error/delay, otherwise success) instead of
emitting and exiting. The inline external-sync-unit emit override is removed
(ESUs flow through the repo; connectors push then return success).
- loading-adapter.ts: loadItemTypes and loadAttachments return a TaskResult;
their former mid-flight emits (rate-limit -> delay, timeout -> progress,
error -> error) become returns. They no longer call process.exit.
- process-task.ts: processTask is split into processExtractionTask and
processLoadingTask over a shared runWorkerTask driver that runs task (then
onTimeout, or a default progress result, on timeout) and emits once from the
returned TaskResult.
- index.ts: export processExtractionTask + processLoadingTask; remove
processTask. emit is no longer part of the public surface.
BREAKING CHANGE: connectors must return a TaskResult from task/onTimeout
instead of calling adapter.emit(...), and import processExtractionTask /
processLoadingTask instead of processTask. adapter.emit is no longer public;
the loader and attachment-streaming methods return a TaskResult to be returned
from the task. onTimeout is now optional (defaults to a progress handoff).
Ref: V2_PROGRESS.md C6
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Documentation-only pass (C7). Brings the v2-new structural code and the under-documented older modules up to the `src/mappers/mappers.ts` style bar (one-line what + "Used to/for ..." usage line + typed @param/@returns). Covered: - adapters: BaseAdapter template-method emit + emitFromResult, ExtractionAdapter (repos/artifacts/attachment streaming), LoadingAdapter (mappers/reports/loading). - state: BaseState lifecycle, the v1->v2 normalizeFetchedState migration shim, ExtractionState window resolution, the mode-based createAdapterState dispatcher, and state.interfaces (SdkState, envelope, V1_SDK_STATE_KEYS). - multithreading: processExtractionTask/processLoadingTask + runWorkerTask driver, spawn/Spawn supervision, and the getEventTypeForResult / EVENT_PHASE_MAP status->event mapping. - repo, uploader (+helpers/interfaces), attachments-streaming-pool. - common: control-protocol emit, install-initial-domain-mapping, errors; types/loading (previously zero JSDoc) and the types barrel. No executable code, type signatures, imports, or string literals changed (verified: every changed line is a comment). Build green, lint clean.
This reverts commit d05434b.
Three independent cleanups from the v2 self-review: 1. Drop the pre-1.15.2 processed-attachments migration. `migrateProcessedAttachments` only upgraded the legacy `string[]` form of `lastProcessedAttachmentsIdsList` to the structured `ProcessedAttachment[]` form. That `string[]` format predates v1.15.2 (commit c3aa151, Feb 2026); from v1.15.2 on, state is already written as `ProcessedAttachment[]`, and the list is per-cycle scratch state cleared at the end of each completed attachment phase. v2 assumes on-disk state written by >= v1.15.2 (connectors are on >= 1.16, typically 1.19, before moving to v2), so the shim is dead weight. The call site now just initializes the list to [] when absent. 2. Move the `emit` primitive `common/control-protocol.ts` -> `multithreading/emit.ts`. The file's sole export is `emit`, used only by the multithreading layer (base-adapter, spawn) — co-locating it with its consumers and naming it after its content. Import paths updated. 3. Remove the dead `createAdapterState` dispatcher from `state.ts`. After C6 split the single entry point into processExtractionTask/processLoadingTask, process-task.ts calls createExtractionState/createLoadingState directly; the mode dispatcher had zero callers. `state.ts` is now a thin re-export barrel. Build green, lint clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v2 refactor of
@devrev/airsync-sdk(formerly@devrev/ts-adaas)Clean, commit-by-commit rebuild of the SDK for v2. Breaking changes are intended. Each commit is single-purpose and keeps
npm run buildgreen; the test suite and api-extractor report are intentionally left for the closing steps.Rename & branding
@devrev/ts-adaas→@devrev/airsync-sdk(2.0.0-beta.0)AirdropEvent/AirdropMessage→AirSyncEvent/AirSyncMessage(hard rename, no alias); proseAirdrop/ADaaS→AirSync/internal/airdrop.*API routes,AIRDROP_*mapping enum, the'ADaaS'literalDeletions / cleanup
src/deprecated/**and its barrel exportsEXTRACTION_*enum members +event-type-translation.ts); backend now sends/accepts only the new event typesmigrateProcessedAttachmentsshim (v2 assumes on-disk state ≥ v1.15.2)createAdapterStatedispatcher (obviated by the C6 entry-point split)State redesign
StateintoBaseState+ExtractionState+LoadingState{ connectorState, sdkState }, with a v1-flat → v2-envelope migration shim on readadapter.statenow returns connector state only; SDK fields move toadapter.sdkStateAdapter redesign
WorkerAdapterintoBaseAdapter+ExtractionAdapter+LoadingAdapteremit()is now a template method (beforeEmit / buildEmitPayload / afterEmit) and SDK-internalExecution model (emit-from-return)
task/onTimeoutnow return aTaskResult(success/progress/delay/error); the SDK maps status → phase event and emits exactly onceprocessTasksplit intoprocessExtractionTask+processLoadingTaskTaskResultinstead of emitting mid-flightMisc
emitprimitivecommon/control-protocol.ts→multithreading/emit.ts(co-located with its only consumers)Remaining before ready-for-review
airsync-sdk.api.md)migrate-v2skill (v1→v2 catalog)🤖 Generated with Claude Code