syncorejs 0.1.0 → 0.2.0

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 (200) hide show
  1. package/dist/{core/src/cli.d.ts → _vendor/cli/app.d.mts} +4 -2
  2. package/dist/_vendor/cli/app.d.mts.map +1 -0
  3. package/dist/_vendor/cli/app.mjs +997 -0
  4. package/dist/_vendor/cli/app.mjs.map +1 -0
  5. package/dist/_vendor/cli/context.mjs +180 -0
  6. package/dist/_vendor/cli/context.mjs.map +1 -0
  7. package/dist/_vendor/cli/dev-session.mjs +49 -0
  8. package/dist/_vendor/cli/dev-session.mjs.map +1 -0
  9. package/dist/_vendor/cli/doctor.mjs +80 -0
  10. package/dist/_vendor/cli/doctor.mjs.map +1 -0
  11. package/dist/_vendor/cli/errors.mjs +22 -0
  12. package/dist/_vendor/cli/errors.mjs.map +1 -0
  13. package/dist/_vendor/cli/help.mjs +26 -0
  14. package/dist/_vendor/cli/help.mjs.map +1 -0
  15. package/dist/_vendor/cli/index.d.mts +2 -0
  16. package/dist/_vendor/cli/index.mjs +23 -0
  17. package/dist/_vendor/cli/index.mjs.map +1 -0
  18. package/dist/_vendor/cli/messages.mjs +32 -0
  19. package/dist/_vendor/cli/messages.mjs.map +1 -0
  20. package/dist/_vendor/cli/preflight.mjs +35 -0
  21. package/dist/_vendor/cli/preflight.mjs.map +1 -0
  22. package/dist/_vendor/cli/project.mjs +583 -0
  23. package/dist/_vendor/cli/project.mjs.map +1 -0
  24. package/dist/_vendor/cli/render.mjs +133 -0
  25. package/dist/_vendor/cli/render.mjs.map +1 -0
  26. package/dist/_vendor/cli/targets.mjs +87 -0
  27. package/dist/_vendor/cli/targets.mjs.map +1 -0
  28. package/dist/_vendor/core/cli.d.mts +59 -1
  29. package/dist/_vendor/core/cli.d.mts.map +1 -1
  30. package/dist/_vendor/core/cli.mjs +528 -75
  31. package/dist/_vendor/core/cli.mjs.map +1 -1
  32. package/dist/_vendor/core/index.d.mts +12 -4
  33. package/dist/_vendor/core/index.d.mts.map +1 -0
  34. package/dist/_vendor/core/index.mjs +4 -3
  35. package/dist/_vendor/core/index.mjs.map +1 -1
  36. package/dist/_vendor/core/runtime/devtools.d.mts +32 -6
  37. package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
  38. package/dist/_vendor/core/runtime/devtools.mjs +397 -182
  39. package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
  40. package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
  41. package/dist/_vendor/core/runtime/runtime.d.mts +89 -7
  42. package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
  43. package/dist/_vendor/core/runtime/runtime.mjs +303 -32
  44. package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
  45. package/dist/_vendor/devtools-protocol/index.d.ts +189 -82
  46. package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
  47. package/dist/_vendor/devtools-protocol/index.js +39 -0
  48. package/dist/_vendor/devtools-protocol/index.js.map +1 -0
  49. package/dist/_vendor/next/config.d.ts.map +1 -1
  50. package/dist/_vendor/next/config.js +2 -5
  51. package/dist/_vendor/next/config.js.map +1 -1
  52. package/dist/_vendor/platform-expo/index.d.ts +15 -5
  53. package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
  54. package/dist/_vendor/platform-expo/index.js +33 -3
  55. package/dist/_vendor/platform-expo/index.js.map +1 -1
  56. package/dist/_vendor/platform-expo/react.js.map +1 -1
  57. package/dist/_vendor/platform-node/index.d.mts +10 -5
  58. package/dist/_vendor/platform-node/index.d.mts.map +1 -1
  59. package/dist/_vendor/platform-node/index.mjs +145 -35
  60. package/dist/_vendor/platform-node/index.mjs.map +1 -1
  61. package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
  62. package/dist/_vendor/platform-web/external-change.d.ts +39 -0
  63. package/dist/_vendor/platform-web/external-change.d.ts.map +1 -0
  64. package/dist/_vendor/platform-web/external-change.js +61 -0
  65. package/dist/_vendor/platform-web/external-change.js.map +1 -0
  66. package/dist/_vendor/platform-web/index.d.ts +27 -5
  67. package/dist/_vendor/platform-web/index.d.ts.map +1 -1
  68. package/dist/_vendor/platform-web/index.js +310 -44
  69. package/dist/_vendor/platform-web/index.js.map +1 -1
  70. package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
  71. package/dist/_vendor/platform-web/opfs.js.map +1 -1
  72. package/dist/_vendor/platform-web/persistence.js.map +1 -1
  73. package/dist/_vendor/platform-web/react.js.map +1 -1
  74. package/dist/_vendor/platform-web/sqljs.js +22 -2
  75. package/dist/_vendor/platform-web/sqljs.js.map +1 -1
  76. package/dist/_vendor/schema/definition.js.map +1 -1
  77. package/dist/_vendor/schema/planner.js.map +1 -1
  78. package/dist/_vendor/schema/validators.js.map +1 -1
  79. package/dist/browser-react.d.ts +1 -1
  80. package/dist/browser-react.js +1 -1
  81. package/dist/browser.d.ts +6 -7
  82. package/dist/browser.d.ts.map +1 -1
  83. package/dist/browser.js +4 -5
  84. package/dist/browser.js.map +1 -1
  85. package/dist/cli.d.ts +1 -1
  86. package/dist/cli.js +12 -3
  87. package/dist/cli.js.map +1 -1
  88. package/dist/expo-react.d.ts +1 -1
  89. package/dist/expo-react.js +1 -1
  90. package/dist/expo.d.ts +1 -2
  91. package/dist/expo.js +1 -2
  92. package/dist/index.d.ts +3 -7
  93. package/dist/index.js +3 -8
  94. package/dist/next-config.d.ts +1 -2
  95. package/dist/next-config.js +1 -2
  96. package/dist/next.d.ts +1 -3
  97. package/dist/next.js +1 -3
  98. package/dist/node-ipc-react.d.ts +1 -1
  99. package/dist/node-ipc-react.js +1 -1
  100. package/dist/node-ipc.d.ts +1 -2
  101. package/dist/node-ipc.js +1 -2
  102. package/dist/node.d.ts +1 -4
  103. package/dist/node.js +1 -3
  104. package/dist/react.d.ts +1 -2
  105. package/dist/react.js +1 -2
  106. package/dist/svelte.d.ts +1 -2
  107. package/dist/svelte.js +1 -2
  108. package/package.json +6 -3
  109. package/dist/core/src/cli.d.ts.map +0 -1
  110. package/dist/core/src/cli.js +0 -1196
  111. package/dist/core/src/cli.js.map +0 -1
  112. package/dist/core/src/index.js +0 -7
  113. package/dist/core/src/runtime/devtools.d.ts +0 -7
  114. package/dist/core/src/runtime/devtools.d.ts.map +0 -1
  115. package/dist/core/src/runtime/devtools.js +0 -300
  116. package/dist/core/src/runtime/devtools.js.map +0 -1
  117. package/dist/core/src/runtime/functions.d.ts +0 -123
  118. package/dist/core/src/runtime/functions.d.ts.map +0 -1
  119. package/dist/core/src/runtime/functions.js +0 -71
  120. package/dist/core/src/runtime/functions.js.map +0 -1
  121. package/dist/core/src/runtime/id.d.ts +0 -13
  122. package/dist/core/src/runtime/id.d.ts.map +0 -1
  123. package/dist/core/src/runtime/id.js +0 -28
  124. package/dist/core/src/runtime/id.js.map +0 -1
  125. package/dist/core/src/runtime/runtime.d.ts +0 -371
  126. package/dist/core/src/runtime/runtime.d.ts.map +0 -1
  127. package/dist/core/src/runtime/runtime.js +0 -1143
  128. package/dist/core/src/runtime/runtime.js.map +0 -1
  129. package/dist/devtools-protocol/src/index.d.ts +0 -201
  130. package/dist/devtools-protocol/src/index.d.ts.map +0 -1
  131. package/dist/next/src/config.d.ts +0 -17
  132. package/dist/next/src/config.d.ts.map +0 -1
  133. package/dist/next/src/config.js +0 -73
  134. package/dist/next/src/config.js.map +0 -1
  135. package/dist/next/src/index.d.ts +0 -80
  136. package/dist/next/src/index.d.ts.map +0 -1
  137. package/dist/next/src/index.js +0 -82
  138. package/dist/next/src/index.js.map +0 -1
  139. package/dist/platform-expo/src/index.d.ts +0 -96
  140. package/dist/platform-expo/src/index.d.ts.map +0 -1
  141. package/dist/platform-expo/src/index.js +0 -198
  142. package/dist/platform-expo/src/index.js.map +0 -1
  143. package/dist/platform-expo/src/react.d.ts +0 -26
  144. package/dist/platform-expo/src/react.d.ts.map +0 -1
  145. package/dist/platform-expo/src/react.js +0 -30
  146. package/dist/platform-expo/src/react.js.map +0 -1
  147. package/dist/platform-node/src/index.d.ts +0 -145
  148. package/dist/platform-node/src/index.d.ts.map +0 -1
  149. package/dist/platform-node/src/index.js +0 -407
  150. package/dist/platform-node/src/index.js.map +0 -1
  151. package/dist/platform-node/src/ipc-react.d.ts +0 -25
  152. package/dist/platform-node/src/ipc-react.d.ts.map +0 -1
  153. package/dist/platform-node/src/ipc-react.js +0 -21
  154. package/dist/platform-node/src/ipc-react.js.map +0 -1
  155. package/dist/platform-node/src/ipc.d.ts +0 -76
  156. package/dist/platform-node/src/ipc.d.ts.map +0 -1
  157. package/dist/platform-node/src/ipc.js +0 -344
  158. package/dist/platform-node/src/ipc.js.map +0 -1
  159. package/dist/platform-web/src/index.d.ts +0 -106
  160. package/dist/platform-web/src/index.d.ts.map +0 -1
  161. package/dist/platform-web/src/index.js +0 -311
  162. package/dist/platform-web/src/index.js.map +0 -1
  163. package/dist/platform-web/src/indexeddb.js +0 -125
  164. package/dist/platform-web/src/indexeddb.js.map +0 -1
  165. package/dist/platform-web/src/opfs.js +0 -146
  166. package/dist/platform-web/src/opfs.js.map +0 -1
  167. package/dist/platform-web/src/persistence.d.ts +0 -20
  168. package/dist/platform-web/src/persistence.d.ts.map +0 -1
  169. package/dist/platform-web/src/persistence.js +0 -23
  170. package/dist/platform-web/src/persistence.js.map +0 -1
  171. package/dist/platform-web/src/react.d.ts +0 -35
  172. package/dist/platform-web/src/react.d.ts.map +0 -1
  173. package/dist/platform-web/src/react.js +0 -42
  174. package/dist/platform-web/src/react.js.map +0 -1
  175. package/dist/platform-web/src/sqljs.js +0 -133
  176. package/dist/platform-web/src/sqljs.js.map +0 -1
  177. package/dist/platform-web/src/worker.d.ts +0 -79
  178. package/dist/platform-web/src/worker.d.ts.map +0 -1
  179. package/dist/platform-web/src/worker.js +0 -308
  180. package/dist/platform-web/src/worker.js.map +0 -1
  181. package/dist/react/src/index.d.ts +0 -59
  182. package/dist/react/src/index.d.ts.map +0 -1
  183. package/dist/react/src/index.js +0 -151
  184. package/dist/react/src/index.js.map +0 -1
  185. package/dist/schema/src/definition.d.ts +0 -98
  186. package/dist/schema/src/definition.d.ts.map +0 -1
  187. package/dist/schema/src/definition.js +0 -84
  188. package/dist/schema/src/definition.js.map +0 -1
  189. package/dist/schema/src/planner.d.ts +0 -42
  190. package/dist/schema/src/planner.d.ts.map +0 -1
  191. package/dist/schema/src/planner.js +0 -131
  192. package/dist/schema/src/planner.js.map +0 -1
  193. package/dist/schema/src/validators.d.ts +0 -194
  194. package/dist/schema/src/validators.d.ts.map +0 -1
  195. package/dist/schema/src/validators.js +0 -158
  196. package/dist/schema/src/validators.js.map +0 -1
  197. package/dist/svelte/src/index.d.ts +0 -44
  198. package/dist/svelte/src/index.d.ts.map +0 -1
  199. package/dist/svelte/src/index.js +0 -75
  200. package/dist/svelte/src/index.js.map +0 -1
