@ontrails/store 1.0.0-beta.14 → 1.0.0-beta.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.
Files changed (92) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +7 -0
  3. package/README.md +126 -61
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/internal/signal-identity.d.ts +17 -0
  9. package/dist/internal/signal-identity.d.ts.map +1 -0
  10. package/dist/internal/signal-identity.js +81 -0
  11. package/dist/internal/signal-identity.js.map +1 -0
  12. package/dist/jsonfile/index.d.ts +3 -0
  13. package/dist/jsonfile/index.d.ts.map +1 -0
  14. package/dist/jsonfile/index.js +2 -0
  15. package/dist/jsonfile/index.js.map +1 -0
  16. package/dist/jsonfile/runtime.d.ts +19 -0
  17. package/dist/jsonfile/runtime.d.ts.map +1 -0
  18. package/dist/jsonfile/runtime.js +403 -0
  19. package/dist/jsonfile/runtime.js.map +1 -0
  20. package/dist/jsonfile/types.d.ts +40 -0
  21. package/dist/jsonfile/types.d.ts.map +1 -0
  22. package/dist/{drizzle → jsonfile}/types.js.map +1 -1
  23. package/dist/store.d.ts +8 -18
  24. package/dist/store.d.ts.map +1 -1
  25. package/dist/store.js +152 -94
  26. package/dist/store.js.map +1 -1
  27. package/dist/testing.d.ts +28 -0
  28. package/dist/testing.d.ts.map +1 -0
  29. package/dist/testing.js +90 -0
  30. package/dist/testing.js.map +1 -0
  31. package/dist/trails/crud.d.ts +38 -0
  32. package/dist/trails/crud.d.ts.map +1 -0
  33. package/dist/trails/crud.js +112 -0
  34. package/dist/trails/crud.js.map +1 -0
  35. package/dist/trails/index.d.ts +7 -0
  36. package/dist/trails/index.d.ts.map +1 -0
  37. package/dist/trails/index.js +4 -0
  38. package/dist/trails/index.js.map +1 -0
  39. package/dist/trails/reconcile.d.ts +36 -0
  40. package/dist/trails/reconcile.d.ts.map +1 -0
  41. package/dist/trails/reconcile.js +142 -0
  42. package/dist/trails/reconcile.js.map +1 -0
  43. package/dist/trails/sync.d.ts +25 -0
  44. package/dist/trails/sync.d.ts.map +1 -0
  45. package/dist/trails/sync.js +96 -0
  46. package/dist/trails/sync.js.map +1 -0
  47. package/dist/trails/utils.d.ts +51 -0
  48. package/dist/trails/utils.d.ts.map +1 -0
  49. package/dist/trails/utils.js +65 -0
  50. package/dist/trails/utils.js.map +1 -0
  51. package/dist/types.d.ts +205 -35
  52. package/dist/types.d.ts.map +1 -1
  53. package/package.json +6 -9
  54. package/src/__tests__/crud.test.ts +346 -0
  55. package/src/__tests__/jsonfile.test.ts +502 -0
  56. package/src/__tests__/store.test.ts +239 -33
  57. package/src/__tests__/sync-reconcile.test.ts +646 -0
  58. package/src/index.ts +12 -8
  59. package/src/internal/signal-identity.ts +162 -0
  60. package/src/jsonfile/index.ts +6 -0
  61. package/src/jsonfile/runtime.ts +702 -0
  62. package/src/jsonfile/types.ts +50 -0
  63. package/src/store.ts +296 -134
  64. package/src/testing.ts +175 -0
  65. package/src/trails/crud.ts +355 -0
  66. package/src/trails/index.ts +10 -0
  67. package/src/trails/reconcile.ts +281 -0
  68. package/src/trails/sync.ts +251 -0
  69. package/src/trails/utils.ts +96 -0
  70. package/src/types.ts +355 -63
  71. package/tsconfig.tests.json +10 -0
  72. package/tsconfig.tsbuildinfo +1 -1
  73. package/dist/drizzle/index.d.ts +0 -3
  74. package/dist/drizzle/index.d.ts.map +0 -1
  75. package/dist/drizzle/index.js +0 -2
  76. package/dist/drizzle/index.js.map +0 -1
  77. package/dist/drizzle/runtime.d.ts +0 -21
  78. package/dist/drizzle/runtime.d.ts.map +0 -1
  79. package/dist/drizzle/runtime.js +0 -458
  80. package/dist/drizzle/runtime.js.map +0 -1
  81. package/dist/drizzle/schema.d.ts +0 -15
  82. package/dist/drizzle/schema.d.ts.map +0 -1
  83. package/dist/drizzle/schema.js +0 -322
  84. package/dist/drizzle/schema.js.map +0 -1
  85. package/dist/drizzle/types.d.ts +0 -40
  86. package/dist/drizzle/types.d.ts.map +0 -1
  87. package/src/drizzle/__tests__/drizzle.test.ts +0 -469
  88. package/src/drizzle/index.ts +0 -17
  89. package/src/drizzle/runtime.ts +0 -853
  90. package/src/drizzle/schema.ts +0 -577
  91. package/src/drizzle/types.ts +0 -70
  92. /package/dist/{drizzle → jsonfile}/types.js +0 -0
