@livestore/cli 0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8 → 0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e
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/dist/cli.d.ts +1 -15
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/mcp-coach.d.ts +2 -2
- package/dist/commands/mcp-coach.d.ts.map +1 -1
- package/dist/commands/mcp-tool-handlers.d.ts +1 -5
- package/dist/commands/mcp-tool-handlers.d.ts.map +1 -1
- package/dist/commands/mcp-tool-handlers.js +4 -42
- package/dist/commands/mcp-tool-handlers.js.map +1 -1
- package/dist/commands/mcp-tools-defs.d.ts +1 -31
- package/dist/commands/mcp-tools-defs.d.ts.map +1 -1
- package/dist/commands/mcp-tools-defs.js +5 -87
- package/dist/commands/mcp-tools-defs.js.map +1 -1
- package/dist/commands/new-project.d.ts +1 -1
- package/dist/mcp-runtime/runtime.d.ts +3 -4
- package/dist/mcp-runtime/runtime.d.ts.map +1 -1
- package/dist/mcp-runtime/runtime.js +53 -20
- package/dist/mcp-runtime/runtime.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -15
- package/src/cli.ts +1 -2
- package/src/commands/mcp-tool-handlers.ts +5 -50
- package/src/commands/mcp-tools-defs.ts +4 -92
- package/src/mcp-runtime/runtime.ts +65 -32
- package/dist/__tests__/fixtures/mock-config.d.ts +0 -56
- package/dist/__tests__/fixtures/mock-config.d.ts.map +0 -1
- package/dist/__tests__/fixtures/mock-config.js +0 -88
- package/dist/__tests__/fixtures/mock-config.js.map +0 -1
- package/dist/__tests__/sync-operations.test.d.ts +0 -2
- package/dist/__tests__/sync-operations.test.d.ts.map +0 -1
- package/dist/__tests__/sync-operations.test.js +0 -167
- package/dist/__tests__/sync-operations.test.js.map +0 -1
- package/dist/commands/import-export.d.ts +0 -34
- package/dist/commands/import-export.d.ts.map +0 -1
- package/dist/commands/import-export.js +0 -133
- package/dist/commands/import-export.js.map +0 -1
- package/dist/module-loader.d.ts +0 -22
- package/dist/module-loader.d.ts.map +0 -1
- package/dist/module-loader.js +0 -75
- package/dist/module-loader.js.map +0 -1
- package/dist/sync-operations.d.ts +0 -121
- package/dist/sync-operations.d.ts.map +0 -1
- package/dist/sync-operations.js +0 -180
- package/dist/sync-operations.js.map +0 -1
- package/src/__tests__/fixtures/mock-config.ts +0 -104
- package/src/__tests__/sync-operations.test.ts +0 -230
- package/src/commands/import-export.ts +0 -278
- package/src/module-loader.ts +0 -93
- package/src/sync-operations.ts +0 -360
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/cli",
|
|
3
|
-
"version": "0.0.0-snapshot-
|
|
3
|
+
"version": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -10,25 +10,18 @@
|
|
|
10
10
|
"livestore": "./dist/bin.js"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@effect/ai": "0.29.0",
|
|
14
13
|
"@effect/ai-openai": "0.32.0",
|
|
15
|
-
"@
|
|
16
|
-
"@
|
|
17
|
-
"@
|
|
18
|
-
"@
|
|
19
|
-
"@
|
|
20
|
-
"
|
|
21
|
-
"@livestore/common": "0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8",
|
|
22
|
-
"@livestore/sync-cf": "0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8",
|
|
23
|
-
"@livestore/adapter-node": "0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8",
|
|
24
|
-
"@livestore/livestore": "0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8",
|
|
25
|
-
"@livestore/peer-deps": "0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8",
|
|
26
|
-
"@livestore/utils": "0.0.0-snapshot-0f27d343553b9bb260543bf20de36d216f53c5d8"
|
|
14
|
+
"@livestore/adapter-node": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e",
|
|
15
|
+
"@livestore/common": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e",
|
|
16
|
+
"@livestore/sync-cf": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e",
|
|
17
|
+
"@livestore/livestore": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e",
|
|
18
|
+
"@livestore/peer-deps": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e",
|
|
19
|
+
"@livestore/utils": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e"
|
|
27
20
|
},
|
|
28
21
|
"devDependencies": {
|
|
29
22
|
"@types/node": "24.10.1",
|
|
30
23
|
"typescript": "5.9.2",
|
|
31
|
-
"@livestore/utils-dev": "0.0.0-snapshot-
|
|
24
|
+
"@livestore/utils-dev": "0.0.0-snapshot-b2da08eec7583e23c0679970016a84b93438039e"
|
|
32
25
|
},
|
|
33
26
|
"files": [
|
|
34
27
|
"package.json",
|
package/src/cli.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Cli } from '@livestore/utils/node'
|
|
2
|
-
import { syncCommand } from './commands/import-export.ts'
|
|
3
2
|
import { mcpCommand } from './commands/mcp.ts'
|
|
4
3
|
import { createCommand } from './commands/new-project.ts'
|
|
5
4
|
|
|
6
5
|
export const command = Cli.Command.make('livestore', {
|
|
7
6
|
verbose: Cli.Options.boolean('verbose').pipe(Cli.Options.withDefault(false)),
|
|
8
|
-
}).pipe(Cli.Command.withSubcommands([mcpCommand, createCommand
|
|
7
|
+
}).pipe(Cli.Command.withSubcommands([mcpCommand, createCommand]))
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
import { Effect
|
|
2
|
-
import { PlatformNode } from '@livestore/utils/node'
|
|
1
|
+
import { Effect } from '@livestore/utils/effect'
|
|
3
2
|
import { blogSchemaContent } from '../mcp-content/schemas/blog.ts'
|
|
4
3
|
import { ecommerceSchemaContent } from '../mcp-content/schemas/ecommerce.ts'
|
|
5
4
|
import { socialSchemaContent } from '../mcp-content/schemas/social.ts'
|
|
6
5
|
import { todoSchemaContent } from '../mcp-content/schemas/todo.ts'
|
|
7
6
|
import * as Runtime from '../mcp-runtime/runtime.ts'
|
|
8
|
-
import * as SyncOps from '../sync-operations.ts'
|
|
9
7
|
import { coachToolHandler } from './mcp-coach.ts'
|
|
10
8
|
import { livestoreToolkit } from './mcp-tools-defs.ts'
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
type LivestoreToolHandlers = Toolkit.HandlersFrom<Toolkit.Tools<typeof livestoreToolkit>>
|
|
16
|
-
|
|
17
|
-
export const toolHandlers: LivestoreToolHandlers = livestoreToolkit.of({
|
|
10
|
+
// Tool handlers using Tim Smart's pattern
|
|
11
|
+
export const toolHandlers: any = livestoreToolkit.of({
|
|
18
12
|
livestore_coach: coachToolHandler,
|
|
19
13
|
|
|
20
14
|
livestore_generate_schema: Effect.fnUntraced(function* ({ schemaType, customDescription }) {
|
|
@@ -127,13 +121,8 @@ export const schema = Schema.create({
|
|
|
127
121
|
}),
|
|
128
122
|
|
|
129
123
|
// Connect the single in-process LiveStore instance from user module
|
|
130
|
-
livestore_instance_connect: Effect.fnUntraced(function* ({
|
|
131
|
-
const store = yield* Runtime.init({
|
|
132
|
-
configPath,
|
|
133
|
-
storeId,
|
|
134
|
-
...(clientId !== undefined ? { clientId } : {}),
|
|
135
|
-
...(sessionId !== undefined ? { sessionId } : {}),
|
|
136
|
-
}).pipe(Effect.orDie)
|
|
124
|
+
livestore_instance_connect: Effect.fnUntraced(function* ({ storePath, storeId, clientId, sessionId }) {
|
|
125
|
+
const store = yield* Runtime.init({ storePath, storeId, clientId, sessionId }).pipe(Effect.orDie)
|
|
137
126
|
const eventNames = Array.from(store.schema.eventsDefsMap.keys())
|
|
138
127
|
const tableNames = Array.from(store.schema.state.sqlite.tables.keys())
|
|
139
128
|
|
|
@@ -167,38 +156,4 @@ export const schema = Schema.create({
|
|
|
167
156
|
livestore_instance_disconnect: Effect.fnUntraced(function* () {
|
|
168
157
|
return yield* Runtime.disconnect
|
|
169
158
|
}),
|
|
170
|
-
|
|
171
|
-
// Sync export - pull all events from sync backend
|
|
172
|
-
livestore_sync_export: Effect.fnUntraced(function* ({ configPath, storeId, clientId }) {
|
|
173
|
-
const result = yield* SyncOps.pullEventsFromSyncBackend({
|
|
174
|
-
configPath,
|
|
175
|
-
storeId,
|
|
176
|
-
clientId: clientId ?? 'mcp-export',
|
|
177
|
-
}).pipe(Effect.scoped, Effect.provide(SyncOpsLayer), Effect.orDie)
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
storeId: result.storeId,
|
|
181
|
-
eventCount: result.eventCount,
|
|
182
|
-
exportedAt: result.exportedAt,
|
|
183
|
-
data: result.data,
|
|
184
|
-
}
|
|
185
|
-
}),
|
|
186
|
-
|
|
187
|
-
// Sync import - push events to sync backend
|
|
188
|
-
livestore_sync_import: Effect.fnUntraced(function* ({ configPath, storeId, clientId, data, force, dryRun }) {
|
|
189
|
-
const result = yield* SyncOps.pushEventsToSyncBackend({
|
|
190
|
-
configPath,
|
|
191
|
-
storeId,
|
|
192
|
-
clientId: clientId ?? 'mcp-import',
|
|
193
|
-
data,
|
|
194
|
-
force: force ?? false,
|
|
195
|
-
dryRun: dryRun ?? false,
|
|
196
|
-
}).pipe(Effect.scoped, Effect.provide(SyncOpsLayer), Effect.orDie)
|
|
197
|
-
|
|
198
|
-
return {
|
|
199
|
-
storeId: result.storeId,
|
|
200
|
-
eventCount: result.eventCount,
|
|
201
|
-
dryRun: result.dryRun,
|
|
202
|
-
}
|
|
203
|
-
}),
|
|
204
159
|
})
|
|
@@ -43,7 +43,7 @@ export const livestoreToolkit = Toolkit.make(
|
|
|
43
43
|
Notes:
|
|
44
44
|
- Only one instance can be active at a time; calling connect again shuts down and replaces the previous instance.
|
|
45
45
|
- Reconnecting creates a fresh, in-memory client database. The state visible to queries is populated by your backend's initial sync behavior; depending on configuration, you may briefly observe empty or partial data until sync completes.
|
|
46
|
-
- \`
|
|
46
|
+
- \`storePath\` is resolved relative to the current working directory.
|
|
47
47
|
- \`syncBackend\` must be a function (factory) that returns a backend; \`syncPayload\` must be JSON-serializable.
|
|
48
48
|
|
|
49
49
|
Module contract (generic example):
|
|
@@ -63,13 +63,13 @@ export const syncPayload = { authToken: process.env.LIVESTORE_SYNC_AUTH_TOKEN ??
|
|
|
63
63
|
|
|
64
64
|
Connect parameters:
|
|
65
65
|
{
|
|
66
|
-
"
|
|
66
|
+
"storePath": "<path-to-your-mcp-module>.ts",
|
|
67
67
|
"storeId": "<store-id>"
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
Optional identifiers to group client state on the server:
|
|
71
71
|
{
|
|
72
|
-
"
|
|
72
|
+
"storePath": "<path-to-your-mcp-module>.ts",
|
|
73
73
|
"storeId": "<store-id>",
|
|
74
74
|
"clientId": "<client-id>",
|
|
75
75
|
"sessionId": "<session-id>"
|
|
@@ -86,7 +86,7 @@ Returns on success:
|
|
|
86
86
|
}
|
|
87
87
|
}`,
|
|
88
88
|
parameters: {
|
|
89
|
-
|
|
89
|
+
storePath: Schema.String.annotations({
|
|
90
90
|
description: 'Path to a module that exports named variables: schema and syncBackend',
|
|
91
91
|
}),
|
|
92
92
|
storeId: Schema.String.annotations({ description: 'Required store id for the LiveStore instance.' }),
|
|
@@ -226,92 +226,4 @@ Example success:
|
|
|
226
226
|
parameters: {},
|
|
227
227
|
success: Schema.TaggedStruct('disconnected', {}),
|
|
228
228
|
}),
|
|
229
|
-
|
|
230
|
-
Tool.make('livestore_sync_export', {
|
|
231
|
-
description: `Export all events from a sync backend to JSON data.
|
|
232
|
-
|
|
233
|
-
This tool connects directly to the sync backend (without creating a full LiveStore instance) and pulls all events. Useful for backup, migration, and debugging.
|
|
234
|
-
|
|
235
|
-
Module contract (same as livestore_instance_connect):
|
|
236
|
-
\`\`\`ts
|
|
237
|
-
export { schema } from './src/livestore/schema.ts'
|
|
238
|
-
export const syncBackend = makeWsSync({ url: process.env.LIVESTORE_SYNC_URL ?? 'ws://localhost:8787' })
|
|
239
|
-
export const syncPayload = { authToken: process.env.LIVESTORE_SYNC_AUTH_TOKEN }
|
|
240
|
-
\`\`\`
|
|
241
|
-
|
|
242
|
-
Example parameters:
|
|
243
|
-
{
|
|
244
|
-
"configPath": "livestore-cli.config.ts",
|
|
245
|
-
"storeId": "my-store"
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
Returns on success:
|
|
249
|
-
{
|
|
250
|
-
"storeId": "my-store",
|
|
251
|
-
"eventCount": 127,
|
|
252
|
-
"exportedAt": "2024-01-15T10:30:00.000Z",
|
|
253
|
-
"data": { "version": 1, "storeId": "my-store", ... }
|
|
254
|
-
}`,
|
|
255
|
-
parameters: {
|
|
256
|
-
configPath: Schema.String.annotations({
|
|
257
|
-
description: 'Path to a module that exports schema and syncBackend',
|
|
258
|
-
}),
|
|
259
|
-
storeId: Schema.String.annotations({ description: 'Store identifier' }),
|
|
260
|
-
clientId: Schema.optional(Schema.String.annotations({ description: 'Client identifier (default: mcp-export)' })),
|
|
261
|
-
},
|
|
262
|
-
success: Schema.Struct({
|
|
263
|
-
storeId: Schema.String,
|
|
264
|
-
eventCount: Schema.Number,
|
|
265
|
-
exportedAt: Schema.String,
|
|
266
|
-
data: Schema.JsonValue.annotations({ description: 'The export file data (can be saved or passed to import)' }),
|
|
267
|
-
}),
|
|
268
|
-
}).annotate(Tool.Readonly, true),
|
|
269
|
-
|
|
270
|
-
Tool.make('livestore_sync_import', {
|
|
271
|
-
description: `Import events from export data to a sync backend.
|
|
272
|
-
|
|
273
|
-
This tool connects directly to the sync backend and pushes events. The sync backend must be empty.
|
|
274
|
-
|
|
275
|
-
Example parameters:
|
|
276
|
-
{
|
|
277
|
-
"configPath": "livestore-cli.config.ts",
|
|
278
|
-
"storeId": "my-store",
|
|
279
|
-
"data": { "version": 1, "storeId": "my-store", "events": [...] }
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
With options:
|
|
283
|
-
{
|
|
284
|
-
"configPath": "livestore-cli.config.ts",
|
|
285
|
-
"storeId": "my-store",
|
|
286
|
-
"data": { ... },
|
|
287
|
-
"force": true, // Import even if store ID doesn't match
|
|
288
|
-
"dryRun": true // Validate without importing
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
Returns on success:
|
|
292
|
-
{
|
|
293
|
-
"storeId": "my-store",
|
|
294
|
-
"eventCount": 127,
|
|
295
|
-
"dryRun": false
|
|
296
|
-
}`,
|
|
297
|
-
parameters: {
|
|
298
|
-
configPath: Schema.String.annotations({
|
|
299
|
-
description: 'Path to a module that exports schema and syncBackend',
|
|
300
|
-
}),
|
|
301
|
-
storeId: Schema.String.annotations({ description: 'Store identifier' }),
|
|
302
|
-
clientId: Schema.optional(Schema.String.annotations({ description: 'Client identifier (default: mcp-import)' })),
|
|
303
|
-
data: Schema.JsonValue.annotations({
|
|
304
|
-
description: 'The export data to import (from livestore_sync_export or a file)',
|
|
305
|
-
}),
|
|
306
|
-
force: Schema.optional(
|
|
307
|
-
Schema.Boolean.annotations({ description: 'Force import even if store ID does not match' }),
|
|
308
|
-
),
|
|
309
|
-
dryRun: Schema.optional(Schema.Boolean.annotations({ description: 'Validate without actually importing' })),
|
|
310
|
-
},
|
|
311
|
-
success: Schema.Struct({
|
|
312
|
-
storeId: Schema.String,
|
|
313
|
-
eventCount: Schema.Number,
|
|
314
|
-
dryRun: Schema.Boolean,
|
|
315
|
-
}),
|
|
316
|
-
}).annotate(Tool.Destructive, true),
|
|
317
229
|
)
|
|
@@ -1,40 +1,77 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { pathToFileURL } from 'node:url'
|
|
1
3
|
import { makeAdapter as makeNodeAdapter } from '@livestore/adapter-node'
|
|
2
|
-
import {
|
|
3
|
-
import { LiveStoreEvent, SystemTables } from '@livestore/common/schema'
|
|
4
|
+
import { isLiveStoreSchema, LiveStoreEvent, SystemTables } from '@livestore/common/schema'
|
|
4
5
|
import type { Store } from '@livestore/livestore'
|
|
5
6
|
import { createStorePromise } from '@livestore/livestore'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import { loadModuleConfig } from '../module-loader.ts'
|
|
7
|
+
import { shouldNeverHappen } from '@livestore/utils'
|
|
8
|
+
import { Effect, Option, Schema } from '@livestore/utils/effect'
|
|
10
9
|
|
|
11
10
|
/** Currently connected store */
|
|
12
11
|
let store: Store<any> | undefined
|
|
13
12
|
|
|
14
|
-
/** Layer providing FileSystem and HttpClient for module loading */
|
|
15
|
-
const ModuleLoaderLayer = Layer.mergeAll(PlatformNode.NodeFileSystem.layer, FetchHttpClient.layer)
|
|
16
|
-
|
|
17
13
|
/**
|
|
18
14
|
* Dynamically imports a module that exports a `makeStore({ storeId }): Promise<Store>` function,
|
|
19
15
|
* calls it with the provided storeId, and caches the Store instance for subsequent tool calls.
|
|
20
16
|
*/
|
|
21
17
|
export const init = ({
|
|
22
|
-
|
|
18
|
+
storePath,
|
|
23
19
|
storeId,
|
|
24
20
|
clientId,
|
|
25
21
|
sessionId,
|
|
26
22
|
}: {
|
|
27
|
-
|
|
23
|
+
storePath: string
|
|
28
24
|
storeId: string
|
|
29
25
|
clientId?: string
|
|
30
26
|
sessionId?: string
|
|
31
|
-
})
|
|
32
|
-
Effect.
|
|
27
|
+
}) =>
|
|
28
|
+
Effect.promise(async () => {
|
|
33
29
|
if (!storeId || typeof storeId !== 'string') {
|
|
34
|
-
|
|
30
|
+
throw new Error('Invalid storeId: expected a non-empty string')
|
|
31
|
+
}
|
|
32
|
+
// Resolve to absolute path and import as file URL
|
|
33
|
+
const abs = path.isAbsolute(storePath) ? storePath : path.resolve(process.cwd(), storePath)
|
|
34
|
+
const mod = await import(pathToFileURL(abs).href)
|
|
35
|
+
|
|
36
|
+
// Validate required exports
|
|
37
|
+
const schema = (mod as any)?.schema
|
|
38
|
+
if (!isLiveStoreSchema(schema)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Module at ${abs} must export a valid LiveStore 'schema'. Ex: export { schema } from './src/livestore/schema.ts'`,
|
|
41
|
+
)
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
const
|
|
44
|
+
const syncBackend = (mod as any)?.syncBackend
|
|
45
|
+
if (typeof syncBackend !== 'function') {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Module at ${abs} must export a 'syncBackend' constructor (e.g., makeWsSync({ url })). Ex: export const syncBackend = makeWsSync({ url })`,
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Optional: syncPayload for authenticated backends
|
|
52
|
+
const syncPayloadSchemaExport = (mod as any)?.syncPayloadSchema
|
|
53
|
+
const syncPayloadSchema =
|
|
54
|
+
syncPayloadSchemaExport === undefined
|
|
55
|
+
? Schema.JsonValue
|
|
56
|
+
: Schema.isSchema(syncPayloadSchemaExport)
|
|
57
|
+
? (syncPayloadSchemaExport as Schema.Schema<any>)
|
|
58
|
+
: shouldNeverHappen(
|
|
59
|
+
`Exported 'syncPayloadSchema' from ${abs} must be an Effect Schema (received ${typeof syncPayloadSchemaExport}).`,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
const syncPayloadExport = (mod as any)?.syncPayload
|
|
63
|
+
const syncPayload =
|
|
64
|
+
syncPayloadExport === undefined
|
|
65
|
+
? undefined
|
|
66
|
+
: (() => {
|
|
67
|
+
try {
|
|
68
|
+
return Schema.decodeSync(syncPayloadSchema)(syncPayloadExport)
|
|
69
|
+
} catch (error) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Failed to decode 'syncPayload' from ${abs} using the provided schema: ${(error as Error).message}`,
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
})()
|
|
38
75
|
|
|
39
76
|
// Build Node adapter internally
|
|
40
77
|
const adapter = makeNodeAdapter({
|
|
@@ -42,36 +79,32 @@ export const init = ({
|
|
|
42
79
|
...(clientId ? { clientId } : {}),
|
|
43
80
|
...(sessionId ? { sessionId } : {}),
|
|
44
81
|
sync: {
|
|
45
|
-
backend:
|
|
82
|
+
backend: syncBackend as any,
|
|
46
83
|
initialSyncOptions: { _tag: 'Blocking', timeout: 5000 },
|
|
47
84
|
onSyncError: 'shutdown',
|
|
48
85
|
},
|
|
49
86
|
})
|
|
50
87
|
|
|
51
88
|
// Create the store
|
|
52
|
-
const s =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}),
|
|
61
|
-
)
|
|
89
|
+
const s = await createStorePromise({
|
|
90
|
+
schema,
|
|
91
|
+
storeId,
|
|
92
|
+
adapter,
|
|
93
|
+
disableDevtools: true,
|
|
94
|
+
syncPayload,
|
|
95
|
+
syncPayloadSchema,
|
|
96
|
+
})
|
|
62
97
|
|
|
63
98
|
// Replace existing store if any
|
|
64
99
|
if (store) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
} catch {}
|
|
69
|
-
})
|
|
100
|
+
try {
|
|
101
|
+
await store.shutdownPromise()
|
|
102
|
+
} catch {}
|
|
70
103
|
}
|
|
71
104
|
|
|
72
105
|
store = s
|
|
73
106
|
return store
|
|
74
|
-
})
|
|
107
|
+
})
|
|
75
108
|
|
|
76
109
|
export const getStore = Effect.sync(() => Option.fromNullable(store))
|
|
77
110
|
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { State } from '@livestore/common/schema';
|
|
2
|
-
import type { MockSyncBackend } from '@livestore/common/sync';
|
|
3
|
-
import { EventFactory } from '@livestore/common/testing';
|
|
4
|
-
import { Effect, FileSystem, type Mailbox } from '@livestore/utils/effect';
|
|
5
|
-
export declare const events: {
|
|
6
|
-
itemAdded: State.SQLite.EventDef<"itemAdded", {
|
|
7
|
-
readonly id: string;
|
|
8
|
-
readonly title: string;
|
|
9
|
-
}, {
|
|
10
|
-
readonly id: string;
|
|
11
|
-
readonly title: string;
|
|
12
|
-
}>;
|
|
13
|
-
};
|
|
14
|
-
export declare const schema: import("@livestore/common/schema").FromInputSchema.DeriveSchema<{
|
|
15
|
-
state: import("@livestore/common/schema").InternalState;
|
|
16
|
-
events: {
|
|
17
|
-
itemAdded: State.SQLite.EventDef<"itemAdded", {
|
|
18
|
-
readonly id: string;
|
|
19
|
-
readonly title: string;
|
|
20
|
-
}, {
|
|
21
|
-
readonly id: string;
|
|
22
|
-
readonly title: string;
|
|
23
|
-
}>;
|
|
24
|
-
};
|
|
25
|
-
}>;
|
|
26
|
-
/**
|
|
27
|
-
* Creates a temporary config module (schema + mock backend) and cleans it up afterwards.
|
|
28
|
-
* Returns the module path plus handles to the backend and connection event mailbox, keeping lifecycle assertions local to each test.
|
|
29
|
-
*/
|
|
30
|
-
export declare const useMockConfig: Effect.Effect<{
|
|
31
|
-
configPath: string;
|
|
32
|
-
mockBackend: MockSyncBackend;
|
|
33
|
-
connectionEvents: Mailbox.Mailbox<"connect" | "disconnect", never>;
|
|
34
|
-
}, Error | import("@effect/platform/Error").PlatformError, FileSystem.FileSystem | import("effect/Scope").Scope>;
|
|
35
|
-
export declare const makeEventFactory: () => {
|
|
36
|
-
itemAdded: {
|
|
37
|
-
next: (args: {
|
|
38
|
-
readonly id: string;
|
|
39
|
-
readonly title: string;
|
|
40
|
-
}) => {
|
|
41
|
-
readonly name: string;
|
|
42
|
-
readonly args: any;
|
|
43
|
-
readonly seqNum: any;
|
|
44
|
-
readonly parentSeqNum: any;
|
|
45
|
-
readonly clientId: string;
|
|
46
|
-
readonly sessionId: string;
|
|
47
|
-
};
|
|
48
|
-
advanceTo: (seq: number, parent?: EventFactory.SequenceValue) => void;
|
|
49
|
-
setParent: (parent: EventFactory.SequenceValue) => void;
|
|
50
|
-
current: () => {
|
|
51
|
-
seq: number;
|
|
52
|
-
parent: EventFactory.SequenceValue;
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
};
|
|
56
|
-
//# sourceMappingURL=mock-config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mock-config.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/mock-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,OAAO,EAAU,MAAM,yBAAyB,CAAA;AAYlF,eAAO,MAAM,MAAM;;;;;;;;CAKlB,CAAA;AAWD,eAAO,MAAM,MAAM;;;;;;;;;;;EAAgC,CAAA;AAiCnD;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;gHA0BzB,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;uCApDC,CAAC;;;;;;;CAyD3B,CAAA"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import path from 'node:path';
|
|
10
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
11
|
-
import { Events, makeSchema, State } from '@livestore/common/schema';
|
|
12
|
-
import { EventFactory } from '@livestore/common/testing';
|
|
13
|
-
import { Effect, FileSystem, Schema } from '@livestore/utils/effect';
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
const items = State.SQLite.table({
|
|
16
|
-
name: 'items',
|
|
17
|
-
columns: {
|
|
18
|
-
id: State.SQLite.text({ primaryKey: true }),
|
|
19
|
-
title: State.SQLite.text({ default: '', nullable: false }),
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
export const events = {
|
|
23
|
-
itemAdded: Events.synced({
|
|
24
|
-
name: 'itemAdded',
|
|
25
|
-
schema: Schema.Struct({ id: Schema.String, title: Schema.String }),
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
const materializers = State.SQLite.materializers(events, {
|
|
29
|
-
itemAdded: ({ id, title }) => items.insert({ id, title }),
|
|
30
|
-
});
|
|
31
|
-
const state = State.SQLite.makeState({
|
|
32
|
-
tables: { items },
|
|
33
|
-
materializers,
|
|
34
|
-
});
|
|
35
|
-
export const schema = makeSchema({ state, events });
|
|
36
|
-
const tmpDir = path.join(process.cwd(), 'tmp', 'cli-sync-tests');
|
|
37
|
-
const schemaModuleUrl = pathToFileURL(path.join(__dirname, 'mock-config.ts')).href;
|
|
38
|
-
/** Generates a per-test config module exporting schema, a mock backend, and connection event taps. */
|
|
39
|
-
const makeTempConfig = () => {
|
|
40
|
-
const moduleSource = `
|
|
41
|
-
import { schema } from ${JSON.stringify(schemaModuleUrl)}
|
|
42
|
-
import { makeMockSyncBackend } from '@livestore/common/sync'
|
|
43
|
-
import { Effect, Mailbox } from '@livestore/utils/effect'
|
|
44
|
-
|
|
45
|
-
export const mockBackend = await Effect.runPromise(Effect.scoped(makeMockSyncBackend({ startConnected: true })))
|
|
46
|
-
export const connectionEvents = await Effect.runPromise(Mailbox.make<'connect' | 'disconnect'>())
|
|
47
|
-
|
|
48
|
-
export { schema }
|
|
49
|
-
|
|
50
|
-
export const syncBackend = (_args) =>
|
|
51
|
-
mockBackend.makeSyncBackend.pipe(
|
|
52
|
-
Effect.tap(() => connectionEvents.offer('connect')),
|
|
53
|
-
Effect.map((backend) => {
|
|
54
|
-
const disconnect = backend.disconnect ?? Effect.void
|
|
55
|
-
return {
|
|
56
|
-
...backend,
|
|
57
|
-
disconnect: disconnect.pipe(Effect.tap(() => connectionEvents.offer('disconnect'))),
|
|
58
|
-
}
|
|
59
|
-
}),
|
|
60
|
-
)
|
|
61
|
-
`;
|
|
62
|
-
return moduleSource;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Creates a temporary config module (schema + mock backend) and cleans it up afterwards.
|
|
66
|
-
* Returns the module path plus handles to the backend and connection event mailbox, keeping lifecycle assertions local to each test.
|
|
67
|
-
*/
|
|
68
|
-
export const useMockConfig = Effect.acquireRelease(Effect.gen(function* () {
|
|
69
|
-
const fs = yield* FileSystem.FileSystem;
|
|
70
|
-
yield* fs.makeDirectory(tmpDir, { recursive: true });
|
|
71
|
-
const tempPath = path.join(tmpDir, `mock-config-${Date.now()}-${Math.random().toString(16).slice(2)}.ts`);
|
|
72
|
-
const moduleSource = makeTempConfig();
|
|
73
|
-
yield* fs.writeFileString(tempPath, moduleSource);
|
|
74
|
-
const mod = (yield* Effect.tryPromise({
|
|
75
|
-
try: () => import(__rewriteRelativeImportExtension(pathToFileURL(tempPath).href)),
|
|
76
|
-
catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))),
|
|
77
|
-
}));
|
|
78
|
-
return { configPath: tempPath, mockBackend: mod.mockBackend, connectionEvents: mod.connectionEvents };
|
|
79
|
-
}), ({ configPath }) => Effect.gen(function* () {
|
|
80
|
-
const fs = yield* FileSystem.FileSystem;
|
|
81
|
-
yield* fs.remove(configPath, { recursive: false }).pipe(Effect.catchAll(() => Effect.void));
|
|
82
|
-
}));
|
|
83
|
-
export const makeEventFactory = () => EventFactory.makeFactory(events)({
|
|
84
|
-
client: EventFactory.clientIdentity('cli-test-client'),
|
|
85
|
-
startSeq: 1,
|
|
86
|
-
initialParent: 'root',
|
|
87
|
-
});
|
|
88
|
-
//# sourceMappingURL=mock-config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mock-config.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/mock-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sync-operations.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sync-operations.test.ts"],"names":[],"mappings":""}
|