@korajs/cli 1.0.0-beta.1 → 1.0.0-beta.10
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 +593 -290
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +122 -35
- 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/package.json +8 -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/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;
|
|
@@ -2099,7 +2099,7 @@ var init_spectator_manager = __esm({
|
|
|
2099
2099
|
this.runtime = null;
|
|
2100
2100
|
}
|
|
2101
2101
|
if (this.tmpDir) {
|
|
2102
|
-
(0,
|
|
2102
|
+
(0, import_node_fs7.rmSync)(this.tmpDir, { recursive: true, force: true });
|
|
2103
2103
|
this.tmpDir = null;
|
|
2104
2104
|
}
|
|
2105
2105
|
}
|
|
@@ -2182,13 +2182,13 @@ function summarizeEvent(type, payload) {
|
|
|
2182
2182
|
return type.replace("lab:", "");
|
|
2183
2183
|
}
|
|
2184
2184
|
}
|
|
2185
|
-
var
|
|
2185
|
+
var import_node_fs8, import_node_os2, import_node_path29, import_core3, DEFAULT_CHAOS, FORWARDED_EVENTS2, MAX_EVENT_BUFFER2, LabManager;
|
|
2186
2186
|
var init_lab_manager = __esm({
|
|
2187
2187
|
"src/commands/studio/lab-manager.ts"() {
|
|
2188
2188
|
"use strict";
|
|
2189
|
-
|
|
2189
|
+
import_node_fs8 = require("fs");
|
|
2190
2190
|
import_node_os2 = require("os");
|
|
2191
|
-
|
|
2191
|
+
import_node_path29 = require("path");
|
|
2192
2192
|
import_core3 = require("@korajs/core");
|
|
2193
2193
|
DEFAULT_CHAOS = {
|
|
2194
2194
|
dropRate: 0,
|
|
@@ -2246,7 +2246,7 @@ var init_lab_manager = __esm({
|
|
|
2246
2246
|
}
|
|
2247
2247
|
async start(initialDevices = 2) {
|
|
2248
2248
|
const harness = await this.loadHarness();
|
|
2249
|
-
this.tmpDir = (0,
|
|
2249
|
+
this.tmpDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path29.join)((0, import_node_os2.tmpdir)(), "kora-studio-lab-"));
|
|
2250
2250
|
this.server = new harness.TestServer(this.schema);
|
|
2251
2251
|
for (let i = 0; i < initialDevices; i++) {
|
|
2252
2252
|
await this.addDevice();
|
|
@@ -2298,7 +2298,7 @@ var init_lab_manager = __esm({
|
|
|
2298
2298
|
nodeId: entry.device.getNodeId(),
|
|
2299
2299
|
connected: entry.device.isConnected(),
|
|
2300
2300
|
chaos: { ...entry.chaos },
|
|
2301
|
-
dbPath: (0,
|
|
2301
|
+
dbPath: (0, import_node_path29.join)(this.tmpDir ?? "", `test-device-${name}.db`),
|
|
2302
2302
|
pendingOperations: entry.device.getSyncEngine()?.getStatus().pendingOperations ?? 0
|
|
2303
2303
|
};
|
|
2304
2304
|
}
|
|
@@ -2377,7 +2377,7 @@ var init_lab_manager = __esm({
|
|
|
2377
2377
|
});
|
|
2378
2378
|
this.server = null;
|
|
2379
2379
|
if (this.tmpDir) {
|
|
2380
|
-
(0,
|
|
2380
|
+
(0, import_node_fs8.rmSync)(this.tmpDir, { recursive: true, force: true });
|
|
2381
2381
|
this.tmpDir = null;
|
|
2382
2382
|
}
|
|
2383
2383
|
}
|
|
@@ -2409,12 +2409,13 @@ var init_lab_manager = __esm({
|
|
|
2409
2409
|
});
|
|
2410
2410
|
|
|
2411
2411
|
// src/bin.ts
|
|
2412
|
-
var
|
|
2412
|
+
var import_citty13 = require("citty");
|
|
2413
2413
|
|
|
2414
|
-
// src/commands/
|
|
2415
|
-
var
|
|
2416
|
-
var
|
|
2414
|
+
// src/commands/agents/agents-command.ts
|
|
2415
|
+
var import_promises2 = require("fs/promises");
|
|
2416
|
+
var import_node_path2 = require("path");
|
|
2417
2417
|
var import_citty = require("citty");
|
|
2418
|
+
init_fs_helpers();
|
|
2418
2419
|
|
|
2419
2420
|
// src/utils/logger.ts
|
|
2420
2421
|
var RESET = "\x1B[0m";
|
|
@@ -2451,22 +2452,233 @@ function createLogger(options) {
|
|
|
2451
2452
|
banner() {
|
|
2452
2453
|
console.log();
|
|
2453
2454
|
console.log(
|
|
2454
|
-
color(BOLD + CYAN, " Kora.js") + color(DIM, "
|
|
2455
|
+
color(BOLD + CYAN, " Kora.js") + color(DIM, ", the offline-first application framework")
|
|
2455
2456
|
);
|
|
2456
2457
|
console.log();
|
|
2457
2458
|
}
|
|
2458
2459
|
};
|
|
2459
2460
|
}
|
|
2460
2461
|
|
|
2462
|
+
// src/commands/agents/agents-md-content.ts
|
|
2463
|
+
var AGENTS_FRAMEWORKS = ["react", "vue", "svelte"];
|
|
2464
|
+
function isAgentsFramework(value) {
|
|
2465
|
+
return AGENTS_FRAMEWORKS.includes(value);
|
|
2466
|
+
}
|
|
2467
|
+
function detectFrameworkFromManifest(manifest) {
|
|
2468
|
+
if (typeof manifest !== "object" || manifest === null) return null;
|
|
2469
|
+
const record = manifest;
|
|
2470
|
+
const deps = collectDependencyNames(record.dependencies, record.devDependencies);
|
|
2471
|
+
if (deps.has("@korajs/react")) return "react";
|
|
2472
|
+
if (deps.has("@korajs/vue")) return "vue";
|
|
2473
|
+
if (deps.has("@korajs/svelte")) return "svelte";
|
|
2474
|
+
return null;
|
|
2475
|
+
}
|
|
2476
|
+
function collectDependencyNames(...groups) {
|
|
2477
|
+
const names = /* @__PURE__ */ new Set();
|
|
2478
|
+
for (const group of groups) {
|
|
2479
|
+
if (typeof group !== "object" || group === null) continue;
|
|
2480
|
+
for (const name of Object.keys(group)) {
|
|
2481
|
+
names.add(name);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
return names;
|
|
2485
|
+
}
|
|
2486
|
+
var FRAMEWORK_BINDINGS = {
|
|
2487
|
+
react: `## React bindings
|
|
2488
|
+
|
|
2489
|
+
\`\`\`tsx
|
|
2490
|
+
import { KoraProvider, useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/react'
|
|
2491
|
+
|
|
2492
|
+
// Wrap the tree once near your app entry: <KoraProvider app={app}><App /></KoraProvider>
|
|
2493
|
+
|
|
2494
|
+
const todos = useCollection('todos')
|
|
2495
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt'))
|
|
2496
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
2497
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
2498
|
+
await addTodo.mutateAsync({ title: 'x' }) // resolves with the result; throws on failure
|
|
2499
|
+
const status = useSyncStatus() // status.status, status.pendingOperations
|
|
2500
|
+
\`\`\`
|
|
2501
|
+
|
|
2502
|
+
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.`,
|
|
2503
|
+
vue: `## Vue bindings
|
|
2504
|
+
|
|
2505
|
+
\`\`\`ts
|
|
2506
|
+
import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/vue'
|
|
2507
|
+
|
|
2508
|
+
const todos = useCollection('todos')
|
|
2509
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // readonly reactive ref
|
|
2510
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
2511
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
2512
|
+
const status = useSyncStatus() // status.status, status.pendingOperations
|
|
2513
|
+
\`\`\`
|
|
2514
|
+
|
|
2515
|
+
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\`).`,
|
|
2516
|
+
svelte: `## Svelte bindings
|
|
2517
|
+
|
|
2518
|
+
Kora's Svelte bindings from \`@korajs/svelte\` expose \`useCollection\`, \`useQuery\`, \`useMutation\`, and \`useSyncStatus\`, wired through the provider set up in your app entry.
|
|
2519
|
+
|
|
2520
|
+
\`\`\`ts
|
|
2521
|
+
import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/svelte'
|
|
2522
|
+
|
|
2523
|
+
const todos = useCollection('todos')
|
|
2524
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // reactive store
|
|
2525
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
2526
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
2527
|
+
const status = useSyncStatus() // readable store; read $status.status in markup
|
|
2528
|
+
\`\`\`
|
|
2529
|
+
|
|
2530
|
+
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.`
|
|
2531
|
+
};
|
|
2532
|
+
function generateAgentsMd(framework) {
|
|
2533
|
+
return `# AGENTS.md
|
|
2534
|
+
|
|
2535
|
+
Guidance for AI coding agents working in this project. Humans: this is useful for you too.
|
|
2536
|
+
|
|
2537
|
+
## What this project is
|
|
2538
|
+
|
|
2539
|
+
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.
|
|
2540
|
+
|
|
2541
|
+
## Golden rules
|
|
2542
|
+
|
|
2543
|
+
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.
|
|
2544
|
+
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.
|
|
2545
|
+
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.
|
|
2546
|
+
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.
|
|
2547
|
+
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.
|
|
2548
|
+
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.
|
|
2549
|
+
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.
|
|
2550
|
+
|
|
2551
|
+
## Data API cheat sheet
|
|
2552
|
+
|
|
2553
|
+
\`\`\`ts
|
|
2554
|
+
await app.ready
|
|
2555
|
+
const rec = await app.todos.insert({ title: 'x' }) // defaults and .auto() fields applied
|
|
2556
|
+
await app.todos.update(rec.id, { completed: true }) // partial update, changed fields only
|
|
2557
|
+
await app.todos.delete(rec.id)
|
|
2558
|
+
const one = await app.todos.findById(rec.id)
|
|
2559
|
+
const unsubscribe = app.todos
|
|
2560
|
+
.where({ completed: false })
|
|
2561
|
+
.orderBy('createdAt', 'desc')
|
|
2562
|
+
.subscribe((rows) => {/* fires immediately, then on every change */})
|
|
2563
|
+
\`\`\`
|
|
2564
|
+
|
|
2565
|
+
Schema example (\`src/schema.ts\`):
|
|
2566
|
+
|
|
2567
|
+
\`\`\`ts
|
|
2568
|
+
import { defineSchema, t } from 'korajs'
|
|
2569
|
+
|
|
2570
|
+
export default defineSchema({
|
|
2571
|
+
version: 1,
|
|
2572
|
+
collections: {
|
|
2573
|
+
todos: {
|
|
2574
|
+
fields: {
|
|
2575
|
+
title: t.string(),
|
|
2576
|
+
completed: t.boolean().default(false),
|
|
2577
|
+
tags: t.array(t.string()).default([]),
|
|
2578
|
+
priority: t.enum(['low', 'medium', 'high']).default('medium'),
|
|
2579
|
+
createdAt: t.timestamp().auto(), // set automatically; never pass it on insert
|
|
2580
|
+
},
|
|
2581
|
+
indexes: ['completed', 'createdAt'],
|
|
2582
|
+
},
|
|
2583
|
+
},
|
|
2584
|
+
})
|
|
2585
|
+
\`\`\`
|
|
2586
|
+
|
|
2587
|
+
If you change collection shapes, increment \`version\` and run \`npx kora migrate\`.
|
|
2588
|
+
|
|
2589
|
+
## Conflict handling
|
|
2590
|
+
|
|
2591
|
+
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.
|
|
2592
|
+
|
|
2593
|
+
## Sync and auth
|
|
2594
|
+
|
|
2595
|
+
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.
|
|
2596
|
+
|
|
2597
|
+
${FRAMEWORK_BINDINGS[framework]}
|
|
2598
|
+
|
|
2599
|
+
## Commands
|
|
2600
|
+
|
|
2601
|
+
- \`npx kora dev\` runs the dev environment (app server, local sync server when configured, schema watcher).
|
|
2602
|
+
- \`npx kora doctor\` diagnoses a broken setup.
|
|
2603
|
+
- \`npx kora migrate\` applies a schema change to the local store.
|
|
2604
|
+
- In a running app, the DevTools overlay (Ctrl+Shift+K, Cmd+Shift+K on macOS) inspects operations, merges, and sync status.
|
|
2605
|
+
`;
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// src/commands/agents/agents-command.ts
|
|
2609
|
+
async function fileExists(path) {
|
|
2610
|
+
try {
|
|
2611
|
+
await (0, import_promises2.access)(path);
|
|
2612
|
+
return true;
|
|
2613
|
+
} catch {
|
|
2614
|
+
return false;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
async function readManifest(root) {
|
|
2618
|
+
try {
|
|
2619
|
+
return JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.join)(root, "package.json"), "utf-8"));
|
|
2620
|
+
} catch {
|
|
2621
|
+
return null;
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
function resolveFramework(override, manifest) {
|
|
2625
|
+
if (override !== void 0 && isAgentsFramework(override)) return override;
|
|
2626
|
+
return detectFrameworkFromManifest(manifest) ?? "react";
|
|
2627
|
+
}
|
|
2628
|
+
var agentsCommand = (0, import_citty.defineCommand)({
|
|
2629
|
+
meta: {
|
|
2630
|
+
name: "agents-md",
|
|
2631
|
+
description: "Write an AGENTS.md with Kora rules for AI coding agents into this project"
|
|
2632
|
+
},
|
|
2633
|
+
args: {
|
|
2634
|
+
force: {
|
|
2635
|
+
type: "boolean",
|
|
2636
|
+
description: "Overwrite an existing AGENTS.md",
|
|
2637
|
+
default: false
|
|
2638
|
+
},
|
|
2639
|
+
framework: {
|
|
2640
|
+
type: "string",
|
|
2641
|
+
description: "Override framework detection (react, vue, or svelte)"
|
|
2642
|
+
}
|
|
2643
|
+
},
|
|
2644
|
+
async run({ args }) {
|
|
2645
|
+
const logger = createLogger();
|
|
2646
|
+
const projectRoot = await findProjectRoot() ?? process.cwd();
|
|
2647
|
+
const manifest = await readManifest(projectRoot);
|
|
2648
|
+
const override = typeof args.framework === "string" ? args.framework : void 0;
|
|
2649
|
+
if (override !== void 0 && !isAgentsFramework(override)) {
|
|
2650
|
+
logger.error(`Unknown framework "${override}". Use one of: react, vue, svelte.`);
|
|
2651
|
+
process.exitCode = 1;
|
|
2652
|
+
return;
|
|
2653
|
+
}
|
|
2654
|
+
const framework = resolveFramework(override, manifest);
|
|
2655
|
+
const target = (0, import_node_path2.join)(projectRoot, "AGENTS.md");
|
|
2656
|
+
const force = args.force === true;
|
|
2657
|
+
if (await fileExists(target) && !force) {
|
|
2658
|
+
logger.warn("AGENTS.md already exists. Re-run with --force to overwrite it.");
|
|
2659
|
+
process.exitCode = 1;
|
|
2660
|
+
return;
|
|
2661
|
+
}
|
|
2662
|
+
await (0, import_promises2.writeFile)(target, generateAgentsMd(framework), "utf-8");
|
|
2663
|
+
logger.banner();
|
|
2664
|
+
logger.success(`Wrote AGENTS.md (${framework} bindings) to ${target}`);
|
|
2665
|
+
logger.step("Commit it so coding agents pick up Kora conventions automatically.");
|
|
2666
|
+
logger.blank();
|
|
2667
|
+
}
|
|
2668
|
+
});
|
|
2669
|
+
|
|
2461
2670
|
// src/commands/backup/backup-command.ts
|
|
2671
|
+
var import_promises3 = require("fs/promises");
|
|
2672
|
+
var import_node_path3 = require("path");
|
|
2673
|
+
var import_citty2 = require("citty");
|
|
2462
2674
|
var DEFAULT_SYNC_PORT = 3001;
|
|
2463
|
-
var backupCommand = (0,
|
|
2675
|
+
var backupCommand = (0, import_citty2.defineCommand)({
|
|
2464
2676
|
meta: {
|
|
2465
2677
|
name: "backup",
|
|
2466
2678
|
description: "Backup and restore Kora sync server data"
|
|
2467
2679
|
},
|
|
2468
2680
|
subCommands: {
|
|
2469
|
-
create: (0,
|
|
2681
|
+
create: (0, import_citty2.defineCommand)({
|
|
2470
2682
|
meta: {
|
|
2471
2683
|
name: "create",
|
|
2472
2684
|
description: "Create a backup of the sync server"
|
|
@@ -2506,7 +2718,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2506
2718
|
);
|
|
2507
2719
|
}
|
|
2508
2720
|
const buffer = await response.arrayBuffer();
|
|
2509
|
-
await (0,
|
|
2721
|
+
await (0, import_promises3.writeFile)(outFile, new Uint8Array(buffer));
|
|
2510
2722
|
const size = (buffer.byteLength / 1024).toFixed(1);
|
|
2511
2723
|
logger.success(`Backup saved to ${outFile} (${size} KB)`);
|
|
2512
2724
|
} catch (error) {
|
|
@@ -2518,7 +2730,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2518
2730
|
}
|
|
2519
2731
|
}
|
|
2520
2732
|
}),
|
|
2521
|
-
restore: (0,
|
|
2733
|
+
restore: (0, import_citty2.defineCommand)({
|
|
2522
2734
|
meta: {
|
|
2523
2735
|
name: "restore",
|
|
2524
2736
|
description: "Restore a backup to the sync server"
|
|
@@ -2553,7 +2765,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2553
2765
|
logger.banner();
|
|
2554
2766
|
logger.info(`Restoring backup from ${filePath} to ${url}...`);
|
|
2555
2767
|
try {
|
|
2556
|
-
const data = await (0,
|
|
2768
|
+
const data = await (0, import_promises3.readFile)(filePath);
|
|
2557
2769
|
const restoreUrl = `${url.replace(/\/$/, "")}/__kora/backup/import?merge=${merge}`;
|
|
2558
2770
|
const response = await fetch(restoreUrl, {
|
|
2559
2771
|
method: "POST",
|
|
@@ -2581,7 +2793,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2581
2793
|
}
|
|
2582
2794
|
}
|
|
2583
2795
|
}),
|
|
2584
|
-
info: (0,
|
|
2796
|
+
info: (0, import_citty2.defineCommand)({
|
|
2585
2797
|
meta: {
|
|
2586
2798
|
name: "info",
|
|
2587
2799
|
description: "Show backup file information"
|
|
@@ -2597,7 +2809,7 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2597
2809
|
const logger = createLogger();
|
|
2598
2810
|
const filePath = typeof args.file === "string" ? args.file : "";
|
|
2599
2811
|
try {
|
|
2600
|
-
const data = await (0,
|
|
2812
|
+
const data = await (0, import_promises3.readFile)(filePath);
|
|
2601
2813
|
const { readBackupManifest } = await import("@korajs/store");
|
|
2602
2814
|
const manifest = readBackupManifest(
|
|
2603
2815
|
new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
@@ -2624,8 +2836,8 @@ var backupCommand = (0, import_citty.defineCommand)({
|
|
|
2624
2836
|
});
|
|
2625
2837
|
|
|
2626
2838
|
// src/commands/compact/compact-command.ts
|
|
2627
|
-
var
|
|
2628
|
-
var
|
|
2839
|
+
var import_node_path6 = require("path");
|
|
2840
|
+
var import_citty3 = require("citty");
|
|
2629
2841
|
|
|
2630
2842
|
// src/errors.ts
|
|
2631
2843
|
var import_core = require("@korajs/core");
|
|
@@ -2685,8 +2897,8 @@ init_fs_helpers();
|
|
|
2685
2897
|
|
|
2686
2898
|
// src/commands/dev/kora-config.ts
|
|
2687
2899
|
var import_node_child_process = require("child_process");
|
|
2688
|
-
var
|
|
2689
|
-
var
|
|
2900
|
+
var import_promises4 = require("fs/promises");
|
|
2901
|
+
var import_node_path4 = require("path");
|
|
2690
2902
|
var import_node_url = require("url");
|
|
2691
2903
|
init_fs_helpers();
|
|
2692
2904
|
var CONFIG_CANDIDATES = [
|
|
@@ -2700,7 +2912,7 @@ var CONFIG_CANDIDATES = [
|
|
|
2700
2912
|
async function loadKoraConfig(projectRoot) {
|
|
2701
2913
|
const configPath = await findKoraConfigFile(projectRoot);
|
|
2702
2914
|
if (!configPath) return null;
|
|
2703
|
-
const ext = (0,
|
|
2915
|
+
const ext = (0, import_node_path4.extname)(configPath);
|
|
2704
2916
|
if (ext === ".ts" || ext === ".mts" || ext === ".cts") {
|
|
2705
2917
|
const loaded2 = await loadTypeScriptConfig(configPath, projectRoot);
|
|
2706
2918
|
return toConfigObject(loaded2);
|
|
@@ -2710,9 +2922,9 @@ async function loadKoraConfig(projectRoot) {
|
|
|
2710
2922
|
}
|
|
2711
2923
|
async function findKoraConfigFile(projectRoot) {
|
|
2712
2924
|
for (const file of CONFIG_CANDIDATES) {
|
|
2713
|
-
const candidate = (0,
|
|
2925
|
+
const candidate = (0, import_node_path4.join)(projectRoot, file);
|
|
2714
2926
|
try {
|
|
2715
|
-
await (0,
|
|
2927
|
+
await (0, import_promises4.access)(candidate);
|
|
2716
2928
|
return candidate;
|
|
2717
2929
|
} catch {
|
|
2718
2930
|
}
|
|
@@ -2777,7 +2989,7 @@ function toConfigObject(mod) {
|
|
|
2777
2989
|
|
|
2778
2990
|
// src/commands/compact/compact-command.ts
|
|
2779
2991
|
init_schema_loader();
|
|
2780
|
-
var compactCommand = (0,
|
|
2992
|
+
var compactCommand = (0, import_citty3.defineCommand)({
|
|
2781
2993
|
meta: {
|
|
2782
2994
|
name: "compact",
|
|
2783
2995
|
description: "Compact the local Kora operation log after server ack"
|
|
@@ -2808,12 +3020,12 @@ var compactCommand = (0, import_citty2.defineCommand)({
|
|
|
2808
3020
|
if (!projectRoot) {
|
|
2809
3021
|
throw new InvalidProjectError(process.cwd());
|
|
2810
3022
|
}
|
|
2811
|
-
const dbPath = typeof args.db === "string" ? (0,
|
|
3023
|
+
const dbPath = typeof args.db === "string" ? (0, import_node_path6.resolve)(projectRoot, args.db) : void 0;
|
|
2812
3024
|
if (!dbPath) {
|
|
2813
3025
|
throw new Error("Missing --db <path> to the local SQLite database file.");
|
|
2814
3026
|
}
|
|
2815
3027
|
const config = await loadKoraConfig(projectRoot);
|
|
2816
|
-
const schemaPath = typeof args.schema === "string" ? (0,
|
|
3028
|
+
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
3029
|
if (!schemaPath) {
|
|
2818
3030
|
throw new Error("Could not resolve schema path. Pass --schema <path>.");
|
|
2819
3031
|
}
|
|
@@ -2850,9 +3062,9 @@ var compactCommand = (0, import_citty2.defineCommand)({
|
|
|
2850
3062
|
// src/commands/create/create-command.ts
|
|
2851
3063
|
var import_node_child_process4 = require("child_process");
|
|
2852
3064
|
var import_node_fs2 = require("fs");
|
|
2853
|
-
var
|
|
3065
|
+
var import_node_path10 = require("path");
|
|
2854
3066
|
var import_node_url4 = require("url");
|
|
2855
|
-
var
|
|
3067
|
+
var import_citty4 = require("citty");
|
|
2856
3068
|
|
|
2857
3069
|
// src/prompts/preferences.ts
|
|
2858
3070
|
var import_conf = __toESM(require("conf"), 1);
|
|
@@ -3099,8 +3311,8 @@ function getRunDevCommand(pm) {
|
|
|
3099
3311
|
}
|
|
3100
3312
|
|
|
3101
3313
|
// src/commands/create/environment-detection.ts
|
|
3102
|
-
var
|
|
3103
|
-
var
|
|
3314
|
+
var import_promises5 = require("fs/promises");
|
|
3315
|
+
var import_node_path7 = require("path");
|
|
3104
3316
|
function detectEditorFromEnvironment(env = process.env) {
|
|
3105
3317
|
const termProgram = String(env.TERM_PROGRAM ?? "").toLowerCase();
|
|
3106
3318
|
const editorValue = `${String(env.EDITOR ?? "")} ${String(env.VISUAL ?? "")}`.toLowerCase();
|
|
@@ -3126,18 +3338,18 @@ async function detectGitContext(startDir) {
|
|
|
3126
3338
|
};
|
|
3127
3339
|
}
|
|
3128
3340
|
async function detectMonorepoContext(startDir) {
|
|
3129
|
-
let current = (0,
|
|
3341
|
+
let current = (0, import_node_path7.resolve)(startDir);
|
|
3130
3342
|
for (; ; ) {
|
|
3131
|
-
if (await
|
|
3343
|
+
if (await fileExists2((0, import_node_path7.join)(current, "pnpm-workspace.yaml"))) {
|
|
3132
3344
|
return { isMonorepo: true, root: current, kind: "pnpm-workspace" };
|
|
3133
3345
|
}
|
|
3134
|
-
if (await
|
|
3346
|
+
if (await fileExists2((0, import_node_path7.join)(current, "turbo.json"))) {
|
|
3135
3347
|
return { isMonorepo: true, root: current, kind: "turborepo" };
|
|
3136
3348
|
}
|
|
3137
|
-
const packageJsonPath = (0,
|
|
3138
|
-
if (await
|
|
3349
|
+
const packageJsonPath = (0, import_node_path7.join)(current, "package.json");
|
|
3350
|
+
if (await fileExists2(packageJsonPath)) {
|
|
3139
3351
|
try {
|
|
3140
|
-
const packageJsonRaw = await (0,
|
|
3352
|
+
const packageJsonRaw = await (0, import_promises5.readFile)(packageJsonPath, "utf-8");
|
|
3141
3353
|
const parsed = JSON.parse(packageJsonRaw);
|
|
3142
3354
|
if (Array.isArray(parsed.workspaces) || isNpmWorkspaceObject(parsed.workspaces)) {
|
|
3143
3355
|
return { isMonorepo: true, root: current, kind: "npm-workspaces" };
|
|
@@ -3145,7 +3357,7 @@ async function detectMonorepoContext(startDir) {
|
|
|
3145
3357
|
} catch {
|
|
3146
3358
|
}
|
|
3147
3359
|
}
|
|
3148
|
-
const parent = (0,
|
|
3360
|
+
const parent = (0, import_node_path7.dirname)(current);
|
|
3149
3361
|
if (parent === current) {
|
|
3150
3362
|
return { isMonorepo: false, root: null, kind: "none" };
|
|
3151
3363
|
}
|
|
@@ -3157,9 +3369,9 @@ async function applyEditorWorkspacePreset(params) {
|
|
|
3157
3369
|
if (editor !== "vscode" && editor !== "cursor" && editor !== "windsurf") {
|
|
3158
3370
|
return { applied: false, filePath: null };
|
|
3159
3371
|
}
|
|
3160
|
-
const vscodeDir = (0,
|
|
3161
|
-
const extensionsPath = (0,
|
|
3162
|
-
await (0,
|
|
3372
|
+
const vscodeDir = (0, import_node_path7.join)(targetDir, ".vscode");
|
|
3373
|
+
const extensionsPath = (0, import_node_path7.join)(vscodeDir, "extensions.json");
|
|
3374
|
+
await (0, import_promises5.mkdir)(vscodeDir, { recursive: true });
|
|
3163
3375
|
const recommendations = ["korajs.kora-devtools"];
|
|
3164
3376
|
const existing = await readJsonObject(extensionsPath);
|
|
3165
3377
|
const existingRecommendations = Array.isArray(existing?.recommendations) ? existing.recommendations.filter((item) => typeof item === "string") : [];
|
|
@@ -3167,19 +3379,19 @@ async function applyEditorWorkspacePreset(params) {
|
|
|
3167
3379
|
const next = {
|
|
3168
3380
|
recommendations: mergedRecommendations
|
|
3169
3381
|
};
|
|
3170
|
-
await (0,
|
|
3382
|
+
await (0, import_promises5.writeFile)(extensionsPath, `${JSON.stringify(next, null, 2)}
|
|
3171
3383
|
`, "utf-8");
|
|
3172
3384
|
return { applied: true, filePath: extensionsPath };
|
|
3173
3385
|
}
|
|
3174
3386
|
function resolveMonorepoTargetDirectory(monorepoRoot, projectName) {
|
|
3175
|
-
return (0,
|
|
3387
|
+
return (0, import_node_path7.join)(monorepoRoot, "packages", projectName);
|
|
3176
3388
|
}
|
|
3177
3389
|
function dedupeStrings(values) {
|
|
3178
3390
|
return Array.from(new Set(values));
|
|
3179
3391
|
}
|
|
3180
3392
|
async function readJsonObject(path) {
|
|
3181
3393
|
try {
|
|
3182
|
-
const content = await (0,
|
|
3394
|
+
const content = await (0, import_promises5.readFile)(path, "utf-8");
|
|
3183
3395
|
const parsed = JSON.parse(content);
|
|
3184
3396
|
if (typeof parsed === "object" && parsed !== null) {
|
|
3185
3397
|
return parsed;
|
|
@@ -3194,24 +3406,24 @@ function isNpmWorkspaceObject(value) {
|
|
|
3194
3406
|
const record = value;
|
|
3195
3407
|
return Array.isArray(record.packages);
|
|
3196
3408
|
}
|
|
3197
|
-
async function
|
|
3409
|
+
async function fileExists2(path) {
|
|
3198
3410
|
try {
|
|
3199
|
-
await (0,
|
|
3411
|
+
await (0, import_promises5.access)(path);
|
|
3200
3412
|
return true;
|
|
3201
3413
|
} catch {
|
|
3202
3414
|
return false;
|
|
3203
3415
|
}
|
|
3204
3416
|
}
|
|
3205
3417
|
async function findNearestAncestorWithEntry(startDir, entryName) {
|
|
3206
|
-
let current = (0,
|
|
3418
|
+
let current = (0, import_node_path7.resolve)(startDir);
|
|
3207
3419
|
for (; ; ) {
|
|
3208
|
-
const candidate = (0,
|
|
3420
|
+
const candidate = (0, import_node_path7.join)(current, entryName);
|
|
3209
3421
|
try {
|
|
3210
|
-
await (0,
|
|
3422
|
+
await (0, import_promises5.stat)(candidate);
|
|
3211
3423
|
return current;
|
|
3212
3424
|
} catch {
|
|
3213
3425
|
}
|
|
3214
|
-
const parent = (0,
|
|
3426
|
+
const parent = (0, import_node_path7.dirname)(current);
|
|
3215
3427
|
if (parent === current) {
|
|
3216
3428
|
return null;
|
|
3217
3429
|
}
|
|
@@ -3490,8 +3702,8 @@ function validateProjectName(name) {
|
|
|
3490
3702
|
}
|
|
3491
3703
|
|
|
3492
3704
|
// src/commands/create/sync-provider-preset.ts
|
|
3493
|
-
var
|
|
3494
|
-
var
|
|
3705
|
+
var import_promises6 = require("fs/promises");
|
|
3706
|
+
var import_node_path8 = require("path");
|
|
3495
3707
|
async function applySyncProviderPreset(options) {
|
|
3496
3708
|
if (!isSyncTemplate(options.template)) {
|
|
3497
3709
|
return;
|
|
@@ -3501,10 +3713,10 @@ async function applySyncProviderPreset(options) {
|
|
|
3501
3713
|
}
|
|
3502
3714
|
const providerName = getProviderDisplayName(options.dbProvider);
|
|
3503
3715
|
const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
|
|
3504
|
-
const envPath = (0,
|
|
3505
|
-
const readmePath = (0,
|
|
3506
|
-
const existingReadme = await (0,
|
|
3507
|
-
const existingEnv = await (0,
|
|
3716
|
+
const envPath = (0, import_node_path8.join)(options.targetDir, ".env.example");
|
|
3717
|
+
const readmePath = (0, import_node_path8.join)(options.targetDir, "README.md");
|
|
3718
|
+
const existingReadme = await (0, import_promises6.readFile)(readmePath, "utf-8");
|
|
3719
|
+
const existingEnv = await (0, import_promises6.readFile)(envPath, "utf-8");
|
|
3508
3720
|
const trimmedReadme = existingReadme.trimEnd();
|
|
3509
3721
|
const trimmedEnv = existingEnv.trimEnd();
|
|
3510
3722
|
const envSuffix = [
|
|
@@ -3524,9 +3736,9 @@ async function applySyncProviderPreset(options) {
|
|
|
3524
3736
|
""
|
|
3525
3737
|
].join("\n");
|
|
3526
3738
|
const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
|
|
3527
|
-
await (0,
|
|
3739
|
+
await (0, import_promises6.writeFile)(envPath, `${trimmedEnv}${envSuffix}
|
|
3528
3740
|
`, "utf-8");
|
|
3529
|
-
await (0,
|
|
3741
|
+
await (0, import_promises6.writeFile)(readmePath, readmeTemplate, "utf-8");
|
|
3530
3742
|
}
|
|
3531
3743
|
function isSyncTemplate(template) {
|
|
3532
3744
|
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 +3782,8 @@ function getProviderConnectionStringExample(provider) {
|
|
|
3570
3782
|
|
|
3571
3783
|
// src/templates/composer.ts
|
|
3572
3784
|
var import_node_fs = require("fs");
|
|
3573
|
-
var
|
|
3574
|
-
var
|
|
3785
|
+
var import_promises7 = require("fs/promises");
|
|
3786
|
+
var import_node_path9 = require("path");
|
|
3575
3787
|
var import_node_url3 = require("url");
|
|
3576
3788
|
var import_meta = {};
|
|
3577
3789
|
function substituteVariables(template, context) {
|
|
@@ -3581,16 +3793,16 @@ function substituteVariables(template, context) {
|
|
|
3581
3793
|
});
|
|
3582
3794
|
}
|
|
3583
3795
|
function getTemplatePath(templateName) {
|
|
3584
|
-
let dir = (0,
|
|
3796
|
+
let dir = (0, import_node_path9.dirname)((0, import_node_url3.fileURLToPath)(import_meta.url));
|
|
3585
3797
|
for (let i = 0; i < 7; i++) {
|
|
3586
|
-
const candidate = (0,
|
|
3798
|
+
const candidate = (0, import_node_path9.resolve)(dir, "templates", templateName);
|
|
3587
3799
|
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
3588
3800
|
return candidate;
|
|
3589
3801
|
}
|
|
3590
|
-
dir = (0,
|
|
3802
|
+
dir = (0, import_node_path9.dirname)(dir);
|
|
3591
3803
|
}
|
|
3592
|
-
const currentDir = (0,
|
|
3593
|
-
return (0,
|
|
3804
|
+
const currentDir = (0, import_node_path9.dirname)((0, import_node_url3.fileURLToPath)(import_meta.url));
|
|
3805
|
+
return (0, import_node_path9.resolve)(currentDir, "..", "..", "..", "templates", templateName);
|
|
3594
3806
|
}
|
|
3595
3807
|
function createCompatibilityLayerPlan(templateName) {
|
|
3596
3808
|
const baseLayer = { category: "base", name: "base", sourceTemplate: "react-basic" };
|
|
@@ -3723,22 +3935,22 @@ async function composeTemplateLayers(plan, targetDir, context) {
|
|
|
3723
3935
|
}
|
|
3724
3936
|
}
|
|
3725
3937
|
async function copyDirectory(src, dest, vars) {
|
|
3726
|
-
await (0,
|
|
3727
|
-
const entries = await (0,
|
|
3938
|
+
await (0, import_promises7.mkdir)(dest, { recursive: true });
|
|
3939
|
+
const entries = await (0, import_promises7.readdir)(src);
|
|
3728
3940
|
for (const entry of entries) {
|
|
3729
|
-
const srcPath = (0,
|
|
3730
|
-
const srcStat = await (0,
|
|
3941
|
+
const srcPath = (0, import_node_path9.join)(src, entry);
|
|
3942
|
+
const srcStat = await (0, import_promises7.stat)(srcPath);
|
|
3731
3943
|
if (srcStat.isDirectory()) {
|
|
3732
|
-
await copyDirectory(srcPath, (0,
|
|
3944
|
+
await copyDirectory(srcPath, (0, import_node_path9.join)(dest, entry), vars);
|
|
3733
3945
|
continue;
|
|
3734
3946
|
}
|
|
3735
3947
|
if (entry.endsWith(".hbs")) {
|
|
3736
|
-
const content = await (0,
|
|
3948
|
+
const content = await (0, import_promises7.readFile)(srcPath, "utf-8");
|
|
3737
3949
|
const outputName = entry.slice(0, -4);
|
|
3738
|
-
await (0,
|
|
3950
|
+
await (0, import_promises7.writeFile)((0, import_node_path9.join)(dest, outputName), substituteVariables(content, vars), "utf-8");
|
|
3739
3951
|
continue;
|
|
3740
3952
|
}
|
|
3741
|
-
await (0,
|
|
3953
|
+
await (0, import_promises7.copyFile)(srcPath, (0, import_node_path9.join)(dest, entry));
|
|
3742
3954
|
}
|
|
3743
3955
|
}
|
|
3744
3956
|
|
|
@@ -3750,7 +3962,7 @@ async function scaffoldTemplate(templateName, targetDir, context) {
|
|
|
3750
3962
|
|
|
3751
3963
|
// src/commands/create/create-command.ts
|
|
3752
3964
|
var import_meta2 = {};
|
|
3753
|
-
var createCommand = (0,
|
|
3965
|
+
var createCommand = (0, import_citty4.defineCommand)({
|
|
3754
3966
|
meta: {
|
|
3755
3967
|
name: "create",
|
|
3756
3968
|
description: "Create a new Kora application"
|
|
@@ -3891,7 +4103,7 @@ var createCommand = (0, import_citty3.defineCommand)({
|
|
|
3891
4103
|
const editorDetection = detectEditorFromEnvironment();
|
|
3892
4104
|
const gitContext = await detectGitContext(process.cwd());
|
|
3893
4105
|
const monorepoContext = await detectMonorepoContext(process.cwd());
|
|
3894
|
-
let targetDir = (0,
|
|
4106
|
+
let targetDir = (0, import_node_path10.resolve)(process.cwd(), projectName);
|
|
3895
4107
|
if (!useDefaults && monorepoContext.isMonorepo && monorepoContext.root !== null) {
|
|
3896
4108
|
const useWorkspaceTarget = await prompts.confirm(
|
|
3897
4109
|
`Detected ${formatMonorepoKind(monorepoContext.kind)} at ${monorepoContext.root}. Create app under packages/${projectName}?`,
|
|
@@ -4061,29 +4273,33 @@ function relativeToTarget(targetDir, filePath) {
|
|
|
4061
4273
|
}
|
|
4062
4274
|
function resolveKoraVersion() {
|
|
4063
4275
|
try {
|
|
4064
|
-
let dir = (0,
|
|
4276
|
+
let dir = (0, import_node_path10.dirname)((0, import_node_url4.fileURLToPath)(import_meta2.url));
|
|
4065
4277
|
for (let i = 0; i < 5; i++) {
|
|
4066
|
-
const pkgPath = (0,
|
|
4278
|
+
const pkgPath = (0, import_node_path10.resolve)(dir, "package.json");
|
|
4067
4279
|
if ((0, import_node_fs2.existsSync)(pkgPath)) {
|
|
4068
4280
|
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
|
|
4069
4281
|
if (pkg.name === "@korajs/cli") {
|
|
4070
|
-
|
|
4071
|
-
const parts = pkg.version.split(".");
|
|
4072
|
-
return `^${parts[0]}.${parts[1]}.0`;
|
|
4282
|
+
return deriveKoraTemplateVersion(pkg.version);
|
|
4073
4283
|
}
|
|
4074
4284
|
}
|
|
4075
|
-
dir = (0,
|
|
4285
|
+
dir = (0, import_node_path10.dirname)(dir);
|
|
4076
4286
|
}
|
|
4077
4287
|
return "latest";
|
|
4078
4288
|
} catch {
|
|
4079
4289
|
return "latest";
|
|
4080
4290
|
}
|
|
4081
4291
|
}
|
|
4292
|
+
function deriveKoraTemplateVersion(version) {
|
|
4293
|
+
if (version === "0.0.0") return "latest";
|
|
4294
|
+
if (version.includes("-")) return version;
|
|
4295
|
+
const parts = version.split(".");
|
|
4296
|
+
return `^${parts[0]}.${parts[1]}.0`;
|
|
4297
|
+
}
|
|
4082
4298
|
|
|
4083
4299
|
// src/commands/deploy/deploy-command.ts
|
|
4084
4300
|
var import_node_fs4 = require("fs");
|
|
4085
|
-
var
|
|
4086
|
-
var
|
|
4301
|
+
var import_node_path21 = require("path");
|
|
4302
|
+
var import_citty5 = require("citty");
|
|
4087
4303
|
init_fs_helpers();
|
|
4088
4304
|
|
|
4089
4305
|
// src/commands/deploy/adapters/adapter.ts
|
|
@@ -4102,13 +4318,13 @@ function isDeployPlatform(value) {
|
|
|
4102
4318
|
|
|
4103
4319
|
// src/commands/deploy/adapters/aws-ecs-adapter.ts
|
|
4104
4320
|
var import_node_child_process6 = require("child_process");
|
|
4105
|
-
var
|
|
4321
|
+
var import_node_path13 = require("path");
|
|
4106
4322
|
|
|
4107
4323
|
// src/commands/deploy/builder/client-builder.ts
|
|
4108
4324
|
var import_node_child_process5 = require("child_process");
|
|
4109
4325
|
var import_node_fs3 = require("fs");
|
|
4110
|
-
var
|
|
4111
|
-
var
|
|
4326
|
+
var import_promises8 = require("fs/promises");
|
|
4327
|
+
var import_node_path11 = require("path");
|
|
4112
4328
|
init_fs_helpers();
|
|
4113
4329
|
async function buildClient(options) {
|
|
4114
4330
|
const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
|
|
@@ -4130,15 +4346,15 @@ async function buildClient(options) {
|
|
|
4130
4346
|
return { outDir: options.outDir };
|
|
4131
4347
|
}
|
|
4132
4348
|
async function patchSqliteWasmAssets(projectRoot, outDir) {
|
|
4133
|
-
const assetsDir = (0,
|
|
4349
|
+
const assetsDir = (0, import_node_path11.join)(outDir, "assets");
|
|
4134
4350
|
if (!(0, import_node_fs3.existsSync)(assetsDir)) return;
|
|
4135
|
-
const files = await (0,
|
|
4351
|
+
const files = await (0, import_promises8.readdir)(assetsDir);
|
|
4136
4352
|
const hashedWasm = files.find((f) => /^sqlite3-.+\.wasm$/.test(f));
|
|
4137
4353
|
if (hashedWasm && !files.includes("sqlite3.wasm")) {
|
|
4138
|
-
await (0,
|
|
4354
|
+
await (0, import_promises8.copyFile)((0, import_node_path11.join)(assetsDir, hashedWasm), (0, import_node_path11.join)(assetsDir, "sqlite3.wasm"));
|
|
4139
4355
|
}
|
|
4140
4356
|
if (!files.includes("sqlite3-opfs-async-proxy.js")) {
|
|
4141
|
-
const proxyFile = (0,
|
|
4357
|
+
const proxyFile = (0, import_node_path11.resolve)(
|
|
4142
4358
|
projectRoot,
|
|
4143
4359
|
"node_modules",
|
|
4144
4360
|
"@sqlite.org",
|
|
@@ -4148,7 +4364,7 @@ async function patchSqliteWasmAssets(projectRoot, outDir) {
|
|
|
4148
4364
|
"sqlite3-opfs-async-proxy.js"
|
|
4149
4365
|
);
|
|
4150
4366
|
if ((0, import_node_fs3.existsSync)(proxyFile)) {
|
|
4151
|
-
await (0,
|
|
4367
|
+
await (0, import_promises8.copyFile)(proxyFile, (0, import_node_path11.join)(assetsDir, "sqlite3-opfs-async-proxy.js"));
|
|
4152
4368
|
}
|
|
4153
4369
|
}
|
|
4154
4370
|
}
|
|
@@ -4173,9 +4389,9 @@ async function runProcess(command, args, cwd) {
|
|
|
4173
4389
|
}
|
|
4174
4390
|
|
|
4175
4391
|
// src/commands/deploy/builder/server-bundler.ts
|
|
4176
|
-
var import_promises8 = require("fs/promises");
|
|
4177
4392
|
var import_promises9 = require("fs/promises");
|
|
4178
|
-
var
|
|
4393
|
+
var import_promises10 = require("fs/promises");
|
|
4394
|
+
var import_node_path12 = require("path");
|
|
4179
4395
|
var import_esbuild = require("esbuild");
|
|
4180
4396
|
var DEFAULT_ENTRY_CANDIDATES = [
|
|
4181
4397
|
"server.ts",
|
|
@@ -4191,8 +4407,8 @@ async function bundleServer(options) {
|
|
|
4191
4407
|
`Could not find a server entry file in ${options.projectRoot}. Looked for: ${candidates.join(", ")}`
|
|
4192
4408
|
);
|
|
4193
4409
|
}
|
|
4194
|
-
await (0,
|
|
4195
|
-
const outputFilePath = (0,
|
|
4410
|
+
await (0, import_promises9.mkdir)(options.deployDirectory, { recursive: true });
|
|
4411
|
+
const outputFilePath = (0, import_node_path12.join)(options.deployDirectory, "server-bundled.js");
|
|
4196
4412
|
await (0, import_esbuild.build)({
|
|
4197
4413
|
entryPoints: [entryFilePath],
|
|
4198
4414
|
outfile: outputFilePath,
|
|
@@ -4214,9 +4430,9 @@ async function bundleServer(options) {
|
|
|
4214
4430
|
}
|
|
4215
4431
|
async function resolveServerEntry(projectRoot, candidates) {
|
|
4216
4432
|
for (const candidate of candidates) {
|
|
4217
|
-
const fullPath = (0,
|
|
4433
|
+
const fullPath = (0, import_node_path12.join)(projectRoot, candidate);
|
|
4218
4434
|
try {
|
|
4219
|
-
await (0,
|
|
4435
|
+
await (0, import_promises10.access)(fullPath);
|
|
4220
4436
|
return fullPath;
|
|
4221
4437
|
} catch {
|
|
4222
4438
|
}
|
|
@@ -4318,19 +4534,19 @@ var AwsEcsAdapter = class {
|
|
|
4318
4534
|
appName: config.appName,
|
|
4319
4535
|
region: config.region
|
|
4320
4536
|
};
|
|
4321
|
-
const deployDirectory = (0,
|
|
4537
|
+
const deployDirectory = (0, import_node_path13.join)(config.projectRoot, ".kora", "deploy");
|
|
4322
4538
|
await bundleServer({
|
|
4323
4539
|
projectRoot: config.projectRoot,
|
|
4324
4540
|
deployDirectory
|
|
4325
4541
|
});
|
|
4326
4542
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
4327
4543
|
projectRoot: config.projectRoot,
|
|
4328
|
-
outDir: (0,
|
|
4544
|
+
outDir: (0, import_node_path13.join)(deployDirectory, "dist"),
|
|
4329
4545
|
mode: "production"
|
|
4330
4546
|
});
|
|
4331
4547
|
return {
|
|
4332
4548
|
clientDirectory: client?.outDir ?? null,
|
|
4333
|
-
serverBundlePath: (0,
|
|
4549
|
+
serverBundlePath: (0, import_node_path13.join)(deployDirectory, "server-bundled.js"),
|
|
4334
4550
|
deployDirectory
|
|
4335
4551
|
};
|
|
4336
4552
|
}
|
|
@@ -4596,7 +4812,7 @@ function inferLogLevel(line) {
|
|
|
4596
4812
|
|
|
4597
4813
|
// src/commands/deploy/adapters/aws-lightsail-adapter.ts
|
|
4598
4814
|
var import_node_child_process7 = require("child_process");
|
|
4599
|
-
var
|
|
4815
|
+
var import_node_path14 = require("path");
|
|
4600
4816
|
var AwsLightsailAdapter = class {
|
|
4601
4817
|
name = "aws-lightsail";
|
|
4602
4818
|
logger = createLogger();
|
|
@@ -4669,19 +4885,19 @@ var AwsLightsailAdapter = class {
|
|
|
4669
4885
|
appName: config.appName,
|
|
4670
4886
|
region: config.region
|
|
4671
4887
|
};
|
|
4672
|
-
const deployDirectory = (0,
|
|
4888
|
+
const deployDirectory = (0, import_node_path14.join)(config.projectRoot, ".kora", "deploy");
|
|
4673
4889
|
await bundleServer({
|
|
4674
4890
|
projectRoot: config.projectRoot,
|
|
4675
4891
|
deployDirectory
|
|
4676
4892
|
});
|
|
4677
4893
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
4678
4894
|
projectRoot: config.projectRoot,
|
|
4679
|
-
outDir: (0,
|
|
4895
|
+
outDir: (0, import_node_path14.join)(deployDirectory, "dist"),
|
|
4680
4896
|
mode: "production"
|
|
4681
4897
|
});
|
|
4682
4898
|
return {
|
|
4683
4899
|
clientDirectory: client?.outDir ?? null,
|
|
4684
|
-
serverBundlePath: (0,
|
|
4900
|
+
serverBundlePath: (0, import_node_path14.join)(deployDirectory, "server-bundled.js"),
|
|
4685
4901
|
deployDirectory
|
|
4686
4902
|
};
|
|
4687
4903
|
}
|
|
@@ -4981,11 +5197,11 @@ function inferLogLevel2(line) {
|
|
|
4981
5197
|
|
|
4982
5198
|
// src/commands/deploy/adapters/fly-adapter.ts
|
|
4983
5199
|
var import_node_child_process8 = require("child_process");
|
|
4984
|
-
var
|
|
5200
|
+
var import_node_path16 = require("path");
|
|
4985
5201
|
|
|
4986
5202
|
// src/commands/deploy/artifacts/fly-toml-generator.ts
|
|
4987
|
-
var
|
|
4988
|
-
var
|
|
5203
|
+
var import_promises11 = require("fs/promises");
|
|
5204
|
+
var import_node_path15 = require("path");
|
|
4989
5205
|
var GENERATED_HEADER = "# Generated by kora deploy \u2014 do not edit manually";
|
|
4990
5206
|
function generateFlyToml(options) {
|
|
4991
5207
|
const internalPort = options.internalPort ?? 3e3;
|
|
@@ -5015,9 +5231,9 @@ function generateFlyToml(options) {
|
|
|
5015
5231
|
].join("\n");
|
|
5016
5232
|
}
|
|
5017
5233
|
async function writeFlyTomlArtifact(deployDirectory, options) {
|
|
5018
|
-
await (0,
|
|
5019
|
-
const filePath = (0,
|
|
5020
|
-
await (0,
|
|
5234
|
+
await (0, import_promises11.mkdir)(deployDirectory, { recursive: true });
|
|
5235
|
+
const filePath = (0, import_node_path15.join)(deployDirectory, "fly.toml");
|
|
5236
|
+
await (0, import_promises11.writeFile)(filePath, generateFlyToml(options), "utf-8");
|
|
5021
5237
|
return filePath;
|
|
5022
5238
|
}
|
|
5023
5239
|
|
|
@@ -5111,7 +5327,7 @@ var FlyAdapter = class {
|
|
|
5111
5327
|
appName: config.appName,
|
|
5112
5328
|
region: config.region
|
|
5113
5329
|
};
|
|
5114
|
-
const deployDirectory = (0,
|
|
5330
|
+
const deployDirectory = (0, import_node_path16.join)(config.projectRoot, ".kora", "deploy");
|
|
5115
5331
|
await writeFlyTomlArtifact(deployDirectory, {
|
|
5116
5332
|
appName: config.appName,
|
|
5117
5333
|
region: config.region ?? "iad"
|
|
@@ -5122,12 +5338,12 @@ var FlyAdapter = class {
|
|
|
5122
5338
|
});
|
|
5123
5339
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
5124
5340
|
projectRoot: config.projectRoot,
|
|
5125
|
-
outDir: (0,
|
|
5341
|
+
outDir: (0, import_node_path16.join)(deployDirectory, "dist"),
|
|
5126
5342
|
mode: "production"
|
|
5127
5343
|
});
|
|
5128
5344
|
return {
|
|
5129
5345
|
clientDirectory: client?.outDir ?? null,
|
|
5130
|
-
serverBundlePath: (0,
|
|
5346
|
+
serverBundlePath: (0, import_node_path16.join)(deployDirectory, "server-bundled.js"),
|
|
5131
5347
|
deployDirectory
|
|
5132
5348
|
};
|
|
5133
5349
|
}
|
|
@@ -5349,11 +5565,11 @@ ${stdout}`.toLowerCase();
|
|
|
5349
5565
|
|
|
5350
5566
|
// src/commands/deploy/adapters/railway-adapter.ts
|
|
5351
5567
|
var import_node_child_process9 = require("child_process");
|
|
5352
|
-
var
|
|
5568
|
+
var import_node_path18 = require("path");
|
|
5353
5569
|
|
|
5354
5570
|
// src/commands/deploy/artifacts/railway-json-generator.ts
|
|
5355
|
-
var
|
|
5356
|
-
var
|
|
5571
|
+
var import_promises12 = require("fs/promises");
|
|
5572
|
+
var import_node_path17 = require("path");
|
|
5357
5573
|
var GENERATED_HEADER2 = "Generated by kora deploy - do not edit manually.";
|
|
5358
5574
|
function generateRailwayJson(options) {
|
|
5359
5575
|
const file = {
|
|
@@ -5378,9 +5594,9 @@ function generateRailwayJson(options) {
|
|
|
5378
5594
|
`;
|
|
5379
5595
|
}
|
|
5380
5596
|
async function writeRailwayJsonArtifact(deployDirectory, options) {
|
|
5381
|
-
await (0,
|
|
5382
|
-
const filePath = (0,
|
|
5383
|
-
await (0,
|
|
5597
|
+
await (0, import_promises12.mkdir)(deployDirectory, { recursive: true });
|
|
5598
|
+
const filePath = (0, import_node_path17.join)(deployDirectory, "railway.json");
|
|
5599
|
+
await (0, import_promises12.writeFile)(filePath, generateRailwayJson(options), "utf-8");
|
|
5384
5600
|
return filePath;
|
|
5385
5601
|
}
|
|
5386
5602
|
|
|
@@ -5469,7 +5685,7 @@ var RailwayAdapter = class {
|
|
|
5469
5685
|
appName: config.appName,
|
|
5470
5686
|
region: config.region
|
|
5471
5687
|
};
|
|
5472
|
-
const deployDirectory = (0,
|
|
5688
|
+
const deployDirectory = (0, import_node_path18.join)(config.projectRoot, ".kora", "deploy");
|
|
5473
5689
|
await writeRailwayJsonArtifact(deployDirectory, {
|
|
5474
5690
|
appName: config.appName,
|
|
5475
5691
|
environment: config.environment
|
|
@@ -5480,12 +5696,12 @@ var RailwayAdapter = class {
|
|
|
5480
5696
|
});
|
|
5481
5697
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
5482
5698
|
projectRoot: config.projectRoot,
|
|
5483
|
-
outDir: (0,
|
|
5699
|
+
outDir: (0, import_node_path18.join)(deployDirectory, "dist"),
|
|
5484
5700
|
mode: "production"
|
|
5485
5701
|
});
|
|
5486
5702
|
return {
|
|
5487
5703
|
clientDirectory: client?.outDir ?? null,
|
|
5488
|
-
serverBundlePath: (0,
|
|
5704
|
+
serverBundlePath: (0, import_node_path18.join)(deployDirectory, "server-bundled.js"),
|
|
5489
5705
|
deployDirectory
|
|
5490
5706
|
};
|
|
5491
5707
|
}
|
|
@@ -5770,8 +5986,8 @@ function createDeployAdapter(platform) {
|
|
|
5770
5986
|
}
|
|
5771
5987
|
|
|
5772
5988
|
// src/commands/deploy/artifacts/dockerfile-generator.ts
|
|
5773
|
-
var
|
|
5774
|
-
var
|
|
5989
|
+
var import_promises13 = require("fs/promises");
|
|
5990
|
+
var import_node_path19 = require("path");
|
|
5775
5991
|
var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually";
|
|
5776
5992
|
function generateDockerfile(options = {}) {
|
|
5777
5993
|
const nodeVersion = options.nodeVersion ?? "20-alpine";
|
|
@@ -5837,37 +6053,37 @@ function generateDockerIgnore() {
|
|
|
5837
6053
|
].join("\n");
|
|
5838
6054
|
}
|
|
5839
6055
|
async function writeDockerfileArtifact(deployDirectory, options = {}) {
|
|
5840
|
-
await (0,
|
|
5841
|
-
const dockerfilePath = (0,
|
|
5842
|
-
await (0,
|
|
6056
|
+
await (0, import_promises13.mkdir)(deployDirectory, { recursive: true });
|
|
6057
|
+
const dockerfilePath = (0, import_node_path19.join)(deployDirectory, "Dockerfile");
|
|
6058
|
+
await (0, import_promises13.writeFile)(dockerfilePath, generateDockerfile(options), "utf-8");
|
|
5843
6059
|
if (options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0) {
|
|
5844
|
-
const pkgJsonPath = (0,
|
|
5845
|
-
await (0,
|
|
6060
|
+
const pkgJsonPath = (0, import_node_path19.join)(deployDirectory, "package.json");
|
|
6061
|
+
await (0, import_promises13.writeFile)(pkgJsonPath, generateDeployPackageJson(options.nativeDependencies), "utf-8");
|
|
5846
6062
|
}
|
|
5847
6063
|
return dockerfilePath;
|
|
5848
6064
|
}
|
|
5849
6065
|
async function writeDockerIgnoreArtifact(deployDirectory) {
|
|
5850
|
-
await (0,
|
|
5851
|
-
const dockerIgnorePath = (0,
|
|
5852
|
-
await (0,
|
|
6066
|
+
await (0, import_promises13.mkdir)(deployDirectory, { recursive: true });
|
|
6067
|
+
const dockerIgnorePath = (0, import_node_path19.join)(deployDirectory, ".dockerignore");
|
|
6068
|
+
await (0, import_promises13.writeFile)(dockerIgnorePath, generateDockerIgnore(), "utf-8");
|
|
5853
6069
|
return dockerIgnorePath;
|
|
5854
6070
|
}
|
|
5855
6071
|
|
|
5856
6072
|
// src/commands/deploy/state/deploy-state.ts
|
|
5857
|
-
var
|
|
5858
|
-
var
|
|
5859
|
-
var KORA_DEPLOY_DIRECTORY = (0,
|
|
6073
|
+
var import_promises14 = require("fs/promises");
|
|
6074
|
+
var import_node_path20 = require("path");
|
|
6075
|
+
var KORA_DEPLOY_DIRECTORY = (0, import_node_path20.join)(".kora", "deploy");
|
|
5860
6076
|
var DEPLOY_STATE_FILENAME = "deploy.json";
|
|
5861
6077
|
function resolveDeployDirectory(projectRoot) {
|
|
5862
|
-
return (0,
|
|
6078
|
+
return (0, import_node_path20.join)(projectRoot, KORA_DEPLOY_DIRECTORY);
|
|
5863
6079
|
}
|
|
5864
6080
|
function resolveDeployStatePath(projectRoot) {
|
|
5865
|
-
return (0,
|
|
6081
|
+
return (0, import_node_path20.join)(resolveDeployDirectory(projectRoot), DEPLOY_STATE_FILENAME);
|
|
5866
6082
|
}
|
|
5867
6083
|
async function readDeployState(projectRoot) {
|
|
5868
6084
|
const statePath = resolveDeployStatePath(projectRoot);
|
|
5869
6085
|
try {
|
|
5870
|
-
const source = await (0,
|
|
6086
|
+
const source = await (0, import_promises14.readFile)(statePath, "utf-8");
|
|
5871
6087
|
const parsed = JSON.parse(source);
|
|
5872
6088
|
return parseDeployState(parsed);
|
|
5873
6089
|
} catch (error) {
|
|
@@ -5914,13 +6130,13 @@ async function updateDeployState(projectRoot, patch, now = /* @__PURE__ */ new D
|
|
|
5914
6130
|
return nextState;
|
|
5915
6131
|
}
|
|
5916
6132
|
async function resetDeployState(projectRoot) {
|
|
5917
|
-
await (0,
|
|
6133
|
+
await (0, import_promises14.rm)(resolveDeployDirectory(projectRoot), { recursive: true, force: true });
|
|
5918
6134
|
}
|
|
5919
6135
|
async function persistDeployState(projectRoot, state) {
|
|
5920
6136
|
const deployDir = resolveDeployDirectory(projectRoot);
|
|
5921
6137
|
const statePath = resolveDeployStatePath(projectRoot);
|
|
5922
|
-
await (0,
|
|
5923
|
-
await (0,
|
|
6138
|
+
await (0, import_promises14.mkdir)(deployDir, { recursive: true });
|
|
6139
|
+
await (0, import_promises14.writeFile)(statePath, `${JSON.stringify(state, null, 2)}
|
|
5924
6140
|
`, "utf-8");
|
|
5925
6141
|
}
|
|
5926
6142
|
function parseDeployState(value) {
|
|
@@ -5970,7 +6186,7 @@ function readOptionalString(value, field) {
|
|
|
5970
6186
|
}
|
|
5971
6187
|
|
|
5972
6188
|
// src/commands/deploy/deploy-command.ts
|
|
5973
|
-
var deployCommand = (0,
|
|
6189
|
+
var deployCommand = (0, import_citty5.defineCommand)({
|
|
5974
6190
|
meta: {
|
|
5975
6191
|
name: "deploy",
|
|
5976
6192
|
description: "Deploy a Kora project to your selected platform"
|
|
@@ -6005,7 +6221,7 @@ var deployCommand = (0, import_citty4.defineCommand)({
|
|
|
6005
6221
|
}
|
|
6006
6222
|
},
|
|
6007
6223
|
subCommands: {
|
|
6008
|
-
status: (0,
|
|
6224
|
+
status: (0, import_citty5.defineCommand)({
|
|
6009
6225
|
meta: {
|
|
6010
6226
|
name: "status",
|
|
6011
6227
|
description: "Show current deployment status"
|
|
@@ -6036,7 +6252,7 @@ var deployCommand = (0, import_citty4.defineCommand)({
|
|
|
6036
6252
|
logger.step(`Sync URL: ${state.syncUrl ?? "n/a"}`);
|
|
6037
6253
|
}
|
|
6038
6254
|
}),
|
|
6039
|
-
rollback: (0,
|
|
6255
|
+
rollback: (0, import_citty5.defineCommand)({
|
|
6040
6256
|
meta: {
|
|
6041
6257
|
name: "rollback",
|
|
6042
6258
|
description: "Rollback the current deployment"
|
|
@@ -6067,7 +6283,7 @@ var deployCommand = (0, import_citty4.defineCommand)({
|
|
|
6067
6283
|
logger.success(`Rolled back ${state.platform} deployment to ${deploymentId}.`);
|
|
6068
6284
|
}
|
|
6069
6285
|
}),
|
|
6070
|
-
logs: (0,
|
|
6286
|
+
logs: (0, import_citty5.defineCommand)({
|
|
6071
6287
|
meta: {
|
|
6072
6288
|
name: "logs",
|
|
6073
6289
|
description: "Read deployment logs"
|
|
@@ -6254,7 +6470,7 @@ function resolveAppName(argValue, storedValue, projectRoot, confirm) {
|
|
|
6254
6470
|
"Missing app name in --confirm mode. Provide --app or run an interactive deploy first."
|
|
6255
6471
|
);
|
|
6256
6472
|
}
|
|
6257
|
-
return sanitizeAppName((0,
|
|
6473
|
+
return sanitizeAppName((0, import_node_path21.basename)(projectRoot));
|
|
6258
6474
|
}
|
|
6259
6475
|
function resolveRegion(argValue, storedValue, confirm) {
|
|
6260
6476
|
if (typeof argValue === "string" && argValue.length > 0) return argValue;
|
|
@@ -6289,17 +6505,18 @@ function configureAdapterContext(adapter, context) {
|
|
|
6289
6505
|
}
|
|
6290
6506
|
}
|
|
6291
6507
|
function detectDeployTarget(projectRoot) {
|
|
6292
|
-
return (0, import_node_fs4.existsSync)((0,
|
|
6508
|
+
return (0, import_node_fs4.existsSync)((0, import_node_path21.join)(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
|
|
6293
6509
|
}
|
|
6294
6510
|
function hasContextSetter(adapter) {
|
|
6295
6511
|
return typeof adapter.setContext === "function";
|
|
6296
6512
|
}
|
|
6297
6513
|
|
|
6298
6514
|
// src/commands/dev/dev-command.ts
|
|
6299
|
-
var
|
|
6300
|
-
var
|
|
6515
|
+
var import_node_fs6 = require("fs");
|
|
6516
|
+
var import_promises15 = require("fs/promises");
|
|
6301
6517
|
var import_node_path23 = require("path");
|
|
6302
|
-
var
|
|
6518
|
+
var import_node_path24 = require("path");
|
|
6519
|
+
var import_citty6 = require("citty");
|
|
6303
6520
|
init_fs_helpers();
|
|
6304
6521
|
|
|
6305
6522
|
// src/commands/dev/process-manager.ts
|
|
@@ -6307,6 +6524,7 @@ var import_node_child_process10 = require("child_process");
|
|
|
6307
6524
|
var ProcessManager = class {
|
|
6308
6525
|
processes = /* @__PURE__ */ new Map();
|
|
6309
6526
|
spawn(config) {
|
|
6527
|
+
this.processes.get(config.label)?.child.kill("SIGTERM");
|
|
6310
6528
|
const options = {
|
|
6311
6529
|
cwd: config.cwd,
|
|
6312
6530
|
env: { ...process.env, ...config.env },
|
|
@@ -6350,6 +6568,20 @@ var ProcessManager = class {
|
|
|
6350
6568
|
hasRunning() {
|
|
6351
6569
|
return this.processes.size > 0;
|
|
6352
6570
|
}
|
|
6571
|
+
async restart(config) {
|
|
6572
|
+
await this.stop(config.label);
|
|
6573
|
+
this.spawn(config);
|
|
6574
|
+
}
|
|
6575
|
+
async stop(label) {
|
|
6576
|
+
const running = this.processes.get(label);
|
|
6577
|
+
if (!running) return;
|
|
6578
|
+
running.child.kill("SIGTERM");
|
|
6579
|
+
await Promise.race([running.exitPromise, delay(5e3)]);
|
|
6580
|
+
const remaining = this.processes.get(label);
|
|
6581
|
+
if (!remaining) return;
|
|
6582
|
+
remaining.child.kill("SIGKILL");
|
|
6583
|
+
await remaining.exitPromise;
|
|
6584
|
+
}
|
|
6353
6585
|
async shutdownAll() {
|
|
6354
6586
|
const running = Array.from(this.processes.values());
|
|
6355
6587
|
if (running.length === 0) return;
|
|
@@ -6392,8 +6624,9 @@ function delay(ms) {
|
|
|
6392
6624
|
// src/commands/dev/schema-watcher.ts
|
|
6393
6625
|
var import_node_child_process11 = require("child_process");
|
|
6394
6626
|
var import_node_fs5 = require("fs");
|
|
6395
|
-
var
|
|
6627
|
+
var import_node_path22 = require("path");
|
|
6396
6628
|
init_fs_helpers();
|
|
6629
|
+
init_schema_loader();
|
|
6397
6630
|
var SchemaWatcher = class {
|
|
6398
6631
|
constructor(config) {
|
|
6399
6632
|
this.config = config;
|
|
@@ -6403,6 +6636,7 @@ var SchemaWatcher = class {
|
|
|
6403
6636
|
debounceMs;
|
|
6404
6637
|
watcher = null;
|
|
6405
6638
|
debounceTimer = null;
|
|
6639
|
+
schemaVersion = null;
|
|
6406
6640
|
start() {
|
|
6407
6641
|
if (this.watcher) return;
|
|
6408
6642
|
this.watcher = (0, import_node_fs5.watch)(this.config.schemaPath, () => {
|
|
@@ -6411,6 +6645,9 @@ var SchemaWatcher = class {
|
|
|
6411
6645
|
this.watcher.on("error", (error) => {
|
|
6412
6646
|
this.config.onError?.(toError(error));
|
|
6413
6647
|
});
|
|
6648
|
+
void this.refreshSchemaVersion().catch((error) => {
|
|
6649
|
+
this.config.onError?.(toError(error));
|
|
6650
|
+
});
|
|
6414
6651
|
}
|
|
6415
6652
|
stop() {
|
|
6416
6653
|
if (this.debounceTimer) {
|
|
@@ -6421,7 +6658,7 @@ var SchemaWatcher = class {
|
|
|
6421
6658
|
this.watcher = null;
|
|
6422
6659
|
}
|
|
6423
6660
|
async regenerate() {
|
|
6424
|
-
const koraBinJs = (0,
|
|
6661
|
+
const koraBinJs = (0, import_node_path22.join)(
|
|
6425
6662
|
this.config.projectRoot,
|
|
6426
6663
|
"node_modules",
|
|
6427
6664
|
"@korajs",
|
|
@@ -6434,6 +6671,15 @@ var SchemaWatcher = class {
|
|
|
6434
6671
|
const args = hasTsx ? ["--import", "tsx", koraBinJs, "generate", "types", "--schema", this.config.schemaPath] : [koraBinJs, "generate", "types", "--schema", this.config.schemaPath];
|
|
6435
6672
|
await spawnCommand(command, args, this.config.projectRoot);
|
|
6436
6673
|
this.config.onRegenerate?.();
|
|
6674
|
+
await this.refreshSchemaVersion();
|
|
6675
|
+
}
|
|
6676
|
+
async refreshSchemaVersion() {
|
|
6677
|
+
const schema = await loadSchemaDefinition(this.config.schemaPath, this.config.projectRoot);
|
|
6678
|
+
const previous = this.schemaVersion;
|
|
6679
|
+
this.schemaVersion = schema.version;
|
|
6680
|
+
if (previous !== null && previous !== schema.version) {
|
|
6681
|
+
this.config.onSchemaVersionChange?.({ previous, next: schema.version });
|
|
6682
|
+
}
|
|
6437
6683
|
}
|
|
6438
6684
|
scheduleRegeneration() {
|
|
6439
6685
|
if (this.debounceTimer) {
|
|
@@ -6487,7 +6733,7 @@ function toError(error) {
|
|
|
6487
6733
|
}
|
|
6488
6734
|
|
|
6489
6735
|
// src/commands/dev/dev-command.ts
|
|
6490
|
-
var devCommand = (0,
|
|
6736
|
+
var devCommand = (0, import_citty6.defineCommand)({
|
|
6491
6737
|
meta: {
|
|
6492
6738
|
name: "dev",
|
|
6493
6739
|
description: "Start the Kora development environment"
|
|
@@ -6518,6 +6764,7 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6518
6764
|
if (!projectRoot) {
|
|
6519
6765
|
throw new InvalidProjectError(process.cwd());
|
|
6520
6766
|
}
|
|
6767
|
+
loadProjectEnv(projectRoot);
|
|
6521
6768
|
const config = await loadKoraConfig(projectRoot);
|
|
6522
6769
|
const vitePort = typeof args.port === "string" ? args.port : String(config?.dev?.port ?? 5173);
|
|
6523
6770
|
const syncPortFromConfig = typeof config?.dev?.sync === "object" && typeof config.dev.sync.port === "number" ? config.dev.sync.port : 3001;
|
|
@@ -6527,7 +6774,7 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6527
6774
|
const watchDebounceMs = typeof config?.dev?.watch === "object" && typeof config.dev.watch.debounceMs === "number" ? config.dev.watch.debounceMs : 300;
|
|
6528
6775
|
const viteEntryPoint = await resolveProjectBinaryEntryPoint(projectRoot, "vite", "vite");
|
|
6529
6776
|
if (!viteEntryPoint) {
|
|
6530
|
-
throw new DevServerError("vite", (0,
|
|
6777
|
+
throw new DevServerError("vite", (0, import_node_path23.join)(projectRoot, "node_modules", ".bin", "vite"));
|
|
6531
6778
|
}
|
|
6532
6779
|
const syncServerFile = await findSyncServerFile(projectRoot);
|
|
6533
6780
|
let managedSyncStore = normalizeManagedSyncStore(config, projectRoot);
|
|
@@ -6542,8 +6789,8 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6542
6789
|
}
|
|
6543
6790
|
}
|
|
6544
6791
|
if (shouldStartSync && syncServerFile === null && managedSyncStore) {
|
|
6545
|
-
const hasServerPackage = await
|
|
6546
|
-
(0,
|
|
6792
|
+
const hasServerPackage = await fileExists3(
|
|
6793
|
+
(0, import_node_path23.join)(projectRoot, "node_modules", "@korajs", "server", "package.json")
|
|
6547
6794
|
);
|
|
6548
6795
|
if (!hasServerPackage) {
|
|
6549
6796
|
logger.warn(
|
|
@@ -6560,8 +6807,8 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6560
6807
|
}
|
|
6561
6808
|
let configuredSchemaPath = null;
|
|
6562
6809
|
if (typeof config?.schema === "string") {
|
|
6563
|
-
const candidate = (0,
|
|
6564
|
-
if (await
|
|
6810
|
+
const candidate = (0, import_node_path24.resolve)(projectRoot, config.schema);
|
|
6811
|
+
if (await fileExists3(candidate)) {
|
|
6565
6812
|
configuredSchemaPath = candidate;
|
|
6566
6813
|
} else {
|
|
6567
6814
|
logger.warn(
|
|
@@ -6619,7 +6866,9 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6619
6866
|
logger.step(" Schema watcher disabled (schema.ts not found)");
|
|
6620
6867
|
}
|
|
6621
6868
|
logger.blank();
|
|
6622
|
-
logger.step(
|
|
6869
|
+
logger.step(
|
|
6870
|
+
" Kora DevTools overlay: Ctrl+Shift+K (Cmd+Shift+K on macOS) when devtools is enabled"
|
|
6871
|
+
);
|
|
6623
6872
|
processManager.spawn({
|
|
6624
6873
|
label: "vite",
|
|
6625
6874
|
command: process.execPath,
|
|
@@ -6630,33 +6879,31 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6630
6879
|
},
|
|
6631
6880
|
onExit: onManagedProcessExit
|
|
6632
6881
|
});
|
|
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
|
-
});
|
|
6882
|
+
const syncProcessConfig = shouldStartSync && hasTsx && syncServerFile ? {
|
|
6883
|
+
label: "sync",
|
|
6884
|
+
command: process.execPath,
|
|
6885
|
+
args: ["--import", "tsx", syncServerFile],
|
|
6886
|
+
cwd: projectRoot,
|
|
6887
|
+
env: {
|
|
6888
|
+
PORT: String(syncPort),
|
|
6889
|
+
KORA_SYNC_PORT: String(syncPort)
|
|
6890
|
+
},
|
|
6891
|
+
onExit: onManagedProcessExit
|
|
6892
|
+
} : shouldStartSync && syncServerFile === null && managedSyncStore !== null ? {
|
|
6893
|
+
label: "sync",
|
|
6894
|
+
command: process.execPath,
|
|
6895
|
+
args: ["--input-type=module", "--eval", MANAGED_SYNC_BOOTSTRAP_SCRIPT],
|
|
6896
|
+
cwd: projectRoot,
|
|
6897
|
+
env: {
|
|
6898
|
+
KORA_DEV_SYNC_CONFIG: JSON.stringify({
|
|
6899
|
+
port: Number(syncPort),
|
|
6900
|
+
store: managedSyncStore
|
|
6901
|
+
})
|
|
6902
|
+
},
|
|
6903
|
+
onExit: onManagedProcessExit
|
|
6904
|
+
} : null;
|
|
6905
|
+
if (syncProcessConfig) {
|
|
6906
|
+
processManager.spawn(syncProcessConfig);
|
|
6660
6907
|
}
|
|
6661
6908
|
if (watchEnabled && schemaPath) {
|
|
6662
6909
|
schemaWatcher = new SchemaWatcher({
|
|
@@ -6666,6 +6913,16 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6666
6913
|
onRegenerate: () => {
|
|
6667
6914
|
logger.success("Regenerated types from schema changes");
|
|
6668
6915
|
},
|
|
6916
|
+
onSchemaVersionChange: ({ previous, next }) => {
|
|
6917
|
+
if (!syncProcessConfig) {
|
|
6918
|
+
logger.warn(
|
|
6919
|
+
`Schema version changed from ${previous} to ${next}; restart your sync server before clients can sync.`
|
|
6920
|
+
);
|
|
6921
|
+
return;
|
|
6922
|
+
}
|
|
6923
|
+
logger.warn(`Schema version changed from ${previous} to ${next}; restarting sync server.`);
|
|
6924
|
+
void processManager.restart(syncProcessConfig);
|
|
6925
|
+
},
|
|
6669
6926
|
onError: (error) => {
|
|
6670
6927
|
logger.error(`Schema watcher error: ${error.message}`);
|
|
6671
6928
|
}
|
|
@@ -6678,31 +6935,68 @@ var devCommand = (0, import_citty5.defineCommand)({
|
|
|
6678
6935
|
}
|
|
6679
6936
|
});
|
|
6680
6937
|
async function findSyncServerFile(projectRoot) {
|
|
6681
|
-
const candidates = [(0,
|
|
6938
|
+
const candidates = [(0, import_node_path23.join)(projectRoot, "server.ts"), (0, import_node_path23.join)(projectRoot, "server.js")];
|
|
6682
6939
|
for (const candidate of candidates) {
|
|
6683
6940
|
try {
|
|
6684
|
-
await (0,
|
|
6941
|
+
await (0, import_promises15.access)(candidate);
|
|
6685
6942
|
return candidate;
|
|
6686
6943
|
} catch {
|
|
6687
6944
|
}
|
|
6688
6945
|
}
|
|
6689
6946
|
return null;
|
|
6690
6947
|
}
|
|
6691
|
-
async function
|
|
6948
|
+
async function fileExists3(path) {
|
|
6692
6949
|
try {
|
|
6693
|
-
await (0,
|
|
6950
|
+
await (0, import_promises15.access)(path);
|
|
6694
6951
|
return true;
|
|
6695
6952
|
} catch {
|
|
6696
6953
|
return false;
|
|
6697
6954
|
}
|
|
6698
6955
|
}
|
|
6956
|
+
function loadProjectEnv(projectRoot, mode = "development") {
|
|
6957
|
+
const files = [".env", ".env.local", `.env.${mode}`, `.env.${mode}.local`];
|
|
6958
|
+
const existingKeys = new Set(Object.keys(process.env));
|
|
6959
|
+
for (const file of files) {
|
|
6960
|
+
const path = (0, import_node_path23.join)(projectRoot, file);
|
|
6961
|
+
if (!(0, import_node_fs6.existsSync)(path)) continue;
|
|
6962
|
+
const parsed = parseEnvFile((0, import_node_fs6.readFileSync)(path, "utf8"));
|
|
6963
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
6964
|
+
if (!existingKeys.has(key)) {
|
|
6965
|
+
process.env[key] = value;
|
|
6966
|
+
}
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
}
|
|
6970
|
+
function parseEnvFile(contents) {
|
|
6971
|
+
const env = {};
|
|
6972
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
6973
|
+
const line = rawLine.trim();
|
|
6974
|
+
if (!line || line.startsWith("#")) continue;
|
|
6975
|
+
const normalized = line.startsWith("export ") ? line.slice("export ".length).trim() : line;
|
|
6976
|
+
const equalsIndex = normalized.indexOf("=");
|
|
6977
|
+
if (equalsIndex <= 0) continue;
|
|
6978
|
+
const key = normalized.slice(0, equalsIndex).trim();
|
|
6979
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue;
|
|
6980
|
+
env[key] = parseEnvValue(normalized.slice(equalsIndex + 1).trim());
|
|
6981
|
+
}
|
|
6982
|
+
return env;
|
|
6983
|
+
}
|
|
6984
|
+
function parseEnvValue(value) {
|
|
6985
|
+
const quote = value[0];
|
|
6986
|
+
if ((quote === '"' || quote === "'") && value[value.length - 1] === quote) {
|
|
6987
|
+
const inner = value.slice(1, -1);
|
|
6988
|
+
return quote === '"' ? inner.replace(/\\n/g, "\n").replace(/\\r/g, "\r") : inner;
|
|
6989
|
+
}
|
|
6990
|
+
const commentIndex = value.search(/\s#/);
|
|
6991
|
+
return (commentIndex >= 0 ? value.slice(0, commentIndex) : value).trim();
|
|
6992
|
+
}
|
|
6699
6993
|
function normalizeManagedSyncStore(config, projectRoot) {
|
|
6700
6994
|
const sync = config?.dev?.sync;
|
|
6701
6995
|
if (typeof sync !== "object" || sync === null) return null;
|
|
6702
6996
|
const store = sync.store;
|
|
6703
6997
|
if (store === void 0) return { type: "memory" };
|
|
6704
6998
|
if (store === "memory") return { type: "memory" };
|
|
6705
|
-
if (store === "sqlite") return { type: "sqlite", filename: (0,
|
|
6999
|
+
if (store === "sqlite") return { type: "sqlite", filename: (0, import_node_path23.join)(projectRoot, "kora-sync.db") };
|
|
6706
7000
|
if (store === "postgres") {
|
|
6707
7001
|
const connectionString = process.env.DATABASE_URL;
|
|
6708
7002
|
if (!connectionString) return null;
|
|
@@ -6711,7 +7005,7 @@ function normalizeManagedSyncStore(config, projectRoot) {
|
|
|
6711
7005
|
if (typeof store === "object" && store !== null) {
|
|
6712
7006
|
if (store.type === "memory") return { type: "memory" };
|
|
6713
7007
|
if (store.type === "sqlite") {
|
|
6714
|
-
const filename = typeof store.filename === "string" && store.filename.length > 0 ? (0,
|
|
7008
|
+
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
7009
|
return { type: "sqlite", filename };
|
|
6716
7010
|
}
|
|
6717
7011
|
if (store.type === "postgres" && typeof store.connectionString === "string") {
|
|
@@ -6775,12 +7069,12 @@ await new Promise(() => {});
|
|
|
6775
7069
|
`;
|
|
6776
7070
|
|
|
6777
7071
|
// src/commands/doctor/doctor-command.ts
|
|
6778
|
-
var
|
|
7072
|
+
var import_citty7 = require("citty");
|
|
6779
7073
|
init_fs_helpers();
|
|
6780
7074
|
|
|
6781
7075
|
// src/commands/doctor/doctor-checks.ts
|
|
6782
|
-
var
|
|
6783
|
-
var
|
|
7076
|
+
var import_promises16 = require("fs/promises");
|
|
7077
|
+
var import_node_path25 = require("path");
|
|
6784
7078
|
init_fs_helpers();
|
|
6785
7079
|
init_schema_loader();
|
|
6786
7080
|
var STATUS_ENDPOINT = "/__kora/status";
|
|
@@ -6860,9 +7154,9 @@ async function runDoctorChecks(options) {
|
|
|
6860
7154
|
}
|
|
6861
7155
|
async function resolveSchemaPath(projectRoot, configSchema) {
|
|
6862
7156
|
if (typeof configSchema === "string") {
|
|
6863
|
-
const resolved = (0,
|
|
7157
|
+
const resolved = (0, import_node_path25.resolve)(projectRoot, configSchema);
|
|
6864
7158
|
try {
|
|
6865
|
-
await (0,
|
|
7159
|
+
await (0, import_promises16.access)(resolved);
|
|
6866
7160
|
return resolved;
|
|
6867
7161
|
} catch {
|
|
6868
7162
|
}
|
|
@@ -6871,12 +7165,12 @@ async function resolveSchemaPath(projectRoot, configSchema) {
|
|
|
6871
7165
|
}
|
|
6872
7166
|
async function checkWorkerFile(projectRoot) {
|
|
6873
7167
|
const candidates = [
|
|
6874
|
-
(0,
|
|
6875
|
-
(0,
|
|
7168
|
+
(0, import_node_path25.join)(projectRoot, "src", "kora-worker.ts"),
|
|
7169
|
+
(0, import_node_path25.join)(projectRoot, "src", "kora-worker.js")
|
|
6876
7170
|
];
|
|
6877
7171
|
for (const path of candidates) {
|
|
6878
7172
|
try {
|
|
6879
|
-
await (0,
|
|
7173
|
+
await (0, import_promises16.access)(path);
|
|
6880
7174
|
return {
|
|
6881
7175
|
id: "worker",
|
|
6882
7176
|
title: "SQLite WASM worker",
|
|
@@ -6896,7 +7190,7 @@ async function checkWorkerFile(projectRoot) {
|
|
|
6896
7190
|
}
|
|
6897
7191
|
async function checkDependencies(projectRoot) {
|
|
6898
7192
|
try {
|
|
6899
|
-
const raw = await (0,
|
|
7193
|
+
const raw = await (0, import_promises16.readFile)((0, import_node_path25.join)(projectRoot, "package.json"), "utf-8");
|
|
6900
7194
|
const pkg = JSON.parse(raw);
|
|
6901
7195
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
6902
7196
|
const hasKora = Boolean(deps.korajs || deps.kora);
|
|
@@ -6945,9 +7239,9 @@ async function resolveSyncHttpUrl(projectRoot, config) {
|
|
|
6945
7239
|
}
|
|
6946
7240
|
async function readEnvSyncUrl(projectRoot) {
|
|
6947
7241
|
for (const file of [".env", ".env.local"]) {
|
|
6948
|
-
const path = (0,
|
|
7242
|
+
const path = (0, import_node_path25.join)(projectRoot, file);
|
|
6949
7243
|
try {
|
|
6950
|
-
const content = await (0,
|
|
7244
|
+
const content = await (0, import_promises16.readFile)(path, "utf-8");
|
|
6951
7245
|
for (const line of content.split("\n")) {
|
|
6952
7246
|
const trimmed = line.trim();
|
|
6953
7247
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -7038,7 +7332,7 @@ function doctorHasFailures(results) {
|
|
|
7038
7332
|
}
|
|
7039
7333
|
|
|
7040
7334
|
// src/commands/doctor/doctor-command.ts
|
|
7041
|
-
var doctorCommand = (0,
|
|
7335
|
+
var doctorCommand = (0, import_citty7.defineCommand)({
|
|
7042
7336
|
meta: {
|
|
7043
7337
|
name: "doctor",
|
|
7044
7338
|
description: "Check Kora project setup (schema, worker, sync server, versions)"
|
|
@@ -7093,9 +7387,9 @@ var doctorCommand = (0, import_citty6.defineCommand)({
|
|
|
7093
7387
|
});
|
|
7094
7388
|
|
|
7095
7389
|
// src/commands/generate/generate-command.ts
|
|
7096
|
-
var
|
|
7097
|
-
var
|
|
7098
|
-
var
|
|
7390
|
+
var import_promises17 = require("fs/promises");
|
|
7391
|
+
var import_node_path26 = require("path");
|
|
7392
|
+
var import_citty8 = require("citty");
|
|
7099
7393
|
init_fs_helpers();
|
|
7100
7394
|
init_schema_loader();
|
|
7101
7395
|
|
|
@@ -7250,13 +7544,13 @@ function toPascalCase2(name) {
|
|
|
7250
7544
|
}
|
|
7251
7545
|
|
|
7252
7546
|
// src/commands/generate/generate-command.ts
|
|
7253
|
-
var generateCommand = (0,
|
|
7547
|
+
var generateCommand = (0, import_citty8.defineCommand)({
|
|
7254
7548
|
meta: {
|
|
7255
7549
|
name: "generate",
|
|
7256
7550
|
description: "Generate code from your Kora schema"
|
|
7257
7551
|
},
|
|
7258
7552
|
subCommands: {
|
|
7259
|
-
types: (0,
|
|
7553
|
+
types: (0, import_citty8.defineCommand)({
|
|
7260
7554
|
meta: {
|
|
7261
7555
|
name: "types",
|
|
7262
7556
|
description: "Generate TypeScript types from your schema"
|
|
@@ -7280,7 +7574,7 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7280
7574
|
}
|
|
7281
7575
|
let schemaPath;
|
|
7282
7576
|
if (args.schema && typeof args.schema === "string") {
|
|
7283
|
-
schemaPath = (0,
|
|
7577
|
+
schemaPath = (0, import_node_path26.resolve)(args.schema);
|
|
7284
7578
|
} else {
|
|
7285
7579
|
const found = await findSchemaFile(projectRoot);
|
|
7286
7580
|
if (!found) {
|
|
@@ -7303,13 +7597,13 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7303
7597
|
}
|
|
7304
7598
|
const output = generateTypes(schema);
|
|
7305
7599
|
const outputFile = typeof args.output === "string" ? args.output : "kora/generated/types.ts";
|
|
7306
|
-
const outputPath = (0,
|
|
7307
|
-
await (0,
|
|
7308
|
-
await (0,
|
|
7600
|
+
const outputPath = (0, import_node_path26.resolve)(projectRoot, outputFile);
|
|
7601
|
+
await (0, import_promises17.mkdir)((0, import_node_path26.dirname)(outputPath), { recursive: true });
|
|
7602
|
+
await (0, import_promises17.writeFile)(outputPath, output, "utf-8");
|
|
7309
7603
|
logger.success(`Generated types at ${outputPath}`);
|
|
7310
7604
|
}
|
|
7311
7605
|
}),
|
|
7312
|
-
hooks: (0,
|
|
7606
|
+
hooks: (0, import_citty8.defineCommand)({
|
|
7313
7607
|
meta: {
|
|
7314
7608
|
name: "hooks",
|
|
7315
7609
|
description: "Generate per-collection React hook stubs"
|
|
@@ -7338,7 +7632,7 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7338
7632
|
}
|
|
7339
7633
|
let schemaPath;
|
|
7340
7634
|
if (args.schema && typeof args.schema === "string") {
|
|
7341
|
-
schemaPath = (0,
|
|
7635
|
+
schemaPath = (0, import_node_path26.resolve)(projectRoot, args.schema);
|
|
7342
7636
|
} else {
|
|
7343
7637
|
const found = await findSchemaFile(projectRoot);
|
|
7344
7638
|
if (!found) {
|
|
@@ -7352,13 +7646,13 @@ var generateCommand = (0, import_citty7.defineCommand)({
|
|
|
7352
7646
|
schemaPath = found;
|
|
7353
7647
|
}
|
|
7354
7648
|
const schema = await loadSchemaDefinition(schemaPath, projectRoot);
|
|
7355
|
-
const outputDir = typeof args.output === "string" ? (0,
|
|
7649
|
+
const outputDir = typeof args.output === "string" ? (0, import_node_path26.resolve)(projectRoot, args.output) : (0, import_node_path26.resolve)(projectRoot, "kora/generated/hooks");
|
|
7356
7650
|
const files = generateCollectionHooks(schema);
|
|
7357
7651
|
for (const [name, content] of files) {
|
|
7358
7652
|
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,
|
|
7653
|
+
const filePath = (0, import_node_path26.resolve)(outputDir, name);
|
|
7654
|
+
await (0, import_promises17.mkdir)((0, import_node_path26.dirname)(filePath), { recursive: true });
|
|
7655
|
+
await (0, import_promises17.writeFile)(filePath, adjusted, "utf-8");
|
|
7362
7656
|
}
|
|
7363
7657
|
logger.success(`Generated ${String(files.size)} hook file(s) at ${outputDir}`);
|
|
7364
7658
|
logger.step("Run `kora generate types` first if ../types is missing.");
|
|
@@ -7380,10 +7674,10 @@ function isSchemaDefinition2(value) {
|
|
|
7380
7674
|
}
|
|
7381
7675
|
|
|
7382
7676
|
// src/commands/logs/logs-command.ts
|
|
7383
|
-
var
|
|
7677
|
+
var import_citty9 = require("citty");
|
|
7384
7678
|
var DEFAULT_SYNC_PORT2 = 3001;
|
|
7385
7679
|
var EVENTS_ENDPOINT = "/__kora/events";
|
|
7386
|
-
var logsCommand = (0,
|
|
7680
|
+
var logsCommand = (0, import_citty9.defineCommand)({
|
|
7387
7681
|
meta: {
|
|
7388
7682
|
name: "logs",
|
|
7389
7683
|
description: "Stream real-time events from a Kora sync server"
|
|
@@ -7487,9 +7781,9 @@ var logsCommand = (0, import_citty8.defineCommand)({
|
|
|
7487
7781
|
});
|
|
7488
7782
|
|
|
7489
7783
|
// src/commands/migrate/migrate-command.ts
|
|
7490
|
-
var
|
|
7491
|
-
var
|
|
7492
|
-
var
|
|
7784
|
+
var import_promises18 = require("fs/promises");
|
|
7785
|
+
var import_node_path27 = require("path");
|
|
7786
|
+
var import_citty10 = require("citty");
|
|
7493
7787
|
init_fs_helpers();
|
|
7494
7788
|
|
|
7495
7789
|
// src/commands/migrate/migration-generator.ts
|
|
@@ -7833,6 +8127,14 @@ function mapFieldType(descriptor) {
|
|
|
7833
8127
|
return "INTEGER";
|
|
7834
8128
|
case "array":
|
|
7835
8129
|
return "TEXT";
|
|
8130
|
+
case "object":
|
|
8131
|
+
return "TEXT";
|
|
8132
|
+
case "json":
|
|
8133
|
+
return "TEXT";
|
|
8134
|
+
case "blob":
|
|
8135
|
+
return "TEXT";
|
|
8136
|
+
case "secret":
|
|
8137
|
+
return "TEXT";
|
|
7836
8138
|
case "richtext":
|
|
7837
8139
|
return "BLOB";
|
|
7838
8140
|
}
|
|
@@ -7848,7 +8150,7 @@ function quoteIdentifier(identifier) {
|
|
|
7848
8150
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(identifier)) {
|
|
7849
8151
|
throw new Error(`Invalid SQL identifier: ${identifier}`);
|
|
7850
8152
|
}
|
|
7851
|
-
return identifier
|
|
8153
|
+
return `"${identifier}"`;
|
|
7852
8154
|
}
|
|
7853
8155
|
function formatChange(change) {
|
|
7854
8156
|
switch (change.type) {
|
|
@@ -8084,7 +8386,7 @@ function generateOperationTransformModule(fromVersion, toVersion) {
|
|
|
8084
8386
|
init_schema_loader();
|
|
8085
8387
|
var SNAPSHOT_PATH = "kora/schema.snapshot.json";
|
|
8086
8388
|
var MIGRATIONS_DIR = "kora/migrations";
|
|
8087
|
-
var migrateCommand = (0,
|
|
8389
|
+
var migrateCommand = (0, import_citty10.defineCommand)({
|
|
8088
8390
|
meta: {
|
|
8089
8391
|
name: "migrate",
|
|
8090
8392
|
description: "Detect schema changes and generate/apply migrations"
|
|
@@ -8126,12 +8428,12 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8126
8428
|
throw new InvalidProjectError(process.cwd());
|
|
8127
8429
|
}
|
|
8128
8430
|
const config = await loadKoraConfig(projectRoot);
|
|
8129
|
-
const resolvedSchemaPath = typeof args.schema === "string" ? (0,
|
|
8431
|
+
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
8432
|
if (!resolvedSchemaPath) {
|
|
8131
8433
|
throw new SchemaNotFoundError(["src/schema.ts", "schema.ts", "src/schema.js", "schema.js"]);
|
|
8132
8434
|
}
|
|
8133
8435
|
const currentSchema = await loadSchemaDefinition(resolvedSchemaPath, projectRoot);
|
|
8134
|
-
const snapshotFile = (0,
|
|
8436
|
+
const snapshotFile = (0, import_node_path27.join)(projectRoot, SNAPSHOT_PATH);
|
|
8135
8437
|
const previousSchema = await readSchemaSnapshot(snapshotFile);
|
|
8136
8438
|
if (!previousSchema) {
|
|
8137
8439
|
if (args["dry-run"] === true) {
|
|
@@ -8144,7 +8446,7 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8144
8446
|
return;
|
|
8145
8447
|
}
|
|
8146
8448
|
const diff = diffSchemas(previousSchema, currentSchema);
|
|
8147
|
-
const outputDir = typeof args["output-dir"] === "string" ? (0,
|
|
8449
|
+
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
8450
|
if (!diff.hasChanges) {
|
|
8149
8451
|
logger.success("No schema changes detected.");
|
|
8150
8452
|
if (args.apply === true) {
|
|
@@ -8196,7 +8498,7 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8196
8498
|
logger.warn("Dry run enabled: no files written, no migrations applied.");
|
|
8197
8499
|
return;
|
|
8198
8500
|
}
|
|
8199
|
-
await (0,
|
|
8501
|
+
await (0, import_promises18.mkdir)(outputDir, { recursive: true });
|
|
8200
8502
|
const migrationPath = await writeMigrationFile(
|
|
8201
8503
|
outputDir,
|
|
8202
8504
|
diff.fromVersion,
|
|
@@ -8232,7 +8534,7 @@ var migrateCommand = (0, import_citty9.defineCommand)({
|
|
|
8232
8534
|
});
|
|
8233
8535
|
async function readSchemaSnapshot(path) {
|
|
8234
8536
|
try {
|
|
8235
|
-
const content = await (0,
|
|
8537
|
+
const content = await (0, import_promises18.readFile)(path, "utf-8");
|
|
8236
8538
|
return JSON.parse(content);
|
|
8237
8539
|
} catch {
|
|
8238
8540
|
return null;
|
|
@@ -8253,15 +8555,15 @@ function isInteractiveTerminal2() {
|
|
|
8253
8555
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
8254
8556
|
}
|
|
8255
8557
|
async function writeSchemaSnapshot(path, schema) {
|
|
8256
|
-
await (0,
|
|
8257
|
-
await (0,
|
|
8558
|
+
await (0, import_promises18.mkdir)((0, import_node_path27.dirname)(path), { recursive: true });
|
|
8559
|
+
await (0, import_promises18.writeFile)(path, `${JSON.stringify(schema, null, 2)}
|
|
8258
8560
|
`, "utf-8");
|
|
8259
8561
|
}
|
|
8260
8562
|
async function writeMigrationFile(outputDir, fromVersion, toVersion, generated) {
|
|
8261
|
-
const existing = await (0,
|
|
8563
|
+
const existing = await (0, import_promises18.readdir)(outputDir).catch(() => []);
|
|
8262
8564
|
const sequence = existing.filter((file) => /^\d{3}-/.test(file)).length + 1;
|
|
8263
8565
|
const filename = `${String(sequence).padStart(3, "0")}-v${fromVersion}-to-v${toVersion}.ts`;
|
|
8264
|
-
const path = (0,
|
|
8566
|
+
const path = (0, import_node_path27.join)(outputDir, filename);
|
|
8265
8567
|
const migrationId = filename.replace(/\.ts$/, "");
|
|
8266
8568
|
const fileContent = [
|
|
8267
8569
|
`export const up = ${JSON.stringify(generated.up, null, 2)} as const`,
|
|
@@ -8273,10 +8575,10 @@ async function writeMigrationFile(outputDir, fromVersion, toVersion, generated)
|
|
|
8273
8575
|
`export const containsBreakingChanges = ${generated.containsBreakingChanges}`,
|
|
8274
8576
|
""
|
|
8275
8577
|
].join("\n");
|
|
8276
|
-
await (0,
|
|
8277
|
-
const transformsPath = (0,
|
|
8278
|
-
await (0,
|
|
8279
|
-
await writeMigrationManifest((0,
|
|
8578
|
+
await (0, import_promises18.writeFile)(path, fileContent, "utf-8");
|
|
8579
|
+
const transformsPath = (0, import_node_path27.join)(outputDir, `${migrationId}.transforms.ts`);
|
|
8580
|
+
await (0, import_promises18.writeFile)(transformsPath, generateOperationTransformModule(fromVersion, toVersion), "utf-8");
|
|
8581
|
+
await writeMigrationManifest((0, import_node_path27.join)(outputDir, `${migrationId}.json`), {
|
|
8280
8582
|
id: migrationId,
|
|
8281
8583
|
fromVersion,
|
|
8282
8584
|
toVersion,
|
|
@@ -8288,22 +8590,22 @@ async function writeMigrationFile(outputDir, fromVersion, toVersion, generated)
|
|
|
8288
8590
|
return path;
|
|
8289
8591
|
}
|
|
8290
8592
|
async function writeMigrationManifest(path, manifest) {
|
|
8291
|
-
await (0,
|
|
8593
|
+
await (0, import_promises18.writeFile)(path, `${JSON.stringify(manifest, null, 2)}
|
|
8292
8594
|
`, "utf-8");
|
|
8293
8595
|
}
|
|
8294
8596
|
async function listMigrationManifests(outputDir) {
|
|
8295
|
-
const files = await (0,
|
|
8597
|
+
const files = await (0, import_promises18.readdir)(outputDir).catch(() => []);
|
|
8296
8598
|
const migrationFiles = files.filter((file) => /^\d{3}-.*\.ts$/.test(file)).sort((left, right) => left.localeCompare(right));
|
|
8297
8599
|
const manifests = [];
|
|
8298
8600
|
for (const file of migrationFiles) {
|
|
8299
8601
|
const id = file.replace(/\.ts$/, "");
|
|
8300
|
-
const manifestPath = (0,
|
|
8602
|
+
const manifestPath = (0, import_node_path27.join)(outputDir, `${id}.json`);
|
|
8301
8603
|
const jsonManifest = await readMigrationManifest(manifestPath);
|
|
8302
8604
|
if (jsonManifest) {
|
|
8303
8605
|
manifests.push({ ...jsonManifest, id });
|
|
8304
8606
|
continue;
|
|
8305
8607
|
}
|
|
8306
|
-
const migrationPath = (0,
|
|
8608
|
+
const migrationPath = (0, import_node_path27.join)(outputDir, file);
|
|
8307
8609
|
const sourceManifest = await readMigrationManifestFromSource(migrationPath, id);
|
|
8308
8610
|
manifests.push(sourceManifest);
|
|
8309
8611
|
}
|
|
@@ -8311,7 +8613,7 @@ async function listMigrationManifests(outputDir) {
|
|
|
8311
8613
|
}
|
|
8312
8614
|
async function readMigrationManifest(path) {
|
|
8313
8615
|
try {
|
|
8314
|
-
const content = await (0,
|
|
8616
|
+
const content = await (0, import_promises18.readFile)(path, "utf-8");
|
|
8315
8617
|
return JSON.parse(content);
|
|
8316
8618
|
} catch (error) {
|
|
8317
8619
|
const code = error.code;
|
|
@@ -8322,7 +8624,7 @@ async function readMigrationManifest(path) {
|
|
|
8322
8624
|
}
|
|
8323
8625
|
}
|
|
8324
8626
|
async function readMigrationManifestFromSource(path, id) {
|
|
8325
|
-
const content = await (0,
|
|
8627
|
+
const content = await (0, import_promises18.readFile)(path, "utf-8");
|
|
8326
8628
|
const versions = parseVersionsFromMigrationId(id);
|
|
8327
8629
|
return {
|
|
8328
8630
|
id,
|
|
@@ -8384,18 +8686,18 @@ function parseLiteralExport(source, exportName) {
|
|
|
8384
8686
|
}
|
|
8385
8687
|
function resolveSqliteApplyPath(dbArg, projectRoot, config) {
|
|
8386
8688
|
if (typeof dbArg === "string") {
|
|
8387
|
-
return (0,
|
|
8689
|
+
return (0, import_node_path27.resolve)(projectRoot, dbArg);
|
|
8388
8690
|
}
|
|
8389
8691
|
const sync = config?.dev?.sync;
|
|
8390
8692
|
if (typeof sync === "object" && sync !== null) {
|
|
8391
8693
|
if (sync.store === "sqlite") {
|
|
8392
|
-
return (0,
|
|
8694
|
+
return (0, import_node_path27.join)(projectRoot, "kora-sync.db");
|
|
8393
8695
|
}
|
|
8394
8696
|
if (typeof sync.store === "object" && sync.store !== null && sync.store.type === "sqlite") {
|
|
8395
8697
|
if (typeof sync.store.filename === "string" && sync.store.filename.length > 0) {
|
|
8396
|
-
return (0,
|
|
8698
|
+
return (0, import_node_path27.resolve)(projectRoot, sync.store.filename);
|
|
8397
8699
|
}
|
|
8398
|
-
return (0,
|
|
8700
|
+
return (0, import_node_path27.join)(projectRoot, "kora-sync.db");
|
|
8399
8701
|
}
|
|
8400
8702
|
}
|
|
8401
8703
|
return void 0;
|
|
@@ -8413,7 +8715,7 @@ function resolvePostgresConnectionString(config) {
|
|
|
8413
8715
|
}
|
|
8414
8716
|
|
|
8415
8717
|
// src/commands/status/status-command.ts
|
|
8416
|
-
var
|
|
8718
|
+
var import_citty11 = require("citty");
|
|
8417
8719
|
var DEFAULT_SYNC_PORT3 = 3001;
|
|
8418
8720
|
var STATUS_ENDPOINT2 = "/__kora/status";
|
|
8419
8721
|
async function fetchServerStatus(url, token) {
|
|
@@ -8440,7 +8742,7 @@ function formatUptime(ms) {
|
|
|
8440
8742
|
parts.push(`${seconds % 60}s`);
|
|
8441
8743
|
return parts.join(" ");
|
|
8442
8744
|
}
|
|
8443
|
-
var statusCommand = (0,
|
|
8745
|
+
var statusCommand = (0, import_citty11.defineCommand)({
|
|
8444
8746
|
meta: {
|
|
8445
8747
|
name: "status",
|
|
8446
8748
|
description: "Show Kora sync server status"
|
|
@@ -8545,10 +8847,10 @@ function printStatus(status, url, logger) {
|
|
|
8545
8847
|
}
|
|
8546
8848
|
|
|
8547
8849
|
// src/commands/studio/studio-command.ts
|
|
8548
|
-
var
|
|
8549
|
-
var
|
|
8550
|
-
var
|
|
8551
|
-
var studioCommand = (0,
|
|
8850
|
+
var import_node_fs9 = require("fs");
|
|
8851
|
+
var import_node_path30 = require("path");
|
|
8852
|
+
var import_citty12 = require("citty");
|
|
8853
|
+
var studioCommand = (0, import_citty12.defineCommand)({
|
|
8552
8854
|
meta: {
|
|
8553
8855
|
name: "studio",
|
|
8554
8856
|
description: "Kora Studio: visualize records, operations, and sync \u2014 or run the sync lab"
|
|
@@ -8597,7 +8899,7 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8597
8899
|
);
|
|
8598
8900
|
}
|
|
8599
8901
|
const { loadSchemaDefinition: loadSchemaDefinition2 } = await Promise.resolve().then(() => (init_schema_loader(), schema_loader_exports));
|
|
8600
|
-
const schema = await loadSchemaDefinition2((0,
|
|
8902
|
+
const schema = await loadSchemaDefinition2((0, import_node_path30.resolve)(process.cwd(), args.schema), process.cwd());
|
|
8601
8903
|
const { SpectatorManager: SpectatorManager2 } = await Promise.resolve().then(() => (init_spectator_manager(), spectator_manager_exports));
|
|
8602
8904
|
const spectator = new SpectatorManager2({
|
|
8603
8905
|
url: args.connect,
|
|
@@ -8624,7 +8926,7 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8624
8926
|
let schema = defaultLabSchema2();
|
|
8625
8927
|
if (typeof args.schema === "string") {
|
|
8626
8928
|
const { loadSchemaDefinition: loadSchemaDefinition2 } = await Promise.resolve().then(() => (init_schema_loader(), schema_loader_exports));
|
|
8627
|
-
schema = await loadSchemaDefinition2((0,
|
|
8929
|
+
schema = await loadSchemaDefinition2((0, import_node_path30.resolve)(process.cwd(), args.schema), process.cwd());
|
|
8628
8930
|
}
|
|
8629
8931
|
const initialDevices = args.devices !== void 0 ? Math.max(1, Number.parseInt(args.devices, 10) || 2) : 2;
|
|
8630
8932
|
const lab = new LabManager2(schema);
|
|
@@ -8649,8 +8951,8 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8649
8951
|
"Pass --db <path> to inspect a database, --lab for the sync laboratory, or --connect <wss url> for live spectator mode."
|
|
8650
8952
|
);
|
|
8651
8953
|
}
|
|
8652
|
-
const dbPath = (0,
|
|
8653
|
-
if (!(0,
|
|
8954
|
+
const dbPath = (0, import_node_path30.resolve)(process.cwd(), args.db);
|
|
8955
|
+
if (!(0, import_node_fs9.existsSync)(dbPath)) {
|
|
8654
8956
|
throw new Error(`Database file not found: ${dbPath}`);
|
|
8655
8957
|
}
|
|
8656
8958
|
const server = await startStudioServer2({ port, dbPath });
|
|
@@ -8668,12 +8970,13 @@ var studioCommand = (0, import_citty11.defineCommand)({
|
|
|
8668
8970
|
});
|
|
8669
8971
|
|
|
8670
8972
|
// src/bin.ts
|
|
8671
|
-
var main = (0,
|
|
8973
|
+
var main = (0, import_citty13.defineCommand)({
|
|
8672
8974
|
meta: {
|
|
8673
8975
|
name: "kora",
|
|
8674
|
-
description: "Kora.js
|
|
8976
|
+
description: "Kora.js, the offline-first application framework"
|
|
8675
8977
|
},
|
|
8676
8978
|
subCommands: {
|
|
8979
|
+
"agents-md": agentsCommand,
|
|
8677
8980
|
backup: backupCommand,
|
|
8678
8981
|
compact: compactCommand,
|
|
8679
8982
|
create: createCommand,
|
|
@@ -8687,5 +8990,5 @@ var main = (0, import_citty12.defineCommand)({
|
|
|
8687
8990
|
studio: studioCommand
|
|
8688
8991
|
}
|
|
8689
8992
|
});
|
|
8690
|
-
(0,
|
|
8993
|
+
(0, import_citty13.runMain)(main);
|
|
8691
8994
|
//# sourceMappingURL=bin.cjs.map
|