@relayfile/adapter-core 0.1.20 → 0.2.1

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.
Files changed (31) hide show
  1. package/dist/src/atomic-index/index.d.ts +117 -0
  2. package/dist/src/atomic-index/index.d.ts.map +1 -0
  3. package/dist/src/atomic-index/index.js +168 -0
  4. package/dist/src/atomic-index/index.js.map +1 -0
  5. package/dist/src/index.d.ts +3 -0
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +3 -0
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/runtime/file-native-router.d.ts +98 -0
  10. package/dist/src/runtime/file-native-router.d.ts.map +1 -0
  11. package/dist/src/runtime/file-native-router.js +399 -0
  12. package/dist/src/runtime/file-native-router.js.map +1 -0
  13. package/dist/src/runtime/file-native-router.test.d.ts +2 -0
  14. package/dist/src/runtime/file-native-router.test.d.ts.map +1 -0
  15. package/dist/src/runtime/file-native-router.test.js +294 -0
  16. package/dist/src/runtime/file-native-router.test.js.map +1 -0
  17. package/dist/src/runtime/writeback-status.d.ts +26 -0
  18. package/dist/src/runtime/writeback-status.d.ts.map +1 -0
  19. package/dist/src/runtime/writeback-status.js +33 -0
  20. package/dist/src/runtime/writeback-status.js.map +1 -0
  21. package/dist/src/storage-bridge/discovery.d.ts +2 -14
  22. package/dist/src/storage-bridge/discovery.d.ts.map +1 -1
  23. package/dist/src/storage-bridge/discovery.js +3 -9
  24. package/dist/src/storage-bridge/discovery.js.map +1 -1
  25. package/dist/tests/atomic-index/atomic-index.test.d.ts +2 -0
  26. package/dist/tests/atomic-index/atomic-index.test.d.ts.map +1 -0
  27. package/dist/tests/atomic-index/atomic-index.test.js +182 -0
  28. package/dist/tests/atomic-index/atomic-index.test.js.map +1 -0
  29. package/dist/tests/storage-bridge/storage-bridge.test.js +1 -1
  30. package/dist/tests/storage-bridge/storage-bridge.test.js.map +1 -1
  31. package/package.json +2 -2
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Optimistic compare-and-swap (CAS) upsert for `_index.json` files.
3
+ *
4
+ * Concurrent ingestions can race when the read-modify-write pattern
5
+ * `read existing rows -> upsert -> write` is not atomic: two writers read
6
+ * the same baseline, each compute their own merged result, and the second
7
+ * write silently overwrites the first row.
8
+ *
9
+ * The helper reads both content and the file revision (when the VFS
10
+ * exposes that metadata), submits a write tagged with `baseRevision`, and
11
+ * retries the read-merge-write loop on conflict. Backends without revision
12
+ * support degrade to plain read-modify-write — the race remains in those
13
+ * legacy backends but is not regressed by this helper.
14
+ *
15
+ * This module is generic — it deliberately knows nothing about github,
16
+ * linear, notion, or any specific record schema. Each adapter wires it up
17
+ * with its own parse / merge / serialize and (optionally) a VfsLike shim
18
+ * around its concrete client.
19
+ */
20
+ /**
21
+ * Minimal duck-typed VFS contract the atomic upsert helper consumes.
22
+ *
23
+ * Adapters whose underlying client uses a single-input shape (e.g. the
24
+ * `RelayFileClient.writeFile({ workspaceId, path, ... })` style used by
25
+ * linear and notion) can satisfy this contract by wrapping the client in
26
+ * a small shim that flattens the call to `(path, content, options)`.
27
+ */
28
+ export interface VfsLike {
29
+ exists?(path: string): Promise<boolean> | boolean;
30
+ get?(path: string): Promise<unknown> | unknown;
31
+ has?(path: string): Promise<boolean> | boolean;
32
+ put?(path: string, content: string, options?: {
33
+ baseRevision?: string;
34
+ }): Promise<unknown> | unknown;
35
+ read?(path: string): Promise<unknown> | unknown;
36
+ readFile?(path: string): Promise<unknown> | unknown;
37
+ set?(path: string, content: string, options?: {
38
+ baseRevision?: string;
39
+ }): Promise<unknown> | unknown;
40
+ stat?(path: string): Promise<unknown> | unknown;
41
+ upsert?(path: string, content: string, options?: {
42
+ baseRevision?: string;
43
+ }): Promise<unknown> | unknown;
44
+ write?(path: string, content: string, options?: {
45
+ baseRevision?: string;
46
+ }): Promise<unknown> | unknown;
47
+ writeFile?(path: string, content: string, options?: {
48
+ baseRevision?: string;
49
+ }): Promise<unknown> | unknown;
50
+ }
51
+ export interface AtomicUpsertOptions {
52
+ /**
53
+ * Maximum number of CAS attempts before throwing
54
+ * {@link AtomicIndexExhaustedError}. Defaults to 5.
55
+ */
56
+ maxAttempts?: number;
57
+ /**
58
+ * Linear backoff base in milliseconds. Each retry waits
59
+ * `baseDelayMs * attemptNumber`. Defaults to 50ms.
60
+ */
61
+ baseDelayMs?: number;
62
+ /**
63
+ * Optional sleep override, primarily exposed for tests so they don't have
64
+ * to wait on real timers.
65
+ */
66
+ sleep?: (ms: number) => Promise<void>;
67
+ }
68
+ export interface AtomicReadResult<TContent> {
69
+ content: TContent | undefined;
70
+ revision: string;
71
+ }
72
+ export declare class AtomicIndexExhaustedError extends Error {
73
+ readonly path: string;
74
+ readonly attempts: number;
75
+ constructor(path: string, attempts: number, cause?: unknown);
76
+ }
77
+ /**
78
+ * Read a text file plus its revision from the VFS.
79
+ *
80
+ * - If the VFS reader returns `{ content, revision }`, both are surfaced.
81
+ * - If the reader returns a plain string, revision falls back to `"0"`
82
+ * (sentinel meaning "no prior revision known").
83
+ * - If the file is missing, `content` is `undefined` and revision is `"0"`.
84
+ */
85
+ export declare function readIndexWithRevision(vfs: VfsLike, path: string): Promise<AtomicReadResult<string>>;
86
+ /**
87
+ * Write a text file via any of the writer aliases the VFS exposes, passing
88
+ * `baseRevision` so revision-aware backends can perform a compare-and-swap.
89
+ *
90
+ * The third argument is positional rather than an options bag because the
91
+ * majority of legacy VFS shims spread the call as `(path, content, ...rest)`
92
+ * and ignore extra positional args; switching to an object would silently
93
+ * regress them.
94
+ */
95
+ export declare function writeIndexWithRevision(vfs: VfsLike, path: string, content: string, baseRevision: string): Promise<void>;
96
+ /**
97
+ * Detect a relayfile / VFS revision-conflict error without taking a hard
98
+ * dependency on the SDK error class — we duck-type on the standard shapes:
99
+ *
100
+ * - `RevisionConflictError` from `@relayfile/sdk` (`name === 'RevisionConflictError'`).
101
+ * - HTTP 409 responses surfaced as plain Errors with a `status` field.
102
+ * - Errors carrying a `code === 'revision_conflict'` field.
103
+ */
104
+ export declare function isConflictError(error: unknown): boolean;
105
+ /**
106
+ * Upsert a JSON-encoded `_index.json` file using optimistic CAS retries.
107
+ *
108
+ * The caller supplies `parse` (string -> rows), `merge` (rows -> rows), and
109
+ * `serialize` (rows -> bytes). Each attempt re-reads the existing rows, runs
110
+ * `merge` against them (so concurrent rows added by another writer survive),
111
+ * and writes with the just-observed revision as `baseRevision`. On conflict
112
+ * we back off linearly and try again, up to {@link AtomicUpsertOptions.maxAttempts}.
113
+ */
114
+ export declare function upsertIndexAtomic<TRow>(vfs: VfsLike, path: string, parse: (content: string | undefined) => TRow[], merge: (rows: TRow[]) => TRow[], serialize: (rows: TRow[]) => string, options?: AtomicUpsertOptions): Promise<{
115
+ existedAtWrite: boolean;
116
+ }>;
117
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic-index/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Optimistic compare-and-swap (CAS) upsert for `_index.json` files.
3
+ *
4
+ * Concurrent ingestions can race when the read-modify-write pattern
5
+ * `read existing rows -> upsert -> write` is not atomic: two writers read
6
+ * the same baseline, each compute their own merged result, and the second
7
+ * write silently overwrites the first row.
8
+ *
9
+ * The helper reads both content and the file revision (when the VFS
10
+ * exposes that metadata), submits a write tagged with `baseRevision`, and
11
+ * retries the read-merge-write loop on conflict. Backends without revision
12
+ * support degrade to plain read-modify-write — the race remains in those
13
+ * legacy backends but is not regressed by this helper.
14
+ *
15
+ * This module is generic — it deliberately knows nothing about github,
16
+ * linear, notion, or any specific record schema. Each adapter wires it up
17
+ * with its own parse / merge / serialize and (optionally) a VfsLike shim
18
+ * around its concrete client.
19
+ */
20
+ const DEFAULT_MAX_ATTEMPTS = 5;
21
+ const DEFAULT_BASE_DELAY_MS = 50;
22
+ export class AtomicIndexExhaustedError extends Error {
23
+ path;
24
+ attempts;
25
+ constructor(path, attempts, cause) {
26
+ super(`atomic index upsert exceeded ${attempts} attempts for ${path}` +
27
+ (cause instanceof Error ? `: ${cause.message}` : ''));
28
+ this.name = 'AtomicIndexExhaustedError';
29
+ this.path = path;
30
+ this.attempts = attempts;
31
+ if (cause !== undefined) {
32
+ // Preserve the underlying cause for diagnostics without forcing
33
+ // dependents to introspect a bespoke field.
34
+ this.cause = cause;
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ * Read a text file plus its revision from the VFS.
40
+ *
41
+ * - If the VFS reader returns `{ content, revision }`, both are surfaced.
42
+ * - If the reader returns a plain string, revision falls back to `"0"`
43
+ * (sentinel meaning "no prior revision known").
44
+ * - If the file is missing, `content` is `undefined` and revision is `"0"`.
45
+ */
46
+ export async function readIndexWithRevision(vfs, path) {
47
+ for (const reader of [vfs.readFile, vfs.read, vfs.get]) {
48
+ if (!reader) {
49
+ continue;
50
+ }
51
+ try {
52
+ const value = await reader.call(vfs, path);
53
+ if (value === null || value === undefined) {
54
+ continue;
55
+ }
56
+ if (typeof value === 'string') {
57
+ return { content: value, revision: '0' };
58
+ }
59
+ if (typeof value === 'object') {
60
+ const record = value;
61
+ const content = typeof record.content === 'string' ? record.content : undefined;
62
+ const revision = typeof record.revision === 'string' ? record.revision : '0';
63
+ if (content !== undefined) {
64
+ return { content, revision };
65
+ }
66
+ }
67
+ }
68
+ catch {
69
+ // A throwing reader should not abort the loop — fall through to the
70
+ // next available reader so we still surface text from working backends.
71
+ continue;
72
+ }
73
+ }
74
+ return { content: undefined, revision: '0' };
75
+ }
76
+ /**
77
+ * Write a text file via any of the writer aliases the VFS exposes, passing
78
+ * `baseRevision` so revision-aware backends can perform a compare-and-swap.
79
+ *
80
+ * The third argument is positional rather than an options bag because the
81
+ * majority of legacy VFS shims spread the call as `(path, content, ...rest)`
82
+ * and ignore extra positional args; switching to an object would silently
83
+ * regress them.
84
+ */
85
+ export async function writeIndexWithRevision(vfs, path, content, baseRevision) {
86
+ const writer = vfs.writeFile ?? vfs.write ?? vfs.put ?? vfs.set ?? vfs.upsert;
87
+ if (!writer) {
88
+ throw new Error('VFS object must expose one of writeFile(path, content), write(path, content), put(path, content), set(path, content), or upsert(path, content).');
89
+ }
90
+ // Pass `baseRevision` as a 3rd positional options arg so revision-aware
91
+ // VFS shims (e.g. relayfile-client) can perform a CAS write. Legacy shims
92
+ // ignore the extra positional arg, so this is safe.
93
+ const variadicWriter = writer;
94
+ await variadicWriter.call(vfs, path, content, { baseRevision });
95
+ }
96
+ /**
97
+ * Detect a relayfile / VFS revision-conflict error without taking a hard
98
+ * dependency on the SDK error class — we duck-type on the standard shapes:
99
+ *
100
+ * - `RevisionConflictError` from `@relayfile/sdk` (`name === 'RevisionConflictError'`).
101
+ * - HTTP 409 responses surfaced as plain Errors with a `status` field.
102
+ * - Errors carrying a `code === 'revision_conflict'` field.
103
+ */
104
+ export function isConflictError(error) {
105
+ if (!error || typeof error !== 'object') {
106
+ return false;
107
+ }
108
+ const candidate = error;
109
+ if (candidate.name === 'RevisionConflictError') {
110
+ return true;
111
+ }
112
+ if (candidate.status === 409 || candidate.statusCode === 409) {
113
+ return true;
114
+ }
115
+ if (candidate.code === 'revision_conflict') {
116
+ return true;
117
+ }
118
+ return false;
119
+ }
120
+ /**
121
+ * Upsert a JSON-encoded `_index.json` file using optimistic CAS retries.
122
+ *
123
+ * The caller supplies `parse` (string -> rows), `merge` (rows -> rows), and
124
+ * `serialize` (rows -> bytes). Each attempt re-reads the existing rows, runs
125
+ * `merge` against them (so concurrent rows added by another writer survive),
126
+ * and writes with the just-observed revision as `baseRevision`. On conflict
127
+ * we back off linearly and try again, up to {@link AtomicUpsertOptions.maxAttempts}.
128
+ */
129
+ export async function upsertIndexAtomic(vfs, path, parse, merge, serialize, options = {}) {
130
+ const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
131
+ const baseDelayMs = options.baseDelayMs ?? DEFAULT_BASE_DELAY_MS;
132
+ const sleep = options.sleep ?? defaultSleep;
133
+ if (maxAttempts < 1) {
134
+ throw new Error('upsertIndexAtomic: maxAttempts must be >= 1');
135
+ }
136
+ let lastError;
137
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
138
+ const { content, revision } = await readIndexWithRevision(vfs, path);
139
+ const merged = merge(parse(content));
140
+ const next = serialize(merged);
141
+ try {
142
+ await writeIndexWithRevision(vfs, path, next, revision);
143
+ // The read that produced the winning baseRevision is authoritative for
144
+ // existed-vs-new accounting: another writer cannot have raced us between
145
+ // this read and the matching CAS write without us seeing a conflict and
146
+ // looping.
147
+ return { existedAtWrite: content !== undefined };
148
+ }
149
+ catch (error) {
150
+ if (!isConflictError(error)) {
151
+ throw error;
152
+ }
153
+ lastError = error;
154
+ // Re-read on conflict; another writer beat us. Linear backoff prevents
155
+ // tight-looping a single hot index path while still resolving quickly.
156
+ if (attempt < maxAttempts - 1) {
157
+ await sleep(baseDelayMs * (attempt + 1));
158
+ }
159
+ }
160
+ }
161
+ throw new AtomicIndexExhaustedError(path, maxAttempts, lastError);
162
+ }
163
+ function defaultSleep(ms) {
164
+ return new Promise((resolve) => {
165
+ setTimeout(resolve, ms);
166
+ });
167
+ }
168
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/atomic-index/index.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ export * from "./ingest/openapi.js";
7
7
  export * from "./ingest/postman.js";
8
8
  export * from "./ingest/sample.js";
9
9
  export * from "./runtime/schema-adapter.js";
10
+ export * from "./runtime/file-native-router.js";
11
+ export * from "./runtime/writeback-status.js";
10
12
  export * from "./generate/adapter-generator.js";
11
13
  export * from "./generate/types-generator.js";
12
14
  export * from "./drift/drift-checker.js";
@@ -18,4 +20,5 @@ export * from "./docs/mapping-generator.js";
18
20
  export * from "./docs/change-detector.js";
19
21
  export * from "./docs/updater.js";
20
22
  export * from "./storage-bridge/index.js";
23
+ export * from "./atomic-index/index.js";
21
24
  //# 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,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"}
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"}
package/dist/src/index.js CHANGED
@@ -7,6 +7,8 @@ export * from "./ingest/openapi.js";
7
7
  export * from "./ingest/postman.js";
8
8
  export * from "./ingest/sample.js";
9
9
  export * from "./runtime/schema-adapter.js";
10
+ export * from "./runtime/file-native-router.js";
11
+ export * from "./runtime/writeback-status.js";
10
12
  export * from "./generate/adapter-generator.js";
11
13
  export * from "./generate/types-generator.js";
12
14
  export * from "./drift/drift-checker.js";
@@ -18,4 +20,5 @@ export * from "./docs/mapping-generator.js";
18
20
  export * from "./docs/change-detector.js";
19
21
  export * from "./docs/updater.js";
20
22
  export * from "./storage-bridge/index.js";
23
+ export * from "./atomic-index/index.js";
21
24
  //# 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,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"}
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"}
@@ -0,0 +1,98 @@
1
+ import { type WritebackStatusEntry } from "./writeback-status.js";
2
+ export type AdapterResourceOperation = "create" | "update" | "delete";
3
+ export interface AdapterResourceConfig {
4
+ readonly name: string;
5
+ readonly path: string;
6
+ readonly pathPattern: RegExp;
7
+ readonly idPattern: RegExp;
8
+ readonly schema: string;
9
+ readonly createExample: string;
10
+ readonly operations?: readonly AdapterResourceOperation[];
11
+ }
12
+ export type FileNativeWritebackKind = "patch" | "create" | "delete";
13
+ export type FileNativeWritebackEvent = "write" | "delete";
14
+ export interface FileNativeWritebackRoute {
15
+ kind: FileNativeWritebackKind;
16
+ resource: AdapterResourceConfig;
17
+ id?: string;
18
+ canonical: boolean;
19
+ }
20
+ export interface FileNativeWritebackRequest {
21
+ readonly method?: string;
22
+ readonly endpoint?: string;
23
+ readonly action?: string;
24
+ readonly body?: unknown;
25
+ readonly [key: string]: unknown;
26
+ }
27
+ export interface FileNativeCreateReceipt {
28
+ readonly draftPath: string;
29
+ readonly canonicalPath?: string;
30
+ readonly id?: string;
31
+ readonly resource: string;
32
+ readonly createdAt: string;
33
+ }
34
+ export interface FileNativeWritebackExecutionOk {
35
+ readonly ok: true;
36
+ readonly route: FileNativeWritebackRoute;
37
+ readonly request?: FileNativeWritebackRequest;
38
+ readonly adapterResult?: unknown;
39
+ readonly createReceipt?: FileNativeCreateReceipt;
40
+ readonly status: WritebackStatusEntry;
41
+ }
42
+ export interface FileNativeWritebackExecutionFailed {
43
+ readonly ok: false;
44
+ readonly route?: FileNativeWritebackRoute;
45
+ readonly errors?: WritebackValidationError[];
46
+ readonly status?: WritebackStatusEntry;
47
+ }
48
+ export type FileNativeWritebackExecutionResult = FileNativeWritebackExecutionOk | FileNativeWritebackExecutionFailed;
49
+ export interface ClassifyWriteOptions {
50
+ fsEvent?: FileNativeWritebackEvent;
51
+ }
52
+ export interface ExecuteFileNativeWritebackOptions {
53
+ path: string;
54
+ content?: string;
55
+ resources: readonly AdapterResourceConfig[];
56
+ fsEvent?: FileNativeWritebackEvent;
57
+ schemaRoot?: string;
58
+ loadSchema?: (resource: AdapterResourceConfig) => JsonSchema | Promise<JsonSchema>;
59
+ resolveWritebackRequest?: (path: string, content: string) => FileNativeWritebackRequest | Promise<FileNativeWritebackRequest>;
60
+ resolveDeleteRequest?: (path: string) => FileNativeWritebackRequest | Promise<FileNativeWritebackRequest>;
61
+ applyWriteback?: (request: FileNativeWritebackRequest, route: FileNativeWritebackRoute) => unknown | Promise<unknown>;
62
+ extractCreatedId?: (result: unknown, request: FileNativeWritebackRequest, route: FileNativeWritebackRoute) => string | undefined;
63
+ makeCanonicalPath?: (id: string, route: FileNativeWritebackRoute) => string | undefined;
64
+ recordStatus?: boolean;
65
+ now?: () => Date;
66
+ }
67
+ export interface JsonSchema {
68
+ readonly type?: string | readonly string[];
69
+ readonly required?: readonly string[];
70
+ readonly properties?: Readonly<Record<string, JsonSchema>>;
71
+ readonly additionalProperties?: boolean | JsonSchema;
72
+ readonly readOnly?: boolean;
73
+ readonly enum?: readonly unknown[];
74
+ readonly items?: JsonSchema;
75
+ }
76
+ export type WritebackValidationReason = "required" | "additionalProperties" | "readOnly" | "type" | "enum";
77
+ export declare class ReadOnlyFieldError extends Error {
78
+ readonly field: string;
79
+ constructor(field: string);
80
+ }
81
+ export declare class WritebackValidationError extends Error {
82
+ readonly field?: string;
83
+ readonly reason: WritebackValidationReason;
84
+ constructor(input: {
85
+ field?: string;
86
+ reason: WritebackValidationReason;
87
+ message?: string;
88
+ });
89
+ }
90
+ export declare function classifyWrite(path: string, resources: readonly AdapterResourceConfig[], opts?: ClassifyWriteOptions): FileNativeWritebackRoute | null;
91
+ export declare function validatePayload(payload: unknown, schema: JsonSchema, op: "patch" | "create"): {
92
+ ok: true;
93
+ } | {
94
+ ok: false;
95
+ errors: WritebackValidationError[];
96
+ };
97
+ export declare function executeFileNativeWriteback(options: ExecuteFileNativeWritebackOptions): Promise<FileNativeWritebackExecutionResult>;
98
+ //# sourceMappingURL=file-native-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-native-router.d.ts","sourceRoot":"","sources":["../../../src/runtime/file-native-router.ts"],"names":[],"mappings":"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"}