@@ -0,0 +1,403 @@
1
+ import { ConflictError, InternalError, Result, resource } from '@ontrails/core';
2
+ import { bindStoreDefinition } from '../internal/signal-identity.js';
3
+ import { versionFieldName } from '../store.js';
4
+ // ---------------------------------------------------------------------------
5
+ // Mutex — single-process in-memory lock
6
+ // ---------------------------------------------------------------------------
7
+ /* eslint-disable promise/avoid-new -- Mutex requires manual promise control */
8
+ const createMutexAcquire = (state, queue) => () => {
9
+ if (!state.locked) {
10
+ state.locked = true;
11
+ return Promise.resolve();
12
+ }
13
+ return new Promise((resolve) => {
14
+ queue.push(resolve);
15
+ });
16
+ };
17
+ /* eslint-enable promise/avoid-new */
18
+ const createMutexRelease = (state, queue) => () => {
19
+ const next = queue.shift();
20
+ if (next) {
21
+ next();
22
+ }
23
+ else {
24
+ state.locked = false;
25
+ }
26
+ };
27
+ const createMutex = () => {
28
+ const state = { locked: false };
29
+ const queue = [];
30
+ return {
31
+ acquire: createMutexAcquire(state, queue),
32
+ release: createMutexRelease(state, queue),
33
+ };
34
+ };
35
+ // ---------------------------------------------------------------------------
36
+ // Helpers
37
+ // ---------------------------------------------------------------------------
38
+ const defaultResourceId = 'store';
39
+ const defaultGenerateIdentity = () => Bun.randomUUIDv7();
40
+ const jsonFilePath = (dir, tableName) => `${dir}/${tableName}.json`;
41
+ const matchesFilters = (entity, filters) => {
42
+ for (const [key, value] of Object.entries(filters)) {
43
+ if (entity[key] !== value) {
44
+ return false;
45
+ }
46
+ }
47
+ return true;
48
+ };
49
+ const applyPagination = (items, options) => {
50
+ if (options === undefined) {
51
+ return items;
52
+ }
53
+ const offset = options.offset ?? 0;
54
+ const limit = options.limit ?? items.length;
55
+ return items.slice(offset, offset + limit);
56
+ };
57
+ // ---------------------------------------------------------------------------
58
+ // Generated field helpers (defined before use, module-level)
59
+ // ---------------------------------------------------------------------------
60
+ const assignIdentity = (payload, identityField, generate) => {
61
+ if (payload[identityField] === undefined) {
62
+ payload[identityField] = generate();
63
+ }
64
+ };
65
+ const assignTimestamp = (payload, generatedFields, isNew) => {
66
+ if (generatedFields.has('createdAt') && isNew) {
67
+ payload['createdAt'] = new Date().toISOString();
68
+ }
69
+ if (generatedFields.has('updatedAt')) {
70
+ payload['updatedAt'] = new Date().toISOString();
71
+ }
72
+ };
73
+ const resolveNextVersion = (existing) => existing === undefined ? 1 : existing[versionFieldName] + 1;
74
+ const assignVersion = (payload, isVersioned, existing) => {
75
+ if (!isVersioned) {
76
+ return;
77
+ }
78
+ payload[versionFieldName] = resolveNextVersion(existing);
79
+ };
80
+ const checkVersionConflict = (tableName, isVersioned, input, existing) => {
81
+ if (!isVersioned) {
82
+ return;
83
+ }
84
+ const inputVersion = input[versionFieldName];
85
+ if (inputVersion === undefined) {
86
+ return;
87
+ }
88
+ const currentVersion = existing[versionFieldName];
89
+ if (inputVersion !== currentVersion) {
90
+ throw new ConflictError(`Version conflict on "${tableName}": expected ${String(inputVersion)}, actual ${String(currentVersion)}`);
91
+ }
92
+ };
93
+ const buildUpsertPayload = (input, existing, identityField, generateIdentity, generatedFields, isVersioned) => {
94
+ const payload = { ...input };
95
+ assignIdentity(payload, identityField, generateIdentity);
96
+ assignTimestamp(payload, generatedFields, existing === undefined);
97
+ assignVersion(payload, isVersioned, existing);
98
+ return payload;
99
+ };
100
+ // ---------------------------------------------------------------------------
101
+ // File I/O helpers
102
+ // ---------------------------------------------------------------------------
103
+ const loadFromDisk = async (path, identityField, index) => {
104
+ const file = Bun.file(path);
105
+ const exists = await file.exists();
106
+ if (!exists) {
107
+ await Bun.write(path, '[]');
108
+ return;
109
+ }
110
+ const text = await file.text();
111
+ const rows = JSON.parse(text);
112
+ for (const row of rows) {
113
+ const id = String(row[identityField]);
114
+ index.set(id, row);
115
+ }
116
+ };
117
+ const flushToDisk = async (path, index) => {
118
+ const rows = [...index.values()];
119
+ await Bun.write(path, JSON.stringify(rows, null, 2));
120
+ };
121
+ // ---------------------------------------------------------------------------
122
+ // Upsert core (extracted to stay under max-statements)
123
+ // ---------------------------------------------------------------------------
124
+ const resolveExisting = (raw, identityField, index) => {
125
+ const id = String(raw[identityField] ?? '');
126
+ return id ? index.get(id) : undefined;
127
+ };
128
+ const mergeAndBuild = (raw, existing, identityField, generateIdentity, generatedFields, isVersioned) => {
129
+ const merged = existing === undefined ? { ...raw } : { ...existing, ...raw };
130
+ const payload = buildUpsertPayload(merged, existing, identityField, generateIdentity, generatedFields, isVersioned);
131
+ return payload;
132
+ };
133
+ // Flush an upsert to disk then commit to the live index. Extracted to keep
134
+ // executeUpsert under the max-statements limit.
135
+ const flushAndCommitUpsert = async (entity, id, index, path) => {
136
+ // Build the intended state, flush to disk, then update the live index.
137
+ // This ensures the in-memory Map stays consistent with the file even if
138
+ // the write fails.
139
+ const next = new Map([...index, [id, entity]]);
140
+ await flushToDisk(path, next);
141
+ index.set(id, entity);
142
+ return structuredClone(entity);
143
+ };
144
+ const executeUpsert = (input, index, path, cfg) => {
145
+ const raw = input;
146
+ const existing = resolveExisting(raw, cfg.identityField, index);
147
+ if (existing !== undefined) {
148
+ checkVersionConflict(cfg.tableName, cfg.isVersioned, raw, existing);
149
+ }
150
+ const entity = mergeAndBuild(raw, existing, cfg.identityField, cfg.generateIdentity, cfg.generatedFields, cfg.isVersioned);
151
+ const id = String(entity[cfg.identityField]);
152
+ return flushAndCommitUpsert(entity, id, index, path);
153
+ };
154
+ const deriveTableConfig = (options) => ({
155
+ generateIdentity: options.generateIdentity,
156
+ generatedFields: new Set(options.table.generated),
157
+ identityField: options.table.identity,
158
+ isVersioned: options.table.versioned,
159
+ tableName: options.table.name,
160
+ });
161
+ const usesGeneratedIdentity = (config) => config.generatedFields.includes(config.identityField);
162
+ const deriveTableReuseConfig = (options) => {
163
+ const generatedFields = [...options.table.generated].toSorted();
164
+ return {
165
+ generateIdentity: usesGeneratedIdentity({
166
+ generatedFields,
167
+ identityField: options.table.identity,
168
+ })
169
+ ? options.generateIdentity
170
+ : undefined,
171
+ generatedFields,
172
+ identityField: options.table.identity,
173
+ isVersioned: options.table.versioned,
174
+ };
175
+ };
176
+ const diffTableReuseConfig = (cached, incoming) => {
177
+ const mismatches = [];
178
+ if (cached.identityField !== incoming.identityField) {
179
+ mismatches.push('identityField');
180
+ }
181
+ if (cached.isVersioned !== incoming.isVersioned) {
182
+ mismatches.push('versioned');
183
+ }
184
+ if (cached.generatedFields.length !== incoming.generatedFields.length ||
185
+ cached.generatedFields.some((field, index) => field !== incoming.generatedFields[index])) {
186
+ mismatches.push('generatedFields');
187
+ }
188
+ if (cached.generateIdentity !== incoming.generateIdentity) {
189
+ mismatches.push('generateIdentity');
190
+ }
191
+ return mismatches;
192
+ };
193
+ const assertCompatibleTableReuse = (path, cached, incoming) => {
194
+ const mismatches = diffTableReuseConfig(cached, incoming);
195
+ if (mismatches.length === 0) {
196
+ return;
197
+ }
198
+ throw new ConflictError(`JSON file table reuse conflict for "${path}": ${mismatches.join(', ')} differ across connections. Reuse the same table config for a shared path or isolate the stores to different directories.`);
199
+ };
200
+ const createGetAccessor = (index) => (id) => {
201
+ const entity = index.get(String(id));
202
+ return Promise.resolve(entity === undefined ? null : structuredClone(entity));
203
+ };
204
+ const createListAccessor = (index) => (filters, opts) => {
205
+ const all = [...index.values()];
206
+ const filtered = filters === undefined
207
+ ? all
208
+ : all.filter((entity) => matchesFilters(entity, filters));
209
+ return Promise.resolve(applyPagination(filtered, opts).map((e) => structuredClone(e)));
210
+ };
211
+ // Flush a remove to disk then commit to the live index. Extracted to keep
212
+ // the remove closure under the max-statements limit.
213
+ const executeRemove = async (key, index, path) => {
214
+ if (!index.has(key)) {
215
+ return { deleted: false };
216
+ }
217
+ // Build the intended state, flush to disk, then update the live index.
218
+ // This ensures the in-memory Map stays consistent with the file even if
219
+ // the write fails.
220
+ const next = new Map([...index].filter(([k]) => k !== key));
221
+ await flushToDisk(path, next);
222
+ index.delete(key);
223
+ return { deleted: true };
224
+ };
225
+ const tableRegistry = new Map();
226
+ const buildAndRegisterTable = (path, options) => {
227
+ const mutex = createMutex();
228
+ const index = new Map();
229
+ const cfg = deriveTableConfig(options);
230
+ const upsert = async (input) => {
231
+ await mutex.acquire();
232
+ try {
233
+ return await executeUpsert(input, index, path, cfg);
234
+ }
235
+ finally {
236
+ mutex.release();
237
+ }
238
+ };
239
+ const remove = async (id) => {
240
+ await mutex.acquire();
241
+ try {
242
+ return await executeRemove(String(id), index, path);
243
+ }
244
+ finally {
245
+ mutex.release();
246
+ }
247
+ };
248
+ const instance = {
249
+ get: createGetAccessor(index),
250
+ list: createListAccessor(index),
251
+ // Skip disk load when the index already has data. This prevents a
252
+ // second `connectJsonFile` call from overwriting in-flight writes
253
+ // (the mutex only guards individual operations, not the full load
254
+ // sequence). It also avoids re-reading stale files on reuse.
255
+ load: async () => {
256
+ if (index.size > 0) {
257
+ return;
258
+ }
259
+ await loadFromDisk(path, cfg.identityField, index);
260
+ },
261
+ remove,
262
+ upsert,
263
+ };
264
+ tableRegistry.set(path, {
265
+ accessor: instance,
266
+ reuseConfig: deriveTableReuseConfig(options),
267
+ });
268
+ return instance;
269
+ };
270
+ /**
271
+ * Return a cached or freshly-built table instance for the given path.
272
+ *
273
+ * @remarks
274
+ * Tables are shared per resolved file path so multiple connections stay
275
+ * coherent in-process. Reuse is only allowed when table-affecting config
276
+ * matches exactly; otherwise the connector throws instead of silently
277
+ * inheriting the first connection's runtime semantics.
278
+ */
279
+ const createJsonFileTable = (options) => {
280
+ const path = jsonFilePath(options.dir, options.table.name);
281
+ const cached = tableRegistry.get(path);
282
+ if (cached === undefined) {
283
+ return buildAndRegisterTable(path, options);
284
+ }
285
+ assertCompatibleTableReuse(path, cached.reuseConfig, deriveTableReuseConfig(options));
286
+ return cached.accessor;
287
+ };
288
+ // Tracks temp directories created by mock factories so `dispose` can clean
289
+ // them up. WeakMap ensures entries are GC'd when the connection is released.
290
+ const mockTmpDirs = new WeakMap();
291
+ const collectMockFixtures = (definition, seed) => {
292
+ const fixturesByTable = new Map();
293
+ for (const tableName of definition.tableNames) {
294
+ const table = definition.tables[tableName];
295
+ if (table === undefined) {
296
+ continue;
297
+ }
298
+ const fixtures = seed?.[tableName] ?? table.fixtures;
299
+ if (fixtures.length > 0) {
300
+ fixturesByTable.set(tableName, fixtures);
301
+ }
302
+ }
303
+ return fixturesByTable;
304
+ };
305
+ const seedMockTable = async (accessor, fixtures) => {
306
+ for (const fixture of fixtures) {
307
+ await accessor.upsert(fixture);
308
+ }
309
+ };
310
+ const seedMockConnection = async (connection, definition, seed) => {
311
+ const fixturesByTable = collectMockFixtures(definition, seed);
312
+ if (fixturesByTable.size === 0) {
313
+ return;
314
+ }
315
+ const accessors = connection;
316
+ for (const tableName of definition.tableNames) {
317
+ const accessor = accessors[tableName];
318
+ const fixtures = fixturesByTable.get(tableName);
319
+ if (accessor === undefined || fixtures === undefined) {
320
+ continue;
321
+ }
322
+ await seedMockTable(accessor, fixtures);
323
+ }
324
+ };
325
+ // ---------------------------------------------------------------------------
326
+ // Public API
327
+ // ---------------------------------------------------------------------------
328
+ /**
329
+ * Connect to a JSON-file-backed store.
330
+ *
331
+ * Creates one `<tableName>.json` file per table in the target directory.
332
+ * Each file holds a JSON array of entities. The entire dataset is loaded
333
+ * into memory on connect and flushed to disk on every write.
334
+ */
335
+ export const connectJsonFile = async (definition, options) => {
336
+ const { dir, generateIdentity = defaultGenerateIdentity } = options;
337
+ const connection = {};
338
+ for (const tableName of definition.tableNames) {
339
+ const table = definition.tables[tableName];
340
+ if (table === undefined) {
341
+ continue;
342
+ }
343
+ const accessor = createJsonFileTable({
344
+ dir,
345
+ generateIdentity,
346
+ table,
347
+ });
348
+ await accessor.load();
349
+ connection[tableName] = accessor;
350
+ }
351
+ return Object.freeze(connection);
352
+ };
353
+ /**
354
+ * Create a JSON-file-backed store resource.
355
+ *
356
+ * Returns a `Resource` that can be registered in a topo and resolved from
357
+ * trail context via `db.from(ctx)`.
358
+ */
359
+ export const jsonFile = (definition, options) => {
360
+ const scope = options.id ?? defaultResourceId;
361
+ const store = bindStoreDefinition(definition, scope);
362
+ return resource(scope, {
363
+ create: async () => {
364
+ try {
365
+ return Result.ok(await connectJsonFile(store, options));
366
+ }
367
+ catch (error) {
368
+ const err = error instanceof Error ? error : new Error(String(error));
369
+ return Result.err(new InternalError(`JSON file store failed to initialize in "${options.dir}": ${err.message}`, { cause: err }));
370
+ }
371
+ },
372
+ description: options.description ??
373
+ 'JSON-file-backed store bound from an @ontrails/store definition.',
374
+ dispose: async (connection) => {
375
+ const tmpDir = mockTmpDirs.get(connection);
376
+ if (tmpDir !== undefined) {
377
+ const { rm } = await import('node:fs/promises');
378
+ await rm(tmpDir, { force: true, recursive: true });
379
+ mockTmpDirs.delete(connection);
380
+ for (const tableName of store.tableNames) {
381
+ tableRegistry.delete(jsonFilePath(tmpDir, tableName));
382
+ }
383
+ }
384
+ },
385
+ meta: options.meta,
386
+ mock: async () => {
387
+ const { mkdtemp } = await import('node:fs/promises');
388
+ const { join } = await import('node:path');
389
+ const { tmpdir } = await import('node:os');
390
+ const tmpDir = await mkdtemp(join(tmpdir(), 'jsonfile-mock-'));
391
+ const connection = await connectJsonFile(store, {
392
+ ...options,
393
+ dir: tmpDir,
394
+ });
395
+ await seedMockConnection(connection, store, options.mockSeed);
396
+ mockTmpDirs.set(connection, tmpDir);
397
+ return connection;
398
+ },
399
+ signals: store.signals,
400
+ });
401
+ };
402
+ export { jsonFile as store };
403
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/jsonfile/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { Resource } from '@ontrails/core';
2
+ import type { AnyStoreDefinition, AnyStoreTable, StoreAccessor, StoreConnectorOptions } from '../types.js';
3
+ /** Connection shape: one StoreAccessor per table name. */
4
+ export type JsonFileConnection<TStore extends Record<string, AnyStoreTable>> = Readonly<{
5
+ [K in keyof TStore]: StoreAccessor<TStore[K]>;
6
+ }>;
7
+ /** Options for creating a jsonfile store. */
8
+ export interface JsonFileStoreOptions<TStore extends AnyStoreDefinition = AnyStoreDefinition> extends StoreConnectorOptions<TStore> {
9
+ /** Directory where JSON files are written. One `<tableName>.json` per table. */
10
+ readonly dir: string;
11
+ /**
12
+ * Optional identity generator. Defaults to `Bun.randomUUIDv7()`.
13
+ *
14
+ * @remarks
15
+ * When a jsonfile table is reused across multiple `connectJsonFile` call
16
+ * sites (same `dir` + table), the runtime enforces that every connection
17
+ * supplies a compatible `generateIdentity`. That compatibility check is
18
+ * intentional reference equality, not a structural or behavioral comparison:
19
+ * two distinct arrow functions that happen to be "logically identical"
20
+ * (e.g. `() => uuid()` written inline in two files) will still be treated
21
+ * as a conflict and surface as a `ConflictError`. Callers that want to
22
+ * share a table across call sites should hoist `generateIdentity` to a
23
+ * stable reference — a module-level `const` or shared utility — and pass
24
+ * that same reference in from every connection, rather than recreating
25
+ * the function inline at each site.
26
+ *
27
+ * The conflict check only fires for custom generators. When no custom
28
+ * generator is provided for an auto-generated-identity store,
29
+ * `deriveTableReuseConfig` normalizes `generateIdentity` to `undefined`
30
+ * regardless of what (if anything) was passed, so two connections that
31
+ * both rely on defaults never conflict on this field. The same
32
+ * normalization also applies when the identity field is not in
33
+ * `generatedFields` — the generator is irrelevant in that case, so the
34
+ * check is skipped.
35
+ */
36
+ readonly generateIdentity?: () => string;
37
+ }
38
+ /** Resource type for a jsonfile store. */
39
+ export type JsonFileStoreResource<TStore extends Record<string, AnyStoreTable>> = Resource<JsonFileConnection<TStore>>;
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/jsonfile/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB,0DAA0D;AAC1D,MAAM,MAAM,kBAAkB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,IACzE,QAAQ,CAAC;KAAG,CAAC,IAAI,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,CAAC;AAE9D,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB,CACnC,MAAM,SAAS,kBAAkB,GAAG,kBAAkB,CACtD,SAAQ,qBAAqB,CAAC,MAAM,CAAC;IACrC,gFAAgF;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;CAC1C;AAED,0CAA0C;AAC1C,MAAM,MAAM,qBAAqB,CAC/B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,IAC1C,QAAQ,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/drizzle/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jsonfile/types.ts"],"names":[],"mappings":""}
package/dist/store.d.ts CHANGED
@@ -1,4 +1,10 @@
1
- import type { StoreDefinition, StoreTable, StoreTablesInput } from './types.js';
1
+ import type { StoreDefinition, StoreOptions, StoreTablesInput } from './types.js';
2
+ /**
3
+ * Name of the framework-managed version column used by versioned tables for
4
+ * optimistic concurrency control. Exported so connectors can gate their own
5
+ * version-handling logic without duplicating the literal.
6
+ */
7
+ export declare const versionFieldName = "version";
2
8
  /**
3
9
  * Declare a connector-agnostic store definition from entity schemas and
4
10
  * persistence metadata.
@@ -6,21 +12,5 @@ import type { StoreDefinition, StoreTable, StoreTablesInput } from './types.js';
6
12
  * The returned value is a normalized, read-only contract that connectors can
7
13
  * bind to a concrete runtime later.
8
14
  */
