@ontrails/store 1.0.0-beta.14
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.
- package/.agents/notes/2026-04-04/handoff-202604032309-9e85a104.md +38 -0
- package/.turbo/turbo-build.log +1 -0
- package/.turbo/turbo-lint.log +3 -0
- package/.turbo/turbo-typecheck.log +1 -0
- package/CHANGELOG.md +12 -0
- package/README.md +213 -0
- package/dist/drizzle/index.d.ts +3 -0
- package/dist/drizzle/index.d.ts.map +1 -0
- package/dist/drizzle/index.js +2 -0
- package/dist/drizzle/index.js.map +1 -0
- package/dist/drizzle/runtime.d.ts +21 -0
- package/dist/drizzle/runtime.d.ts.map +1 -0
- package/dist/drizzle/runtime.js +458 -0
- package/dist/drizzle/runtime.js.map +1 -0
- package/dist/drizzle/schema.d.ts +15 -0
- package/dist/drizzle/schema.d.ts.map +1 -0
- package/dist/drizzle/schema.js +322 -0
- package/dist/drizzle/schema.js.map +1 -0
- package/dist/drizzle/types.d.ts +40 -0
- package/dist/drizzle/types.d.ts.map +1 -0
- package/dist/drizzle/types.js +2 -0
- package/dist/drizzle/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/store.d.ts +26 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +192 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +224 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +29 -0
- package/src/__tests__/store.test.ts +333 -0
- package/src/drizzle/__tests__/drizzle.test.ts +469 -0
- package/src/drizzle/index.ts +17 -0
- package/src/drizzle/runtime.ts +853 -0
- package/src/drizzle/schema.ts +577 -0
- package/src/drizzle/types.ts +70 -0
- package/src/index.ts +39 -0
- package/src/store.ts +367 -0
- package/src/types.ts +361 -0
- package/tsconfig.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { afterEach, describe, expect, test } from 'bun:test';
|
|
2
|
+
import {
|
|
3
|
+
AlreadyExistsError,
|
|
4
|
+
ValidationError,
|
|
5
|
+
createTrailContext,
|
|
6
|
+
} from '@ontrails/core';
|
|
7
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
|
|
12
|
+
import { getSchema, readonlyStore, store } from '../index.js';
|
|
13
|
+
|
|
14
|
+
const userSchema = z.object({
|
|
15
|
+
email: z.string().email(),
|
|
16
|
+
id: z.string(),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const gistSchema = z.object({
|
|
20
|
+
createdAt: z.string(),
|
|
21
|
+
description: z.string().nullable().default(null),
|
|
22
|
+
id: z.string(),
|
|
23
|
+
isPublic: z.boolean().default(true),
|
|
24
|
+
ownerId: z.string(),
|
|
25
|
+
tags: z.array(z.string()).default([]),
|
|
26
|
+
updatedAt: z.string(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const accountSchema = z.object({
|
|
30
|
+
id: z.string(),
|
|
31
|
+
name: z.string(),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const userTable = {
|
|
35
|
+
generated: ['id'],
|
|
36
|
+
primaryKey: 'id',
|
|
37
|
+
schema: userSchema,
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
const gistTable = {
|
|
41
|
+
generated: ['id', 'createdAt', 'updatedAt'],
|
|
42
|
+
indexes: ['ownerId'],
|
|
43
|
+
primaryKey: 'id',
|
|
44
|
+
references: { ownerId: 'users' },
|
|
45
|
+
schema: gistSchema,
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
const createProvisionInput = (rootDir: string) => ({
|
|
49
|
+
config: undefined,
|
|
50
|
+
cwd: rootDir,
|
|
51
|
+
env: {},
|
|
52
|
+
workspaceRoot: rootDir,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const expectOk = async <T>(value: PromiseLike<T> | T): Promise<T> =>
|
|
56
|
+
await value;
|
|
57
|
+
|
|
58
|
+
const unwrapCreated = async <T>(
|
|
59
|
+
value:
|
|
60
|
+
| PromiseLike<{
|
|
61
|
+
unwrap(): T;
|
|
62
|
+
}>
|
|
63
|
+
| {
|
|
64
|
+
unwrap(): T;
|
|
65
|
+
}
|
|
66
|
+
): Promise<T> => {
|
|
67
|
+
const result = await value;
|
|
68
|
+
return result.unwrap();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const createWritableDemoStore = (rootDir: string) =>
|
|
72
|
+
store(
|
|
73
|
+
{
|
|
74
|
+
gists: gistTable,
|
|
75
|
+
users: userTable,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
description: 'Writable demo store',
|
|
79
|
+
id: 'demo.store',
|
|
80
|
+
url: join(rootDir, 'demo.sqlite'),
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const setupWritableDemoStore = async (rootDir: string) => {
|
|
85
|
+
const db = createWritableDemoStore(rootDir);
|
|
86
|
+
return {
|
|
87
|
+
created: await unwrapCreated(db.create(createProvisionInput(rootDir))),
|
|
88
|
+
db,
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
type WritableDemoStoreRuntime = Awaited<
|
|
93
|
+
ReturnType<typeof setupWritableDemoStore>
|
|
94
|
+
>['created'];
|
|
95
|
+
|
|
96
|
+
const expectWritableProvisionDefinition = (
|
|
97
|
+
db: ReturnType<typeof createWritableDemoStore>
|
|
98
|
+
): void => {
|
|
99
|
+
expect(db.kind).toBe('provision');
|
|
100
|
+
expect(db.id).toBe('demo.store');
|
|
101
|
+
expect(db.access).toBe('readwrite');
|
|
102
|
+
expect(db.mock).toBeDefined();
|
|
103
|
+
expect(getSchema(db).gists).toBe(db.tables.gists);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const expectInsertedGist = (
|
|
107
|
+
gist: z.output<typeof gistSchema>,
|
|
108
|
+
ownerId: string
|
|
109
|
+
): void => {
|
|
110
|
+
expect(gist).toEqual(
|
|
111
|
+
expect.objectContaining({
|
|
112
|
+
createdAt: expect.any(String),
|
|
113
|
+
description: null,
|
|
114
|
+
id: expect.any(String),
|
|
115
|
+
isPublic: true,
|
|
116
|
+
ownerId,
|
|
117
|
+
tags: [],
|
|
118
|
+
updatedAt: expect.any(String),
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const seedWritableRecords = async (
|
|
124
|
+
created: WritableDemoStoreRuntime
|
|
125
|
+
): Promise<{
|
|
126
|
+
readonly gist: z.output<typeof gistSchema>;
|
|
127
|
+
readonly user: z.output<typeof userSchema>;
|
|
128
|
+
}> => {
|
|
129
|
+
const user = await expectOk(
|
|
130
|
+
created.users.insert({ email: 'alice@example.com' })
|
|
131
|
+
);
|
|
132
|
+
expect(user.id).toEqual(expect.any(String));
|
|
133
|
+
|
|
134
|
+
const gist = await expectOk(
|
|
135
|
+
created.gists.insert({
|
|
136
|
+
ownerId: user.id,
|
|
137
|
+
})
|
|
138
|
+
);
|
|
139
|
+
expectInsertedGist(gist, user.id);
|
|
140
|
+
return { gist, user };
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const expectStoredGist = async (
|
|
144
|
+
created: WritableDemoStoreRuntime,
|
|
145
|
+
gist: z.output<typeof gistSchema>,
|
|
146
|
+
ownerId: string
|
|
147
|
+
): Promise<void> => {
|
|
148
|
+
expect(await created.gists.get(gist.id)).toEqual(gist);
|
|
149
|
+
expect(await created.gists.list({ ownerId })).toEqual([gist]);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const expectUpdatedGist = async (
|
|
153
|
+
created: WritableDemoStoreRuntime,
|
|
154
|
+
gist: z.output<typeof gistSchema>
|
|
155
|
+
): Promise<void> => {
|
|
156
|
+
const updated = await expectOk(
|
|
157
|
+
created.gists.update(gist.id, {
|
|
158
|
+
description: 'Updated',
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
expect(updated).toEqual(
|
|
163
|
+
expect.objectContaining({
|
|
164
|
+
description: 'Updated',
|
|
165
|
+
id: gist.id,
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
expect(updated?.updatedAt).toEqual(expect.any(String));
|
|
169
|
+
expect(updated?.updatedAt).not.toBe(gist.updatedAt);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const expectQueryEscapeHatch = async (
|
|
173
|
+
created: WritableDemoStoreRuntime
|
|
174
|
+
): Promise<void> => {
|
|
175
|
+
const rows = await created.query(({ drizzle, tables }) =>
|
|
176
|
+
drizzle.select().from(tables.gists).all()
|
|
177
|
+
);
|
|
178
|
+
expect(rows).toHaveLength(1);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const expectDeletedGist = async (
|
|
182
|
+
created: WritableDemoStoreRuntime,
|
|
183
|
+
gistId: string
|
|
184
|
+
): Promise<void> => {
|
|
185
|
+
const deleted = await created.gists.remove(gistId);
|
|
186
|
+
expect(deleted).toEqual({ deleted: true });
|
|
187
|
+
expect(await created.gists.get(gistId)).toBeNull();
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const expectMissingGistDelete = async (
|
|
191
|
+
created: WritableDemoStoreRuntime
|
|
192
|
+
): Promise<void> => {
|
|
193
|
+
const deleted = await created.gists.remove('non-existent-id');
|
|
194
|
+
expect(deleted).toEqual({ deleted: false });
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const expectWritableLifecycle = async (
|
|
198
|
+
created: WritableDemoStoreRuntime
|
|
199
|
+
): Promise<void> => {
|
|
200
|
+
const { gist, user } = await seedWritableRecords(created);
|
|
201
|
+
await expectStoredGist(created, gist, user.id);
|
|
202
|
+
await expectUpdatedGist(created, gist);
|
|
203
|
+
await expectQueryEscapeHatch(created);
|
|
204
|
+
await expectDeletedGist(created, gist.id);
|
|
205
|
+
await expectMissingGistDelete(created);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const expectProvisionResolution = (
|
|
209
|
+
db: ReturnType<typeof createWritableDemoStore>,
|
|
210
|
+
created: WritableDemoStoreRuntime
|
|
211
|
+
): void => {
|
|
212
|
+
const ctx = createTrailContext({
|
|
213
|
+
abortSignal: new AbortController().signal,
|
|
214
|
+
extensions: {
|
|
215
|
+
[db.id]: created,
|
|
216
|
+
},
|
|
217
|
+
requestId: 'store-drizzle',
|
|
218
|
+
});
|
|
219
|
+
expect(db.from(ctx).users).toBeDefined();
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const createFixtureBackedStore = () =>
|
|
223
|
+
store(
|
|
224
|
+
{
|
|
225
|
+
gists: {
|
|
226
|
+
...gistTable,
|
|
227
|
+
fixtures: [
|
|
228
|
+
{
|
|
229
|
+
id: 'gist-seed',
|
|
230
|
+
ownerId: 'user-seed',
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
users: {
|
|
235
|
+
...userTable,
|
|
236
|
+
fixtures: [
|
|
237
|
+
{
|
|
238
|
+
email: 'seed@example.com',
|
|
239
|
+
id: 'user-seed',
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
id: 'demo.store.mock',
|
|
246
|
+
url: ':memory:',
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const createWritableSeedStore = (url: string) =>
|
|
251
|
+
store(
|
|
252
|
+
{
|
|
253
|
+
users: userTable,
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: 'demo.store.seed',
|
|
257
|
+
url,
|
|
258
|
+
}
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
const seedReadonlyFixture = async (
|
|
262
|
+
url: string,
|
|
263
|
+
rootDir: string
|
|
264
|
+
): Promise<z.output<typeof userSchema>> => {
|
|
265
|
+
const writable = createWritableSeedStore(url);
|
|
266
|
+
const seeded = await unwrapCreated(
|
|
267
|
+
writable.create(createProvisionInput(rootDir))
|
|
268
|
+
);
|
|
269
|
+
const inserted = await seeded.users.insert({ email: 'seed@example.com' });
|
|
270
|
+
await writable.dispose?.(seeded);
|
|
271
|
+
return inserted;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const createReadonlyUserStore = (url: string) =>
|
|
275
|
+
readonlyStore(
|
|
276
|
+
{
|
|
277
|
+
users: userTable,
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
id: 'demo.store.readonly',
|
|
281
|
+
url,
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
const setupReadonlyUserStore = async (url: string, rootDir: string) => {
|
|
286
|
+
const db = createReadonlyUserStore(url);
|
|
287
|
+
return {
|
|
288
|
+
created: await unwrapCreated(db.create(createProvisionInput(rootDir))),
|
|
289
|
+
db,
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
type ReadonlyUserStoreRuntime = Awaited<
|
|
294
|
+
ReturnType<typeof setupReadonlyUserStore>
|
|
295
|
+
>['created'];
|
|
296
|
+
|
|
297
|
+
const expectReadonlyReads = async (
|
|
298
|
+
created: ReadonlyUserStoreRuntime,
|
|
299
|
+
inserted: z.output<typeof userSchema>
|
|
300
|
+
): Promise<void> => {
|
|
301
|
+
expect(await created.users.get(inserted.id)).toEqual(inserted);
|
|
302
|
+
expect(await created.users.list()).toEqual([inserted]);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const expectReadonlyWriteFailure = async (
|
|
306
|
+
created: ReadonlyUserStoreRuntime
|
|
307
|
+
): Promise<void> => {
|
|
308
|
+
await expect(
|
|
309
|
+
created.query(({ drizzle, tables }) =>
|
|
310
|
+
drizzle
|
|
311
|
+
.insert(tables.users)
|
|
312
|
+
.values({ email: 'blocked@example.com', id: 'blocked' })
|
|
313
|
+
.run()
|
|
314
|
+
)
|
|
315
|
+
).rejects.toThrow();
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const createErrorStore = (rootDir: string) =>
|
|
319
|
+
store(
|
|
320
|
+
{
|
|
321
|
+
accounts: {
|
|
322
|
+
primaryKey: 'id',
|
|
323
|
+
schema: accountSchema,
|
|
324
|
+
},
|
|
325
|
+
gists: {
|
|
326
|
+
...gistTable,
|
|
327
|
+
references: { ownerId: 'accounts' },
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
id: 'demo.store.errors',
|
|
332
|
+
url: join(rootDir, 'errors.sqlite'),
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
describe('@ontrails/store/drizzle', () => {
|
|
337
|
+
let tmpRoot: string | undefined;
|
|
338
|
+
|
|
339
|
+
afterEach(() => {
|
|
340
|
+
if (tmpRoot !== undefined) {
|
|
341
|
+
rmSync(tmpRoot, { force: true, recursive: true });
|
|
342
|
+
tmpRoot = undefined;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const makeRoot = (): string => {
|
|
347
|
+
tmpRoot = mkdtempSync(join(tmpdir(), 'store-drizzle-'));
|
|
348
|
+
return tmpRoot;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
test('binds a writable provision with CRUD accessors and one escape hatch', async () => {
|
|
352
|
+
const rootDir = makeRoot();
|
|
353
|
+
const { created, db } = await setupWritableDemoStore(rootDir);
|
|
354
|
+
expectWritableProvisionDefinition(db);
|
|
355
|
+
await expectWritableLifecycle(created);
|
|
356
|
+
expectProvisionResolution(db, created);
|
|
357
|
+
await db.dispose?.(created);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
test('creates a writable mock provision seeded from fixtures', async () => {
|
|
361
|
+
const db = createFixtureBackedStore();
|
|
362
|
+
|
|
363
|
+
const mock = await db.mock?.();
|
|
364
|
+
expect(mock).toBeDefined();
|
|
365
|
+
expect(await mock?.users.get('user-seed')).toEqual(
|
|
366
|
+
expect.objectContaining({
|
|
367
|
+
email: 'seed@example.com',
|
|
368
|
+
id: 'user-seed',
|
|
369
|
+
})
|
|
370
|
+
);
|
|
371
|
+
expect(await mock?.gists.get('gist-seed')).toEqual(
|
|
372
|
+
expect.objectContaining({
|
|
373
|
+
createdAt: expect.any(String),
|
|
374
|
+
description: null,
|
|
375
|
+
id: 'gist-seed',
|
|
376
|
+
isPublic: true,
|
|
377
|
+
ownerId: 'user-seed',
|
|
378
|
+
updatedAt: expect.any(String),
|
|
379
|
+
})
|
|
380
|
+
);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
test('opens a read-only store without a mock and enforces writes at the database layer', async () => {
|
|
384
|
+
const rootDir = makeRoot();
|
|
385
|
+
const url = join(rootDir, 'readonly.sqlite');
|
|
386
|
+
const inserted = await seedReadonlyFixture(url, rootDir);
|
|
387
|
+
const { created, db: readOnly } = await setupReadonlyUserStore(
|
|
388
|
+
url,
|
|
389
|
+
rootDir
|
|
390
|
+
);
|
|
391
|
+
expect(readOnly.access).toBe('readonly');
|
|
392
|
+
expect(readOnly.mock).toBeUndefined();
|
|
393
|
+
await expectReadonlyReads(created, inserted);
|
|
394
|
+
await expectReadonlyWriteFailure(created);
|
|
395
|
+
await readOnly.dispose?.(created);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
test('maps primary-key and foreign-key failures into Trails errors', async () => {
|
|
399
|
+
const rootDir = makeRoot();
|
|
400
|
+
const db = createErrorStore(rootDir);
|
|
401
|
+
const created = await unwrapCreated(
|
|
402
|
+
db.create(createProvisionInput(rootDir))
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
await created.accounts.insert({
|
|
406
|
+
id: 'acct-1',
|
|
407
|
+
name: 'Alpha',
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
await expect(
|
|
411
|
+
created.accounts.insert({
|
|
412
|
+
id: 'acct-1',
|
|
413
|
+
name: 'Duplicate',
|
|
414
|
+
})
|
|
415
|
+
).rejects.toBeInstanceOf(AlreadyExistsError);
|
|
416
|
+
|
|
417
|
+
await expect(
|
|
418
|
+
created.gists.insert({
|
|
419
|
+
ownerId: 'missing-account',
|
|
420
|
+
})
|
|
421
|
+
).rejects.toBeInstanceOf(ValidationError);
|
|
422
|
+
|
|
423
|
+
await db.dispose?.(created);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
test('maps z.number().int() to INTEGER (Zod internals regression guard)', () => {
|
|
427
|
+
const intStore = store(
|
|
428
|
+
{
|
|
429
|
+
counters: {
|
|
430
|
+
generated: ['id'],
|
|
431
|
+
primaryKey: 'id',
|
|
432
|
+
schema: z.object({
|
|
433
|
+
id: z.number().int(),
|
|
434
|
+
value: z.number(),
|
|
435
|
+
}),
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
{ url: join(makeRoot(), 'int.sqlite') }
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
const schema = getSchema(intStore);
|
|
442
|
+
const col = schema.counters;
|
|
443
|
+
expect(col).toBeDefined();
|
|
444
|
+
|
|
445
|
+
const idColumn = col.id as unknown as { columnType: string };
|
|
446
|
+
expect(idColumn.columnType).toBe('SQLiteInteger');
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test('update returns null for a non-existent ID', async () => {
|
|
450
|
+
const db = createFixtureBackedStore();
|
|
451
|
+
const mock = await db.mock?.();
|
|
452
|
+
expect(mock).toBeDefined();
|
|
453
|
+
|
|
454
|
+
const result = await mock?.gists.update('ghost-id', {
|
|
455
|
+
description: 'nope',
|
|
456
|
+
});
|
|
457
|
+
expect(result).toBeNull();
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
test('update rejects empty fields even when updatedAt is generated', async () => {
|
|
461
|
+
const db = createFixtureBackedStore();
|
|
462
|
+
const mock = await db.mock?.();
|
|
463
|
+
expect(mock).toBeDefined();
|
|
464
|
+
|
|
465
|
+
await expect(mock?.gists.update('gist-seed', {})).rejects.toBeInstanceOf(
|
|
466
|
+
ValidationError
|
|
467
|
+
);
|
|
468
|
+
});
|
|
469
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export {
|
|
2
|
+
connectDrizzle,
|
|
3
|
+
connectReadOnlyDrizzle,
|
|
4
|
+
getSchema,
|
|
5
|
+
readonlyStore,
|
|
6
|
+
store,
|
|
7
|
+
} from './runtime.js';
|
|
8
|
+
export type {
|
|
9
|
+
ConnectDrizzleOptions,
|
|
10
|
+
DrizzleMockSeed,
|
|
11
|
+
DrizzleQueryContext,
|
|
12
|
+
DrizzleStoreConnection,
|
|
13
|
+
DrizzleStoreProvision,
|
|
14
|
+
DrizzleStoreSchema,
|
|
15
|
+
ReadOnlyDrizzleOptions,
|
|
16
|
+
ReadOnlyDrizzleStoreConnection,
|
|
17
|
+
} from './types.js';
|