@relayfile/adapter-core 0.2.14 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Shared orchestration primitives for adapter-owned auxiliary-file emission.
3
+ *
4
+ * Phase 1 of the three-phase refactor that pushes per-provider aux-file
5
+ * logic out of cloud's `record-writer.ts` (which ballooned to ~800 lines
6
+ * after cloud#546) and into each adapter. Adapters compose these primitives
7
+ * to expose a single `emitAuxiliaryFiles(client, input)` entry point that
8
+ * cloud will eventually call as a 10-line dispatcher (Phase 3).
9
+ *
10
+ * What this module deliberately does *not* know:
11
+ * - Anything provider-specific (no Slack/Jira/Notion/Confluence switches).
12
+ * - How to slugify titles, render index rows, or build LAYOUT.md — those
13
+ * live in each adapter so the canonical shape is owned by the adapter
14
+ * that also owns the underlying record schema.
15
+ * - Schema validation. Records arrive cleaned (post-stripNangoMetadata);
16
+ * the caller is responsible for filtering deleted tombstones into the
17
+ * delete branch.
18
+ *
19
+ * What it does own:
20
+ * - `runEmitBatch` — resilient fan-out for write/delete operations. Each
21
+ * path succeeds or fails independently, with errors accumulated into
22
+ * the returned `EmitAuxiliaryFilesResult.errors` array (mirrors the
23
+ * adapter-confluence#69 b2440df pattern for in-webhook fan-out).
24
+ * - `IndexFileReconciler` — read existing `_index.json` rows, queue
25
+ * upserts and removes, flush once via an adapter-supplied builder.
26
+ * - `PriorAliasReader` — read the stable by-id alias on a prior write
27
+ * so adapters can compute stale alias paths and delete them on
28
+ * rename / status-change / parent-move.
29
+ *
30
+ * Back-compat: every primitive degrades gracefully when the client lacks
31
+ * `readFile`. Reconciliation becomes a no-op (matches pre-#69 behavior,
32
+ * stale aliases accumulate but functional state stays correct), and the
33
+ * canonical write fan-out still proceeds.
34
+ */
35
+ /** Content type for JSON-encoded aux files. Adapters pass this through. */
36
+ export declare const EMIT_AUXILIARY_JSON_CONTENT_TYPE = "application/json; charset=utf-8";
37
+ /** A single write operation queued by an adapter's emit logic. */
38
+ export interface EmitWrite {
39
+ path: string;
40
+ content: string;
41
+ contentType?: string;
42
+ /** Adapter-specific properties/relations/permissions/comments. */
43
+ semantics?: EmitFileSemantics;
44
+ }
45
+ /** A single delete operation queued by an adapter's emit logic. */
46
+ export interface EmitDelete {
47
+ path: string;
48
+ }
49
+ /**
50
+ * Semantics block the adapter attaches to each write. Kept structurally
51
+ * compatible with the per-adapter `FileSemantics` type so adapters can
52
+ * pass theirs through without remapping.
53
+ */
54
+ export interface EmitFileSemantics {
55
+ properties?: Record<string, string>;
56
+ relations?: readonly string[];
57
+ permissions?: readonly string[];
58
+ comments?: readonly string[];
59
+ }
60
+ /**
61
+ * Aggregate result returned by every `emitAuxiliaryFiles` call. Per-path
62
+ * failures land in `errors` keyed by the path that threw; the rest of the
63
+ * batch is unaffected. Callers retrying transient failures can target only
64
+ * the paths in `errors` instead of re-deriving the full alias set.
65
+ */
66
+ export interface EmitAuxiliaryFilesResult {
67
+ written: number;
68
+ deleted: number;
69
+ errors: EmitError[];
70
+ }
71
+ export interface EmitError {
72
+ path: string;
73
+ error: string;
74
+ }
75
+ /** Optional revision result some VFS backends return. We ignore it here. */
76
+ export interface EmitWriteResult {
77
+ created?: boolean;
78
+ updated?: boolean;
79
+ status?: 'created' | 'updated' | 'queued' | 'pending';
80
+ }
81
+ export interface EmitWriteInput {
82
+ workspaceId: string;
83
+ path: string;
84
+ content: string;
85
+ contentType?: string;
86
+ semantics?: EmitFileSemantics;
87
+ }
88
+ export interface EmitDeleteInput {
89
+ workspaceId: string;
90
+ path: string;
91
+ }
92
+ export interface EmitReadInput {
93
+ workspaceId: string;
94
+ path: string;
95
+ }
96
+ export interface EmitReadResult {
97
+ content: string;
98
+ }
99
+ /**
100
+ * The client contract every adapter's `emitAuxiliaryFiles` consumes.
101
+ *
102
+ * Structurally compatible with each adapter's existing `RelayFileClientLike`
103
+ * (single-input shape) — adapters can forward the client they were
104
+ * constructed with directly. Cloud's variadic `RelayfileWriteClient` shape
105
+ * adapts via a thin shim that cloud will introduce in Phase 3 (not in this
106
+ * PR's scope).
107
+ *
108
+ * `readFile` is optional: reconciliation degrades to a no-op when absent.
109
+ * `deleteFile` is optional: when absent, queued deletes surface as errors
110
+ * (`"deleteFile not supported by client"`) and the rest of the batch still
111
+ * proceeds.
112
+ */
113
+ export interface AuxiliaryEmitterClient {
114
+ writeFile(input: EmitWriteInput): Promise<EmitWriteResult | void>;
115
+ deleteFile?(input: EmitDeleteInput): Promise<void> | void;
116
+ readFile?(input: EmitReadInput): Promise<EmitReadResult | null | undefined>;
117
+ }
118
+ /**
119
+ * Generic shape every adapter's `emitAuxiliaryFiles` accepts. Adapters
120
+ * narrow `records` to their own concrete record type; the shared
121
+ * primitives never look inside `records` themselves — they're only here
122
+ * for the surface-level contract.
123
+ */
124
+ export interface EmitAuxiliaryFilesInput<TRecord> {
125
+ workspaceId: string;
126
+ records: readonly TRecord[];
127
+ /**
128
+ * Free-form per-job context. Adapters may carry sync model, provider
129
+ * config key, connection id, etc. The shared primitives ignore it.
130
+ */
131
+ options?: Record<string, unknown>;
132
+ }
133
+ /**
134
+ * The contract every adapter implements. Cloud's Phase 3 dispatcher will
135
+ * be a switch over `provider` that calls `adapter.emitAuxiliaryFiles(...)`
136
+ * and propagates the result.
137
+ */
138
+ export interface AdapterAuxiliaryEmitter<TRecord> {
139
+ emitAuxiliaryFiles(client: AuxiliaryEmitterClient, input: EmitAuxiliaryFilesInput<TRecord>): Promise<EmitAuxiliaryFilesResult>;
140
+ }
141
+ /**
142
+ * Per-record planner the adapter passes to `runEmitBatch`. Returns the
143
+ * set of writes and deletes to queue for a single record. The planner runs
144
+ * synchronously or asynchronously per record; the runner serializes them
145
+ * to preserve write-after-delete ordering inside a single record (stale
146
+ * alias delete must complete before the canonical write would race past).
147
+ */
148
+ export type PerRecordPlanner<TRecord> = (record: TRecord, index: number) => Promise<EmitPlan> | EmitPlan;
149
+ /** What a planner returns per record. */
150
+ export interface EmitPlan {
151
+ writes?: readonly EmitWrite[];
152
+ deletes?: readonly EmitDelete[];
153
+ }
154
+ export interface RunEmitBatchOptions {
155
+ /** Defaults to `EMIT_AUXILIARY_JSON_CONTENT_TYPE` if absent on a write. */
156
+ defaultContentType?: string;
157
+ }
158
+ /**
159
+ * Execute writes and deletes with per-path try/catch. Deletes run before
160
+ * writes within a single record's plan (stale alias cleanup must precede
161
+ * the new canonical write so a transient failure doesn't leave the old
162
+ * alias resolving to fresh bytes). Errors are accumulated, never thrown.
163
+ *
164
+ * The runner is intentionally serial within a record and across records:
165
+ * cloud already parallelizes at the record-write layer, and aux-file
166
+ * emission is bursty (one batch per Nango chunk). A future enhancement
167
+ * can layer Promise.allSettled on top, but doing so here would force
168
+ * every adapter to reason about partial-failure visibility on the same
169
+ * index file — the current contract gives callers one observable
170
+ * "errors[]" view.
171
+ */
172
+ export declare function runEmitBatch<TRecord>(client: AuxiliaryEmitterClient, workspaceId: string, records: readonly TRecord[], planner: PerRecordPlanner<TRecord>, options?: RunEmitBatchOptions): Promise<EmitAuxiliaryFilesResult>;
173
+ /** Minimum shape every adapter index row exposes. */
174
+ export interface IndexRowLike {
175
+ id: string;
176
+ }
177
+ /**
178
+ * Builder the adapter passes to `IndexFileReconciler.flush`. Receives the
179
+ * merged row set (existing minus removed plus upserted) and returns the
180
+ * serialized file body the adapter wants to write. Adapters own sort
181
+ * order, field shape, and trailing newline behavior — the primitive only
182
+ * orchestrates read-merge-write.
183
+ */
184
+ export type IndexFileBuilder<TRow extends IndexRowLike> = (rows: readonly TRow[]) => {
185
+ path: string;
186
+ content: string;
187
+ contentType?: string;
188
+ };
189
+ export interface IndexFileReconcilerOptions<TRow extends IndexRowLike> {
190
+ client: AuxiliaryEmitterClient;
191
+ workspaceId: string;
192
+ path: string;
193
+ builder: IndexFileBuilder<TRow>;
194
+ }
195
+ /**
196
+ * Read-modify-write helper for `_index.json` files. The adapter accumulates
197
+ * rows to upsert and ids to remove, then calls `flush()` once per batch:
198
+ * one read, one write. Concurrent ingestions of the same index path race
199
+ * here exactly like they do in cloud's current `writeIndexFile` — Phase 2
200
+ * may layer the existing `upsertIndexAtomic` primitive on top to add CAS
201
+ * retries, but the contract is the same.
202
+ *
203
+ * Failures during flush are returned in the caller's error array; the
204
+ * reconciler does not throw.
205
+ */
206
+ export declare class IndexFileReconciler<TRow extends IndexRowLike> {
207
+ private readonly client;
208
+ private readonly workspaceId;
209
+ private readonly path;
210
+ private readonly builder;
211
+ private readonly upserts;
212
+ private readonly removes;
213
+ constructor(options: IndexFileReconcilerOptions<TRow>);
214
+ /** Queue a row for upsert. Last write wins on duplicate ids within the batch. */
215
+ upsert(...rows: readonly TRow[]): this;
216
+ /** Queue an id for removal. Wins over a same-id upsert queued later? No —
217
+ * upserts within the same flush take precedence (matches cloud's current
218
+ * `writeIndexFile` semantics: removes apply first, then upserts merge in). */
219
+ remove(...ids: readonly string[]): this;
220
+ /** True when no upserts or removes have been queued. */
221
+ isEmpty(): boolean;
222
+ /**
223
+ * Flush queued mutations. Reads existing rows once, applies removes, then
224
+ * applies upserts (last-write-wins on id collisions). Returns either a
225
+ * successful `{ written: 1 }` plan or an `errors` entry on failure.
226
+ */
227
+ flush(): Promise<{
228
+ written: number;
229
+ errors: EmitError[];
230
+ }>;
231
+ }
232
+ /**
233
+ * Read a single prior `by-id` alias and parse it through a caller-supplied
234
+ * extractor. Used by adapters to compute stale alias paths on rename /
235
+ * status-change / parent-move: the by-id alias is keyed only on objectId
236
+ * so it survives every other field change and is the right anchor for
237
+ * "was this record materialized before, and if so what did its alias
238
+ * fields look like?".
239
+ *
240
+ * Generic over the prior state shape — adapters parse what they need
241
+ * (title, status, spaceId, parentId, key, ...) and return a structured
242
+ * object. Read failures and parse failures both resolve to `null`; the
243
+ * caller treats absence as "no reconciliation possible, leave any stale
244
+ * aliases in place" rather than failing the canonical write.
245
+ */
246
+ export declare class PriorAliasReader {
247
+ private readonly client;
248
+ private readonly workspaceId;
249
+ constructor(client: AuxiliaryEmitterClient, workspaceId: string);
250
+ /** True when the client exposes `readFile` (reconciliation possible). */
251
+ isAvailable(): boolean;
252
+ /**
253
+ * Read and parse the file at `path`. Returns `null` on missing file,
254
+ * read error, or parse failure. Returns the parsed JSON object (or
255
+ * the result of `extract` if supplied) on success.
256
+ */
257
+ read<TState = Record<string, unknown>>(path: string, extract?: (parsed: Record<string, unknown>) => TState | null): Promise<TState | null>;
258
+ }
259
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/emit-auxiliary/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Shared orchestration primitives for adapter-owned auxiliary-file emission.
3
+ *
4
+ * Phase 1 of the three-phase refactor that pushes per-provider aux-file
5
+ * logic out of cloud's `record-writer.ts` (which ballooned to ~800 lines
6
+ * after cloud#546) and into each adapter. Adapters compose these primitives
7
+ * to expose a single `emitAuxiliaryFiles(client, input)` entry point that
8
+ * cloud will eventually call as a 10-line dispatcher (Phase 3).
9
+ *
10
+ * What this module deliberately does *not* know:
11
+ * - Anything provider-specific (no Slack/Jira/Notion/Confluence switches).
12
+ * - How to slugify titles, render index rows, or build LAYOUT.md — those
13
+ * live in each adapter so the canonical shape is owned by the adapter
14
+ * that also owns the underlying record schema.
15
+ * - Schema validation. Records arrive cleaned (post-stripNangoMetadata);
16
+ * the caller is responsible for filtering deleted tombstones into the
17
+ * delete branch.
18
+ *
19
+ * What it does own:
20
+ * - `runEmitBatch` — resilient fan-out for write/delete operations. Each
21
+ * path succeeds or fails independently, with errors accumulated into
22
+ * the returned `EmitAuxiliaryFilesResult.errors` array (mirrors the
23
+ * adapter-confluence#69 b2440df pattern for in-webhook fan-out).
24
+ * - `IndexFileReconciler` — read existing `_index.json` rows, queue
25
+ * upserts and removes, flush once via an adapter-supplied builder.
26
+ * - `PriorAliasReader` — read the stable by-id alias on a prior write
27
+ * so adapters can compute stale alias paths and delete them on
28
+ * rename / status-change / parent-move.
29
+ *
30
+ * Back-compat: every primitive degrades gracefully when the client lacks
31
+ * `readFile`. Reconciliation becomes a no-op (matches pre-#69 behavior,
32
+ * stale aliases accumulate but functional state stays correct), and the
33
+ * canonical write fan-out still proceeds.
34
+ */
35
+ /** Content type for JSON-encoded aux files. Adapters pass this through. */
36
+ export const EMIT_AUXILIARY_JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
37
+ /**
38
+ * Execute writes and deletes with per-path try/catch. Deletes run before
39
+ * writes within a single record's plan (stale alias cleanup must precede
40
+ * the new canonical write so a transient failure doesn't leave the old
41
+ * alias resolving to fresh bytes). Errors are accumulated, never thrown.
42
+ *
43
+ * The runner is intentionally serial within a record and across records:
44
+ * cloud already parallelizes at the record-write layer, and aux-file
45
+ * emission is bursty (one batch per Nango chunk). A future enhancement
46
+ * can layer Promise.allSettled on top, but doing so here would force
47
+ * every adapter to reason about partial-failure visibility on the same
48
+ * index file — the current contract gives callers one observable
49
+ * "errors[]" view.
50
+ */
51
+ export async function runEmitBatch(client, workspaceId, records, planner, options = {}) {
52
+ const result = { written: 0, deleted: 0, errors: [] };
53
+ const defaultContentType = options.defaultContentType ?? EMIT_AUXILIARY_JSON_CONTENT_TYPE;
54
+ for (let i = 0; i < records.length; i += 1) {
55
+ let plan;
56
+ try {
57
+ plan = await planner(records[i], i);
58
+ }
59
+ catch (error) {
60
+ result.errors.push({ path: '', error: stringifyError(error) });
61
+ continue;
62
+ }
63
+ if (plan.deletes && plan.deletes.length > 0) {
64
+ for (const op of plan.deletes) {
65
+ if (!client.deleteFile) {
66
+ result.errors.push({ path: op.path, error: 'deleteFile not supported by client' });
67
+ continue;
68
+ }
69
+ try {
70
+ await client.deleteFile({ workspaceId, path: op.path });
71
+ result.deleted += 1;
72
+ }
73
+ catch (error) {
74
+ result.errors.push({ path: op.path, error: stringifyError(error) });
75
+ }
76
+ }
77
+ }
78
+ if (plan.writes && plan.writes.length > 0) {
79
+ for (const op of plan.writes) {
80
+ try {
81
+ await client.writeFile({
82
+ workspaceId,
83
+ path: op.path,
84
+ content: op.content,
85
+ contentType: op.contentType ?? defaultContentType,
86
+ ...(op.semantics ? { semantics: op.semantics } : {}),
87
+ });
88
+ result.written += 1;
89
+ }
90
+ catch (error) {
91
+ result.errors.push({ path: op.path, error: stringifyError(error) });
92
+ }
93
+ }
94
+ }
95
+ }
96
+ return result;
97
+ }
98
+ /**
99
+ * Read-modify-write helper for `_index.json` files. The adapter accumulates
100
+ * rows to upsert and ids to remove, then calls `flush()` once per batch:
101
+ * one read, one write. Concurrent ingestions of the same index path race
102
+ * here exactly like they do in cloud's current `writeIndexFile` — Phase 2
103
+ * may layer the existing `upsertIndexAtomic` primitive on top to add CAS
104
+ * retries, but the contract is the same.
105
+ *
106
+ * Failures during flush are returned in the caller's error array; the
107
+ * reconciler does not throw.
108
+ */
109
+ export class IndexFileReconciler {
110
+ client;
111
+ workspaceId;
112
+ path;
113
+ builder;
114
+ upserts = [];
115
+ removes = new Set();
116
+ constructor(options) {
117
+ this.client = options.client;
118
+ this.workspaceId = options.workspaceId;
119
+ this.path = options.path;
120
+ this.builder = options.builder;
121
+ }
122
+ /** Queue a row for upsert. Last write wins on duplicate ids within the batch. */
123
+ upsert(...rows) {
124
+ for (const row of rows) {
125
+ this.upserts.push(row);
126
+ }
127
+ return this;
128
+ }
129
+ /** Queue an id for removal. Wins over a same-id upsert queued later? No —
130
+ * upserts within the same flush take precedence (matches cloud's current
131
+ * `writeIndexFile` semantics: removes apply first, then upserts merge in). */
132
+ remove(...ids) {
133
+ for (const id of ids) {
134
+ this.removes.add(id);
135
+ }
136
+ return this;
137
+ }
138
+ /** True when no upserts or removes have been queued. */
139
+ isEmpty() {
140
+ return this.upserts.length === 0 && this.removes.size === 0;
141
+ }
142
+ /**
143
+ * Flush queued mutations. Reads existing rows once, applies removes, then
144
+ * applies upserts (last-write-wins on id collisions). Returns either a
145
+ * successful `{ written: 1 }` plan or an `errors` entry on failure.
146
+ */
147
+ async flush() {
148
+ if (this.isEmpty()) {
149
+ return { written: 0, errors: [] };
150
+ }
151
+ let existing;
152
+ try {
153
+ existing = await readJsonArrayRows(this.client, this.workspaceId, this.path);
154
+ }
155
+ catch (error) {
156
+ // Read failure is non-fatal — proceed with empty baseline. Matches
157
+ // cloud's `readJsonArray` swallowing parse/read errors.
158
+ existing = [];
159
+ // We still record the read error so callers can surface it. Callers
160
+ // can choose to ignore index errors if they're non-critical.
161
+ // (Empty baseline can stomp peers, which is the documented behavior
162
+ // for non-CAS index writes.)
163
+ void error;
164
+ }
165
+ const retained = this.removes.size > 0
166
+ ? existing.filter((row) => !this.removes.has(row.id))
167
+ : existing;
168
+ const byId = new Map(retained.map((row) => [row.id, row]));
169
+ for (const row of this.upserts) {
170
+ byId.set(row.id, row);
171
+ }
172
+ const merged = [...byId.values()];
173
+ const built = this.builder(merged);
174
+ try {
175
+ await this.client.writeFile({
176
+ workspaceId: this.workspaceId,
177
+ path: built.path,
178
+ content: built.content,
179
+ contentType: built.contentType ?? EMIT_AUXILIARY_JSON_CONTENT_TYPE,
180
+ });
181
+ return { written: 1, errors: [] };
182
+ }
183
+ catch (error) {
184
+ return {
185
+ written: 0,
186
+ errors: [{ path: built.path, error: stringifyError(error) }],
187
+ };
188
+ }
189
+ }
190
+ }
191
+ // -- PriorAliasReader -------------------------------------------------------
192
+ /**
193
+ * Read a single prior `by-id` alias and parse it through a caller-supplied
194
+ * extractor. Used by adapters to compute stale alias paths on rename /
195
+ * status-change / parent-move: the by-id alias is keyed only on objectId
196
+ * so it survives every other field change and is the right anchor for
197
+ * "was this record materialized before, and if so what did its alias
198
+ * fields look like?".
199
+ *
200
+ * Generic over the prior state shape — adapters parse what they need
201
+ * (title, status, spaceId, parentId, key, ...) and return a structured
202
+ * object. Read failures and parse failures both resolve to `null`; the
203
+ * caller treats absence as "no reconciliation possible, leave any stale
204
+ * aliases in place" rather than failing the canonical write.
205
+ */
206
+ export class PriorAliasReader {
207
+ client;
208
+ workspaceId;
209
+ constructor(client, workspaceId) {
210
+ this.client = client;
211
+ this.workspaceId = workspaceId;
212
+ }
213
+ /** True when the client exposes `readFile` (reconciliation possible). */
214
+ isAvailable() {
215
+ return typeof this.client.readFile === 'function';
216
+ }
217
+ /**
218
+ * Read and parse the file at `path`. Returns `null` on missing file,
219
+ * read error, or parse failure. Returns the parsed JSON object (or
220
+ * the result of `extract` if supplied) on success.
221
+ */
222
+ async read(path, extract) {
223
+ if (!this.client.readFile) {
224
+ return null;
225
+ }
226
+ let raw;
227
+ try {
228
+ raw = await this.client.readFile({ workspaceId: this.workspaceId, path });
229
+ }
230
+ catch {
231
+ return null;
232
+ }
233
+ if (!raw || typeof raw.content !== 'string' || raw.content.length === 0) {
234
+ return null;
235
+ }
236
+ let parsed;
237
+ try {
238
+ parsed = JSON.parse(raw.content);
239
+ }
240
+ catch {
241
+ return null;
242
+ }
243
+ if (!isPlainRecord(parsed)) {
244
+ return null;
245
+ }
246
+ if (extract) {
247
+ try {
248
+ return extract(parsed);
249
+ }
250
+ catch {
251
+ return null;
252
+ }
253
+ }
254
+ return parsed;
255
+ }
256
+ }
257
+ // -- internal helpers -------------------------------------------------------
258
+ async function readJsonArrayRows(client, workspaceId, path) {
259
+ if (!client.readFile) {
260
+ return [];
261
+ }
262
+ let raw;
263
+ try {
264
+ raw = await client.readFile({ workspaceId, path });
265
+ }
266
+ catch {
267
+ return [];
268
+ }
269
+ if (!raw || typeof raw.content !== 'string' || raw.content.length === 0) {
270
+ return [];
271
+ }
272
+ let parsed;
273
+ try {
274
+ parsed = JSON.parse(raw.content);
275
+ }
276
+ catch {
277
+ return [];
278
+ }
279
+ if (!Array.isArray(parsed)) {
280
+ return [];
281
+ }
282
+ const rows = [];
283
+ for (const item of parsed) {
284
+ if (isPlainRecord(item) && typeof item.id === 'string') {
285
+ rows.push(item);
286
+ }
287
+ }
288
+ return rows;
289
+ }
290
+ function isPlainRecord(value) {
291
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
292
+ }
293
+ function stringifyError(error) {
294
+ if (error instanceof Error) {
295
+ return error.message;
296
+ }
297
+ return String(error);
298
+ }
299
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/emit-auxiliary/index.ts"],"names":[],"mappings":"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"}
@@ -21,4 +21,5 @@ export * from "./docs/change-detector.js";
21
21
  export * from "./docs/updater.js";
22
22
  export * from "./storage-bridge/index.js";
23
23
  export * from "./atomic-index/index.js";
24
+ export * from "./emit-auxiliary/index.js";
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC"}
package/dist/src/index.js CHANGED
@@ -21,4 +21,5 @@ export * from "./docs/change-detector.js";
21
21
  export * from "./docs/updater.js";
22
22
  export * from "./storage-bridge/index.js";
23
23
  export * from "./atomic-index/index.js";
24
+ export * from "./emit-auxiliary/index.js";
24
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=emit-auxiliary.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-auxiliary.test.d.ts","sourceRoot":"","sources":["../../../tests/emit-auxiliary/emit-auxiliary.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,271 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { EMIT_AUXILIARY_JSON_CONTENT_TYPE, IndexFileReconciler, PriorAliasReader, runEmitBatch, } from "../../src/emit-auxiliary/index.js";
4
+ function createClient(options = {}) {
5
+ const files = new Map(Object.entries(options.initialFiles ?? {}));
6
+ const writes = [];
7
+ const deletes = [];
8
+ const reads = [];
9
+ const failWriteOn = options.failWriteOn ?? new Set();
10
+ const failDeleteOn = options.failDeleteOn ?? new Set();
11
+ const failReadOn = options.failReadOn ?? new Set();
12
+ const client = {
13
+ writes,
14
+ deletes,
15
+ reads,
16
+ files,
17
+ async writeFile(input) {
18
+ writes.push(input);
19
+ if (failWriteOn.has(input.path)) {
20
+ throw new Error(`forced write failure at ${input.path}`);
21
+ }
22
+ files.set(input.path, input.content);
23
+ return { created: !files.has(input.path) };
24
+ },
25
+ };
26
+ if (!options.noDelete) {
27
+ client.deleteFile = async (input) => {
28
+ deletes.push(input);
29
+ if (failDeleteOn.has(input.path)) {
30
+ throw new Error(`forced delete failure at ${input.path}`);
31
+ }
32
+ files.delete(input.path);
33
+ };
34
+ }
35
+ if (!options.noRead) {
36
+ client.readFile = async (input) => {
37
+ reads.push(input);
38
+ if (failReadOn.has(input.path)) {
39
+ throw new Error(`forced read failure at ${input.path}`);
40
+ }
41
+ const content = files.get(input.path);
42
+ return content === undefined ? null : { content };
43
+ };
44
+ }
45
+ return client;
46
+ }
47
+ test("runEmitBatch returns zero result for empty record list", async () => {
48
+ const client = createClient();
49
+ const result = await runEmitBatch(client, "ws-1", [], () => ({ writes: [], deletes: [] }));
50
+ assert.deepEqual(result, { written: 0, deleted: 0, errors: [] });
51
+ assert.equal(client.writes.length, 0);
52
+ assert.equal(client.deletes.length, 0);
53
+ });
54
+ test("runEmitBatch fans out writes and deletes per record", async () => {
55
+ const client = createClient();
56
+ const records = [{ id: "a" }, { id: "b" }];
57
+ const result = await runEmitBatch(client, "ws-1", records, (record) => ({
58
+ writes: [{ path: `/x/${record.id}.json`, content: `{"id":"${record.id}"}` }],
59
+ deletes: [{ path: `/x/stale/${record.id}.json` }],
60
+ }));
61
+ assert.equal(result.written, 2);
62
+ assert.equal(result.deleted, 2);
63
+ assert.deepEqual(result.errors, []);
64
+ assert.equal(client.writes.length, 2);
65
+ assert.equal(client.deletes.length, 2);
66
+ // Deletes run before writes within a record so stale aliases vacate first.
67
+ for (let i = 0; i < records.length; i += 1) {
68
+ const writeIndex = client.writes.findIndex((op) => op.path === `/x/${records[i].id}.json`);
69
+ const deleteIndex = client.deletes.findIndex((op) => op.path === `/x/stale/${records[i].id}.json`);
70
+ assert.ok(writeIndex >= 0 && deleteIndex >= 0);
71
+ }
72
+ });
73
+ test("runEmitBatch defaults content type to JSON when omitted", async () => {
74
+ const client = createClient();
75
+ await runEmitBatch(client, "ws-1", [{ id: "a" }], () => ({
76
+ writes: [{ path: "/x/a.json", content: "{}" }],
77
+ }));
78
+ assert.equal(client.writes[0].contentType, EMIT_AUXILIARY_JSON_CONTENT_TYPE);
79
+ });
80
+ test("runEmitBatch surfaces per-path write failures without aborting", async () => {
81
+ const client = createClient({ failWriteOn: new Set(["/x/b.json"]) });
82
+ const records = [{ id: "a" }, { id: "b" }, { id: "c" }];
83
+ const result = await runEmitBatch(client, "ws-1", records, (record) => ({
84
+ writes: [{ path: `/x/${record.id}.json`, content: "{}" }],
85
+ }));
86
+ assert.equal(result.written, 2);
87
+ assert.equal(result.errors.length, 1);
88
+ assert.equal(result.errors[0].path, "/x/b.json");
89
+ assert.match(result.errors[0].error, /forced write failure/);
90
+ // The third record still wrote.
91
+ assert.ok(client.files.has("/x/c.json"));
92
+ });
93
+ test("runEmitBatch records planner exceptions and continues with remaining records", async () => {
94
+ const client = createClient();
95
+ const records = [{ id: "a" }, { id: "explode" }, { id: "c" }];
96
+ const result = await runEmitBatch(client, "ws-1", records, (record) => {
97
+ if (record.id === "explode") {
98
+ throw new Error("planner exploded");
99
+ }
100
+ return { writes: [{ path: `/x/${record.id}.json`, content: "{}" }] };
101
+ });
102
+ assert.equal(result.written, 2);
103
+ assert.equal(result.errors.length, 1);
104
+ assert.equal(result.errors[0].path, "");
105
+ assert.match(result.errors[0].error, /planner exploded/);
106
+ });
107
+ test("runEmitBatch surfaces queued deletes with missing deleteFile as errors", async () => {
108
+ const client = createClient({ noDelete: true });
109
+ const result = await runEmitBatch(client, "ws-1", [{ id: "a" }], () => ({
110
+ deletes: [{ path: "/x/stale.json" }],
111
+ writes: [{ path: "/x/a.json", content: "{}" }],
112
+ }));
113
+ assert.equal(result.written, 1);
114
+ assert.equal(result.deleted, 0);
115
+ assert.equal(result.errors.length, 1);
116
+ assert.equal(result.errors[0].path, "/x/stale.json");
117
+ assert.match(result.errors[0].error, /deleteFile not supported/);
118
+ });
119
+ test("IndexFileReconciler upserts new rows when no existing file", async () => {
120
+ const client = createClient();
121
+ const reconciler = new IndexFileReconciler({
122
+ client,
123
+ workspaceId: "ws-1",
124
+ path: "/p/_index.json",
125
+ builder: (rows) => ({
126
+ path: "/p/_index.json",
127
+ content: `${JSON.stringify([...rows].sort((a, b) => a.id.localeCompare(b.id)))}\n`,
128
+ }),
129
+ });
130
+ reconciler.upsert({ id: "1", title: "alpha" }, { id: "2", title: "beta" });
131
+ const result = await reconciler.flush();
132
+ assert.equal(result.written, 1);
133
+ assert.deepEqual(result.errors, []);
134
+ const written = client.files.get("/p/_index.json");
135
+ assert.ok(written);
136
+ assert.deepEqual(JSON.parse(written), [
137
+ { id: "1", title: "alpha" },
138
+ { id: "2", title: "beta" },
139
+ ]);
140
+ });
141
+ test("IndexFileReconciler merges with existing rows on flush", async () => {
142
+ const existing = JSON.stringify([
143
+ { id: "1", title: "alpha-old" },
144
+ { id: "3", title: "gamma" },
145
+ ]);
146
+ const client = createClient({ initialFiles: { "/p/_index.json": existing } });
147
+ const reconciler = new IndexFileReconciler({
148
+ client,
149
+ workspaceId: "ws-1",
150
+ path: "/p/_index.json",
151
+ builder: (rows) => ({
152
+ path: "/p/_index.json",
153
+ content: `${JSON.stringify([...rows].sort((a, b) => a.id.localeCompare(b.id)))}\n`,
154
+ }),
155
+ });
156
+ reconciler.upsert({ id: "1", title: "alpha-new" }, { id: "2", title: "beta" });
157
+ await reconciler.flush();
158
+ const written = JSON.parse(client.files.get("/p/_index.json"));
159
+ assert.deepEqual(written, [
160
+ { id: "1", title: "alpha-new" },
161
+ { id: "2", title: "beta" },
162
+ { id: "3", title: "gamma" },
163
+ ]);
164
+ });
165
+ test("IndexFileReconciler removes ids before upserting", async () => {
166
+ const existing = JSON.stringify([
167
+ { id: "1", title: "alpha" },
168
+ { id: "2", title: "beta" },
169
+ { id: "3", title: "gamma" },
170
+ ]);
171
+ const client = createClient({ initialFiles: { "/p/_index.json": existing } });
172
+ const reconciler = new IndexFileReconciler({
173
+ client,
174
+ workspaceId: "ws-1",
175
+ path: "/p/_index.json",
176
+ builder: (rows) => ({
177
+ path: "/p/_index.json",
178
+ content: `${JSON.stringify([...rows].sort((a, b) => a.id.localeCompare(b.id)))}\n`,
179
+ }),
180
+ });
181
+ reconciler.remove("2");
182
+ reconciler.upsert({ id: "4", title: "delta" });
183
+ await reconciler.flush();
184
+ const written = JSON.parse(client.files.get("/p/_index.json"));
185
+ assert.deepEqual(written.map((row) => row.id), ["1", "3", "4"]);
186
+ });
187
+ test("IndexFileReconciler flush returns zero when no upserts/removes queued", async () => {
188
+ const client = createClient();
189
+ const reconciler = new IndexFileReconciler({
190
+ client,
191
+ workspaceId: "ws-1",
192
+ path: "/p/_index.json",
193
+ builder: () => ({ path: "/p/_index.json", content: "[]" }),
194
+ });
195
+ assert.equal(reconciler.isEmpty(), true);
196
+ const result = await reconciler.flush();
197
+ assert.deepEqual(result, { written: 0, errors: [] });
198
+ assert.equal(client.writes.length, 0);
199
+ });
200
+ test("IndexFileReconciler degrades gracefully when client lacks readFile", async () => {
201
+ const client = createClient({ noRead: true });
202
+ const reconciler = new IndexFileReconciler({
203
+ client,
204
+ workspaceId: "ws-1",
205
+ path: "/p/_index.json",
206
+ builder: (rows) => ({
207
+ path: "/p/_index.json",
208
+ content: JSON.stringify(rows),
209
+ }),
210
+ });
211
+ reconciler.upsert({ id: "1", title: "alpha" });
212
+ const result = await reconciler.flush();
213
+ assert.equal(result.written, 1);
214
+ assert.deepEqual(result.errors, []);
215
+ });
216
+ test("IndexFileReconciler surfaces write failures in errors", async () => {
217
+ const client = createClient({ failWriteOn: new Set(["/p/_index.json"]) });
218
+ const reconciler = new IndexFileReconciler({
219
+ client,
220
+ workspaceId: "ws-1",
221
+ path: "/p/_index.json",
222
+ builder: () => ({ path: "/p/_index.json", content: "[]" }),
223
+ });
224
+ reconciler.upsert({ id: "1" });
225
+ const result = await reconciler.flush();
226
+ assert.equal(result.written, 0);
227
+ assert.equal(result.errors.length, 1);
228
+ assert.equal(result.errors[0].path, "/p/_index.json");
229
+ });
230
+ test("PriorAliasReader returns null when client has no readFile", async () => {
231
+ const client = createClient({ noRead: true });
232
+ const reader = new PriorAliasReader(client, "ws-1");
233
+ assert.equal(reader.isAvailable(), false);
234
+ const got = await reader.read("/p/by-id/1.json");
235
+ assert.equal(got, null);
236
+ });
237
+ test("PriorAliasReader returns parsed record on success", async () => {
238
+ const client = createClient({
239
+ initialFiles: { "/p/by-id/1.json": JSON.stringify({ title: "alpha" }) },
240
+ });
241
+ const reader = new PriorAliasReader(client, "ws-1");
242
+ const got = await reader.read("/p/by-id/1.json", (parsed) => ({
243
+ title: typeof parsed.title === "string" ? parsed.title : undefined,
244
+ }));
245
+ assert.deepEqual(got, { title: "alpha" });
246
+ });
247
+ test("PriorAliasReader returns null on missing file, read error, parse error, or non-object", async () => {
248
+ const client = createClient({
249
+ initialFiles: {
250
+ "/p/bad.json": "{ not json",
251
+ "/p/array.json": "[1,2,3]",
252
+ },
253
+ failReadOn: new Set(["/p/boom.json"]),
254
+ });
255
+ const reader = new PriorAliasReader(client, "ws-1");
256
+ assert.equal(await reader.read("/p/missing.json"), null);
257
+ assert.equal(await reader.read("/p/boom.json"), null);
258
+ assert.equal(await reader.read("/p/bad.json"), null);
259
+ assert.equal(await reader.read("/p/array.json"), null);
260
+ });
261
+ test("PriorAliasReader returns null when extractor throws", async () => {
262
+ const client = createClient({
263
+ initialFiles: { "/p/by-id/1.json": JSON.stringify({ title: "alpha" }) },
264
+ });
265
+ const reader = new PriorAliasReader(client, "ws-1");
266
+ const got = await reader.read("/p/by-id/1.json", () => {
267
+ throw new Error("extractor exploded");
268
+ });
269
+ assert.equal(got, null);
270
+ });
271
+ //# sourceMappingURL=emit-auxiliary.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-auxiliary.test.js","sourceRoot":"","sources":["../../../tests/emit-auxiliary/emit-auxiliary.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayfile/adapter-core",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "Schema-driven relayfile adapter generator and runtime",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",