@korajs/cli 1.0.0-beta.1 → 1.0.0-beta.11
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/bin.cjs +597 -291
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +123 -36
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-EOWLAAIV.js → chunk-4IKCHRJ6.js} +273 -57
- package/dist/chunk-4IKCHRJ6.js.map +1 -0
- package/dist/{chunk-B5YS4STN.js → chunk-G2PBYMMA.js} +2 -2
- package/dist/{chunk-B5YS4STN.js.map → chunk-G2PBYMMA.js.map} +1 -1
- package/dist/{chunk-BWTKRKNJ.js → chunk-Z7GCXMGW.js} +9 -5
- package/dist/chunk-Z7GCXMGW.js.map +1 -0
- package/dist/create.cjs +8 -4
- package/dist/create.cjs.map +1 -1
- package/dist/create.js +2 -2
- package/dist/index.cjs +389 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +12 -2
- package/dist/{spectator-manager-E2LH2P54.js → spectator-manager-FTH2NFSE.js} +5 -2
- package/dist/spectator-manager-FTH2NFSE.js.map +1 -0
- package/package.json +10 -8
- package/templates/react-basic/README.md.hbs +1 -1
- package/templates/react-basic/src/main.tsx +1 -1
- package/templates/react-basic/src/vite-env.d.ts +1 -0
- package/templates/react-basic/vite.config.ts +7 -4
- package/templates/react-sync/README.md.hbs +6 -5
- package/templates/react-sync/server.ts +46 -3
- package/templates/react-sync/src/main.tsx +1 -1
- package/templates/react-sync/src/vite-env.d.ts +1 -0
- package/templates/react-sync/vite.config.ts +14 -4
- package/templates/react-tailwind/README.md.hbs +1 -1
- package/templates/react-tailwind/src/main.tsx +1 -1
- package/templates/react-tailwind/src/vite-env.d.ts +1 -0
- package/templates/react-tailwind/vite.config.ts +7 -4
- package/templates/react-tailwind-sync/README.md.hbs +6 -5
- package/templates/react-tailwind-sync/server.ts +46 -3
- package/templates/react-tailwind-sync/src/main.tsx +1 -1
- package/templates/react-tailwind-sync/src/vite-env.d.ts +1 -0
- package/templates/react-tailwind-sync/vite.config.ts +14 -4
- package/templates/svelte-basic/README.md.hbs +1 -1
- package/templates/svelte-basic/src/main.ts +1 -1
- package/templates/svelte-basic/vite.config.ts +4 -2
- package/templates/svelte-sync/README.md.hbs +6 -5
- package/templates/svelte-sync/server.ts +46 -3
- package/templates/svelte-sync/src/main.ts +1 -1
- package/templates/svelte-sync/src/vite-env.d.ts +1 -0
- package/templates/svelte-sync/vite.config.ts +11 -2
- package/templates/svelte-tailwind/README.md.hbs +1 -1
- package/templates/svelte-tailwind/src/main.ts +1 -1
- package/templates/svelte-tailwind/vite.config.ts +4 -2
- package/templates/svelte-tailwind-sync/README.md.hbs +6 -5
- package/templates/svelte-tailwind-sync/server.ts +46 -3
- package/templates/svelte-tailwind-sync/src/main.ts +1 -1
- package/templates/svelte-tailwind-sync/src/vite-env.d.ts +1 -0
- package/templates/svelte-tailwind-sync/vite.config.ts +11 -2
- package/templates/tauri-react/server.ts +44 -1
- package/templates/tauri-react/src/AppShell.tsx +1 -1
- package/templates/tauri-react/src/vite-env.d.ts +1 -0
- package/templates/vue-basic/README.md.hbs +1 -1
- package/templates/vue-basic/src/main.ts +1 -1
- package/templates/vue-basic/vite.config.ts +4 -2
- package/templates/vue-sync/README.md.hbs +6 -5
- package/templates/vue-sync/server.ts +46 -3
- package/templates/vue-sync/src/main.ts +1 -1
- package/templates/vue-sync/src/vite-env.d.ts +1 -0
- package/templates/vue-sync/vite.config.ts +11 -2
- package/templates/vue-tailwind/README.md.hbs +1 -1
- package/templates/vue-tailwind/src/main.ts +1 -1
- package/templates/vue-tailwind/vite.config.ts +4 -2
- package/templates/vue-tailwind-sync/README.md.hbs +6 -5
- package/templates/vue-tailwind-sync/server.ts +46 -3
- package/templates/vue-tailwind-sync/src/main.ts +1 -1
- package/templates/vue-tailwind-sync/src/vite-env.d.ts +1 -0
- package/templates/vue-tailwind-sync/vite.config.ts +11 -2
- package/dist/chunk-BWTKRKNJ.js.map +0 -1
- package/dist/chunk-EOWLAAIV.js.map +0 -1
- package/dist/spectator-manager-E2LH2P54.js.map +0 -1
package/dist/bin.cjs
CHANGED
|
@@ -32,25 +32,25 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
32
32
|
// src/utils/fs-helpers.ts
|
|
33
33
|
async function directoryExists(path) {
|
|
34
34
|
try {
|
|
35
|
-
await (0,
|
|
35
|
+
await (0, import_promises.access)(path);
|
|
36
36
|
return true;
|
|
37
37
|
} catch {
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
async function findProjectRoot(startDir) {
|
|
42
|
-
let current = (0,
|
|
42
|
+
let current = (0, import_node_path.resolve)(startDir ?? process.cwd());
|
|
43
43
|
for (; ; ) {
|
|
44
|
-
const pkgPath = (0,
|
|
44
|
+
const pkgPath = (0, import_node_path.join)(current, "package.json");
|
|
45
45
|
try {
|
|
46
|
-
const content = await (0,
|
|
46
|
+
const content = await (0, import_promises.readFile)(pkgPath, "utf-8");
|
|
47
47
|
const pkg = JSON.parse(content);
|
|
48
48
|
if (isKoraProject(pkg)) {
|
|
49
49
|
return current;
|
|
50
50
|
}
|
|
51
51
|
} catch {
|
|
52
52
|
}
|
|
53
|
-
const parent = (0,
|
|
53
|
+
const parent = (0, import_node_path.dirname)(current);
|
|
54
54
|
if (parent === current) break;
|
|
55
55
|
current = parent;
|
|
56
56
|
}
|
|
@@ -58,14 +58,14 @@ async function findProjectRoot(startDir) {
|
|
|
58
58
|
}
|
|
59
59
|
async function findSchemaFile(projectRoot) {
|
|
60
60
|
const candidates = [
|
|
61
|
-
(0,
|
|
62
|
-
(0,
|
|
63
|
-
(0,
|
|
64
|
-
(0,
|
|
61
|
+
(0, import_node_path.join)(projectRoot, "src", "schema.ts"),
|
|
62
|
+
(0, import_node_path.join)(projectRoot, "schema.ts"),
|
|
63
|
+
(0, import_node_path.join)(projectRoot, "src", "schema.js"),
|
|
64
|
+
(0, import_node_path.join)(projectRoot, "schema.js")
|
|
65
65
|
];
|
|
66
66
|
for (const candidate of candidates) {
|
|
67
67
|
try {
|
|
68
|
-
await (0,
|
|
68
|
+
await (0, import_promises.access)(candidate);
|
|
69
69
|
return candidate;
|
|
70
70
|
} catch {
|
|
71
71
|
}
|
|
@@ -74,16 +74,16 @@ async function findSchemaFile(projectRoot) {
|
|
|
74
74
|
}
|
|
75
75
|
async function hasTsxInstalled(projectRoot) {
|
|
76
76
|
try {
|
|
77
|
-
await (0,
|
|
77
|
+
await (0, import_promises.access)((0, import_node_path.join)(projectRoot, "node_modules", "tsx", "package.json"));
|
|
78
78
|
return true;
|
|
79
79
|
} catch {
|
|
80
80
|
return false;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
async function resolveProjectBinaryEntryPoint(projectRoot, packageName, binaryName) {
|
|
84
|
-
const pkgJsonPath = (0,
|
|
84
|
+
const pkgJsonPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, "package.json");
|
|
85
85
|
try {
|
|
86
|
-
const content = await (0,
|
|
86
|
+
const content = await (0, import_promises.readFile)(pkgJsonPath, "utf-8");
|
|
87
87
|
const pkg = JSON.parse(content);
|
|
88
88
|
let binPath;
|
|
89
89
|
if (typeof pkg.bin === "string") {
|
|
@@ -92,8 +92,8 @@ async function resolveProjectBinaryEntryPoint(projectRoot, packageName, binaryNa
|
|
|
92
92
|
binPath = pkg.bin[binaryName];
|
|
93
93
|
}
|
|
94
94
|
if (!binPath) return null;
|
|
95
|
-
const fullPath = (0,
|
|
96
|
-
await (0,
|
|
95
|
+
const fullPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, binPath);
|
|
96
|
+
await (0, import_promises.access)(fullPath);
|
|
97
97
|
return fullPath;
|
|
98
98
|
} catch {
|
|
99
99
|
return null;
|
|
@@ -108,12 +108,12 @@ function hasKoraDep(deps) {
|
|
|
108
108
|
if (typeof deps !== "object" || deps === null) return false;
|
|
109
109
|
return Object.keys(deps).some((key) => key === "kora" || key.startsWith("@korajs/"));
|
|
110
110
|
}
|
|
111
|
-
var
|
|
111
|
+
var import_promises, import_node_path;
|
|
112
112
|
var init_fs_helpers = __esm({
|
|
113
113
|
"src/utils/fs-helpers.ts"() {
|
|
114
114
|
"use strict";
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
import_promises = require("fs/promises");
|
|
116
|
+
import_node_path = require("path");
|
|
117
117
|
}
|
|
118
118
|
});
|
|
119
119
|
|
|
@@ -123,7 +123,7 @@ __export(schema_loader_exports, {
|
|
|
123
123
|
loadSchemaDefinition: () => loadSchemaDefinition
|
|
124
124
|
});
|
|
125
125
|
async function loadSchemaDefinition(schemaPath, projectRoot) {
|
|
126
|
-
const ext = (0,
|
|
126
|
+
const ext = (0, import_node_path5.extname)(schemaPath);
|
|
127
127
|
const moduleValue = ext === ".ts" || ext === ".mts" || ext === ".cts" ? await loadTypeScriptModule(schemaPath, projectRoot) : await import(`${(0, import_node_url2.pathToFileURL)(schemaPath).href}?t=${Date.now()}-${Math.random()}`);
|
|
128
128
|
return extractSchema(moduleValue);
|
|
129
129
|
}
|
|
@@ -190,12 +190,12 @@ async function runCommand2(command, args, cwd) {
|
|
|
190
190
|
});
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
|
-
var import_node_child_process2,
|
|
193
|
+
var import_node_child_process2, import_node_path5, import_node_url2;
|
|
194
194
|
var init_schema_loader = __esm({
|
|
195
195
|
"src/commands/migrate/schema-loader.ts"() {
|
|
196
196
|
"use strict";
|
|
197
197
|
import_node_child_process2 = require("child_process");
|
|
198
|
-
|
|
198
|
+
import_node_path5 = require("path");
|
|
199
199
|
import_node_url2 = require("url");
|
|
200
200
|
init_fs_helpers();
|
|
201
201
|
}
|
|
@@ -1981,13 +1981,13 @@ var spectator_manager_exports = {};
|
|
|
1981
1981
|
__export(spectator_manager_exports, {
|
|
1982
1982
|
SpectatorManager: () => SpectatorManager
|
|
1983
1983
|
});
|
|
1984
|
-
var
|
|
1984
|
+
var import_node_fs7, import_node_os, import_node_path28, FORWARDED_EVENTS, MAX_EVENT_BUFFER, SpectatorManager;
|
|
1985
1985
|
var init_spectator_manager = __esm({
|
|
1986
1986
|
"src/commands/studio/spectator-manager.ts"() {
|
|
1987
1987
|
"use strict";
|
|
1988
|
-
|
|
1988
|
+
import_node_fs7 = require("fs");
|
|
1989
1989
|
import_node_os = require("os");
|
|
1990
|
-
|
|
1990
|
+
import_node_path28 = require("path");
|
|
1991
1991
|
FORWARDED_EVENTS = [
|
|
1992
1992
|
"merge:started",
|
|
1993
1993
|
"merge:conflict",
|
|
@@ -2001,8 +2001,8 @@ var init_spectator_manager = __esm({
|
|
|
2001
2001
|
SpectatorManager = class {
|
|
2002
2002
|
constructor(options) {
|
|
2003
2003
|
this.options = options;
|
|
2004
|
-
this.tmpDir = (0,
|
|
2005
|
-
this.dbPath = (0,
|
|
2004
|
+
this.tmpDir = (0, import_node_fs7.mkdtempSync)((0, import_node_path28.join)((0, import_node_os.tmpdir)(), "kora-studio-spectator-"));
|
|
2005
|
+
this.dbPath = (0, import_node_path28.join)(this.tmpDir, "spectator-replica.db");
|
|
2006
2006
|
}
|
|
2007
2007
|
options;
|
|
2008
2008
|
runtime = null;
|
|
@@ -2023,6 +2023,7 @@ var init_spectator_manager = __esm({
|
|
|
2023
2023
|
MergeEngine: (await import("@korajs/merge")).MergeEngine,
|
|
2024
2024
|
SyncEngine: (await import("@korajs/sync")).SyncEngine,
|
|
2025
2025
|
WebSocketTransport: (await import("@korajs/sync")).WebSocketTransport,
|
|
2026
|
+
WebSocket: (await import("ws")).default,
|
|
2026
2027
|
testing: await import("korajs/testing"),
|
|
2027
2028
|
SimpleEventEmitter: (await import("@korajs/core/internal")).SimpleEventEmitter
|
|
2028
2029
|
};
|
|
@@ -2041,7 +2042,9 @@ var init_spectator_manager = __esm({
|
|
|
2041
2042
|
const unsubscribeAudit = mods.testing.wireAuditPersistence(store, emitter);
|
|
2042
2043
|
const syncStore = new mods.testing.MergeAwareSyncStore(store, mergeEngine, emitter);
|
|
2043
2044
|
const engine = new mods.SyncEngine({
|
|
2044
|
-
transport: new mods.WebSocketTransport(
|
|
2045
|
+
transport: new mods.WebSocketTransport({
|
|
2046
|
+
WebSocketImpl: mods.WebSocket
|
|
2047
|
+
}),
|
|
2045
2048
|
store: syncStore,
|
|
2046
2049
|
queueStorage: new mods.testing.StoreQueueStorage(adapter),
|
|
2047
2050
|
syncState: new mods.testing.StoreSyncStatePersistence(store),
|
|
@@ -2099,7 +2102,7 @@ var init_spectator_manager = __esm({
|
|
|
2099
2102
|
this.runtime = null;
|
|
2100
2103
|
}
|
|
2101
2104
|
if (this.tmpDir) {
|
|
2102
|
-
(0,
|
|
2105
|
+
(0, import_node_fs7.rmSync)(this.tmpDir, { recursive: true, force: true });
|
|
2103
2106
|
this.tmpDir = null;
|
|
2104
2107
|
}
|
|
2105
2108
|
}
|
|
@@ -2182,13 +2185,13 @@ function summarizeEvent(type, payload) {
|
|
|
2182
2185
|
return type.replace("lab:", "");
|
|
2183
2186
|
}
|
|
2184
2187
|
}
|
|
2185
|
-
var
|
|
2188
|
+
var import_node_fs8, import_node_os2, import_node_path29, import_core3, DEFAULT_CHAOS, FORWARDED_EVENTS2, MAX_EVENT_BUFFER2, LabManager;
|
|
2186
2189
|
var init_lab_manager = __esm({
|
|
2187
2190
|
"src/commands/studio/lab-manager.ts"() {
|
|
2188
2191
|
"use strict";
|
|
2189
|
-
|
|
2192
|
+
import_node_fs8 = require("fs");
|
|
2190
2193
|
import_node_os2 = require("os");
|
|
2191
|
-
|
|
2194
|
+
import_node_path29 = require("path");
|
|
2192
2195
|
import_core3 = require("@korajs/core");
|
|
2193
2196
|
DEFAULT_CHAOS = {
|
|
2194
2197
|
dropRate: 0,
|
|
@@ -2246,7 +2249,7 @@ var init_lab_manager = __esm({
|
|
|
2246
2249
|
}
|
|
2247
2250
|
async start(initialDevices = 2) {
|
|
2248
2251
|
const harness = await this.loadHarness();
|
|
2249
|
-
this.tmpDir = (0,
|
|
2252
|
+
this.tmpDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path29.join)((0, import_node_os2.tmpdir)(), "kora-studio-lab-"));
|
|
2250
2253
|
this.server = new harness.TestServer(this.schema);
|
|
2251
2254
|
for (let i = 0; i < initialDevices; i++) {
|
|
2252
2255
|
await this.addDevice();
|
|
@@ -2298,7 +2301,7 @@ var init_lab_manager = __esm({
|
|
|
2298
2301
|
nodeId: entry.device.getNodeId(),
|
|
2299
2302
|
connected: entry.device.isConnected(),
|
|
2300
2303
|
chaos: { ...entry.chaos },
|
|
2301
|
-
dbPath: (0,
|
|
2304
|
+
dbPath: (0, import_node_path29.join)(this.tmpDir ?? "", `test-device-${name}.db`),
|
|
2302
2305
|
pendingOperations: entry.device.getSyncEngine()?.getStatus().pendingOperations ?? 0
|
|
2303
2306
|
};
|
|
2304
2307
|
}
|
|
@@ -2377,7 +2380,7 @@ var init_lab_manager = __esm({
|
|
|
2377
2380
|
});
|
|
2378
2381
|
this.server = null;
|
|
2379
2382
|
if (this.tmpDir) {
|
|
2380
|
-
(0,
|
|
2383
|
+
(0, import_node_fs8.rmSync)(this.tmpDir, { recursive: true, force: true });
|
|
2381
2384
|
this.tmpDir = null;
|
|
2382
2385
|
}
|
|
2383
2386
|
}
|
|
@@ -2409,12 +2412,13 @@ var init_lab_manager = __esm({
|
|
|
2409
2412
|
});
|
|
2410
2413
|
|
|
2411
2414
|
// src/bin.ts
|
|
2412
|
-
var
|
|
2415
|
+
var import_citty13 = require("citty");
|
|
2413
2416
|
|
|
2414
|
-
// src/commands/
|
|
2415
|
-
var
|
|
2416
|
-
var
|
|
2417
|
+
// src/commands/agents/agents-command.ts
|
|
2418
|
+
var import_promises2 = require("fs/promises");
|
|
2419
|
+
var import_node_path2 = require("path");
|
|
2417
2420
|
var import_citty = require("citty");
|
|
2421
|
+
init_fs_helpers();
|
|
2418
2422
|
|
|
2419
2423
|
// src/utils/logger.ts
|
|
2420
2424
|
var RESET = "\x1B[0m";
|
|
@@ -2451,22 +2455,233 @@ function createLogger(options) {
|
|
|
2451
2455
|
banner() {
|
|
2452
2456
|
console.log();
|
|
2453
2457
|
console.log(
|
|
2454
|
-
color(BOLD + CYAN, " Kora.js") + color(DIM, "
|
|
2458
|
+
color(BOLD + CYAN, " Kora.js") + color(DIM, ", the offline-first application framework")
|
|
2455
2459
|
);
|
|
2456
2460
|
console.log();
|
|
2457
2461
|
}
|
|
2458
2462
|
};
|
|
2459
2463
|
}
|
|
2460
2464
|
|
|
2465
|
+
// src/commands/agents/agents-md-content.ts
|
|
2466
|
+
var AGENTS_FRAMEWORKS = ["react", "vue", "svelte"];
|
|
2467
|
+
function isAgentsFramework(value) {
|
|
2468
|
+
return AGENTS_FRAMEWORKS.includes(value);
|
|
2469
|
+
}
|
|
2470
|
+
function detectFrameworkFromManifest(manifest) {
|
|
2471
|
+
if (typeof manifest !== "object" || manifest === null) return null;
|
|
2472
|
+
const record = manifest;
|
|
2473
|
+
const deps = collectDependencyNames(record.dependencies, record.devDependencies);
|
|
2474
|
+
if (deps.has("@korajs/react")) return "react";
|
|
2475
|
+
if (deps.has("@korajs/vue")) return "vue";
|
|
2476
|
+
if (deps.has("@korajs/svelte")) return "svelte";
|
|
2477
|
+
return null;
|
|
2478
|
+
}
|
|
2479
|
+
function collectDependencyNames(...groups) {
|
|
2480
|
+
const names = /* @__PURE__ */ new Set();
|
|
2481
|
+
for (const group of groups) {
|
|
2482
|
+
if (typeof group !== "object" || group === null) continue;
|
|
2483
|
+
for (const name of Object.keys(group)) {
|
|
2484
|
+
names.add(name);
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
return names;
|
|
2488
|
+
}
|
|
2489
|
+
var FRAMEWORK_BINDINGS = {
|
|
2490
|
+
react: `## React bindings
|
|
2491
|
+
|
|
2492
|
+
\`\`\`tsx
|
|
2493
|
+
import { KoraProvider, useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/react'
|
|
2494
|
+
|
|
2495
|
+
// Wrap the tree once near your app entry: <KoraProvider app={app}><App /></KoraProvider>
|
|
2496
|
+
|
|
2497
|
+
const todos = useCollection('todos')
|
|
2498
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt'))
|
|
2499
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
2500
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
2501
|
+
await addTodo.mutateAsync({ title: 'x' }) // resolves with the result; throws on failure
|
|
2502
|
+
const status = useSyncStatus() // status.status, status.pendingOperations
|
|
2503
|
+
\`\`\`
|
|
2504
|
+
|
|
2505
|
+
Rules: always render \`mutation.error\` somewhere. Keep \`<StrictMode>\` in place; the hooks are StrictMode-safe. \`useQuery\` returns data synchronously from the local store, so do not add loading spinners for local reads.`,
|
|
2506
|
+
vue: `## Vue bindings
|
|
2507
|
+
|
|
2508
|
+
\`\`\`ts
|
|
2509
|
+
import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/vue'
|
|
2510
|
+
|
|
2511
|
+
const todos = useCollection('todos')
|
|
2512
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // readonly reactive ref
|
|
2513
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
2514
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
2515
|
+
const status = useSyncStatus() // status.status, status.pendingOperations
|
|
2516
|
+
\`\`\`
|
|
2517
|
+
|
|
2518
|
+
Rules: surface the mutation's error state in the UI. \`useQuery\` reads synchronously from the local store, so avoid loading spinners for local data. The Kora context comes from \`KoraProvider\`, wired in your app entry (for example \`src/main.ts\`).`,
|
|
2519
|
+
svelte: `## Svelte bindings
|
|
2520
|
+
|
|
2521
|
+
Kora's Svelte bindings from \`@korajs/svelte\` expose \`useCollection\`, \`useQuery\`, \`useMutation\`, and \`useSyncStatus\`, wired through the provider set up in your app entry.
|
|
2522
|
+
|
|
2523
|
+
\`\`\`ts
|
|
2524
|
+
import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/svelte'
|
|
2525
|
+
|
|
2526
|
+
const todos = useCollection('todos')
|
|
2527
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // reactive store
|
|
2528
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
2529
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
2530
|
+
const status = useSyncStatus() // readable store; read $status.status in markup
|
|
2531
|
+
\`\`\`
|
|
2532
|
+
|
|
2533
|
+
Rules: queries are reactive stores that read synchronously from the local database, so avoid loading spinners for local reads. Mutations expose an \`error\` state that must be surfaced in the UI.`
|
|
2534
|
+
};
|
|
2535
|
+
function generateAgentsMd(framework) {
|
|
2536
|
+
return `# AGENTS.md
|
|
2537
|
+
|
|
2538
|
+
Guidance for AI coding agents working in this project. Humans: this is useful for you too.
|
|
2539
|
+
|
|
2540
|
+
## What this project is
|
|
2541
|
+
|
|
2542
|
+
This project uses **Kora.js**, an offline-first application framework. All application data lives in a local SQLite database (WASM + OPFS in the browser, native SQLite on desktop and server) and optionally syncs across devices through a Kora sync server. Offline is the normal state, not an error state. Full docs live at https://korajs.dev, with a machine-readable index at https://korajs.dev/llms.txt and the complete docs in one file at https://korajs.dev/llms-full.txt. Any documentation page is available as raw markdown by appending \`.md\` to its URL.
|
|
2543
|
+
|
|
2544
|
+
## Golden rules
|
|
2545
|
+
|
|
2546
|
+
1. **The schema is the source of truth.** Collections are defined with \`defineSchema\` and the \`t.*\` field builders (by convention in \`src/schema.ts\`). To add or change data shapes, edit the schema first; types flow from it automatically. Never hand-write types for records.
|
|
2547
|
+
2. **Never fetch application data over HTTP.** Do not add REST or GraphQL calls for app data, and do not talk to the sync server directly. Read and write through Kora collections only; sync happens automatically in the background.
|
|
2548
|
+
3. **Await readiness before direct collection access.** Outside the UI bindings, \`await app.ready\` before calling \`app.<collection>\` methods. The framework bindings handle this for you inside components.
|
|
2549
|
+
4. **Offline must keep working.** Any feature you add must function with the network off. Never gate a read or write on connectivity. If you are checking \`navigator.onLine\` before a data operation, you are doing it wrong.
|
|
2550
|
+
5. **Surface mutation errors.** Fire-and-forget \`mutate\` calls fold errors into the mutation state. Always render the mutation's \`error\`, or handle the promise from the \`mutateAsync\` variant. Silent failure is the worst failure.
|
|
2551
|
+
6. **Do not add a state library for server or app data.** Kora's reactive queries are the store. Do not reach for react-query, SWR, Redux, Zustand, or similar for data that lives in a collection. Local UI state (form inputs, toggles) can use your framework's normal state tools.
|
|
2552
|
+
7. **Do not add loading spinners for local reads.** \`useQuery\` returns data synchronously from the local store, so there is no loading state to wait on for local data.
|
|
2553
|
+
|
|
2554
|
+
## Data API cheat sheet
|
|
2555
|
+
|
|
2556
|
+
\`\`\`ts
|
|
2557
|
+
await app.ready
|
|
2558
|
+
const rec = await app.todos.insert({ title: 'x' }) // defaults and .auto() fields applied
|
|
2559
|
+
await app.todos.update(rec.id, { completed: true }) // partial update, changed fields only
|
|
2560
|
+
await app.todos.delete(rec.id)
|
|
2561
|
+
const one = await app.todos.findById(rec.id)
|
|
2562
|
+
const unsubscribe = app.todos
|
|
2563
|
+
.where({ completed: false })
|
|
2564
|
+
.orderBy('createdAt', 'desc')
|
|
2565
|
+
.subscribe((rows) => {/* fires immediately, then on every change */})
|
|
2566
|
+
\`\`\`
|
|
2567
|
+
|
|
2568
|
+
Schema example (\`src/schema.ts\`):
|
|
2569
|
+
|
|
2570
|
+
\`\`\`ts
|
|
2571
|
+
import { defineSchema, t } from 'korajs'
|
|
2572
|
+
|
|
2573
|
+
export default defineSchema({
|
|
2574
|
+
version: 1,
|
|
2575
|
+
collections: {
|
|
2576
|
+
todos: {
|
|
2577
|
+
fields: {
|
|
2578
|
+
title: t.string(),
|
|
2579
|
+
completed: t.boolean().default(false),
|
|
2580
|
+
tags: t.array(t.string()).default([]),
|
|
2581
|
+
priority: t.enum(['low', 'medium', 'high']).default('medium'),
|
|
2582
|
+
createdAt: t.timestamp().auto(), // set automatically; never pass it on insert
|
|
2583
|
+
},
|
|
2584
|
+
indexes: ['completed', 'createdAt'],
|
|
2585
|
+
},
|
|
2586
|
+
},
|
|
2587
|
+
})
|
|
2588
|
+
\`\`\`
|
|
2589
|
+
|
|
2590
|
+
If you change collection shapes, increment \`version\` and run \`npx kora migrate\`.
|
|
2591
|
+
|
|
2592
|
+
## Conflict handling
|
|
2593
|
+
|
|
2594
|
+
Concurrent edits merge automatically: last-write-wins per field, add-wins for arrays, and character-level CRDT for \`t.richtext()\` fields. When a field needs domain-specific merging (counters, quantities), add a \`resolve\` function in the schema rather than writing sync logic by hand. Never write your own conflict or merge code.
|
|
2595
|
+
|
|
2596
|
+
## Sync and auth
|
|
2597
|
+
|
|
2598
|
+
Enable sync by adding one line to \`createApp\`: \`createApp({ schema, sync: { url } })\`. When the app is offline, writes queue locally and sync when connectivity returns. If the project uses \`@korajs/auth\`, pass its client as \`createApp({ schema, sync: { url, authClient } })\`. Local writes work without sign-in; sync requires the server to accept the connection.
|
|
2599
|
+
|
|
2600
|
+
${FRAMEWORK_BINDINGS[framework]}
|
|
2601
|
+
|
|
2602
|
+
## Commands
|
|
2603
|
+
|
|
2604
|
+
- \`npx kora dev\` runs the dev environment (app server, local sync server when configured, schema watcher).
|
|
2605
|
+
- \`npx kora doctor\` diagnoses a broken setup.
|
|
2606
|
+
- \`npx kora migrate\` applies a schema change to the local store.
|
|
2607
|
+
- In a running app, the DevTools overlay (Ctrl+Shift+K, Cmd+Shift+K on macOS) inspects operations, merges, and sync status.
|
|
2608
|
+
`;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
// src/commands/agents/agents-command.ts
|
|
2612
|
+
async function fileExists(path) {
|
|
2613
|
+
try {
|
|
2614
|
+
await (0, import_promises2.access)(path);
|
|
2615
|
+
return true;
|
|
2616
|
+
} catch {
|
|
2617
|
+
return false;
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
async function readManifest(root) {
|
|
2621
|
+
try {
|
|
2622
|
+
return JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.join)(root, "package.json"), "utf-8"));
|
|
2623
|
+
} catch {
|
|
2624
|
+
return null;
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
function resolveFramework(override, manifest) {
|
|
2628
|
+
if (override !== void 0 && isAgentsFramework(override)) return override;
|
|
2629
|
+
return detectFrameworkFromManifest(manifest) ?? "react";
|
|
2630
|
+
}
|
|
2631
|
+
var agentsCommand = (0, import_citty.defineCommand)({
|
|
2632
|
+
meta: {
|
|
2633
|
+
name: "agents-md",
|
|
2634
|
+
description: "Write an AGENTS.md with Kora rules for AI coding agents into this project"
|
|
2635
|
+
},
|
|
2636
|
+
args: {
|
|
2637
|
+
force: {
|
|
2638
|
+
type: "boolean",
|
|
2639
|
+
description: "Overwrite an existing AGENTS.md",
|
|
2640
|
+
default: false
|
|
2641
|
+
},
|
|
2642
|
+
framework: {
|
|
2643
|
+
type: "string",
|
|
2644
|
+
description: "Override framework detection (react, vue, or svelte)"
|
|
2645
|
+
}
|
|
2646
|
+
},
|
|
2647
|
+
async run({ args }) {
|
|
2648
|
+
const logger = createLogger();
|
|
2649
|
+
const projectRoot = await findProjectRoot() ?? process.cwd();
|
|
2650
|
+
const manifest = await readManifest(projectRoot);
|
|
2651
|
+
const override = typeof args.framework === "string" ? args.framework : void 0;
|
|
2652
|
+
if (override !== void 0 && !isAgentsFramework(override)) {
|
|
2653
|
+
logger.error(`Unknown framework "${override}". Use one of: react, vue, svelte.`);
|
|
2654
|
+
process.exitCode = 1;
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
const framework = resolveFramework(override, manifest);
|
|
2658
|
+
const target = (0, import_node_path2.join)(projectRoot, "AGENTS.md");
|
|
2659
|
+
const force = args.force === true;
|
|
2660
|
+
if (await fileExists(target) && !force) {
|
|
2661
|
+
logger.warn("AGENTS.md already exists. Re-run with --force to overwrite it.");
|
|
2662
|
+
process.exitCode = 1;
|
|
2663
|
+
return;
|
|
2664
|
+
}
|
|
2665
|
+
await (0, import_promises2.writeFile)(target, generateAgentsMd(framework), "utf-8");
|
|
2666
|
+
logger.banner();
|
|
2667
|
+
logger.success(`Wrote AGENTS.md (${framework} bindings) to ${target}`);
|
|
2668
|
+
logger.step("Commit it so coding agents pick up Kora conventions automatically.");
|
|
2669
|
+
logger.blank();
|
|
2670
|
+
}
|
|
2671
|
+
});
|
|
2672
|
+
|
|
2461
2673
|
// src/commands/backup/backup-command.ts
|
|
2674
|
+
var import_promises3 = require("fs/promises");
|
|
2675
|
+
var import_node_path3 = require("path");
|
|
2676
|
+
var import_citty2 = require("citty");
|
|
2462
2677
|
var DEFAULT_SYNC_PORT = 3001;
|
|
2463
|
-
var backupCommand = (0,
|
|
2678
|
+
var backupCommand = (0, import_citty2.defineCommand)({
|
|
2464
2679
|
meta: {
|
|
2465
2680
|
name: "backup",
|
|
2466
2681
|
description: "Backup and restore Kora sync server data"
|
|
2467
2682
|
},
|
|
2468
2683
|
subCommands: {
|
|
2469
|
-
create: (0,
|
|
2684
|
+
create: (0, import_citty2.defineCommand)({
|
|
2470
2685
|
meta: {
|
|
2471
2686
|
name: "create",
|
|
2472
2687
|
description: "Create a backup of the sync server"
|
|
@@ -2506,7 +2721,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2506
2721
|
);
|
|
2507
2722
|
}
|
|
2508
2723
|
const buffer = await response.arrayBuffer();
|
|
2509
|
-
await (0,
|
|
2724
|
+
await (0, import_promises3.writeFile)(outFile, new Uint8Array(buffer));
|
|
2510
2725
|
const size = (buffer.byteLength / 1024).toFixed(1);
|
|
2511
2726
|
logger.success(`Backup saved to ${outFile} (${size} KB)`);
|
|
2512
2727
|
} catch (error) {
|
|
@@ -2518,7 +2733,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2518
2733
|
}
|
|
2519
2734
|
}
|
|
2520
2735
|
}),
|
|
2521
|
-
restore: (0,
|
|
2736
|
+
restore: (0, import_citty2.defineCommand)({
|
|
2522
2737
|
meta: {
|
|
2523
2738
|
name: "restore",
|
|
2524
2739
|
description: "Restore a backup to the sync server"
|
|
@@ -2553,7 +2768,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2553
2768
|
logger.banner();
|
|
2554
2769
|
logger.info(`Restoring backup from ${filePath} to ${url}...`);
|
|
2555
2770
|
try {
|
|
2556
|
-
const data = await (0,
|
|
2771
|
+
const data = await (0, import_promises3.readFile)(filePath);
|
|
2557
2772
|
const restoreUrl = `${url.replace(/\/$/, "")}/__kora/backup/import?merge=${merge}`;
|
|
2558
2773
|
const response = await fetch(restoreUrl, {
|
|
2559
2774
|
method: "POST",
|
|
@@ -2581,7 +2796,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2581
2796
|
}
|
|
2582
2797
|
}
|
|
2583
2798
|
}),
|
|
2584
|
-
info: (0,
|
|
2799
|
+
info: (0, import_citty2.defineCommand)({
|
|
2585
2800
|
meta: {
|
|
2586
2801
|
name: "info",
|
|
2587
2802
|
description: "Show backup file information"
|
|
@@ -2597,7 +2812,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2597
2812
|
const logger = createLogger();
|
|
2598
2813
|
const filePath = typeof args.file === "string" ? args.file : "";
|
|
2599
2814
|
try {
|
|
2600
|
-
const data = await (0,
|
|
2815
|
+
const data = await (0, import_promises3.readFile)(filePath);
|
|
2601
2816
|
const { readBackupManifest } = await import("@korajs/store");
|
|
2602
2817
|
const manifest = readBackupManifest(
|
|
2603
2818
|
new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
@@ -2624,8 +2839,8 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2624
2839
|
});
|
|
2625
2840
|
|
|
2626
2841
|
// src/commands/compact/compact-command.ts
|
|
2627
|
-
var
|
|
2628
|
-
var
|
|
2842
|
+
var import_node_path6 = require("path");
|
|
2843
|
+
var import_citty3 = require("citty");
|
|
2629
2844
|
|
|
2630
2845
|
// src/errors.ts
|
|
2631
2846
|
var import_core = require("@korajs/core");
|
|
@@ -2685,8 +2900,8 @@ init_fs_helpers();
|
|
|
2685
2900
|
|
|
2686
2901
|
// src/commands/dev/kora-config.ts
|
|
2687
2902
|
var import_node_child_process = require("child_process");
|
|
2688
|
-
var
|
|
2689
|
-
var
|
|
2903
|
+
var import_promises4 = require("fs/promises");
|
|
2904
|
+
var import_node_path4 = require("path");
|
|
2690
2905
|
var import_node_url = require("url");
|
|
2691
2906
|
init_fs_helpers();
|
|
2692
2907
|
var CONFIG_CANDIDATES = [
|
|
@@ -2700,7 +2915,7 @@ var CONFIG_CANDIDATES = [
|
|
|
2700
2915
|
async function loadKoraConfig(projectRoot) {
|
|
2701
2916
|
const configPath = await findKoraConfigFile(projectRoot);
|
|
2702
2917
|
if (!configPath) return null;
|
|
2703
|
-
const ext = (0,
|
|
2918
|
+
const ext = (0, import_node_path4.extname)(configPath);
|
|
2704
2919
|
if (ext === ".ts" || ext === ".mts" || ext === ".cts") {
|
|
2705
2920
|
const loaded2 = await loadTypeScriptConfig(configPath, projectRoot);
|
|
2706
2921
|
return toConfigObject(loaded2);
|
|
@@ -2710,9 +2925,9 @@ async function loadKoraConfig(projectRoot) {
|
|
|
2710
2925
|
}
|
|
2711
2926
|
async function findKoraConfigFile(projectRoot) {
|
|
2712
2927
|
for (const file of CONFIG_CANDIDATES) {
|
|
2713
|
-
const candidate = (0,
|
|
2928
|
+
const candidate = (0, import_node_path4.join)(projectRoot, file);
|
|
2714
2929
|
try {
|
|
2715
|
-
await (0,
|
|
2930
|
+
await (0, import_promises4.access)(candidate);
|
|
2716
2931
|
return candidate;
|
|
2717
2932
|
} catch {
|
|
2718
2933
|
}
|
|
@@ -2777,7 +2992,7 @@ function toConfigObject(mod) {
|
|
|
2777
2992
|
|
|
2778
2993
|
// src/commands/compact/compact-command.ts
|
|
2779
2994
|
init_schema_loader();
|
|
2780
|
-
var compactCommand = (0,
|
|
2995
|
+
var compactCommand = (0, import_citty3.defineCommand)({
|
|
2781
2996
|
meta: {
|
|
2782
2997
|
name: "compact",
|
|
2783
2998
|
description: "Compact the local Kora operation log after server ack"
|
|
@@ -2808,12 +3023,12 @@ var compactCommand = (0, import_citty2.defineCommand)({
|
|
|
2808
3023
|
if (!projectRoot) {
|
|
2809
3024
|
throw new InvalidProjectError(process.cwd());
|
|
2810
3025
|
}
|
|
2811
|
-
const dbPath = typeof args.db === "string" ? (0,
|
|
3026
|
+
const dbPath = typeof args.db === "string" ? (0, import_node_path6.resolve)(projectRoot, args.db) : void 0;
|
|
2812
3027
|
if (!dbPath) {
|
|
2813
3028
|
throw new Error("Missing --db <path> to the local SQLite database file.");
|
|
2814
3029
|
}
|
|
2815
3030
|
const config = await loadKoraConfig(projectRoot);
|
|
2816
|
-
const schemaPath = typeof args.schema === "string" ? (0,
|
|
3031
|
+
const schemaPath = typeof args.schema === "string" ? (0, import_node_path6.resolve)(projectRoot, args.schema) : typeof config?.schema === "string" ? (0, import_node_path6.resolve)(projectRoot, config.schema) : void 0;
|
|
2817
3032
|
if (!schemaPath) {
|
|
2818
3033
|
throw new Error("Could not resolve schema path. Pass --schema <path>.");
|
|
2819
3034
|
}
|
|
@@ -2850,9 +3065,9 @@ var compactCommand = (0, import_citty2.defineCommand)({
|
|
|
2850
3065
|
// src/commands/create/create-command.ts
|
|
2851
3066
|
var import_node_child_process4 = require("child_process");
|
|
2852
3067
|
var import_node_fs2 = require("fs");
|
|
2853
|
-
var
|
|
3068
|
+
var import_node_path10 = require("path");
|
|
2854
3069
|
var import_node_url4 = require("url");
|
|
2855
|
-
var
|
|
3070
|
+
var import_citty4 = require("citty");
|
|
2856
3071
|
|
|
2857
3072
|
// src/prompts/preferences.ts
|
|
2858
3073
|
var import_conf = __toESM(require("conf"), 1);
|
|
@@ -3099,8 +3314,8 @@ function getRunDevCommand(pm) {
|
|
|
3099
3314
|
}
|
|
3100
3315
|
|
|
3101
3316
|
// src/commands/create/environment-detection.ts
|
|
3102
|
-
var
|
|
3103
|
-
var
|
|
3317
|
+
var import_promises5 = require("fs/promises");
|
|
3318
|
+
var import_node_path7 = require("path");
|
|
3104
3319
|
function detectEditorFromEnvironment(env = process.env) {
|
|
3105
3320
|
const termProgram = String(env.TERM_PROGRAM ?? "").toLowerCase();
|
|
3106
3321
|
const editorValue = `${String(env.EDITOR ?? "")} ${String(env.VISUAL ?? "")}`.toLowerCase();
|
|
@@ -3126,18 +3341,18 @@ async function detectGitContext(startDir) {
|
|
|
3126
3341
|
};
|
|
3127
3342
|
}
|
|
3128
3343
|
async function detectMonorepoContext(startDir) {
|
|
3129
|
-
let current = (0,
|
|
3344
|
+
let current = (0, import_node_path7.resolve)(startDir);
|
|
3130
3345
|
for (; ; ) {
|
|
3131
|
-
if (await
|
|
3346
|
+
if (await fileExists2((0, import_node_path7.join)(current, "pnpm-workspace.yaml"))) {
|
|
3132
3347
|
return { isMonorepo: true, root: current, kind: "pnpm-workspace" };
|
|
3133
3348
|
}
|
|
3134
|
-
if (await
|
|
3349
|
+
if (await fileExists2((0, import_node_path7.join)(current, "turbo.json"))) {
|
|
3135
3350
|
return { isMonorepo: true, root: current, kind: "turborepo" };
|
|
3136
3351
|
}
|
|
3137
|
-
const packageJsonPath = (0,
|
|
3138
|
-
if (await
|
|
3352
|
+
const packageJsonPath = (0, import_node_path7.join)(current, "package.json");
|
|
3353
|
+
if (await fileExists2(packageJsonPath)) {
|
|
3139
3354
|
try {
|
|
3140
|
-
const packageJsonRaw = await (0,
|
|
3355
|
+
const packageJsonRaw = await (0, import_promises5.readFile)(packageJsonPath, "utf-8");
|
|
3141
3356
|
const parsed = JSON.parse(packageJsonRaw);
|
|
3142
3357
|
if (Array.isArray(parsed.workspaces) || isNpmWorkspaceObject(parsed.workspaces)) {
|
|
3143
3358
|
return { isMonorepo: true, root: current, kind: "npm-workspaces" };
|
|
@@ -3145,7 +3360,7 @@ async function detectMonorepoContext(startDir) {
|
|
|
3145
3360
|
} catch {
|
|
3146
3361
|
}
|
|
3147
3362
|
}
|
|
3148
|
-
const parent = (0,
|
|
3363
|
+
const parent = (0, import_node_path7.dirname)(current);
|
|
3149
3364
|
if (parent === current) {
|
|
3150
3365
|
return { isMonorepo: false, root: null, kind: "none" };
|
|
3151
3366
|
}
|
|
@@ -3157,9 +3372,9 @@ async function applyEditorWorkspacePreset(params) {
|
|
|
3157
3372
|
if (editor !== "vscode" && editor !== "cursor" && editor !== "windsurf") {
|
|
3158
3373
|
return { applied: false, filePath: null };
|
|
3159
3374
|
}
|
|
3160
|
-
const vscodeDir = (0,
|
|
3161
|
-
const extensionsPath = (0,
|
|
3162
|
-
await (0,
|
|
3375
|
+
const vscodeDir = (0, import_node_path7.join)(targetDir, ".vscode");
|
|
3376
|
+
const extensionsPath = (0, import_node_path7.join)(vscodeDir, "extensions.json");
|
|
3377
|
+
await (0, import_promises5.mkdir)(vscodeDir, { recursive: true });
|
|
3163
3378
|
const recommendations = ["korajs.kora-devtools"];
|
|
3164
3379
|
const existing = await readJsonObject(extensionsPath);
|
|
3165
3380
|
const existingRecommendations = Array.isArray(existing?.recommendations) ? existing.recommendations.filter((item) => typeof item === "string") : [];
|
|
@@ -3167,19 +3382,19 @@ async function applyEditorWorkspacePreset(params) {
|
|
|
3167
3382
|
const next = {
|
|
3168
3383
|
recommendations: mergedRecommendations
|
|
3169
3384
|
};
|
|
3170
|
-
await (0,
|
|
3385
|
+
await (0, import_promises5.writeFile)(extensionsPath, `${JSON.stringify(next, null, 2)}
|
|
3171
3386
|
`, "utf-8");
|
|
3172
3387
|
return { applied: true, filePath: extensionsPath };
|
|
3173
3388
|
}
|
|
3174
3389
|
function resolveMonorepoTargetDirectory(monorepoRoot, projectName) {
|
|
3175
|
-
return (0,
|
|
3390
|
+
return (0, import_node_path7.join)(monorepoRoot, "packages", projectName);
|
|
3176
3391
|
}
|
|
3177
3392
|
function dedupeStrings(values) {
|
|
3178
3393
|
return Array.from(new Set(values));
|
|
3179
3394
|
}
|
|
3180
3395
|
async function readJsonObject(path) {
|
|
3181
3396
|
try {
|
|
3182
|
-
const content = await (0,
|
|
3397
|
+
const content = await (0, import_promises5.readFile)(path, "utf-8");
|
|
3183
3398
|
const parsed = JSON.parse(content);
|
|
3184
3399
|
if (typeof parsed === "object" && parsed !== null) {
|
|
3185
3400
|
return parsed;
|
|
@@ -3194,24 +3409,24 @@ function isNpmWorkspaceObject(value) {
|
|
|
3194
3409
|
const record = value;
|
|
3195
3410
|
return Array.isArray(record.packages);
|
|
3196
3411
|
}
|
|
3197
|
-
async function
|
|
3412
|
+
async function fileExists2(path) {
|
|
3198
3413
|
try {
|
|
3199
|
-
await (0,
|
|
3414
|
+
await (0, import_promises5.access)(path);
|
|
3200
3415
|
return true;
|
|
3201
3416
|
} catch {
|
|
3202
3417
|
return false;
|
|
3203
3418
|
}
|
|
3204
3419
|
}
|
|
3205
3420
|
async function findNearestAncestorWithEntry(startDir, entryName) {
|
|
3206
|
-
let current = (0,
|
|
3421
|
+
let current = (0, import_node_path7.resolve)(startDir);
|
|
3207
3422
|
for (; ; ) {
|
|
3208
|
-
const candidate = (0,
|
|
3423
|
+
const candidate = (0, import_node_path7.join)(current, entryName);
|
|
3209
3424
|
try {
|
|
3210
|
-
await (0,
|
|
3425
|
+
await (0, import_promises5.stat)(candidate);
|
|
3211
3426
|
return current;
|
|
3212
3427
|
} catch {
|
|
3213
3428
|
}
|
|
3214
|
-
const parent = (0,
|
|
3429
|
+
const parent = (0, import_node_path7.dirname)(current);
|
|
3215
3430
|
if (parent === current) {
|
|
3216
3431
|
return null;
|
|
3217
3432
|
}
|
|
@@ -3490,8 +3705,8 @@ function validateProjectName(name) {
|
|
|
3490
3705
|
}
|
|
3491
3706
|
|
|
3492
3707
|
// src/commands/create/sync-provider-preset.ts
|
|
3493
|
-
var
|
|
3494
|
-
var
|
|
3708
|
+
var import_promises6 = require("fs/promises");
|
|
3709
|
+
var import_node_path8 = require("path");
|
|
3495
3710
|
async function applySyncProviderPreset(options) {
|
|
3496
3711
|
if (!isSyncTemplate(options.template)) {
|
|
3497
3712
|
return;
|
|
@@ -3501,10 +3716,10 @@ async function applySyncProviderPreset(options) {
|
|
|
3501
3716
|
}
|
|
3502
3717
|
const providerName = getProviderDisplayName(options.dbProvider);
|
|
3503
3718
|
const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
|
|
3504
|
-
const envPath = (0,
|
|
3505
|
-
const readmePath = (0,
|
|
3506
|
-
const existingReadme = await (0,
|
|
3507
|
-
const existingEnv = await (0,
|
|
3719
|
+
const envPath = (0, import_node_path8.join)(options.targetDir, ".env.example");
|
|
3720
|
+
const readmePath = (0, import_node_path8.join)(options.targetDir, "README.md");
|
|
3721
|
+
const existingReadme = await (0, import_promises6.readFile)(readmePath, "utf-8");
|
|
3722
|
+
const existingEnv = await (0, import_promises6.readFile)(envPath, "utf-8");
|
|
3508
3723
|
const trimmedReadme = existingReadme.trimEnd();
|
|
3509
3724
|
const trimmedEnv = existingEnv.trimEnd();
|
|
3510
3725
|
const envSuffix = [
|
|
@@ -3524,9 +3739,9 @@ async function applySyncProviderPreset(options) {
|
|
|
3524
3739
|
""
|
|
3525
3740
|
].join("\n");
|
|
3526
3741
|
const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
|
|
3527
|
-
await (0,
|
|
3742
|
+
await (0, import_promises6.writeFile)(envPath, `${trimmedEnv}${envSuffix}
|
|
3528
3743
|
`, "utf-8");
|
|
3529
|
-
await (0,
|
|
3744
|
+
await (0, import_promises6.writeFile)(readmePath, readmeTemplate, "utf-8");
|
|
3530
3745
|
}
|
|
3531
3746
|
function isSyncTemplate(template) {
|
|
3532
3747
|
return template === "react-sync" || template === "react-tailwind-sync" || template === "vue-sync" || template === "vue-tailwind-sync" || template === "svelte-sync" || template === "svelte-tailwind-sync" || template === "tauri-react";
|
|
@@ -3570,8 +3785,8 @@ function getProviderConnectionStringExample(provider) {
|
|
|
3570
3785
|
|
|
3571
3786
|
// src/templates/composer.ts
|
|
3572
3787
|
var import_node_fs = require("fs");
|
|
3573
|
-
var
|
|
3574
|
-
var
|
|
3788
|
+
var import_promises7 = require("fs/promises");
|
|
3789
|
+
var import_node_path9 = require("path");
|
|
3575
3790
|
var import_node_url3 = require("url");
|
|
3576
3791
|
var import_meta = {};
|
|
3577
3792
|
function substituteVariables(template, context) {
|
|
@@ -3581,16 +3796,16 @@ function substituteVariables(template, context) {
|
|
|
3581
3796
|
});
|
|
3582
3797
|
}
|
|
3583
3798
|
function getTemplatePath(templateName) {
|
|
3584
|
-
let dir = (0,
|
|
3799
|
+
let dir = (0, import_node_path9.dirname)((0, import_node_url3.fileURLToPath)(import_meta.url));
|
|
3585
3800
|
for (let i = 0; i < 7; i++) {
|
|
3586
|
-
const candidate = (0,
|
|
3801
|
+
const candidate = (0, import_node_path9.resolve)(dir, "templates", templateName);
|
|
3587
3802
|
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
3588
3803
|
return candidate;
|
|
3589
3804
|
}
|
|
3590
|
-
dir = (0,
|
|
3805
|
+
dir = (0, import_node_path9.dirname)(dir);
|
|
3591
3806
|
}
|
|
3592
|
-
const currentDir = (0,
|
|
3593
|
-
return (0,
|
|
3807
|
+
const currentDir = (0, import_node_path9.dirname)((0, import_node_url3.fileURLToPath)(import_meta.url));
|
|
3808
|
+
return (0, import_node_path9.resolve)(currentDir, "..", "..", "..", "templates", templateName);
|
|
3594
3809
|
}
|
|
3595
3810
|
function createCompatibilityLayerPlan(templateName) {
|
|
3596
3811
|
const baseLayer = { category: "base", name: "base", sourceTemplate: "react-basic" };
|
|
@@ -3723,22 +3938,22 @@ async function composeTemplateLayers(plan, targetDir, context) {
|
|
|
3723
3938
|
}
|
|
3724
3939
|
}
|
|
3725
3940
|
async function copyDirectory(src, dest, vars) {
|
|
3726
|
-
await (0,
|
|
3727
|
-
const entries = await (0,
|
|
3941
|
+
await (0, import_promises7.mkdir)(dest, { recursive: true });
|
|
3942
|
+
const entries = await (0, import_promises7.readdir)(src);
|
|
3728
3943
|
for (const entry of entries) {
|
|
3729
|
-
const srcPath = (0,
|
|
3730
|
-
const srcStat = await (0,
|
|
3944
|
+
const srcPath = (0, import_node_path9.join)(src, entry);
|
|
3945
|
+
const srcStat = await (0, import_promises7.stat)(srcPath);
|
|
3731
3946
|
if (srcStat.isDirectory()) {
|
|
3732
|
-
await copyDirectory(srcPath, (0,
|
|
3947
|
+
await copyDirectory(srcPath, (0, import_node_path9.join)(dest, entry), vars);
|
|
3733
3948
|
continue;
|
|
3734
3949
|
}
|
|
3735
3950
|
if (entry.endsWith(".hbs")) {
|
|
3736
|
-
const content = await (0,
|
|
3951
|
+
const content = await (0, import_promises7.readFile)(srcPath, "utf-8");
|
|
3737
3952
|
const outputName = entry.slice(0, -4);
|
|
3738
|
-
await (0,
|
|
3953
|
+
await (0, import_promises7.writeFile)((0, import_node_path9.join)(dest, outputName), substituteVariables(content, vars), "utf-8");
|
|
3739
3954
|
continue;
|
|
3740
3955
|
}
|
|
3741
|
-
await (0,
|
|
3956
|
+
await (0, import_promises7.copyFile)(srcPath, (0, import_node_path9.join)(dest, entry));
|
|
3742
3957
|
}
|
|
3743
3958
|
}
|
|
3744
3959
|
|
|
@@ -3750,7 +3965,7 @@ async function scaffoldTemplate(templateName, targetDir, context) {
|
|
|
3750
3965
|
|
|
3751
3966
|
// src/commands/create/create-command.ts
|
|
3752
3967
|
var import_meta2 = {};
|
|
3753
|
-
var createCommand = (0,
|
|
3968
|
+
var createCommand = (0, import_citty4.defineCommand)({
|
|
3754
3969
|
meta: {
|
|
3755
3970
|
name: "create",
|
|
3756
3971
|
description: "Create a new Kora application"
|
|
@@ -3891,7 +4106,7 @@ var createCommand = (0, import_citty3.defineCommand)({
|
|
|
3891
4106
|
const editorDetection = detectEditorFromEnvironment();
|
|
3892
4107
|
const gitContext = await detectGitContext(process.cwd());
|
|
3893
4108
|
const monorepoContext = await detectMonorepoContext(process.cwd());
|
|
3894
|
-
let targetDir = (0,
|
|
4109
|
+
let targetDir = (0, import_node_path10.resolve)(process.cwd(), projectName);
|
|
3895
4110
|
if (!useDefaults && monorepoContext.isMonorepo && monorepoContext.root !== null) {
|
|
3896
4111
|
const useWorkspaceTarget = await prompts.confirm(
|
|
3897
4112
|
`Detected ${formatMonorepoKind(monorepoContext.kind)} at ${monorepoContext.root}. Create app under packages/${projectName}?`,
|
|
@@ -4061,29 +4276,33 @@ function relativeToTarget(targetDir, filePath) {
|
|
|
4061
4276
|
}
|
|
4062
4277
|
function resolveKoraVersion() {
|
|
4063
4278
|
try {
|
|
4064
|
-
let dir = (0,
|
|
4279
|
+
let dir = (0, import_node_path10.dirname)((0, import_node_url4.fileURLToPath)(import_meta2.url));
|
|
4065
4280
|
for (let i = 0; i < 5; i++) {
|
|
4066
|
-
const pkgPath = (0,
|
|
4281
|
+
const pkgPath = (0, import_node_path10.resolve)(dir, "package.json");
|
|
4067
4282
|
if ((0, import_node_fs2.existsSync)(pkgPath)) {
|
|
4068
4283
|
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
|
|
4069
4284
|
if (pkg.name === "@korajs/cli") {
|
|
4070
|
-
|
|
4071
|
-
const parts = pkg.version.split(".");
|
|
4072
|
-
return `^${parts[0]}.${parts[1]}.0`;
|
|
4285
|
+
return deriveKoraTemplateVersion(pkg.version);
|
|
4073
4286
|
}
|
|
4074
4287
|
}
|
|
4075
|
-
dir = (0,
|
|
4288
|
+
dir = (0, import_node_path10.dirname)(dir);
|
|
4076
4289
|
}
|
|
4077
4290
|
return "latest";
|
|
4078
4291
|
} catch {
|
|
4079
4292
|
return "latest";
|
|
4080
4293
|
}
|
|
4081
4294
|
}
|
|
4295
|
+
function deriveKoraTemplateVersion(version) {
|
|
4296
|
+
if (version === "0.0.0") return "latest";
|
|
4297
|
+
if (version.includes("-")) return version;
|
|
4298
|
+
const parts = version.split(".");
|
|
4299
|
+
return `^${parts[0]}.${parts[1]}.0`;
|
|
4300
|
+
}
|
|
4082
4301
|
|
|
4083
4302
|
// src/commands/deploy/deploy-command.ts
|
|
4084
4303
|
var import_node_fs4 = require("fs");
|
|
4085
|
-
var
|
|
4086
|
-
var
|
|
4304
|
+
var import_node_path21 = require("path");
|
|
4305
|
+
var import_citty5 = require("citty");
|
|
4087
4306
|
init_fs_helpers();
|
|
4088
4307
|
|
|
4089
4308
|
// src/commands/deploy/adapters/adapter.ts
|
|
@@ -4102,13 +4321,13 @@ function isDeployPlatform(value) {
|
|
|
4102
4321
|
|
|
4103
4322
|
// src/commands/deploy/adapters/aws-ecs-adapter.ts
|
|
4104
4323
|
var import_node_child_process6 = require("child_process");
|
|
4105
|
-
var
|
|
4324
|
+
var import_node_path13 = require("path");
|
|
4106
4325
|
|
|
4107
4326
|
// src/commands/deploy/builder/client-builder.ts
|
|
4108
4327
|
var import_node_child_process5 = require("child_process");
|
|
4109
4328
|
var import_node_fs3 = require("fs");
|
|
4110
|
-
var
|
|
4111
|
-
var
|
|
4329
|
+
var import_promises8 = require("fs/promises");
|
|
4330
|
+
var import_node_path11 = require("path");
|
|
4112
4331
|
init_fs_helpers();
|
|
4113
4332
|
async function buildClient(options) {
|
|
4114
4333
|
const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
|
|
@@ -4130,15 +4349,15 @@ async function buildClient(options) {
|
|
|
4130
4349
|
return { outDir: options.outDir };
|
|
4131
4350
|
}
|
|
4132
4351
|
async function patchSqliteWasmAssets(projectRoot, outDir) {
|
|
4133
|
-
const assetsDir = (0,
|
|
4352
|
+
const assetsDir = (0, import_node_path11.join)(outDir, "assets");
|
|
4134
4353
|
if (!(0, import_node_fs3.existsSync)(assetsDir)) return;
|
|
4135
|
-
const files = await (0,
|
|
4354
|
+
const files = await (0, import_promises8.readdir)(assetsDir);
|
|
4136
4355
|
const hashedWasm = files.find((f) => /^sqlite3-.+\.wasm$/.test(f));
|
|
4137
4356
|
if (hashedWasm && !files.includes("sqlite3.wasm")) {
|
|
4138
|
-
await (0,
|
|
4357
|
+
await (0, import_promises8.copyFile)((0, import_node_path11.join)(assetsDir, hashedWasm), (0, import_node_path11.join)(assetsDir, "sqlite3.wasm"));
|
|
4139
4358
|
}
|
|
4140
4359
|
if (!files.includes("sqlite3-opfs-async-proxy.js")) {
|
|
4141
|
-
const proxyFile = (0,
|
|
4360
|
+
const proxyFile = (0, import_node_path11.resolve)(
|
|
4142
4361
|
projectRoot,
|
|
4143
4362
|
"node_modules",
|
|
4144
4363
|
"@sqlite.org",
|
|
@@ -4148,7 +4367,7 @@ async function patchSqliteWasmAssets(projectRoot, outDir) {
|
|
|
4148
4367
|
"sqlite3-opfs-async-proxy.js"
|
|
4149
4368
|
);
|
|
4150
4369
|
if ((0, import_node_fs3.existsSync)(proxyFile)) {
|
|
4151
|
-
await (0,
|
|
4370
|
+
await (0, import_promises8.copyFile)(proxyFile, (0, import_node_path11.join)(assetsDir, "sqlite3-opfs-async-proxy.js"));
|
|
4152
4371
|
}
|
|
4153
4372
|
}
|
|
4154
4373
|
}
|
|
@@ -4173,9 +4392,9 @@ async function runProcess(command, args, cwd) {
|
|
|
4173
4392
|
}
|
|
4174
4393
|
|
|
4175
4394
|
// src/commands/deploy/builder/server-bundler.ts
|
|
4176
|
-
var import_promises8 = require("fs/promises");
|
|
4177
4395
|
var import_promises9 = require("fs/promises");
|
|
4178
|
-
var
|
|
4396
|
+
var import_promises10 = require("fs/promises");
|
|
4397
|
+
var import_node_path12 = require("path");
|
|
4179
4398
|
var import_esbuild = require("esbuild");
|
|
4180
4399
|
var DEFAULT_ENTRY_CANDIDATES = [
|
|
4181
4400
|
"server.ts",
|
|
@@ -4191,8 +4410,8 @@ async function bundleServer(options) {
|
|
|
4191
4410
|
`Could not find a server entry file in ${options.projectRoot}. Looked for: ${candidates.join(", ")}`
|
|
4192
4411
|
);
|
|
4193
4412
|
}
|
|
4194
|
-
await (0,
|
|
4195
|
-
const outputFilePath = (0,
|
|
4413
|
+
await (0, import_promises9.mkdir)(options.deployDirectory, { recursive: true });
|
|
4414
|
+
const outputFilePath = (0, import_node_path12.join)(options.deployDirectory, "server-bundled.js");
|
|
4196
4415
|
await (0, import_esbuild.build)({
|
|
4197
4416
|
entryPoints: [entryFilePath],
|
|
4198
4417
|
outfile: outputFilePath,
|
|
@@ -4214,9 +4433,9 @@ async function bundleServer(options) {
|
|
|
4214
4433
|
}
|
|
4215
4434
|
async function resolveServerEntry(projectRoot, candidates) {
|
|
4216
4435
|
for (const candidate of candidates) {
|
|
4217
|
-
const fullPath = (0,
|
|
4436
|
+
const fullPath = (0, import_node_path12.join)(projectRoot, candidate);
|
|
4218
4437
|
try {
|
|
4219
|
-
await (0,
|
|
4438
|
+
await (0, import_promises10.access)(fullPath);
|
|
4220
4439
|
return fullPath;
|
|
4221
4440
|
} catch {
|
|
4222
4441
|
}
|
|
@@ -4318,19 +4537,19 @@ var AwsEcsAdapter = class {
|
|
|
4318
4537
|
appName: config.appName,
|
|
4319
4538
|
region: config.region
|
|
4320
4539
|
};
|
|
4321
|
-
const deployDirectory = (0,
|
|
4540
|
+
const deployDirectory = (0, import_node_path13.join)(config.projectRoot, ".kora", "deploy");
|
|
4322
4541
|
await bundleServer({
|
|
4323
4542
|
projectRoot: config.projectRoot,
|
|
4324
4543
|
deployDirectory
|
|
4325
4544
|
});
|
|
4326
4545
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
4327
4546
|
projectRoot: config.projectRoot,
|
|
4328
|
-
outDir: (0,
|
|
4547
|
+
outDir: (0, import_node_path13.join)(deployDirectory, "dist"),
|
|
4329
4548
|
mode: "production"
|
|
4330
4549
|
});
|
|
4331
4550
|
return {
|
|
4332
4551
|
clientDirectory: client?.outDir ?? null,
|
|
4333
|
-
serverBundlePath: (0,
|
|
4552
|
+
serverBundlePath: (0, import_node_path13.join)(deployDirectory, "server-bundled.js"),
|
|
4334
4553
|
deployDirectory
|
|
4335
4554
|
};
|
|
4336
4555
|
}
|
|
@@ -4596,7 +4815,7 @@ function inferLogLevel(line) {
|
|
|
4596
4815
|
|
|
4597
4816
|
// src/commands/deploy/adapters/aws-lightsail-adapter.ts
|
|
4598
4817
|
var import_node_child_process7 = require("child_process");
|
|
4599
|
-
var
|
|
4818
|
+
var import_node_path14 = require("path");
|
|
4600
4819
|
var AwsLightsailAdapter = class {
|
|
4601
4820
|
name = "aws-lightsail";
|
|
4602
4821
|
logger = createLogger();
|
|
@@ -4669,19 +4888,19 @@ var AwsLightsailAdapter = class {
|
|
|
4669
4888
|
appName: config.appName,
|
|
4670
4889
|
region: config.region
|
|
4671
4890
|
};
|
|
4672
|
-
const deployDirectory = (0,
|
|
4891
|
+
const deployDirectory = (0, import_node_path14.join)(config.projectRoot, ".kora", "deploy");
|
|
4673
4892
|
await bundleServer({
|
|
4674
4893
|
projectRoot: config.projectRoot,
|
|
4675
4894
|
deployDirectory
|
|
4676
4895
|
});
|
|
4677
4896
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
4678
4897
|
projectRoot: config.projectRoot,
|
|
4679
|
-
outDir: (0,
|
|
4898
|
+
outDir: (0, import_node_path14.join)(deployDirectory, "dist"),
|
|
4680
4899
|
mode: "production"
|
|
4681
4900
|
});
|
|
4682
4901
|
return {
|
|
4683
4902
|
clientDirectory: client?.outDir ?? null,
|
|
4684
|
-
serverBundlePath: (0,
|
|
4903
|
+
serverBundlePath: (0, import_node_path14.join)(deployDirectory, "server-bundled.js"),
|
|
4685
4904
|
deployDirectory
|
|
4686
4905
|
};
|
|
4687
4906
|
}
|
|
@@ -4981,11 +5200,11 @@ function inferLogLevel2(line) {
|
|
|
4981
5200
|
|
|
4982
5201
|
// src/commands/deploy/adapters/fly-adapter.ts
|
|
4983
5202
|
var import_node_child_process8 = require("child_process");
|
|
4984
|
-
var
|
|
5203
|
+
var import_node_path16 = require("path");
|
|
4985
5204
|
|
|
4986
5205
|
// src/commands/deploy/artifacts/fly-toml-generator.ts
|
|
4987
|
-
var
|
|
4988
|
-
var
|
|
5206
|
+
var import_promises11 = require("fs/promises");
|
|
5207
|
+
var import_node_path15 = require("path");
|
|
4989
5208
|
var GENERATED_HEADER = "# Generated by kora deploy \u2014 do not edit manually";
|
|
4990
5209
|
function generateFlyToml(options) {
|
|
4991
5210
|
const internalPort = options.internalPort ?? 3e3;
|
|
@@ -5015,9 +5234,9 @@ function generateFlyToml(options) {
|
|
|
5015
5234
|
].join("\n");
|
|
5016
5235
|
}
|
|
5017
5236
|
async function writeFlyTomlArtifact(deployDirectory, options) {
|
|
5018
|
-
await (0,
|
|
5019
|
-
const filePath = (0,
|
|
5020
|
-
await (0,
|
|
5237
|
+
await (0, import_promises11.mkdir)(deployDirectory, { recursive: true });
|
|
5238
|
+
const filePath = (0, import_node_path15.join)(deployDirectory, "fly.toml");
|
|
5239
|
+
await (0, import_promises11.writeFile)(filePath, generateFlyToml(options), "utf-8");
|
|
5021
5240
|
return filePath;
|
|
5022
5241
|
}
|
|
5023
5242
|
|
|
@@ -5111,7 +5330,7 @@ var FlyAdapter = class {
|
|
|
5111
5330
|
appName: config.appName,
|
|
5112
5331
|
region: config.region
|
|
5113
5332
|
};
|
|
5114
|
-
const deployDirectory = (0,
|
|
5333
|
+
const deployDirectory = (0, import_node_path16.join)(config.projectRoot, ".kora", "deploy");
|
|
5115
5334
|
await writeFlyTomlArtifact(deployDirectory, {
|
|
5116
5335
|
appName: config.appName,
|
|
5117
5336
|
region: config.region ?? "iad"
|
|
@@ -5122,12 +5341,12 @@ var FlyAdapter = class {
|
|
|
5122
5341
|
});
|
|
5123
5342
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
5124
5343
|
projectRoot: config.projectRoot,
|
|
5125
|
-
outDir: (0,
|
|
5344
|
+
outDir: (0, import_node_path16.join)(deployDirectory, "dist"),
|
|
5126
5345
|
mode: "production"
|
|
5127
5346
|
});
|
|
5128
5347
|
return {
|
|
5129
5348
|
clientDirectory: client?.outDir ?? null,
|
|
5130
|
-
serverBundlePath: (0,
|
|
5349
|
+
serverBundlePath: (0, import_node_path16.join)(deployDirectory, "server-bundled.js"),
|
|
5131
5350
|
deployDirectory
|
|
5132
5351
|
};
|
|
5133
5352
|
}
|
|
@@ -5349,11 +5568,11 @@ ${stdout}`.toLowerCase();
|
|
|
5349
5568
|
|
|
5350
5569
|
// src/commands/deploy/adapters/railway-adapter.ts
|
|
5351
5570
|
var import_node_child_process9 = require("child_process");
|
|
5352
|
-
var
|
|
5571
|
+
var import_node_path18 = require("path");
|
|
5353
5572
|
|
|
5354
5573
|
// src/commands/deploy/artifacts/railway-json-generator.ts
|
|
5355
|
-
var
|
|
5356
|
-
var
|
|
5574
|
+
var import_promises12 = require("fs/promises");
|
|
5575
|
+
var import_node_path17 = require("path");
|
|
5357
5576
|
var GENERATED_HEADER2 = "Generated by kora deploy - do not edit manually.";
|
|
5358
5577
|
function generateRailwayJson(options) {
|
|
5359
5578
|
const file = {
|
|
@@ -5378,9 +5597,9 @@ function generateRailwayJson(options) {
|
|
|
5378
5597
|
`;
|
|
5379
5598
|
}
|
|
5380
5599
|
async function writeRailwayJsonArtifact(deployDirectory, options) {
|
|
5381
|
-
await (0,
|
|
5382
|
-
const filePath = (0,
|
|
5383
|
-
await (0,
|
|
5600
|
+
await (0, import_promises12.mkdir)(deployDirectory, { recursive: true });
|
|
5601
|
+
const filePath = (0, import_node_path17.join)(deployDirectory, "railway.json");
|
|
5602
|
+
await (0, import_promises12.writeFile)(filePath, generateRailwayJson(options), "utf-8");
|
|
5384
5603
|
return filePath;
|
|
5385
5604
|
}
|
|
5386
5605
|
|
|
@@ -5469,7 +5688,7 @@ var RailwayAdapter = class {
|
|
|
5469
5688
|
appName: config.appName,
|
|
5470
5689
|
region: config.region
|
|
5471
5690
|
};
|
|
5472
|
-
const deployDirectory = (0,
|
|
5691
|
+
const deployDirectory = (0, import_node_path18.join)(config.projectRoot, ".kora", "deploy");
|
|
5473
5692
|
await writeRailwayJsonArtifact(deployDirectory, {
|
|
5474
5693
|
appName: config.appName,
|
|
5475
5694
|
environment: config.environment
|
|
@@ -5480,12 +5699,12 @@ var RailwayAdapter = class {
|
|
|
5480
5699
|
});
|
|
5481
5700
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
5482
5701
|
projectRoot: config.projectRoot,
|
|
5483
|
-
outDir: (0,
|
|
5702
|
+
outDir: (0, import_node_path18.join)(deployDirectory, "dist"),
|
|
5484
5703
|
mode: "production"
|
|
5485
5704
|
});
|
|
5486
5705
|
return {
|
|
5487
5706
|
clientDirectory: client?.outDir ?? null,
|
|
5488
|
-
serverBundlePath: (0,
|
|
5707
|
+
serverBundlePath: (0, import_node_path18.join)(deployDirectory, "server-bundled.js"),
|
|
5489
5708
|
deployDirectory
|
|
5490
5709
|
};
|
|
5491
5710
|
}
|
|
@@ -5770,8 +5989,8 @@ function createDeployAdapter(platform) {
|
|
|
5770
5989
|
}
|
|
5771
5990
|
|
|
5772
5991
|
// src/commands/deploy/artifacts/dockerfile-generator.ts
|
|
5773
|
-
var
|
|
5774
|
-
var
|
|
5992
|
+
var import_promises13 = require("fs/promises");
|
|
5993
|
+
var import_node_path19 = require("path");
|
|
5775
5994
|
var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually";
|
|
5776
5995
|
function generateDockerfile(options = {}) {
|
|
5777
5996
|
const nodeVersion = options.nodeVersion ?? "20-alpine";
|
|
@@ -5837,37 +6056,37 @@ function generateDockerIgnore() {
|
|
|
5837
6056
|
].join("\n");
|
|
5838
6057
|
}
|
|
5839
6058
|
async function writeDockerfileArtifact(deployDirectory, options = {}) {
|
|
5840
|
-
await (0,
|
|
5841
|
-
const dockerfilePath = (0,
|
|
5842
|
-
await (0,
|
|
6059
|
+
await (0, import_promises13.mkdir)(deployDirectory, { recursive: true });
|
|
6060
|
+
const dockerfilePath = (0, import_node_path19.join)(deployDirectory, "Dockerfile");
|
|
6061
|
+
await (0, import_promises13.writeFile)(dockerfilePath, generateDockerfile(options), "utf-8");
|
|
5843
6062
|
if (options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0) {
|
|
5844
|
-
const pkgJsonPath = (0,
|
|
5845
|
-
await (0,
|
|
6063
|
+
const pkgJsonPath = (0, import_node_path19.join)(deployDirectory, "package.json");
|
|
6064
|
+
await (0, import_promises13.writeFile)(pkgJsonPath, generateDeployPackageJson(options.nativeDependencies), "utf-8");
|
|
5846
6065
|
}
|
|
5847
6066
|
return dockerfilePath;
|
|
5848
6067
|
}
|
|
5849
6068
|
async function writeDockerIgnoreArtifact(deployDirectory) {
|
|
5850
|
-
await (0,
|
|
5851
|
-
const dockerIgnorePath = (0,
|
|
5852
|
-
await (0,
|
|
6069
|
+
await (0, import_promises13.mkdir)(deployDirectory, { recursive: true });
|
|
6070
|
+
const dockerIgnorePath = (0, import_node_path19.join)(deployDirectory, ".dockerignore");
|
|
6071
|
+
await (0, import_promises13.writeFile)(dockerIgnorePath, generateDockerIgnore(), "utf-8");
|
|
5853
6072
|
return dockerIgnorePath;
|
|
5854
6073
|
}
|
|
5855
6074
|
|
|
5856
6075
|
// src/commands/deploy/state/deploy-state.ts
|
|
5857
|
-
var
|
|
5858
|
-
var
|
|
5859
|
-
var KORA_DEPLOY_DIRECTORY = (0,
|
|
6076
|
+
var import_promises14 = require("fs/promises");
|
|
6077
|
+
var import_node_path20 = require("path");
|
|
6078
|
+
var KORA_DEPLOY_DIRECTORY = (0, import_node_path20.join)(".kora", "deploy");
|
|
5860
6079
|
var DEPLOY_STATE_FILENAME = "deploy.json";
|
|
5861
6080
|
function resolveDeployDirectory(projectRoot) {
|
|
5862
|
-
return (0,
|
|
6081
|
+
return (0, import_node_path20.join)(projectRoot, KORA_DEPLOY_DIRECTORY);
|
|
5863
6082
|
}
|
|
5864
6083
|
function resolveDeployStatePath(projectRoot) {
|
|
5865
|
-
return (0,
|
|
6084
|
+
return (0, import_node_path20.join)(resolveDeployDirectory(projectRoot), DEPLOY_STATE_FILENAME);
|
|
5866
6085
|
}
|
|
5867
6086
|
async function readDeployState(projectRoot) {
|
|
5868
6087
|
const statePath = resolveDeployStatePath(projectRoot);
|
|
5869
6088
|
try {
|
|
5870
|
-
const source = await (0,
|
|
6089
|
+
const source = await (0, import_promises14.readFile)(statePath, "utf-8");
|
|
5871
6090
|
const parsed = JSON.parse(source);
|
|
5872
6091
|
return parseDeployState(parsed);
|
|
5873
6092
|
} catch (error) {
|
|
@@ -5914,13 +6133,13 @@ async function updateDeployState(projectRoot, patch, now = /* @__PURE__ */ new D
|
|
|
5914
6133
|
return nextState;
|
|
5915
6134
|
}
|
|
5916
6135
|
async function resetDeployState(projectRoot) {
|
|
5917
|
-
await (0,
|
|
6136
|
+
await (0, import_promises14.rm)(resolveDeployDirectory(projectRoot), { recursive: true, force: true });
|
|
5918
6137
|
}
|
|
5919
6138
|
async function persistDeployState(projectRoot, state) {
|
|
5920
6139
|
const deployDir = resolveDeployDirectory(projectRoot);
|
|
5921
6140
|
const statePath = resolveDeployStatePath(projectRoot);
|
|
5922
|
-
await (0,
|
|
5923
|
-
await (0,
|
|
6141
|
+
await (0, import_promises14.mkdir)(deployDir, { recursive: true });
|
|
6142
|
+
await (0, import_promises14.writeFile)(statePath, `${JSON.stringify(state, null, 2)}
|
|
5924
6143
|
`, "utf-8");
|
|
5925
6144
|
}
|
|
5926
6145
|
function parseDeployState(value) {
|
|
@@ -5970,7 +6189,7 @@ function readOptionalString(value, field) {
|
|
|
5970
6189
|
}
|
|
5971
6190
|
|
|
5972
6191
|
// src/commands/deploy/deploy-command.ts
|
|
5973
|
-
var deployCommand = (0,
|
|
6192
|
+
var deployCommand = (0, import_citty5.defineCommand)({
|
|
5974
6193
|
meta: {
|
|
5975
6194
|
name: "deploy",
|
|
5976
6195
|
description: "Deploy a Kora project to your selected platform"
|
|
@@ -6005,7 +6224,7 @@ var deployCommand = (0, import_citty4.defineCommand)({
|
|
|
6005
6224
|
}
|
|
6006
6225
|
},
|
|
6007
6226
|
subCommands: {
|
|
6008
|
-
status: (0,
|
|
6227
|
+
status: (0, import_citty5.defineCommand)({
|
|
6009
6228
|
meta: {
|
|
6010
6229
|
name: "status",
|
|
6011
6230
|
description: "Show current deployment status"
|
|
@@ -6036,7 +6255,7 @@ var deployCommand = (0, import_citty4.defineCommand)({
|
|
|
6036
6255
|
logger.step(`Sync URL: ${state.syncUrl ?? "n/a"}`);
|
|
6037
6256
|
}
|
|
6038
6257
|
}),
|
|
6039
|
-
rollback: (0,
|
|
6258
|
+
rollback: (0, import_citty5.defineCommand)({
|
|
6040
6259
|
meta: {
|
|
6041
6260
|
name: "rollback",
|
|
6042
6261
|
description: "Rollback the current deployment"
|
|
@@ -6067,7 +6286,7 @@ var deployCommand = (0, import_citty4.defineCommand)({
|
|
|
6067
6286
|
logger.success(`Rolled back ${state.platform} deployment to ${deploymentId}.`);
|
|
6068
6287
|
}
|
|
6069
6288
|
}),
|
|
6070
|
-
logs: (0,
|
|
6289
|
+
logs: (0, import_citty5.defineCommand)({
|
|
6071
6290
|
meta: {
|
|
6072
6291
|
name: "logs",
|
|
6073
6292
|
description: "Read deployment logs"
|
|
@@ -6254,7 +6473,7 @@ function resolveAppName(argValue, storedValue, projectRoot, confirm) {
|
|
|
6254
6473
|
"Missing app name in --confirm mode. Provide --app or run an interactive deploy first."
|
|
6255
6474
|
);
|
|
6256
6475
|
}
|
|
6257
|
-
return sanitizeAppName((0,
|
|
6476
|
+
return sanitizeAppName((0, import_node_path21.basename)(projectRoot));
|
|
6258
6477
|
}
|
|
6259
6478
|
function resolveRegion(argValue, storedValue, confirm) {
|
|
6260
6479
|
if (typeof argValue === "string" && argValue.length > 0) return argValue;
|
|
@@ -6289,17 +6508,18 @@ function configureAdapterContext(adapter, context) {
|
|
|
6289
6508
|
}
|
|
6290
6509
|
}
|
|
6291
6510
|
function detectDeployTarget(projectRoot) {
|
|
6292
|
-
return (0, import_node_fs4.existsSync)((0,
|
|
6511
|
+
return (0, import_node_fs4.existsSync)((0, import_node_path21.join)(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
|
|
6293
6512
|
}
|
|
6294
6513
|
function hasContextSetter(adapter) {
|
|
6295
6514
|
return typeof adapter.setContext === "function";
|
|
6296
6515
|
}
|
|
6297
6516
|
|
|
6298
6517
|
// src/commands/dev/dev-command.ts
|
|
6299
|
-
var
|
|
6300
|
-
var
|
|
6518
|
+
var import_node_fs6 = require("fs");
|
|
6519
|
+
var import_promises15 = require("fs/promises");
|
|
6301
6520
|
var import_node_path23 = require("path");
|
|
6302
|
-
var
|
|
6521
|
+
var import_node_path24 = require("path");
|
|
6522
|
+
var import_citty6 = require("citty");
|
|
6303
6523
|
init_fs_helpers();
|
|
6304
6524
|
|
|
6305
6525
|
// src/commands/dev/process-manager.ts
|
|
@@ -6307,6 +6527,7 @@ var import_node_child_process10 = require("child_process");
|
|
|
6307
6527
|
var ProcessManager = class {
|
|
6308
6528
|
processes = /* @__PURE__ */ new Map();
|
|
6309
6529
|
spawn(config) {
|
|
6530
|
+
this.processes.get(config.label)?.child.kill("SIGTERM");
|
|
6310
6531
|
const options = {
|
|
6311
6532
|
cwd: config.cwd,
|
|
6312
6533
|
env: { ...process.env, ...config.env },
|
|
@@ -6350,6 +6571,20 @@ var ProcessManager = class {
|
|
|
6350
6571
|
hasRunning() {
|
|
6351
6572
|
return this.processes.size > 0;
|
|
6352
6573
|
}
|
|
6574
|
+
async restart(config) {
|
|
6575
|
+
await this.stop(config.label);
|
|
6576
|
+
this.spawn(config);
|
|
6577
|
+
}
|
|
6578
|
+
async stop(label) {
|
|
6579
|
+
const running = this.processes.get(label);
|
|
6580
|
+
if (!running) return;
|
|
6581
|
+
running.child.kill("SIGTERM");
|
|
6582
|
+
await Promise.race([running.exitPromise, delay(5e3)]);
|
|
6583
|
+
const remaining = this.processes.get(label);
|
|
6584
|
+
if (!remaining) return;
|
|
6585
|
+
remaining.child.kill("SIGKILL");
|
|
6586
|
+
await remaining.exitPromise;
|
|
6587
|
+
}
|
|
6353
6588
|
async shutdownAll() {
|
|
6354
6589
|
const running = Array.from(this.processes.values());
|
|
6355
6590
|
if (running.length === 0) return;
|
|
@@ -6392,8 +6627,9 @@ function delay(ms) {
|
|
|
6392
6627
|
// src/commands/dev/schema-watcher.ts
|
|
6393
6628
|
var import_node_child_process11 = require("child_process");
|
|
6394
6629
|
var import_node_fs5 = require("fs");
|
|
6395
|
-
var
|
|
6630
|
+
var import_node_path22 = require("path");
|
|
6396
6631
|
init_fs_helpers();
|
|
6632
|
+
init_schema_loader();
|
|
6397
6633
|
var SchemaWatcher = class {
|
|
6398
6634
|
constructor(config) {
|
|
6399
6635
|
this.config = config;
|
|
@@ -6403,6 +6639,7 @@ var SchemaWatcher = class {
|
|
|
6403
6639
|
debounceMs;
|
|
6404
6640
|
watcher = null;
|
|
6405
6641
|
debounceTimer = null;
|
|
6642
|
+
schemaVersion = null;
|
|
6406
6643
|
start() {
|
|
6407
6644
|
if (this.watcher) return;
|
|
6408
6645
|
this.watcher = (0, import_node_fs5.watch)(this.config.schemaPath, () => {
|
|
@@ -6411,6 +6648,9 @@ var SchemaWatcher = class {
|
|
|
6411
6648
|
this.watcher.on("error", (error) => {
|
|
6412
6649
|
this.config.onError?.(toError(error));
|
|
6413
6650
|
});
|
|
6651
|
+
void this.refreshSchemaVersion().catch((error) => {
|
|
6652
|
+
this.config.onError?.(toError(error));
|
|
6653
|
+
});
|
|
6414
6654
|
}
|
|
6415
6655
|
stop() {
|
|
6416
6656
|
if (this.debounceTimer) {
|
|
@@ -6421,7 +6661,7 @@ var SchemaWatcher = class {
|
|
|
6421
6661
|
this.watcher = null;
|
|
6422
6662
|
}
|
|
6423
6663
|
async regenerate() {
|
|
6424
|
-
const koraBinJs = (0,
|
|
6664
|
+
const koraBinJs = (0, import_node_path22.join)(
|
|
6425
6665
|
this.config.projectRoot,
|
|
6426
6666
|
"node_modules",
|
|
6427
6667
|
"@korajs",
|
|
@@ -6434,6 +6674,15 @@ var SchemaWatcher = class {
|
|
|
6434
6674
|
const args = hasTsx ? ["--import", "tsx", koraBinJs, "generate", "types", "--schema", this.config.schemaPath] : [koraBinJs, "generate", "types", "--schema", this.config.schemaPath];
|
|
6435
6675
|
await spawnCommand(command, args, this.config.projectRoot);
|
|
6436
6676
|
this.config.onRegenerate?.();
|
|
6677
|
+
await this.refreshSchemaVersion();
|
|
6678
|
+
}
|
|
6679
|
+
async refreshSchemaVersion() {
|
|
6680
|
+
const schema = await loadSchemaDefinition(this.config.schemaPath, this.config.projectRoot);
|
|
6681
|
+
const previous = this.schemaVersion;
|
|
6682
|
+
this.schemaVersion = schema.version;
|
|
6683
|
+
if (previous !== null && previous !== schema.version) {
|
|
6684
|
+
this.config.onSchemaVersionChange?.({ previous, next: schema.version });
|
|
6685
|
+
}
|
|
6437
6686
|
}
|
|
6438
6687
|
scheduleRegeneration() {
|
|
6439
6688
|
if (this.debounceTimer) {
|
|
@@ -6487,7 +6736,7 @@ function toError(error) {
|
|
|
6487
6736
|
}
|
|
6488
6737
|
|
|
6489
6738
|
// src/commands/dev/dev-command.ts
|
|
6490
|
-
var devCommand = (0,
|
|
6739
|
+
var devCommand = (0, import_citty6.defineCommand)({
|
|
6491
6740
|
meta: {
|
|
6492
6741
|
name: "dev",
|
|
6493
6742
|
description: "Start the Kora development environment"
|
|
@@ -6518,6 +6767,7 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6518
6767
|
if (!projectRoot) {
|
|
6519
6768
|
throw new InvalidProjectError(process.cwd());
|
|
6520
6769
|
}
|
|
6770
|
+
loadProjectEnv(projectRoot);
|
|
6521
6771
|
const config = await loadKoraConfig(projectRoot);
|
|
6522
6772
|
const vitePort = typeof args.port === "string" ? args.port : String(config?.dev?.port ?? 5173);
|
|
6523
6773
|
const syncPortFromConfig = typeof config?.dev?.sync === "object" && typeof config.dev.sync.port === "number" ? config.dev.sync.port : 3001;
|
|
@@ -6527,7 +6777,7 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6527
6777
|
const watchDebounceMs = typeof config?.dev?.watch === "object" && typeof config.dev.watch.debounceMs === "number" ? config.dev.watch.debounceMs : 300;
|
|
6528
6778
|
const viteEntryPoint = await resolveProjectBinaryEntryPoint(projectRoot, "vite", "vite");
|
|
6529
6779
|
if (!viteEntryPoint) {
|
|
6530
|
-
throw new DevServerError("vite", (0,
|
|
6780
|
+
throw new DevServerError("vite", (0, import_node_path23.join)(projectRoot, "node_modules", ".bin", "vite"));
|
|
6531
6781
|
}
|
|
6532
6782
|
const syncServerFile = await findSyncServerFile(projectRoot);
|
|
6533
6783
|
let managedSyncStore = normalizeManagedSyncStore(config, projectRoot);
|
|
@@ -6542,8 +6792,8 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6542
6792
|
}
|
|
6543
6793
|
}
|
|
6544
6794
|
if (shouldStartSync && syncServerFile === null && managedSyncStore) {
|
|
6545
|
-
const hasServerPackage = await
|
|
6546
|
-
(0,
|
|
6795
|
+
const hasServerPackage = await fileExists3(
|
|
6796
|
+
(0, import_node_path23.join)(projectRoot, "node_modules", "@korajs", "server", "package.json")
|
|
6547
6797
|
);
|
|
6548
6798
|
if (!hasServerPackage) {
|
|
6549
6799
|
logger.warn(
|
|
@@ -6560,8 +6810,8 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6560
6810
|
}
|
|
6561
6811
|
let configuredSchemaPath = null;
|
|
6562
6812
|
if (typeof config?.schema === "string") {
|
|
6563
|
-
const candidate = (0,
|
|
6564
|
-
if (await
|
|
6813
|
+
const candidate = (0, import_node_path24.resolve)(projectRoot, config.schema);
|
|
6814
|
+
if (await fileExists3(candidate)) {
|
|
6565
6815
|
configuredSchemaPath = candidate;
|
|
6566
6816
|
} else {
|
|
6567
6817
|
logger.warn(
|
|
@@ -6619,7 +6869,9 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6619
6869
|
logger.step(" Schema watcher disabled (schema.ts not found)");
|
|
6620
6870
|
}
|
|
6621
6871
|
logger.blank();
|
|
6622
|
-
logger.step(
|
|
6872
|
+
logger.step(
|
|
6873
|
+
" Kora DevTools overlay: Ctrl+Shift+K (Cmd+Shift+K on macOS) when devtools is enabled"
|
|
6874
|
+
);
|
|
6623
6875
|
processManager.spawn({
|
|
6624
6876
|
label: "vite",
|
|
6625
6877
|
command: process.execPath,
|
|
@@ -6630,33 +6882,31 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6630
6882
|
},
|
|
6631
6883
|
onExit: onManagedProcessExit
|
|
6632
6884
|
});
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
onExit: onManagedProcessExit
|
|
6659
|
-
});
|
|
6885
|
+
const syncProcessConfig = shouldStartSync && hasTsx && syncServerFile ? {
|
|
6886
|
+
label: "sync",
|
|
6887
|
+
command: process.execPath,
|
|
6888
|
+
args: ["--import", "tsx", syncServerFile],
|
|
6889
|
+
cwd: projectRoot,
|
|
6890
|
+
env: {
|
|
6891
|
+
PORT: String(syncPort),
|
|
6892
|
+
KORA_SYNC_PORT: String(syncPort)
|
|
6893
|
+
},
|
|
6894
|
+
onExit: onManagedProcessExit
|
|
6895
|
+
} : shouldStartSync && syncServerFile === null && managedSyncStore !== null ? {
|
|
6896
|
+
label: "sync",
|
|
6897
|
+
command: process.execPath,
|
|
6898
|
+
args: ["--input-type=module", "--eval", MANAGED_SYNC_BOOTSTRAP_SCRIPT],
|
|
6899
|
+
cwd: projectRoot,
|
|
6900
|
+
env: {
|
|
6901
|
+
KORA_DEV_SYNC_CONFIG: JSON.stringify({
|
|
6902
|
+
port: Number(syncPort),
|
|
6903
|
+
store: managedSyncStore
|
|
6904
|
+
})
|
|
6905
|
+
},
|
|
6906
|
+
onExit: onManagedProcessExit
|
|
6907
|
+
} : null;
|
|
6908
|
+
if (syncProcessConfig) {
|
|
6909
|
+
processManager.spawn(syncProcessConfig);
|
|
6660
6910
|
}
|
|
6661
6911
|
if (watchEnabled && schemaPath) {
|
|
6662
6912
|
schemaWatcher = new SchemaWatcher({
|
|
@@ -6666,6 +6916,16 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6666
6916
|
onRegenerate: () => {
|
|
6667
6917
|
logger.success("Regenerated types from schema changes");
|
|
6668
6918
|
},
|
|
6919
|
+
onSchemaVersionChange: ({ previous, next }) => {
|
|
6920
|
+
if (!syncProcessConfig) {
|
|
6921
|
+
logger.warn(
|
|
6922
|
+
`Schema version changed from ${previous} to ${next}; restart your sync server before clients can sync.`
|
|
6923
|
+
);
|
|
6924
|
+
return;
|
|
6925
|
+
}
|
|
6926
|
+
logger.warn(`Schema version changed from ${previous} to ${next}; restarting sync server.`);
|
|
6927
|
+
void processManager.restart(syncProcessConfig);
|
|
6928
|
+
},
|
|
6669
6929
|
onError: (error) => {
|
|
6670
6930
|
logger.error(`Schema watcher error: ${error.message}`);
|
|
6671
6931
|
}
|
|
@@ -6678,31 +6938,68 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6678
6938
|
}
|
|
6679
6939
|
});
|
|
6680
6940
|
async function findSyncServerFile(projectRoot) {
|
|
6681
|
-
const candidates = [(0,
|
|
6941
|
+
const candidates = [(0, import_node_path23.join)(projectRoot, "server.ts"), (0, import_node_path23.join)(projectRoot, "server.js")];
|
|
6682
6942
|
for (const candidate of candidates) {
|
|
6683
6943
|
try {
|
|
6684
|
-
await (0,
|
|
6944
|
+
await (0, import_promises15.access)(candidate);
|
|
6685
6945
|
return candidate;
|
|
6686
6946
|
} catch {
|
|
6687
6947
|
}
|
|
6688
6948
|
}
|
|
6689
6949
|
return null;
|
|
6690
6950
|
}
|
|
6691
|
-
async function
|
|
6951
|
+
async function fileExists3(path) {
|
|
6692
6952
|
try {
|
|
6693
|
-
await (0,
|
|
6953
|
+
await (0, import_promises15.access)(path);
|
|
6694
6954
|
return true;
|
|
6695
6955
|
} catch {
|
|
6696
6956
|
return false;
|
|
6697
6957
|
}
|
|
6698
6958
|
}
|
|
6959
|
+
function loadProjectEnv(projectRoot, mode = "development") {
|
|
6960
|
+
const files = [".env", ".env.local", `.env.${mode}`, `.env.${mode}.local`];
|
|
6961
|
+
const existingKeys = new Set(Object.keys(process.env));
|
|
6962
|
+
for (const file of files) {
|
|
6963
|
+
const path = (0, import_node_path23.join)(projectRoot, file);
|
|
6964
|
+
if (!(0, import_node_fs6.existsSync)(path)) continue;
|
|
6965
|
+
const parsed = parseEnvFile((0, import_node_fs6.readFileSync)(path, "utf8"));
|
|
6966
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
6967
|
+
if (!existingKeys.has(key)) {
|
|
6968
|
+
process.env[key] = value;
|
|
6969
|
+
}
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6972
|
+
}
|
|
6973
|
+
function parseEnvFile(contents) {
|
|
6974
|
+
const env = {};
|
|
6975
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
6976
|
+
const line = rawLine.trim();
|
|
6977
|
+
if (!line || line.startsWith("#")) continue;
|
|
6978
|
+
const normalized = line.startsWith("export ") ? line.slice("export ".length).trim() : line;
|
|
6979
|
+
const equalsIndex = normalized.indexOf("=");
|
|
6980
|
+
if (equalsIndex <= 0) continue;
|
|
6981
|
+
const key = normalized.slice(0, equalsIndex).trim();
|
|
6982
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue;
|
|
6983
|
+
env[key] = parseEnvValue(normalized.slice(equalsIndex + 1).trim());
|
|
6984
|
+
}
|
|
6985
|
+
return env;
|
|
6986
|
+
}
|
|
6987
|
+
function parseEnvValue(value) {
|
|
6988
|
+
const quote = value[0];
|
|
6989
|
+
if ((quote === '"' || quote === "'") && value[value.length - 1] === quote) {
|
|
6990
|
+
const inner = value.slice(1, -1);
|
|
6991
|
+
return quote === '"' ? inner.replace(/\\n/g, "\n").replace(/\\r/g, "\r") : inner;
|
|
6992
|
+
}
|
|
6993
|
+
const commentIndex = value.search(/\s#/);
|
|
6994
|
+
return (commentIndex >= 0 ? value.slice(0, commentIndex) : value).trim();
|
|
6995
|
+
}
|
|
6699
6996
|
function normalizeManagedSyncStore(config, projectRoot) {
|
|
6700
6997
|
const sync = config?.dev?.sync;
|
|
6701
6998
|
if (typeof sync !== "object" || sync === null) return null;
|
|
6702
6999
|
const store = sync.store;
|
|
6703
7000
|
if (store === void 0) return { type: "memory" };
|
|
6704
7001
|
if (store === "memory") return { type: "memory" };
|
|
6705
|
-
if (store === "sqlite") return { type: "sqlite", filename: (0,
|
|
7002
|
+
if (store === "sqlite") return { type: "sqlite", filename: (0, import_node_path23.join)(projectRoot, "kora-sync.db") };
|
|
6706
7003
|
if (store === "postgres") {
|
|
6707
7004
|
const connectionString = process.env.DATABASE_URL;
|
|
6708
7005
|
if (!connectionString) return null;
|
|
@@ -6711,7 +7008,7 @@ function normalizeManagedSyncStore(config, projectRoot) {
|
|
|
6711
7008
|
if (typeof store === "object" && store !== null) {
|
|
6712
7009
|
if (store.type === "memory") return { type: "memory" };
|
|
6713
7010
|
if (store.type === "sqlite") {
|
|
6714
|
-
const filename = typeof store.filename === "string" && store.filename.length > 0 ? (0,
|
|
7011
|
+
const filename = typeof store.filename === "string" && store.filename.length > 0 ? (0, import_node_path24.resolve)(projectRoot, store.filename) : (0, import_node_path23.join)(projectRoot, "kora-sync.db");
|
|
6715
7012
|
return { type: "sqlite", filename };
|
|
6716
7013
|
}
|
|
6717
7014
|
if (store.type === "postgres" && typeof store.connectionString === "string") {
|
|
@@ -6775,12 +7072,12 @@ await new Promise(() => {});
|
|
|
6775
7072
|
`;
|
|
6776
7073
|
|
|
6777
7074
|
// src/commands/doctor/doctor-command.ts
|
|
6778
|
-
var
|
|
7075
|
+
var import_citty7 = require("citty");
|
|
6779
7076
|
init_fs_helpers();
|
|
6780
7077
|
|
|
6781
7078
|
// src/commands/doctor/doctor-checks.ts
|
|
6782
|
-
var
|
|
6783
|
-
var
|
|
7079
|
+
var import_promises16 = require("fs/promises");
|
|
7080
|
+
var import_node_path25 = require("path");
|
|
6784
7081
|
init_fs_helpers();
|
|
6785
7082
|
init_schema_loader();
|
|
6786
7083
|
var STATUS_ENDPOINT = "/__kora/status";
|
|
@@ -6860,9 +7157,9 @@ async function runDoctorChecks(options) {
|
|
|
6860
7157
|
}
|
|
6861
7158
|
async function resolveSchemaPath(projectRoot, configSchema) {
|
|
6862
7159
|
if (typeof configSchema === "string") {
|
|
6863
|
-
const resolved = (0,
|
|
7160
|
+
const resolved = (0, import_node_path25.resolve)(projectRoot, configSchema);
|
|
6864
7161
|
try {
|
|
6865
|
-
await (0,
|
|
7162
|
+
await (0, import_promises16.access)(resolved);
|
|
6866
7163
|
return resolved;
|
|
6867
7164
|
} catch {
|
|
6868
7165
|
}
|
|
@@ -6871,12 +7168,12 @@ async function resolveSchemaPath(projectRoot, configSchema) {
|
|
|
6871
7168
|
}
|
|
6872
7169
|
async function checkWorkerFile(projectRoot) {
|
|
6873
7170
|
const candidates = [
|
|
6874
|
-
(0,
|
|
6875
|
-
(0,
|
|
7171
|
+
(0, import_node_path25.join)(projectRoot, "src", "kora-worker.ts"),
|
|
7172
|
+
(0, import_node_path25.join)(projectRoot, "src", "kora-worker.js")
|
|
6876
7173
|
];
|
|
6877
7174
|
for (const path of candidates) {
|
|
6878
7175
|
try {
|
|
6879
|
-
await (0,
|
|
7176
|
+
await (0, import_promises16.access)(path);
|
|
6880
7177
|
return {
|
|
6881
7178
|
id: "worker",
|
|
6882
7179
|
title: "SQLite WASM worker",
|
|
@@ -6896,7 +7193,7 @@ async function checkWorkerFile(projectRoot) {
|
|
|
6896
7193
|
}
|
|
6897
7194
|
async function checkDependencies(projectRoot) {
|
|
6898
7195
|
try {
|
|
6899
|
-
const raw = await (0,
|
|
7196
|
+
const raw = await (0, import_promises16.readFile)((0, import_node_path25.join)(projectRoot, "package.json"), "utf-8");
|
|
6900
7197
|
const pkg = JSON.parse(raw);
|
|
6901
7198
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
6902
7199
|
const hasKora = Boolean(deps.korajs || deps.kora);
|
|
@@ -6945,9 +7242,9 @@ async function resolveSyncHttpUrl(projectRoot, config) {
|
|
|
6945
7242
|
}
|
|
6946
7243
|
async function readEnvSyncUrl(projectRoot) {
|
|
6947
7244
|
for (const file of [".env", ".env.local"]) {
|
|
6948
|
-
const path = (0,
|
|
7245
|
+
const path = (0, import_node_path25.join)(projectRoot, file);
|
|
6949
7246
|
try {
|
|
6950
|
-
const content = await (0,
|
|
7247
|
+
const content = await (0, import_promises16.readFile)(path, "utf-8");
|
|
6951
7248
|
for (const line of content.split("\n")) {
|
|
6952
7249
|
const trimmed = line.trim();
|
|
6953
7250
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -7038,7 +7335,7 @@ function doctorHasFailures(results) {
|
|
|
7038
7335
|
}
|
|
7039
7336
|
|
|
7040
7337
|
// src/commands/doctor/doctor-command.ts
|
|
7041
|
-
var doctorCommand = (0,
|
|
7338
|
+
var doctorCommand = (0, import_citty7.defineCommand)({
|
|
7042
7339
|
meta: {
|
|
7043
7340
|
name: "doctor",
|
|
7044
7341
|
description: "Check Kora project setup (schema, worker, sync server, versions)"
|
|
@@ -7093,9 +7390,9 @@ var doctorCommand = (0, import_citty6.defineCommand)({
|
|
|
7093
7390
|
});
|
|
7094
7391
|
|
|
7095
7392
|
// src/commands/generate/generate-command.ts
|
|
7096
|
-
var
|
|
7097
|
-
var
|
|
7098
|
-
var
|
|
7393
|
+
var import_promises17 = require("fs/promises");
|
|
7394
|
+
var import_node_path26 = require("path");
|
|
7395
|
+
var import_citty8 = require("citty");
|
|
7099
7396
|
init_fs_helpers();
|
|
7100
7397
|
init_schema_loader();
|
|
7101
7398
|
|
|
@@ -7250,13 +7547,13 @@ function toPascalCase2(name) {
|
|
|
7250
7547
|
}
|
|
7251
7548
|
|
|
7252
7549
|
// src/commands/generate/generate-command.ts
|
|
7253
|
-
var generateCommand = (0,
|
|
7550
|
+
var generateCommand = (0, import_citty8.defineCommand)({
|
|
7254
7551
|
meta: {
|
|
7255
7552
|
name: "generate",
|
|
7256
7553
|
description: "Generate code from your Kora schema"
|
|
7257
7554
|
},
|
|
7258
7555
|
subCommands: {
|
|
7259
|
-
types: (0,
|
|
7556
|
+
types: (0, import_citty8.defineCommand)({
|
|
7260
7557
|
meta: {
|
|
7261
7558
|
name: "types",
|
|
7262
7559
|
description: "Generate TypeScript types from your schema"
|
|
@@ -7280,7 +7577,7 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7280
7577
|
}
|
|
7281
7578
|
let schemaPath;
|
|
7282
7579
|
if (args.schema && typeof args.schema === "string") {
|
|
7283
|
-
schemaPath = (0,
|
|
7580
|
+
schemaPath = (0, import_node_path26.resolve)(args.schema);
|
|
7284
7581
|
} else {
|
|
7285
7582
|
const found = await findSchemaFile(projectRoot);
|
|
7286
7583
|
if (!found) {
|
|
@@ -7303,13 +7600,13 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7303
7600
|
}
|
|
7304
7601
|
const output = generateTypes(schema);
|
|
7305
7602
|
const outputFile = typeof args.output === "string" ? args.output : "kora/generated/types.ts";
|
|
7306
|
-
const outputPath = (0,
|
|
7307
|
-
await (0,
|
|
7308
|
-
await (0,
|
|
7603
|
+
const outputPath = (0, import_node_path26.resolve)(projectRoot, outputFile);
|
|
7604
|
+
await (0, import_promises17.mkdir)((0, import_node_path26.dirname)(outputPath), { recursive: true });
|
|
7605
|
+
await (0, import_promises17.writeFile)(outputPath, output, "utf-8");
|
|
7309
7606
|
logger.success(`Generated types at ${outputPath}`);
|
|
7310
7607
|
}
|
|
7311
7608
|
}),
|
|
7312
|
-
hooks: (0,
|
|
7609
|
+
hooks: (0, import_citty8.defineCommand)({
|
|
7313
7610
|
meta: {
|
|
7314
7611
|
name: "hooks",
|
|
7315
7612
|
description: "Generate per-collection React hook stubs"
|
|
@@ -7338,7 +7635,7 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7338
7635
|
}
|
|
7339
7636
|
let schemaPath;
|
|
7340
7637
|
if (args.schema && typeof args.schema === "string") {
|
|
7341
|
-
schemaPath = (0,
|
|
7638
|
+
schemaPath = (0, import_node_path26.resolve)(projectRoot, args.schema);
|
|
7342
7639
|
} else {
|
|
7343
7640
|
const found = await findSchemaFile(projectRoot);
|
|
7344
7641
|
if (!found) {
|
|
@@ -7352,13 +7649,13 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7352
7649
|
schemaPath = found;
|
|
7353
7650
|
}
|
|
7354
7651
|
const schema = await loadSchemaDefinition(schemaPath, projectRoot);
|
|
7355
|
-
const outputDir = typeof args.output === "string" ? (0,
|
|
7652
|
+
const outputDir = typeof args.output === "string" ? (0, import_node_path26.resolve)(projectRoot, args.output) : (0, import_node_path26.resolve)(projectRoot, "kora/generated/hooks");
|
|
7356
7653
|
const files = generateCollectionHooks(schema);
|
|
7357
7654
|
for (const [name, content] of files) {
|
|
7358
7655
|
const adjusted = typeof args.types === "string" && args.types !== "../types" ? content.replace("from '../types'", `from '${args.types}'`) : content;
|
|
7359
|
-
const filePath = (0,
|
|
7360
|
-
await (0,
|
|
7361
|
-
await (0,
|
|
7656
|
+
const filePath = (0, import_node_path26.resolve)(outputDir, name);
|
|
7657
|
+
await (0, import_promises17.mkdir)((0, import_node_path26.dirname)(filePath), { recursive: true });
|
|
7658
|
+
await (0, import_promises17.writeFile)(filePath, adjusted, "utf-8");
|
|
7362
7659
|
}
|
|
7363
7660
|
logger.success(`Generated ${String(files.size)} hook file(s) at ${outputDir}`);
|
|
7364
7661
|
logger.step("Run `kora generate types` first if ../types is missing.");
|
|
@@ -7380,10 +7677,10 @@ function isSchemaDefinition2(value) {
|
|
|
7380
7677
|
}
|
|
7381
7678
|
|
|
7382
7679
|
// src/commands/logs/logs-command.ts
|
|
7383
|
-
var
|
|
7680
|
+
var import_citty9 = require("citty");
|
|
7384
7681
|
var DEFAULT_SYNC_PORT2 = 3001;
|
|
7385
7682
|
var EVENTS_ENDPOINT = "/__kora/events";
|
|
7386
|
-
var logsCommand = (0,
|
|
7683
|
+
var logsCommand = (0, import_citty9.defineCommand)({
|
|
7387
7684
|
meta: {
|
|
7388
7685
|
name: "logs",
|
|
7389
7686
|
description: "Stream real-time events from a Kora sync server"
|
|
@@ -7487,9 +7784,9 @@ var logsCommand = (0, import_citty8.defineCommand)({
|
|
|
7487
7784
|
});
|
|
7488
7785
|
|
|
7489
7786
|
// src/commands/migrate/migrate-command.ts
|
|
7490
|
-
var
|
|
7491
|
-
var
|
|
7492
|
-
var
|
|
7787
|
+
var import_promises18 = require("fs/promises");
|
|
7788
|
+
var import_node_path27 = require("path");
|
|
7789
|
+
var import_citty10 = require("citty");
|
|
7493
7790
|
init_fs_helpers();
|
|
7494
7791
|
|
|
7495
7792
|
// src/commands/migrate/migration-generator.ts
|
|
@@ -7833,6 +8130,14 @@ function mapFieldType(descriptor) {
|
|
|
7833
8130
|
return "INTEGER";
|
|
7834
8131
|
case "array":
|
|
7835
8132
|
return "TEXT";
|
|
8133
|
+
case "object":
|
|
8134
|
+
return "TEXT";
|
|
8135
|
+
case "json":
|
|
8136
|
+
return "TEXT";
|
|
8137
|
+
case "blob":
|
|
8138
|
+
return "TEXT";
|
|
8139
|
+
case "secret":
|
|
8140
|
+
return "TEXT";
|
|
7836
8141
|
case "richtext":
|
|
7837
8142
|
return "BLOB";
|
|
7838
8143
|
}
|
|
@@ -7848,7 +8153,7 @@ function quoteIdentifier(identifier) {
|
|
|
7848
8153
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(identifier)) {
|
|
7849
8154
|
throw new Error(`Invalid SQL identifier: ${identifier}`);
|
|
7850
8155
|
}
|
|
7851
|
-
return identifier
|
|
8156
|
+
return `"${identifier}"`;
|
|
7852
8157
|
}
|
|
7853
8158
|
function formatChange(change) {
|
|
7854
8159
|
switch (change.type) {
|
|
@@ -8084,7 +8389,7 @@ function generateOperationTransformModule(fromVersion, toVersion) {
|
|
|
8084
8389
|
init_schema_loader();
|
|
8085
8390
|
var SNAPSHOT_PATH = "kora/schema.snapshot.json";
|
|
8086
8391
|
var MIGRATIONS_DIR = "kora/migrations";
|
|
8087
|
-
var migrateCommand = (0,
|
|
8392
|
+
var migrateCommand = (0, import_citty10.defineCommand)({
|
|
8088
8393
|
meta: {
|
|
8089
8394
|
name: "migrate",
|
|
8090
8395
|
description: "Detect schema changes and generate/apply migrations"
|
|
@@ -8126,12 +8431,12 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8126
8431
|
throw new InvalidProjectError(process.cwd());
|
|
8127
8432
|
}
|
|
8128
8433
|
const config = await loadKoraConfig(projectRoot);
|
|
8129
|
-
const resolvedSchemaPath = typeof args.schema === "string" ? (0,
|
|
8434
|
+
const resolvedSchemaPath = typeof args.schema === "string" ? (0, import_node_path27.resolve)(projectRoot, args.schema) : typeof config?.schema === "string" ? (0, import_node_path27.resolve)(projectRoot, config.schema) : await findSchemaFile(projectRoot);
|
|
8130
8435
|
if (!resolvedSchemaPath) {
|
|
8131
8436
|
throw new SchemaNotFoundError(["src/schema.ts", "schema.ts", "src/schema.js", "schema.js"]);
|
|
8132
8437
|
}
|
|
8133
8438
|
const currentSchema = await loadSchemaDefinition(resolvedSchemaPath, projectRoot);
|
|
8134
|
-
const snapshotFile = (0,
|
|
8439
|
+
const snapshotFile = (0, import_node_path27.join)(projectRoot, SNAPSHOT_PATH);
|
|
8135
8440
|
const previousSchema = await readSchemaSnapshot(snapshotFile);
|
|
8136
8441
|
if (!previousSchema) {
|
|
8137
8442
|
if (args["dry-run"] === true) {
|
|
@@ -8144,7 +8449,7 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8144
8449
|
return;
|
|
8145
8450
|
}
|
|
8146
8451
|
const diff = diffSchemas(previousSchema, currentSchema);
|
|
8147
|
-
const outputDir = typeof args["output-dir"] === "string" ? (0,
|
|
8452
|
+
const outputDir = typeof args["output-dir"] === "string" ? (0, import_node_path27.resolve)(projectRoot, args["output-dir"]) : (0, import_node_path27.resolve)(projectRoot, MIGRATIONS_DIR);
|
|
8148
8453
|
if (!diff.hasChanges) {
|
|
8149
8454
|
logger.success("No schema changes detected.");
|
|
8150
8455
|
if (args.apply === true) {
|
|
@@ -8196,7 +8501,7 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8196
8501
|
logger.warn("Dry run enabled: no files written, no migrations applied.");
|
|
8197
8502
|
return;
|
|
8198
8503
|
}
|
|
8199
|
-
await (0,
|
|
8504
|
+
await (0, import_promises18.mkdir)(outputDir, { recursive: true });
|
|
8200
8505
|
const migrationPath = await writeMigrationFile(
|
|
8201
8506
|
outputDir,
|
|
8202
8507
|
diff.fromVersion,
|
|
@@ -8232,7 +8537,7 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8232
8537
|
});
|
|
8233
8538
|
async function readSchemaSnapshot(path) {
|
|
8234
8539
|
try {
|
|
8235
|
-
const content = await (0,
|
|
8540
|
+
const content = await (0, import_promises18.readFile)(path, "utf-8");
|
|
8236
8541
|
return JSON.parse(content);
|
|
8237
8542
|
} catch {
|
|
8238
8543
|
return null;
|
|
@@ -8253,15 +8558,15 @@ function isInteractiveTerminal2() {
|
|
|
8253
8558
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
8254
8559
|
}
|
|
8255
8560
|
async function writeSchemaSnapshot(path, schema) {
|
|
8256
|
-
await (0,
|
|
8257
|
-
await (0,
|
|
8561
|
+
await (0, import_promises18.mkdir)((0, import_node_path27.dirname)(path), { recursive: true });
|
|
8562
|
+
await (0, import_promises18.writeFile)(path, `${JSON.stringify(schema, null, 2)}
|
|
8258
8563
|
`, "utf-8");
|
|
8259
8564
|
}
|
|
8260
8565
|
async function writeMigrationFile(outputDir, fromVersion, toVersion, generated) {
|
|
8261
|
-
const existing = await (0,
|
|
8566
|
+
const existing = await (0, import_promises18.readdir)(outputDir).catch(() => []);
|
|
8262
8567
|
const sequence = existing.filter((file) => /^\d{3}-/.test(file)).length + 1;
|
|
8263
8568
|
const filename = `${String(sequence).padStart(3, "0")}-v${fromVersion}-to-v${toVersion}.ts`;
|
|
8264
|
-
const path = (0,
|
|
8569
|
+
const path = (0, import_node_path27.join)(outputDir, filename);
|
|
8265
8570
|
const migrationId = filename.replace(/\.ts$/, "");
|
|
8266
8571
|
const fileContent = [
|
|
8267
8572
|
`export const up = ${JSON.stringify(generated.up, null, 2)} as const`,
|
|
@@ -8273,10 +8578,10 @@ async function writeMigrationFile(outputDir, fromVersion, toVersion, generated)
|
|
|
8273
8578
|
`export const containsBreakingChanges = ${generated.containsBreakingChanges}`,
|
|
8274
8579
|
""
|
|
8275
8580
|
].join("\n");
|
|
8276
|
-
await (0,
|
|
8277
|
-
const transformsPath = (0,
|
|
8278
|
-
await (0,
|
|
8279
|
-
await writeMigrationManifest((0,
|
|
8581
|
+
await (0, import_promises18.writeFile)(path, fileContent, "utf-8");
|
|
8582
|
+
const transformsPath = (0, import_node_path27.join)(outputDir, `${migrationId}.transforms.ts`);
|
|
8583
|
+
await (0, import_promises18.writeFile)(transformsPath, generateOperationTransformModule(fromVersion, toVersion), "utf-8");
|
|
8584
|
+
await writeMigrationManifest((0, import_node_path27.join)(outputDir, `${migrationId}.json`), {
|
|
8280
8585
|
id: migrationId,
|
|
8281
8586
|
fromVersion,
|
|
8282
8587
|
toVersion,
|
|
@@ -8288,22 +8593,22 @@ async function writeMigrationFile(outputDir, fromVersion, toVersion, generated)
|
|
|
8288
8593
|
return path;
|
|
8289
8594
|
}
|
|
8290
8595
|
async function writeMigrationManifest(path, manifest) {
|
|
8291
|
-
await (0,
|
|
8596
|
+
await (0, import_promises18.writeFile)(path, `${JSON.stringify(manifest, null, 2)}
|
|
8292
8597
|
`, "utf-8");
|
|
8293
8598
|
}
|
|
8294
8599
|
async function listMigrationManifests(outputDir) {
|
|
8295
|
-
const files = await (0,
|
|
8600
|
+
const files = await (0, import_promises18.readdir)(outputDir).catch(() => []);
|
|
8296
8601
|
const migrationFiles = files.filter((file) => /^\d{3}-.*\.ts$/.test(file)).sort((left, right) => left.localeCompare(right));
|
|
8297
8602
|
const manifests = [];
|
|
8298
8603
|
for (const file of migrationFiles) {
|
|
8299
8604
|
const id = file.replace(/\.ts$/, "");
|
|
8300
|
-
const manifestPath = (0,
|
|
8605
|
+
const manifestPath = (0, import_node_path27.join)(outputDir, `${id}.json`);
|
|
8301
8606
|
const jsonManifest = await readMigrationManifest(manifestPath);
|
|
8302
8607
|
if (jsonManifest) {
|
|
8303
8608
|
manifests.push({ ...jsonManifest, id });
|
|
8304
8609
|
continue;
|
|
8305
8610
|
}
|
|
8306
|
-
const migrationPath = (0,
|
|
8611
|
+
const migrationPath = (0, import_node_path27.join)(outputDir, file);
|
|
8307
8612
|
const sourceManifest = await readMigrationManifestFromSource(migrationPath, id);
|
|
8308
8613
|
manifests.push(sourceManifest);
|
|
8309
8614
|
}
|
|
@@ -8311,7 +8616,7 @@ async function listMigrationManifests(outputDir) {
|
|
|
8311
8616
|
}
|
|
8312
8617
|
async function readMigrationManifest(path) {
|
|
8313
8618
|
try {
|
|
8314
|
-
const content = await (0,
|
|
8619
|
+
const content = await (0, import_promises18.readFile)(path, "utf-8");
|
|
8315
8620
|
return JSON.parse(content);
|
|
8316
8621
|
} catch (error) {
|
|
8317
8622
|
const code = error.code;
|
|
@@ -8322,7 +8627,7 @@ async function readMigrationManifest(path) {
|
|
|
8322
8627
|
}
|
|
8323
8628
|
}
|
|
8324
8629
|
async function readMigrationManifestFromSource(path, id) {
|
|
8325
|
-
const content = await (0,
|
|
8630
|
+
const content = await (0, import_promises18.readFile)(path, "utf-8");
|
|
8326
8631
|
const versions = parseVersionsFromMigrationId(id);
|
|
8327
8632
|
return {
|
|
8328
8633
|
id,
|
|
@@ -8384,18 +8689,18 @@ function parseLiteralExport(source, exportName) {
|
|
|
8384
8689
|
}
|
|
8385
8690
|
function resolveSqliteApplyPath(dbArg, projectRoot, config) {
|
|
8386
8691
|
if (typeof dbArg === "string") {
|
|
8387
|
-
return (0,
|
|
8692
|
+
return (0, import_node_path27.resolve)(projectRoot, dbArg);
|
|
8388
8693
|
}
|
|
8389
8694
|
const sync = config?.dev?.sync;
|
|
8390
8695
|
if (typeof sync === "object" && sync !== null) {
|
|
8391
8696
|
if (sync.store === "sqlite") {
|
|
8392
|
-
return (0,
|
|
8697
|
+
return (0, import_node_path27.join)(projectRoot, "kora-sync.db");
|
|
8393
8698
|
}
|
|
8394
8699
|
if (typeof sync.store === "object" && sync.store !== null && sync.store.type === "sqlite") {
|
|
8395
8700
|
if (typeof sync.store.filename === "string" && sync.store.filename.length > 0) {
|
|
8396
|
-
return (0,
|
|
8701
|
+
return (0, import_node_path27.resolve)(projectRoot, sync.store.filename);
|
|
8397
8702
|
}
|
|
8398
|
-
return (0,
|
|
8703
|
+
return (0, import_node_path27.join)(projectRoot, "kora-sync.db");
|
|
8399
8704
|
}
|
|
8400
8705
|
}
|
|
8401
8706
|
return void 0;
|
|
@@ -8413,7 +8718,7 @@ function resolvePostgresConnectionString(config) {
|
|
|
8413
8718
|
}
|
|
8414
8719
|
|
|
8415
8720
|
// src/commands/status/status-command.ts
|
|
8416
|
-
var
|
|
8721
|
+
var import_citty11 = require("citty");
|
|
8417
8722
|
var DEFAULT_SYNC_PORT3 = 3001;
|
|
8418
8723
|
var STATUS_ENDPOINT2 = "/__kora/status";
|
|
8419
8724
|
async function fetchServerStatus(url, token) {
|
|
@@ -8440,7 +8745,7 @@ function formatUptime(ms) {
|
|
|
8440
8745
|
parts.push(`${seconds % 60}s`);
|
|
8441
8746
|
return parts.join(" ");
|
|
8442
8747
|
}
|
|
8443
|
-
var statusCommand = (0,
|
|
8748
|
+
var statusCommand = (0, import_citty11.defineCommand)({
|
|
8444
8749
|
meta: {
|
|
8445
8750
|
name: "status",
|
|
8446
8751
|
description: "Show Kora sync server status"
|
|
@@ -8545,10 +8850,10 @@ function printStatus(status, url, logger) {
|
|
|
8545
8850
|
}
|
|
8546
8851
|
|
|
8547
8852
|
// src/commands/studio/studio-command.ts
|
|
8548
|
-
var
|
|
8549
|
-
var
|
|
8550
|
-
var
|
|
8551
|
-
var studioCommand = (0,
|
|
8853
|
+
var import_node_fs9 = require("fs");
|
|
8854
|
+
var import_node_path30 = require("path");
|
|
8855
|
+
var import_citty12 = require("citty");
|
|
8856
|
+
var studioCommand = (0, import_citty12.defineCommand)({
|
|
8552
8857
|
meta: {
|
|
8553
8858
|
name: "studio",
|
|
8554
8859
|
description: "Kora Studio: visualize records, operations, and sync \u2014 or run the sync lab"
|
|
@@ -8597,7 +8902,7 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8597
8902
|
);
|
|
8598
8903
|
}
|
|
8599
8904
|
const { loadSchemaDefinition: loadSchemaDefinition2 } = await Promise.resolve().then(() => (init_schema_loader(), schema_loader_exports));
|
|
8600
|
-
const schema = await loadSchemaDefinition2((0,
|
|
8905
|
+
const schema = await loadSchemaDefinition2((0, import_node_path30.resolve)(process.cwd(), args.schema), process.cwd());
|
|
8601
8906
|
const { SpectatorManager: SpectatorManager2 } = await Promise.resolve().then(() => (init_spectator_manager(), spectator_manager_exports));
|
|
8602
8907
|
const spectator = new SpectatorManager2({
|
|
8603
8908
|
url: args.connect,
|
|
@@ -8624,7 +8929,7 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8624
8929
|
let schema = defaultLabSchema2();
|
|
8625
8930
|
if (typeof args.schema === "string") {
|
|
8626
8931
|
const { loadSchemaDefinition: loadSchemaDefinition2 } = await Promise.resolve().then(() => (init_schema_loader(), schema_loader_exports));
|
|
8627
|
-
schema = await loadSchemaDefinition2((0,
|
|
8932
|
+
schema = await loadSchemaDefinition2((0, import_node_path30.resolve)(process.cwd(), args.schema), process.cwd());
|
|
8628
8933
|
}
|
|
8629
8934
|
const initialDevices = args.devices !== void 0 ? Math.max(1, Number.parseInt(args.devices, 10) || 2) : 2;
|
|
8630
8935
|
const lab = new LabManager2(schema);
|
|
@@ -8649,8 +8954,8 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8649
8954
|
"Pass --db <path> to inspect a database, --lab for the sync laboratory, or --connect <wss url> for live spectator mode."
|
|
8650
8955
|
);
|
|
8651
8956
|
}
|
|
8652
|
-
const dbPath = (0,
|
|
8653
|
-
if (!(0,
|
|
8957
|
+
const dbPath = (0, import_node_path30.resolve)(process.cwd(), args.db);
|
|
8958
|
+
if (!(0, import_node_fs9.existsSync)(dbPath)) {
|
|
8654
8959
|
throw new Error(`Database file not found: ${dbPath}`);
|
|
8655
8960
|
}
|
|
8656
8961
|
const server = await startStudioServer2({ port, dbPath });
|
|
@@ -8668,12 +8973,13 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8668
8973
|
});
|
|
8669
8974
|
|
|
8670
8975
|
// src/bin.ts
|
|
8671
|
-
var main = (0,
|
|
8976
|
+
var main = (0, import_citty13.defineCommand)({
|
|
8672
8977
|
meta: {
|
|
8673
8978
|
name: "kora",
|
|
8674
|
-
description: "Kora.js
|
|
8979
|
+
description: "Kora.js, the offline-first application framework"
|
|
8675
8980
|
},
|
|
8676
8981
|
subCommands: {
|
|
8982
|
+
"agents-md": agentsCommand,
|
|
8677
8983
|
backup: backupCommand,
|
|
8678
8984
|
compact: compactCommand,
|
|
8679
8985
|
create: createCommand,
|
|
@@ -8687,5 +8993,5 @@ var main = (0, import_citty12.defineCommand)({
|
|
|
8687
8993
|
studio: studioCommand
|
|
8688
8994
|
}
|
|
8689
8995
|
});
|
|
8690
|
-
(0,
|
|
8996
|
+
(0, import_citty13.runMain)(main);
|
|
8691
8997
|
//# sourceMappingURL=bin.cjs.map
|