@@ -0,0 +1,583 @@
1
+ import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { VALID_SYNCORE_TEMPLATES, detectProjectTemplate, fileExists, importJsonlIntoProject, isLocalPortInUse, loadProjectConfig, loadProjectFunctions, loadProjectSchema, resolvePortFromEnv, resolveProjectTargetConfig, runCodegen } from "../core/cli.mjs";
4
+ import os from "node:os";
5
+ import { pathToFileURL } from "node:url";
6
+ import AdmZip from "adm-zip";
7
+ import { createPublicRuntimeId, createPublicTargetId } from "../devtools-protocol/index.js";
8
+ import { NodeSqliteDriver, createManagedNodeSyncoreClient } from "../platform-node/index.mjs";
9
+ import WebSocket from "ws";
10
+ //#region src/project.ts
11
+ const PROJECT_TARGET_CAPABILITIES = [
12
+ "run",
13
+ "readData",
14
+ "writeData",
15
+ "exportData"
16
+ ];
17
+ const CLIENT_TARGET_CAPABILITIES = [
18
+ "run",
19
+ "readData",
20
+ "writeData",
21
+ "exportData",
22
+ "streamLogs"
23
+ ];
24
+ function createPublicRuntimeId$1(runtimeId, runtimeIds) {
25
+ return createPublicRuntimeId(runtimeId, runtimeIds);
26
+ }
27
+ function getClientRuntimeLabel(input) {
28
+ return input.sessionLabel ?? input.appName ?? input.platform;
29
+ }
30
+ function buildRuntimeLookup(targets) {
31
+ const lookup = /* @__PURE__ */ new Map();
32
+ for (const target of targets) {
33
+ if (target.kind !== "client") continue;
34
+ for (const runtime of target.runtimes) lookup.set(runtime.runtimeId, {
35
+ ...runtime,
36
+ targetId: target.id,
37
+ targetLabel: target.label
38
+ });
39
+ }
40
+ return lookup;
41
+ }
42
+ async function resolveProjectPaths(cwd) {
43
+ if (!await fileExists(path.join(cwd, "syncore.config.ts"))) return null;
44
+ const projectTarget = resolveProjectTargetConfig(await loadProjectConfig(cwd));
45
+ if (!projectTarget) return null;
46
+ return {
47
+ databasePath: path.resolve(cwd, projectTarget.databasePath),
48
+ storageDirectory: path.resolve(cwd, projectTarget.storageDirectory)
49
+ };
50
+ }
51
+ async function requireProjectPaths(cwd) {
52
+ const paths = await resolveProjectPaths(cwd);
53
+ if (!paths) throw new Error("This Syncore project does not define a projectTarget. Use a connected client target instead.");
54
+ return paths;
55
+ }
56
+ async function resolveProjectTargetDescriptor(cwd) {
57
+ const paths = await resolveProjectPaths(cwd);
58
+ if (!paths) return null;
59
+ return {
60
+ id: "project",
61
+ kind: "project",
62
+ label: `project (${path.basename(paths.databasePath)})`,
63
+ databasePath: paths.databasePath,
64
+ storageDirectory: paths.storageDirectory,
65
+ online: true,
66
+ capabilities: [...PROJECT_TARGET_CAPABILITIES]
67
+ };
68
+ }
69
+ async function createManagedProjectClient(cwd) {
70
+ const [paths, schema, functions] = await Promise.all([
71
+ requireProjectPaths(cwd),
72
+ loadProjectSchema(cwd),
73
+ loadRuntimeProjectFunctions(cwd)
74
+ ]);
75
+ return await createManagedNodeSyncoreClient({
76
+ databasePath: paths.databasePath,
77
+ storageDirectory: paths.storageDirectory,
78
+ schema,
79
+ functions,
80
+ devtools: false,
81
+ platform: "cli"
82
+ });
83
+ }
84
+ async function resolveProjectFunction(cwd, requestedName) {
85
+ const functions = await loadRuntimeProjectFunctions(cwd);
86
+ const normalizedName = normalizeFunctionName(requestedName, functions);
87
+ const definition = functions[normalizedName];
88
+ if (!definition) {
89
+ const available = Object.keys(functions).sort((left, right) => left.localeCompare(right));
90
+ const suggestions = suggestFunctionNames(requestedName, available);
91
+ throw new Error(`Unknown function ${JSON.stringify(requestedName)}.${suggestions.length > 0 ? ` Did you mean: ${suggestions.join(", ")}?` : ""} Available functions: ${available.join(", ")}`);
92
+ }
93
+ return {
94
+ name: normalizedName,
95
+ definition,
96
+ reference: {
97
+ kind: definition.kind,
98
+ name: normalizedName
99
+ }
100
+ };
101
+ }
102
+ function suggestFunctionNames(requestedName, available) {
103
+ const normalized = requestedName.trim().replace(/^api\./, "").replaceAll(".", "/").replaceAll(":", "/").toLowerCase();
104
+ return available.map((name) => ({
105
+ name,
106
+ score: (name.toLowerCase() === normalized ? 100 : 0) + (name.toLowerCase().startsWith(normalized) ? 30 : 0) + (name.toLowerCase().includes(normalized) ? 20 : 0) + sharedSegmentsScore(normalized, name.toLowerCase())
107
+ })).filter((entry) => entry.score > 0).sort((left, right) => right.score - left.score || left.name.localeCompare(right.name)).slice(0, 5).map((entry) => entry.name);
108
+ }
109
+ function sharedSegmentsScore(left, right) {
110
+ const leftSegments = left.split("/").filter(Boolean);
111
+ const rightSegments = right.split("/").filter(Boolean);
112
+ let score = 0;
113
+ for (const segment of leftSegments) if (rightSegments.includes(segment)) score += 10;
114
+ return score;
115
+ }
116
+ function normalizeFunctionName(requestedName, functions) {
117
+ const trimmed = requestedName.trim();
118
+ const candidates = [
119
+ trimmed,
120
+ trimmed.replace(/^api\./, "").replaceAll(".", "/"),
121
+ trimmed.replace(/^api\./, "").replaceAll(".", "/").replaceAll(":", "/"),
122
+ trimmed.replaceAll(":", "/"),
123
+ trimmed.replaceAll(".", "/")
124
+ ];
125
+ for (const candidate of candidates) if (functions[candidate]) return candidate;
126
+ return trimmed.replace(/^api\./, "").replaceAll(".", "/").replaceAll(":", "/");
127
+ }
128
+ async function listProjectTables(cwd) {
129
+ const [paths, schema] = await Promise.all([requireProjectPaths(cwd), loadProjectSchema(cwd)]);
130
+ await mkdir(path.dirname(paths.databasePath), { recursive: true });
131
+ const driver = new NodeSqliteDriver(paths.databasePath);
132
+ try {
133
+ const results = [];
134
+ for (const tableName of schema.tableNames()) {
135
+ const row = await driver.get(`SELECT COUNT(*) AS count FROM ${quoteIdentifier(tableName)}`);
136
+ results.push({
137
+ name: tableName,
138
+ documentCount: Number(row?.count ?? 0)
139
+ });
140
+ }
141
+ return results;
142
+ } finally {
143
+ await driver.close();
144
+ }
145
+ }
146
+ async function readProjectTable(cwd, tableName, options) {
147
+ const driver = new NodeSqliteDriver((await requireProjectPaths(cwd)).databasePath);
148
+ try {
149
+ return {
150
+ table: tableName,
151
+ rows: (await driver.all(`SELECT _id, _creationTime, _json FROM ${quoteIdentifier(tableName)} ORDER BY _creationTime ${options.order.toUpperCase()} LIMIT ?`, [options.limit])).map((row) => ({
152
+ _id: row._id,
153
+ _creationTime: row._creationTime,
154
+ ...JSON.parse(row._json)
155
+ }))
156
+ };
157
+ } finally {
158
+ await driver.close();
159
+ }
160
+ }
161
+ async function exportProjectData(cwd, outputPath, options = {}) {
162
+ const resolvedOutput = path.resolve(cwd, outputPath);
163
+ const tables = options.table ? [options.table] : (await listProjectTables(cwd)).map((table) => table.name);
164
+ if (tables.length === 0) throw new Error("No tables are available to export.");
165
+ return await writeExportData(resolvedOutput, await Promise.all(tables.map(async (table) => ({
166
+ table,
167
+ rows: (await readProjectTable(cwd, table, {
168
+ limit: Number.MAX_SAFE_INTEGER,
169
+ order: "asc"
170
+ })).rows
171
+ }))));
172
+ }
173
+ async function writeExportData(resolvedOutput, payloads) {
174
+ const tables = payloads.map((payload) => payload.table);
175
+ if (tables.length === 0) throw new Error("No tables are available to export.");
176
+ const extension = path.extname(resolvedOutput).toLowerCase();
177
+ if (extension === ".json" || extension === ".jsonl") {
178
+ if (tables.length !== 1) throw new Error(`Single-file exports require --table. Available tables: ${tables.join(", ")}`);
179
+ const payload = payloads[0];
180
+ await mkdir(path.dirname(resolvedOutput), { recursive: true });
181
+ await writeFile(resolvedOutput, extension === ".json" ? `${JSON.stringify(payload.rows, null, 2)}\n` : `${payload.rows.map((row) => JSON.stringify(row)).join("\n")}\n`);
182
+ return {
183
+ path: resolvedOutput,
184
+ tables: [payload.table],
185
+ format: extension === ".json" ? "json" : "jsonl"
186
+ };
187
+ }
188
+ if (extension === ".zip") {
189
+ const zip = new AdmZip();
190
+ for (const payload of payloads) zip.addFile(`${payload.table}.jsonl`, Buffer.from(`${payload.rows.map((row) => JSON.stringify(row)).join("\n")}\n`));
191
+ await mkdir(path.dirname(resolvedOutput), { recursive: true });
192
+ zip.writeZip(resolvedOutput);
193
+ return {
194
+ path: resolvedOutput,
195
+ tables,
196
+ format: "zip"
197
+ };
198
+ }
199
+ await mkdir(resolvedOutput, { recursive: true });
200
+ for (const payload of payloads) await writeFile(path.join(resolvedOutput, `${payload.table}.jsonl`), `${payload.rows.map((row) => JSON.stringify(row)).join("\n")}\n`);
201
+ return {
202
+ path: resolvedOutput,
203
+ tables,
204
+ format: "directory"
205
+ };
206
+ }
207
+ async function importProjectData(cwd, sourcePath, options = {}) {
208
+ const resolvedSource = path.resolve(cwd, sourcePath);
209
+ const extension = path.extname(resolvedSource).toLowerCase();
210
+ const cleanupDirectories = [];
211
+ try {
212
+ const sources = extension === ".zip" ? await extractImportSourcesFromZip(resolvedSource, cleanupDirectories) : await resolveImportSources(resolvedSource, options.table, cleanupDirectories);
213
+ const imported = [];
214
+ for (const source of sources) {
215
+ const importedCount = await importJsonlIntoProject(cwd, source.table, source.filePath);
216
+ imported.push({
217
+ table: source.table,
218
+ importedCount
219
+ });
220
+ }
221
+ return imported;
222
+ } finally {
223
+ for (const directory of cleanupDirectories) await rm(directory, {
224
+ recursive: true,
225
+ force: true
226
+ });
227
+ }
228
+ }
229
+ async function loadImportDocumentBatches(cwd, sourcePath, options = {}) {
230
+ const resolvedSource = path.resolve(cwd, sourcePath);
231
+ const extension = path.extname(resolvedSource).toLowerCase();
232
+ const cleanupDirectories = [];
233
+ try {
234
+ const sources = extension === ".zip" ? await extractImportSourcesFromZip(resolvedSource, cleanupDirectories) : await resolveImportSources(resolvedSource, options.table, cleanupDirectories);
235
+ return await Promise.all(sources.map(async (source) => ({
236
+ table: source.table,
237
+ rows: await readJsonlRows(source.filePath)
238
+ })));
239
+ } finally {
240
+ for (const directory of cleanupDirectories) await rm(directory, {
241
+ recursive: true,
242
+ force: true
243
+ });
244
+ }
245
+ }
246
+ async function findWorkspaceSyncoreProjects(cwd) {
247
+ const packageJsonPath = path.join(cwd, "package.json");
248
+ if (!await fileExists(packageJsonPath)) return [];
249
+ let workspaces = [];
250
+ try {
251
+ workspaces = JSON.parse(await readFile(packageJsonPath, "utf8")).workspaces ?? [];
252
+ } catch {
253
+ return [];
254
+ }
255
+ const directories = /* @__PURE__ */ new Set();
256
+ for (const workspace of workspaces) {
257
+ const prefix = workspace.replace(/\/\*+$/, "");
258
+ const fullPrefix = path.join(cwd, prefix);
259
+ if (!await fileExists(fullPrefix)) continue;
260
+ const entries = await readdir(fullPrefix, { withFileTypes: true });
261
+ for (const entry of entries) if (entry.isDirectory()) directories.add(path.join(fullPrefix, entry.name));
262
+ }
263
+ const matches = [];
264
+ for (const directory of directories) {
265
+ if (!await fileExists(path.join(directory, "syncore.config.ts"))) continue;
266
+ matches.push({
267
+ path: directory,
268
+ relativePath: path.relative(cwd, directory).replaceAll("\\", "/"),
269
+ template: await detectProjectTemplate(directory)
270
+ });
271
+ }
272
+ return matches.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
273
+ }
274
+ async function resolveDocsTarget(cwd) {
275
+ const template = await detectProjectTemplate(cwd);
276
+ const docsFile = template === "react-web" ? path.join("docs", "quickstarts", "react-web.md") : template === "next" ? path.join("docs", "quickstarts", "next-pwa.md") : template === "expo" ? path.join("docs", "quickstarts", "expo.md") : template === "electron" ? path.join("docs", "quickstarts", "electron.md") : template === "node" ? path.join("docs", "quickstarts", "node-script.md") : path.join("README.md");
277
+ return pathToFileURL(path.resolve(import.meta.dirname, "..", "..", "..", docsFile)).href;
278
+ }
279
+ function resolveDashboardUrl() {
280
+ return `http://localhost:${resolvePortFromEnv("SYNCORE_DASHBOARD_PORT", 4310)}`;
281
+ }
282
+ function resolveDevtoolsUrl() {
283
+ return `ws://127.0.0.1:${resolvePortFromEnv("SYNCORE_DEVTOOLS_PORT", 4311)}`;
284
+ }
285
+ async function listConnectedClientTargets(devtoolsUrl = resolveDevtoolsUrl()) {
286
+ const port = Number.parseInt(new URL(devtoolsUrl).port, 10);
287
+ if (!Number.isFinite(port) || !await isLocalPortInUse(port)) return [];
288
+ let hub;
289
+ try {
290
+ hub = await connectToDevtoolsHub(devtoolsUrl);
291
+ } catch {
292
+ return [];
293
+ }
294
+ try {
295
+ return buildClientTargets((await hub.collectSnapshot()).hellos);
296
+ } finally {
297
+ await hub.dispose();
298
+ }
299
+ }
300
+ async function listAvailableTargets(cwd) {
301
+ const [projectTarget, clientTargets] = await Promise.all([resolveProjectTargetDescriptor(cwd), listConnectedClientTargets()]);
302
+ return [...projectTarget ? [projectTarget] : [], ...clientTargets];
303
+ }
304
+ async function connectToProjectHub(devtoolsUrl = resolveDevtoolsUrl()) {
305
+ const port = Number.parseInt(new URL(devtoolsUrl).port, 10);
306
+ if (!Number.isFinite(port) || !await isLocalPortInUse(port)) return null;
307
+ try {
308
+ return await connectToDevtoolsHub(devtoolsUrl);
309
+ } catch {
310
+ return null;
311
+ }
312
+ }
313
+ function isKnownTemplate(value) {
314
+ return VALID_SYNCORE_TEMPLATES.includes(value);
315
+ }
316
+ async function loadRuntimeProjectFunctions(cwd) {
317
+ try {
318
+ return await loadProjectFunctions(cwd);
319
+ } catch (error) {
320
+ if (!await fileExists(path.join(cwd, "syncore", "functions"))) throw error;
321
+ await runCodegen(cwd);
322
+ return await loadProjectFunctions(cwd);
323
+ }
324
+ }
325
+ function quoteIdentifier(value) {
326
+ return `"${value.replaceAll("\"", "\"\"")}"`;
327
+ }
328
+ async function resolveImportSources(sourcePath, explicitTable, cleanupDirectories) {
329
+ const extension = path.extname(sourcePath).toLowerCase();
330
+ if (extension === ".jsonl") {
331
+ if (!explicitTable) throw new Error("`syncorejs import` requires --table when importing a .jsonl file.");
332
+ return [{
333
+ table: explicitTable,
334
+ filePath: sourcePath
335
+ }];
336
+ }
337
+ if (extension === ".json") {
338
+ if (!explicitTable) throw new Error("`syncorejs import` requires --table when importing a .json file.");
339
+ const rows = JSON.parse(await readFile(sourcePath, "utf8"));
340
+ if (!Array.isArray(rows)) throw new Error(`${sourcePath} must contain a JSON array.`);
341
+ const { directory, filePath } = await writeRowsToTempJsonl(rows);
342
+ cleanupDirectories.push(directory);
343
+ return [{
344
+ table: explicitTable,
345
+ filePath
346
+ }];
347
+ }
348
+ if (await isDirectory(sourcePath)) {
349
+ const entries = await readdir(sourcePath, { withFileTypes: true });
350
+ const sources = [];
351
+ for (const entry of entries) {
352
+ const fullPath = path.join(sourcePath, entry.name);
353
+ if (entry.isFile() && entry.name.endsWith(".jsonl")) sources.push({
354
+ table: entry.name.replace(/\.jsonl$/i, ""),
355
+ filePath: fullPath
356
+ });
357
+ if (entry.isDirectory()) {
358
+ const nestedPath = path.join(fullPath, "documents.jsonl");
359
+ if (await fileExists(nestedPath)) sources.push({
360
+ table: entry.name,
361
+ filePath: nestedPath
362
+ });
363
+ }
364
+ }
365
+ if (sources.length === 0) throw new Error(`No importable JSONL files were found in ${sourcePath}.`);
366
+ return sources.sort((left, right) => left.table.localeCompare(right.table));
367
+ }
368
+ throw new Error(`Unsupported import source: ${sourcePath}`);
369
+ }
370
+ async function extractImportSourcesFromZip(sourcePath, cleanupDirectories) {
371
+ const tempDirectory = await mkdtemp(path.join(os.tmpdir(), "syncore-cli-import-"));
372
+ cleanupDirectories.push(tempDirectory);
373
+ new AdmZip(sourcePath).extractAllTo(tempDirectory, true);
374
+ return await resolveImportSources(tempDirectory, void 0, cleanupDirectories);
375
+ }
376
+ async function writeRowsToTempJsonl(rows) {
377
+ const tempDirectory = await mkdtemp(path.join(os.tmpdir(), "syncore-cli-json-"));
378
+ const tempFile = path.join(tempDirectory, "rows.jsonl");
379
+ await writeFile(tempFile, `${rows.map((row) => JSON.stringify(row)).join("\n")}\n`);
380
+ return {
381
+ directory: tempDirectory,
382
+ filePath: tempFile
383
+ };
384
+ }
385
+ async function readJsonlRows(filePath) {
386
+ const source = await readFile(filePath, "utf8");
387
+ const rows = [];
388
+ let lineNumber = 0;
389
+ for (const line of source.split(/\r?\n/)) {
390
+ const trimmed = line.trim();
391
+ if (!trimmed) continue;
392
+ lineNumber += 1;
393
+ const parsed = JSON.parse(trimmed);
394
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`Line ${lineNumber} of ${filePath} must contain a JSON object.`);
395
+ rows.push(parsed);
396
+ }
397
+ return rows;
398
+ }
399
+ async function isDirectory(filePath) {
400
+ try {
401
+ const entries = await readdir(filePath);
402
+ return Array.isArray(entries);
403
+ } catch {
404
+ return false;
405
+ }
406
+ }
407
+ async function connectToDevtoolsHub(url) {
408
+ const socket = new WebSocket(url);
409
+ socket.on("error", () => {});
410
+ const hellos = /* @__PURE__ */ new Map();
411
+ const events = [];
412
+ const eventListeners = /* @__PURE__ */ new Set();
413
+ const commandResolvers = /* @__PURE__ */ new Map();
414
+ const subscriptionHandlers = /* @__PURE__ */ new Map();
415
+ await new Promise((resolve, reject) => {
416
+ socket.once("open", () => resolve());
417
+ socket.once("error", (error) => reject(error));
418
+ });
419
+ socket.on("message", (rawPayload) => {
420
+ const payload = typeof rawPayload === "string" ? rawPayload : rawPayload instanceof Buffer ? rawPayload.toString("utf8") : Array.isArray(rawPayload) ? Buffer.concat(rawPayload).toString("utf8") : rawPayload instanceof ArrayBuffer ? Buffer.from(rawPayload).toString("utf8") : Buffer.from(rawPayload.buffer, rawPayload.byteOffset, rawPayload.byteLength).toString("utf8");
421
+ if (payload.length === 0) return;
422
+ const message = JSON.parse(payload);
423
+ if (message.type === "hello") {
424
+ hellos.set(message.runtimeId, message);
425
+ return;
426
+ }
427
+ if (message.type === "event") {
428
+ events.unshift(message.event);
429
+ events.splice(200);
430
+ if (message.event.type === "runtime.disconnected") hellos.delete(message.event.runtimeId);
431
+ for (const listener of eventListeners) listener(message.event);
432
+ return;
433
+ }
434
+ if (message.type === "command.result") {
435
+ const resolver = commandResolvers.get(message.commandId);
436
+ if (!resolver) return;
437
+ commandResolvers.delete(message.commandId);
438
+ resolver.resolve(message.payload);
439
+ return;
440
+ }
441
+ if (message.type === "subscription.data") {
442
+ subscriptionHandlers.get(message.subscriptionId)?.onData(message.payload);
443
+ return;
444
+ }
445
+ if (message.type === "subscription.error") subscriptionHandlers.get(message.subscriptionId)?.onError?.(message.error);
446
+ });
447
+ const dispose = async () => {
448
+ for (const [commandId, resolver] of commandResolvers) {
449
+ commandResolvers.delete(commandId);
450
+ resolver.reject(/* @__PURE__ */ new Error("Syncore devtools hub disconnected."));
451
+ }
452
+ subscriptionHandlers.clear();
453
+ if (socket.readyState === WebSocket.CLOSED) return;
454
+ await new Promise((resolve) => {
455
+ socket.once("close", () => resolve());
456
+ socket.close();
457
+ });
458
+ };
459
+ return {
460
+ async collectSnapshot(timeoutMs = 120) {
461
+ await new Promise((resolve) => setTimeout(resolve, timeoutMs));
462
+ return {
463
+ hellos: [...hellos.values()],
464
+ events: [...events]
465
+ };
466
+ },
467
+ listRuntimeHellos() {
468
+ return [...hellos.values()];
469
+ },
470
+ onEvent(listener) {
471
+ eventListeners.add(listener);
472
+ return () => {
473
+ eventListeners.delete(listener);
474
+ };
475
+ },
476
+ async sendCommand(runtimeId, payload) {
477
+ const commandId = createHubRequestId("command");
478
+ return await new Promise((resolve, reject) => {
479
+ commandResolvers.set(commandId, {
480
+ resolve,
481
+ reject
482
+ });
483
+ socket.send(JSON.stringify({
484
+ type: "command",
485
+ commandId,
486
+ targetRuntimeId: runtimeId,
487
+ payload
488
+ }));
489
+ });
490
+ },
491
+ subscribe(runtimeId, payload, handlers) {
492
+ const subscriptionId = createHubRequestId("subscription");
493
+ subscriptionHandlers.set(subscriptionId, handlers);
494
+ socket.send(JSON.stringify({
495
+ type: "subscribe",
496
+ subscriptionId,
497
+ targetRuntimeId: runtimeId,
498
+ payload
499
+ }));
500
+ return () => {
501
+ if (!subscriptionHandlers.has(subscriptionId)) return;
502
+ subscriptionHandlers.delete(subscriptionId);
503
+ socket.send(JSON.stringify({
504
+ type: "unsubscribe",
505
+ subscriptionId,
506
+ targetRuntimeId: runtimeId
507
+ }));
508
+ };
509
+ },
510
+ dispose
511
+ };
512
+ }
513
+ function buildClientTargets(hellos) {
514
+ const groups = /* @__PURE__ */ new Map();
515
+ for (const hello of hellos) {
516
+ if (hello.runtimeId === "syncore-dev-hub") continue;
517
+ const key = hello.storageIdentity ?? `runtime::${hello.runtimeId}`;
518
+ const group = groups.get(key) ?? {
519
+ key,
520
+ runtimes: []
521
+ };
522
+ group.runtimes.push(hello);
523
+ groups.set(key, group);
524
+ }
525
+ const allRuntimeIds = hellos.filter((hello) => hello.runtimeId !== "syncore-dev-hub").map((hello) => hello.runtimeId).sort();
526
+ return [...groups.values()].map(({ key, runtimes }) => {
527
+ const sortedRuntimes = [...runtimes].sort((left, right) => left.runtimeId.localeCompare(right.runtimeId));
528
+ const primary = sortedRuntimes[0];
529
+ const sessionLabels = Array.from(new Set(sortedRuntimes.map((entry) => entry.sessionLabel).filter((value) => typeof value === "string")));
530
+ const runtimeIds = sortedRuntimes.map((entry) => entry.runtimeId);
531
+ const runtimeDescriptors = sortedRuntimes.map((entry, index) => ({
532
+ id: createPublicRuntimeId$1(entry.runtimeId, allRuntimeIds),
533
+ runtimeId: entry.runtimeId,
534
+ label: getClientRuntimeLabel({
535
+ ...entry.sessionLabel ? { sessionLabel: entry.sessionLabel } : {},
536
+ ...entry.appName ? { appName: entry.appName } : {},
537
+ platform: entry.platform
538
+ }),
539
+ platform: entry.platform,
540
+ ...entry.appName ? { appName: entry.appName } : {},
541
+ ...entry.origin ? { origin: entry.origin } : {},
542
+ ...entry.sessionLabel ? { sessionLabel: entry.sessionLabel } : {},
543
+ ...entry.storageIdentity ? { storageIdentity: entry.storageIdentity } : {},
544
+ online: true,
545
+ primary: index === 0
546
+ }));
547
+ return {
548
+ id: createPublicClientTargetId(key, groups),
549
+ kind: "client",
550
+ label: renderClientTargetLabel(primary, runtimes.length),
551
+ runtimeId: primary.runtimeId,
552
+ runtimeIds,
553
+ runtimes: runtimeDescriptors,
554
+ platform: primary.platform,
555
+ ...primary.appName ? { appName: primary.appName } : {},
556
+ ...primary.origin ? { origin: primary.origin } : {},
557
+ sessionLabels,
558
+ ...primary.storageProtocol ? { storageProtocol: primary.storageProtocol } : {},
559
+ ...primary.databaseLabel ? { databaseLabel: primary.databaseLabel } : {},
560
+ ...primary.storageIdentity ? { storageIdentity: primary.storageIdentity } : {},
561
+ connectedSessions: runtimes.length,
562
+ online: true,
563
+ capabilities: [...CLIENT_TARGET_CAPABILITIES]
564
+ };
565
+ }).sort((left, right) => left.label.localeCompare(right.label));
566
+ }
567
+ function createPublicClientTargetId(key, groupsOrKeys) {
568
+ return createPublicTargetId(key, groupsOrKeys instanceof Map ? [...groupsOrKeys.keys()] : [...groupsOrKeys]);
569
+ }
570
+ function targetSupportsCapability(target, capability) {
571
+ return target.capabilities.includes(capability);
572
+ }
573
+ function renderClientTargetLabel(hello, connectedSessions) {
574
+ const base = hello.appName ?? hello.databaseLabel ?? hello.origin ?? `${hello.platform} client`;
575
+ return connectedSessions > 1 ? `${base} (${connectedSessions} sessions)` : base;
576
+ }
577
+ function createHubRequestId(prefix) {
578
+ return `syncore-cli-${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
579
+ }
580
+ //#endregion
581
+ export { buildRuntimeLookup, connectToProjectHub, createManagedProjectClient, createPublicRuntimeId$1 as createPublicRuntimeId, exportProjectData, findWorkspaceSyncoreProjects, importProjectData, isKnownTemplate, listAvailableTargets, listConnectedClientTargets, listProjectTables, loadImportDocumentBatches, readProjectTable, resolveDashboardUrl, resolveDevtoolsUrl, resolveDocsTarget, resolveProjectFunction, resolveProjectTargetDescriptor, targetSupportsCapability, writeExportData };
582
+
583
+ //# sourceMappingURL=project.mjs.map