@livestore/cli 0.0.0-snapshot-75de2b24a1fb1df981b56b5d9ec7381ea351e95b → 0.0.0-snapshot-8ed820c4fc69291ddbf497c7639246e903f3a299
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 +0 -14
- 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-tool-handlers.d.ts.map +1 -1
- package/dist/commands/mcp-tool-handlers.js +1 -30
- package/dist/commands/mcp-tool-handlers.js.map +1 -1
- package/dist/commands/mcp-tools-defs.d.ts +0 -30
- package/dist/commands/mcp-tools-defs.d.ts.map +1 -1
- package/dist/commands/mcp-tools-defs.js +3 -85
- package/dist/commands/mcp-tools-defs.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/cli.ts +1 -2
- package/src/commands/mcp-tool-handlers.ts +1 -34
- package/src/commands/mcp-tools-defs.ts +2 -90
- 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 -123
- package/dist/commands/import-export.js.map +0 -1
- package/dist/sync-operations.d.ts +0 -111
- package/dist/sync-operations.d.ts.map +0 -1
- package/dist/sync-operations.js +0 -230
- package/dist/sync-operations.js.map +0 -1
- package/src/commands/import-export.ts +0 -262
- package/src/sync-operations.ts +0 -413
package/dist/sync-operations.js
DELETED
|
@@ -1,230 +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
|
-
/**
|
|
10
|
-
* Shared sync operations for CLI and MCP.
|
|
11
|
-
* Contains the core logic for exporting and importing events from sync backends.
|
|
12
|
-
*/
|
|
13
|
-
import path from 'node:path';
|
|
14
|
-
import { pathToFileURL } from 'node:url';
|
|
15
|
-
import { UnknownError } from '@livestore/common';
|
|
16
|
-
import { isLiveStoreSchema, LiveStoreEvent } from '@livestore/common/schema';
|
|
17
|
-
import { shouldNeverHappen } from '@livestore/utils';
|
|
18
|
-
import { Cause, Effect, FileSystem, KeyValueStore, Layer, Option, Schema, Stream, } from '@livestore/utils/effect';
|
|
19
|
-
/** Connection timeout for sync backend ping (5 seconds) */
|
|
20
|
-
const CONNECTION_TIMEOUT_MS = 5000;
|
|
21
|
-
/**
|
|
22
|
-
* Schema for the export file format.
|
|
23
|
-
* Contains metadata about the export and an array of events in global encoded format.
|
|
24
|
-
*/
|
|
25
|
-
export const ExportFileSchema = Schema.Struct({
|
|
26
|
-
/** Format version for future compatibility */
|
|
27
|
-
version: Schema.Literal(1),
|
|
28
|
-
/** Store identifier */
|
|
29
|
-
storeId: Schema.String,
|
|
30
|
-
/** ISO timestamp of when the export was created */
|
|
31
|
-
exportedAt: Schema.String,
|
|
32
|
-
/** Total number of events in the export */
|
|
33
|
-
eventCount: Schema.Number,
|
|
34
|
-
/** Array of events in global encoded format */
|
|
35
|
-
events: Schema.Array(LiveStoreEvent.Global.Encoded),
|
|
36
|
-
});
|
|
37
|
-
export class ConnectionError extends Schema.TaggedError()('ConnectionError', {
|
|
38
|
-
cause: Schema.Defect,
|
|
39
|
-
note: Schema.String,
|
|
40
|
-
}) {
|
|
41
|
-
}
|
|
42
|
-
export class ExportError extends Schema.TaggedError()('ExportError', {
|
|
43
|
-
cause: Schema.Defect,
|
|
44
|
-
note: Schema.String,
|
|
45
|
-
}) {
|
|
46
|
-
}
|
|
47
|
-
export class ImportError extends Schema.TaggedError()('ImportError', {
|
|
48
|
-
cause: Schema.Defect,
|
|
49
|
-
note: Schema.String,
|
|
50
|
-
}) {
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Creates a sync backend connection from a user module and verifies connectivity.
|
|
54
|
-
* This is a simplified version of the MCP runtime that only creates the sync backend.
|
|
55
|
-
*/
|
|
56
|
-
export const makeSyncBackend = ({ storePath, storeId, clientId, }) => Effect.gen(function* () {
|
|
57
|
-
const abs = path.isAbsolute(storePath) ? storePath : path.resolve(process.cwd(), storePath);
|
|
58
|
-
const fs = yield* FileSystem.FileSystem;
|
|
59
|
-
const exists = yield* fs.exists(abs).pipe(UnknownError.mapToUnknownError);
|
|
60
|
-
if (!exists) {
|
|
61
|
-
return yield* Effect.fail(UnknownError.make({
|
|
62
|
-
cause: `Store module not found at ${abs}`,
|
|
63
|
-
note: 'Make sure the path points to a valid LiveStore module',
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
const mod = yield* Effect.tryPromise({
|
|
67
|
-
try: () => import(__rewriteRelativeImportExtension(pathToFileURL(abs).href)),
|
|
68
|
-
catch: (cause) => UnknownError.make({
|
|
69
|
-
cause,
|
|
70
|
-
note: `Failed to import module at ${abs}`,
|
|
71
|
-
}),
|
|
72
|
-
});
|
|
73
|
-
const schema = mod?.schema;
|
|
74
|
-
if (!isLiveStoreSchema(schema)) {
|
|
75
|
-
return yield* Effect.fail(UnknownError.make({
|
|
76
|
-
cause: `Module at ${abs} must export a valid LiveStore 'schema'`,
|
|
77
|
-
note: `Ex: export { schema } from './src/livestore/schema.ts'`,
|
|
78
|
-
}));
|
|
79
|
-
}
|
|
80
|
-
const syncBackendConstructor = mod?.syncBackend;
|
|
81
|
-
if (typeof syncBackendConstructor !== 'function') {
|
|
82
|
-
return yield* Effect.fail(UnknownError.make({
|
|
83
|
-
cause: `Module at ${abs} must export a 'syncBackend' constructor`,
|
|
84
|
-
note: `Ex: export const syncBackend = makeWsSync({ url })`,
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
const syncPayloadSchemaExport = mod?.syncPayloadSchema;
|
|
88
|
-
const syncPayloadSchema = syncPayloadSchemaExport === undefined
|
|
89
|
-
? Schema.JsonValue
|
|
90
|
-
: Schema.isSchema(syncPayloadSchemaExport)
|
|
91
|
-
? syncPayloadSchemaExport
|
|
92
|
-
: shouldNeverHappen(`Exported 'syncPayloadSchema' from ${abs} must be an Effect Schema (received ${typeof syncPayloadSchemaExport}).`);
|
|
93
|
-
const syncPayloadExport = mod?.syncPayload;
|
|
94
|
-
const syncPayload = yield* (syncPayloadExport === undefined
|
|
95
|
-
? Effect.succeed(undefined)
|
|
96
|
-
: Schema.decodeUnknown(syncPayloadSchema)(syncPayloadExport)).pipe(UnknownError.mapToUnknownError);
|
|
97
|
-
/** Simple in-memory key-value store for sync backend state */
|
|
98
|
-
const kvStore = { backendId: undefined };
|
|
99
|
-
const syncBackend = yield* syncBackendConstructor({
|
|
100
|
-
storeId,
|
|
101
|
-
clientId,
|
|
102
|
-
payload: syncPayload,
|
|
103
|
-
}).pipe(Effect.provide(Layer.succeed(KeyValueStore.KeyValueStore, KeyValueStore.makeStringOnly({
|
|
104
|
-
get: (_key) => Effect.succeed(Option.fromNullable(kvStore.backendId)),
|
|
105
|
-
set: (_key, value) => Effect.sync(() => {
|
|
106
|
-
kvStore.backendId = value;
|
|
107
|
-
}),
|
|
108
|
-
clear: Effect.dieMessage('Not implemented'),
|
|
109
|
-
remove: () => Effect.dieMessage('Not implemented'),
|
|
110
|
-
size: Effect.dieMessage('Not implemented'),
|
|
111
|
-
}))), UnknownError.mapToUnknownError);
|
|
112
|
-
/** Connect to the sync backend */
|
|
113
|
-
yield* syncBackend.connect.pipe(Effect.mapError((cause) => new ConnectionError({
|
|
114
|
-
cause,
|
|
115
|
-
note: `Failed to connect to sync backend: ${cause._tag === 'IsOfflineError' ? 'Backend is offline or unreachable' : String(cause)}`,
|
|
116
|
-
})));
|
|
117
|
-
/** Verify connectivity with a ping (with timeout) */
|
|
118
|
-
yield* syncBackend.ping.pipe(Effect.timeout(CONNECTION_TIMEOUT_MS), Effect.catchAll((cause) => {
|
|
119
|
-
if (Cause.isTimeoutException(cause)) {
|
|
120
|
-
return Effect.fail(new ConnectionError({
|
|
121
|
-
cause,
|
|
122
|
-
note: `Connection timeout: Sync backend did not respond within ${CONNECTION_TIMEOUT_MS}ms`,
|
|
123
|
-
}));
|
|
124
|
-
}
|
|
125
|
-
return Effect.fail(new ConnectionError({
|
|
126
|
-
cause,
|
|
127
|
-
note: `Failed to ping sync backend: ${cause._tag === 'IsOfflineError' ? 'Backend is offline or unreachable' : String(cause)}`,
|
|
128
|
-
}));
|
|
129
|
-
}));
|
|
130
|
-
return syncBackend;
|
|
131
|
-
});
|
|
132
|
-
/**
|
|
133
|
-
* Core export operation - pulls all events from sync backend.
|
|
134
|
-
* Returns the export data structure without writing to file.
|
|
135
|
-
*/
|
|
136
|
-
export const pullEventsFromSyncBackend = ({ storePath, storeId, clientId, }) => Effect.gen(function* () {
|
|
137
|
-
const syncBackend = yield* makeSyncBackend({ storePath, storeId, clientId });
|
|
138
|
-
const events = [];
|
|
139
|
-
yield* syncBackend.pull(Option.none(), { live: false }).pipe(Stream.tap((item) => Effect.sync(() => {
|
|
140
|
-
for (const { eventEncoded } of item.batch) {
|
|
141
|
-
events.push(eventEncoded);
|
|
142
|
-
}
|
|
143
|
-
})), Stream.takeUntil((item) => item.pageInfo._tag === 'NoMore'), Stream.runDrain, Effect.mapError((cause) => new ExportError({
|
|
144
|
-
cause,
|
|
145
|
-
note: `Failed to pull events from sync backend: ${cause}`,
|
|
146
|
-
})));
|
|
147
|
-
const exportedAt = new Date().toISOString();
|
|
148
|
-
const exportData = {
|
|
149
|
-
version: 1,
|
|
150
|
-
storeId,
|
|
151
|
-
exportedAt,
|
|
152
|
-
eventCount: events.length,
|
|
153
|
-
events,
|
|
154
|
-
};
|
|
155
|
-
return {
|
|
156
|
-
storeId,
|
|
157
|
-
eventCount: events.length,
|
|
158
|
-
exportedAt,
|
|
159
|
-
data: exportData,
|
|
160
|
-
};
|
|
161
|
-
}).pipe(Effect.withSpan('sync:pullEvents'));
|
|
162
|
-
/**
|
|
163
|
-
* Validates an export file for import.
|
|
164
|
-
* Returns validation info without actually importing.
|
|
165
|
-
*/
|
|
166
|
-
export const validateExportData = ({ data, targetStoreId, }) => Effect.gen(function* () {
|
|
167
|
-
const exportData = yield* Schema.decodeUnknown(ExportFileSchema)(data).pipe(Effect.mapError((cause) => new ImportError({
|
|
168
|
-
cause: new Error(`Invalid export file format: ${cause}`),
|
|
169
|
-
note: `Invalid export file format: ${cause}`,
|
|
170
|
-
})));
|
|
171
|
-
return {
|
|
172
|
-
storeId: targetStoreId,
|
|
173
|
-
eventCount: exportData.events.length,
|
|
174
|
-
sourceStoreId: exportData.storeId,
|
|
175
|
-
storeIdMismatch: exportData.storeId !== targetStoreId,
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
/**
|
|
179
|
-
* Core import operation - pushes events to sync backend.
|
|
180
|
-
* Validates that the backend is empty before importing.
|
|
181
|
-
*/
|
|
182
|
-
export const pushEventsToSyncBackend = ({ storePath, storeId, clientId, data, force, dryRun, }) => Effect.gen(function* () {
|
|
183
|
-
const exportData = yield* Schema.decodeUnknown(ExportFileSchema)(data).pipe(Effect.mapError((cause) => new ImportError({
|
|
184
|
-
cause: new Error(`Invalid export file format: ${cause}`),
|
|
185
|
-
note: `Invalid export file format: ${cause}`,
|
|
186
|
-
})));
|
|
187
|
-
if (exportData.storeId !== storeId && !force) {
|
|
188
|
-
return yield* Effect.fail(new ImportError({
|
|
189
|
-
cause: new Error(`Store ID mismatch: file has '${exportData.storeId}', expected '${storeId}'`),
|
|
190
|
-
note: `The export file was created for a different store. Use force option to import anyway.`,
|
|
191
|
-
}));
|
|
192
|
-
}
|
|
193
|
-
if (dryRun) {
|
|
194
|
-
return {
|
|
195
|
-
storeId,
|
|
196
|
-
eventCount: exportData.events.length,
|
|
197
|
-
dryRun: true,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
const syncBackend = yield* makeSyncBackend({ storePath, storeId, clientId });
|
|
201
|
-
/** Check if events already exist by pulling from the backend first */
|
|
202
|
-
let existingEventCount = 0;
|
|
203
|
-
yield* syncBackend.pull(Option.none(), { live: false }).pipe(Stream.tap((item) => Effect.sync(() => {
|
|
204
|
-
existingEventCount += item.batch.length;
|
|
205
|
-
})), Stream.takeUntil((item) => item.pageInfo._tag === 'NoMore'), Stream.runDrain, Effect.mapError((cause) => new ImportError({
|
|
206
|
-
cause,
|
|
207
|
-
note: `Failed to check existing events: ${cause}`,
|
|
208
|
-
})));
|
|
209
|
-
if (existingEventCount > 0) {
|
|
210
|
-
return yield* Effect.fail(new ImportError({
|
|
211
|
-
cause: new Error(`Sync backend already contains ${existingEventCount} events`),
|
|
212
|
-
note: `Cannot import into a non-empty sync backend. The sync backend must be empty.`,
|
|
213
|
-
}));
|
|
214
|
-
}
|
|
215
|
-
/** Push events in batches of 100 (sync backend constraint) */
|
|
216
|
-
const batchSize = 100;
|
|
217
|
-
for (let i = 0; i < exportData.events.length; i += batchSize) {
|
|
218
|
-
const batch = exportData.events.slice(i, i + batchSize);
|
|
219
|
-
yield* syncBackend.push(batch).pipe(Effect.mapError((cause) => new ImportError({
|
|
220
|
-
cause,
|
|
221
|
-
note: `Failed to push events at position ${i}: ${cause}`,
|
|
222
|
-
})));
|
|
223
|
-
}
|
|
224
|
-
return {
|
|
225
|
-
storeId,
|
|
226
|
-
eventCount: exportData.events.length,
|
|
227
|
-
dryRun: false,
|
|
228
|
-
};
|
|
229
|
-
}).pipe(Effect.withSpan('sync:pushEvents'));
|
|
230
|
-
//# sourceMappingURL=sync-operations.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sync-operations.js","sourceRoot":"","sources":["../src/sync-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import type { UnknownError } from '@livestore/common'
|
|
3
|
-
import { Console, Effect, FileSystem, type HttpClient, type Scope } from '@livestore/utils/effect'
|
|
4
|
-
import { Cli } from '@livestore/utils/node'
|
|
5
|
-
import * as SyncOps from '../sync-operations.ts'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Export events from the sync backend to a JSON file.
|
|
9
|
-
*/
|
|
10
|
-
const exportEvents = ({
|
|
11
|
-
storePath,
|
|
12
|
-
storeId,
|
|
13
|
-
clientId,
|
|
14
|
-
outputPath,
|
|
15
|
-
}: {
|
|
16
|
-
storePath: string
|
|
17
|
-
storeId: string
|
|
18
|
-
clientId: string
|
|
19
|
-
outputPath: string
|
|
20
|
-
}): Effect.Effect<
|
|
21
|
-
void,
|
|
22
|
-
SyncOps.ExportError | SyncOps.ConnectionError | UnknownError,
|
|
23
|
-
FileSystem.FileSystem | HttpClient.HttpClient | Scope.Scope
|
|
24
|
-
> =>
|
|
25
|
-
Effect.gen(function* () {
|
|
26
|
-
yield* Console.log(`Connecting to sync backend...`)
|
|
27
|
-
|
|
28
|
-
const result = yield* SyncOps.pullEventsFromSyncBackend({ storePath, storeId, clientId })
|
|
29
|
-
|
|
30
|
-
yield* Console.log(`✓ Connected to sync backend`)
|
|
31
|
-
yield* Console.log(`Pulled ${result.eventCount} events`)
|
|
32
|
-
|
|
33
|
-
const fs = yield* FileSystem.FileSystem
|
|
34
|
-
const absOutputPath = path.isAbsolute(outputPath) ? outputPath : path.resolve(process.cwd(), outputPath)
|
|
35
|
-
|
|
36
|
-
yield* fs.writeFileString(absOutputPath, JSON.stringify(result.data, null, 2)).pipe(
|
|
37
|
-
Effect.mapError(
|
|
38
|
-
(cause) =>
|
|
39
|
-
new SyncOps.ExportError({
|
|
40
|
-
cause,
|
|
41
|
-
note: `Failed to write export file: ${cause}`,
|
|
42
|
-
}),
|
|
43
|
-
),
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
yield* Console.log(`Exported ${result.eventCount} events to ${absOutputPath}`)
|
|
47
|
-
}).pipe(Effect.withSpan('cli:export'))
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Import events from a JSON file to the sync backend.
|
|
51
|
-
*/
|
|
52
|
-
const importEvents = ({
|
|
53
|
-
storePath,
|
|
54
|
-
storeId,
|
|
55
|
-
clientId,
|
|
56
|
-
inputPath,
|
|
57
|
-
force,
|
|
58
|
-
dryRun,
|
|
59
|
-
}: {
|
|
60
|
-
storePath: string
|
|
61
|
-
storeId: string
|
|
62
|
-
clientId: string
|
|
63
|
-
inputPath: string
|
|
64
|
-
force: boolean
|
|
65
|
-
dryRun: boolean
|
|
66
|
-
}): Effect.Effect<
|
|
67
|
-
void,
|
|
68
|
-
SyncOps.ImportError | SyncOps.ConnectionError | UnknownError,
|
|
69
|
-
FileSystem.FileSystem | HttpClient.HttpClient | Scope.Scope
|
|
70
|
-
> =>
|
|
71
|
-
Effect.gen(function* () {
|
|
72
|
-
const fs = yield* FileSystem.FileSystem
|
|
73
|
-
const absInputPath = path.isAbsolute(inputPath) ? inputPath : path.resolve(process.cwd(), inputPath)
|
|
74
|
-
|
|
75
|
-
const exists = yield* fs.exists(absInputPath).pipe(
|
|
76
|
-
Effect.mapError(
|
|
77
|
-
(cause) =>
|
|
78
|
-
new SyncOps.ImportError({
|
|
79
|
-
cause,
|
|
80
|
-
note: `Failed to check file existence: ${cause}`,
|
|
81
|
-
}),
|
|
82
|
-
),
|
|
83
|
-
)
|
|
84
|
-
if (!exists) {
|
|
85
|
-
return yield* new SyncOps.ImportError({
|
|
86
|
-
cause: new Error(`File not found: ${absInputPath}`),
|
|
87
|
-
note: `Import file does not exist at ${absInputPath}`,
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
yield* Console.log(`Reading import file...`)
|
|
92
|
-
|
|
93
|
-
const fileContent = yield* fs.readFileString(absInputPath).pipe(
|
|
94
|
-
Effect.mapError(
|
|
95
|
-
(cause) =>
|
|
96
|
-
new SyncOps.ImportError({
|
|
97
|
-
cause,
|
|
98
|
-
note: `Failed to read import file: ${cause}`,
|
|
99
|
-
}),
|
|
100
|
-
),
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
const parsedContent = yield* Effect.try({
|
|
104
|
-
try: () => JSON.parse(fileContent),
|
|
105
|
-
catch: (error) =>
|
|
106
|
-
new SyncOps.ImportError({
|
|
107
|
-
cause: new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`),
|
|
108
|
-
note: `Invalid JSON in import file: ${error instanceof Error ? error.message : String(error)}`,
|
|
109
|
-
}),
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
/** Validate export file format before proceeding */
|
|
113
|
-
const validation = yield* SyncOps.validateExportData({ data: parsedContent, targetStoreId: storeId })
|
|
114
|
-
|
|
115
|
-
if (validation.storeIdMismatch) {
|
|
116
|
-
if (!force) {
|
|
117
|
-
return yield* new SyncOps.ImportError({
|
|
118
|
-
cause: new Error(`Store ID mismatch: file has '${validation.sourceStoreId}', expected '${storeId}'`),
|
|
119
|
-
note: `The export file was created for a different store. Use --force to import anyway.`,
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
yield* Console.log(
|
|
123
|
-
`Store ID mismatch: file has '${validation.sourceStoreId}', importing to '${storeId}' (--force)`,
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
yield* Console.log(`Found ${validation.eventCount} events in export file`)
|
|
128
|
-
|
|
129
|
-
if (dryRun) {
|
|
130
|
-
yield* Console.log(`Dry run - validating import file...`)
|
|
131
|
-
yield* Console.log(`Dry run complete. ${validation.eventCount} events would be imported.`)
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
yield* Console.log(`Connecting to sync backend...`)
|
|
136
|
-
|
|
137
|
-
const result = yield* SyncOps.pushEventsToSyncBackend({
|
|
138
|
-
storePath,
|
|
139
|
-
storeId,
|
|
140
|
-
clientId,
|
|
141
|
-
data: parsedContent,
|
|
142
|
-
force,
|
|
143
|
-
dryRun: false,
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
yield* Console.log(`✓ Connected to sync backend`)
|
|
147
|
-
yield* Console.log(`Successfully imported ${result.eventCount} events`)
|
|
148
|
-
}).pipe(Effect.withSpan('cli:import'))
|
|
149
|
-
|
|
150
|
-
export const exportCommand = Cli.Command.make(
|
|
151
|
-
'export',
|
|
152
|
-
{
|
|
153
|
-
store: Cli.Options.text('store').pipe(
|
|
154
|
-
Cli.Options.withAlias('s'),
|
|
155
|
-
Cli.Options.withDescription('Path to the store module that exports schema and syncBackend'),
|
|
156
|
-
),
|
|
157
|
-
storeId: Cli.Options.text('store-id').pipe(
|
|
158
|
-
Cli.Options.withAlias('i'),
|
|
159
|
-
Cli.Options.withDescription('Store identifier'),
|
|
160
|
-
),
|
|
161
|
-
clientId: Cli.Options.text('client-id').pipe(
|
|
162
|
-
Cli.Options.withDefault('cli-export'),
|
|
163
|
-
Cli.Options.withDescription('Client identifier for the sync connection'),
|
|
164
|
-
),
|
|
165
|
-
output: Cli.Args.text({ name: 'file' }).pipe(Cli.Args.withDescription('Output JSON file path')),
|
|
166
|
-
},
|
|
167
|
-
Effect.fn(function* ({
|
|
168
|
-
store,
|
|
169
|
-
storeId,
|
|
170
|
-
clientId,
|
|
171
|
-
output,
|
|
172
|
-
}: {
|
|
173
|
-
store: string
|
|
174
|
-
storeId: string
|
|
175
|
-
clientId: string
|
|
176
|
-
output: string
|
|
177
|
-
}) {
|
|
178
|
-
yield* Console.log(`Exporting events from LiveStore...`)
|
|
179
|
-
yield* Console.log(` Store: ${store}`)
|
|
180
|
-
yield* Console.log(` Store ID: ${storeId}`)
|
|
181
|
-
yield* Console.log(` Output: ${output}`)
|
|
182
|
-
yield* Console.log('')
|
|
183
|
-
|
|
184
|
-
yield* exportEvents({
|
|
185
|
-
storePath: store,
|
|
186
|
-
storeId,
|
|
187
|
-
clientId,
|
|
188
|
-
outputPath: output,
|
|
189
|
-
}).pipe(Effect.scoped)
|
|
190
|
-
}),
|
|
191
|
-
).pipe(
|
|
192
|
-
Cli.Command.withDescription(
|
|
193
|
-
'Export all events from the sync backend to a JSON file. Useful for backup and migration.',
|
|
194
|
-
),
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
export const importCommand = Cli.Command.make(
|
|
198
|
-
'import',
|
|
199
|
-
{
|
|
200
|
-
store: Cli.Options.text('store').pipe(
|
|
201
|
-
Cli.Options.withAlias('s'),
|
|
202
|
-
Cli.Options.withDescription('Path to the store module that exports schema and syncBackend'),
|
|
203
|
-
),
|
|
204
|
-
storeId: Cli.Options.text('store-id').pipe(
|
|
205
|
-
Cli.Options.withAlias('i'),
|
|
206
|
-
Cli.Options.withDescription('Store identifier'),
|
|
207
|
-
),
|
|
208
|
-
clientId: Cli.Options.text('client-id').pipe(
|
|
209
|
-
Cli.Options.withDefault('cli-import'),
|
|
210
|
-
Cli.Options.withDescription('Client identifier for the sync connection'),
|
|
211
|
-
),
|
|
212
|
-
force: Cli.Options.boolean('force').pipe(
|
|
213
|
-
Cli.Options.withAlias('f'),
|
|
214
|
-
Cli.Options.withDefault(false),
|
|
215
|
-
Cli.Options.withDescription('Force import even if store ID does not match'),
|
|
216
|
-
),
|
|
217
|
-
dryRun: Cli.Options.boolean('dry-run').pipe(
|
|
218
|
-
Cli.Options.withDefault(false),
|
|
219
|
-
Cli.Options.withDescription('Validate the import file without actually importing'),
|
|
220
|
-
),
|
|
221
|
-
input: Cli.Args.text({ name: 'file' }).pipe(Cli.Args.withDescription('Input JSON file to import')),
|
|
222
|
-
},
|
|
223
|
-
Effect.fn(function* ({
|
|
224
|
-
store,
|
|
225
|
-
storeId,
|
|
226
|
-
clientId,
|
|
227
|
-
force,
|
|
228
|
-
dryRun,
|
|
229
|
-
input,
|
|
230
|
-
}: {
|
|
231
|
-
store: string
|
|
232
|
-
storeId: string
|
|
233
|
-
clientId: string
|
|
234
|
-
force: boolean
|
|
235
|
-
dryRun: boolean
|
|
236
|
-
input: string
|
|
237
|
-
}) {
|
|
238
|
-
yield* Console.log(`Importing events to LiveStore...`)
|
|
239
|
-
yield* Console.log(` Store: ${store}`)
|
|
240
|
-
yield* Console.log(` Store ID: ${storeId}`)
|
|
241
|
-
yield* Console.log(` Input: ${input}`)
|
|
242
|
-
if (force) yield* Console.log(` Force: enabled`)
|
|
243
|
-
if (dryRun) yield* Console.log(` Dry run: enabled`)
|
|
244
|
-
yield* Console.log('')
|
|
245
|
-
|
|
246
|
-
yield* importEvents({
|
|
247
|
-
storePath: store,
|
|
248
|
-
storeId,
|
|
249
|
-
clientId,
|
|
250
|
-
inputPath: input,
|
|
251
|
-
force,
|
|
252
|
-
dryRun,
|
|
253
|
-
}).pipe(Effect.scoped)
|
|
254
|
-
}),
|
|
255
|
-
).pipe(
|
|
256
|
-
Cli.Command.withDescription('Import events from a JSON file to the sync backend. The sync backend must be empty.'),
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
export const syncCommand = Cli.Command.make('sync').pipe(
|
|
260
|
-
Cli.Command.withSubcommands([exportCommand, importCommand]),
|
|
261
|
-
Cli.Command.withDescription('Import and export events from the sync backend'),
|
|
262
|
-
)
|