9
- export declare const store: <const TTables extends StoreTablesInput>(tables: TTables) => StoreDefinition<TTables>;
10
- /**
11
- * Read the full entity schema from a normalized store table.
12
- */
13
- export declare const entitySchemaOf: <TTable extends StoreTable>(table: TTable) => TTable["schema"];
14
- /**
15
- * Read the fixture schema from a normalized store table.
16
- */
17
- export declare const fixtureSchemaOf: <TTable extends StoreTable>(table: TTable) => TTable["fixtureSchema"];
18
- /**
19
- * Read the insert schema from a normalized store table.
20
- */
21
- export declare const insertSchemaOf: <TTable extends StoreTable>(table: TTable) => TTable["insertSchema"];
22
- /**
23
- * Read the update schema from a normalized store table.
24
- */
25
- export declare const updateSchemaOf: <TTable extends StoreTable>(table: TTable) => TTable["updateSchema"];
15
+ export declare const store: <const TTables extends StoreTablesInput>(tables: TTables, options?: StoreOptions) => StoreDefinition<TTables>;
26
16
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EAEf,UAAU,EAEV,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAuSpB;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,CAAC,OAAO,SAAS,gBAAgB,EAC1D,QAAQ,OAAO,KACd,eAAe,CAAC,OAAO,CAyBzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,UAAU,EACtD,OAAO,MAAM,KACZ,MAAM,CAAC,QAAQ,CAAiB,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,SAAS,UAAU,EACvD,OAAO,MAAM,KACZ,MAAM,CAAC,eAAe,CAAwB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,UAAU,EACtD,OAAO,MAAM,KACZ,MAAM,CAAC,cAAc,CAAuB,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,UAAU,EACtD,OAAO,MAAM,KACZ,MAAM,CAAC,cAAc,CAAuB,CAAC"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EAEf,YAAY,EAIZ,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAC;AA4d1C;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,CAAC,OAAO,SAAS,gBAAgB,EAC1D,QAAQ,OAAO,EACf,UAAS,YAAiB,KACzB,eAAe,CAAC,OAAO,CAkBzB,CAAC"}