@korajs/cli 1.0.0-beta.1 → 1.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +597 -291
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +123 -36
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-EOWLAAIV.js → chunk-4IKCHRJ6.js} +273 -57
- package/dist/chunk-4IKCHRJ6.js.map +1 -0
- package/dist/{chunk-B5YS4STN.js → chunk-G2PBYMMA.js} +2 -2
- package/dist/{chunk-B5YS4STN.js.map → chunk-G2PBYMMA.js.map} +1 -1
- package/dist/{chunk-BWTKRKNJ.js → chunk-Z7GCXMGW.js} +9 -5
- package/dist/chunk-Z7GCXMGW.js.map +1 -0
- package/dist/create.cjs +8 -4
- package/dist/create.cjs.map +1 -1
- package/dist/create.js +2 -2
- package/dist/index.cjs +389 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +12 -2
- package/dist/{spectator-manager-E2LH2P54.js → spectator-manager-FTH2NFSE.js} +5 -2
- package/dist/spectator-manager-FTH2NFSE.js.map +1 -0
- package/package.json +10 -8
- package/templates/react-basic/README.md.hbs +1 -1
- package/templates/react-basic/src/main.tsx +1 -1
- package/templates/react-basic/src/vite-env.d.ts +1 -0
- package/templates/react-basic/vite.config.ts +7 -4
- package/templates/react-sync/README.md.hbs +6 -5
- package/templates/react-sync/server.ts +46 -3
- package/templates/react-sync/src/main.tsx +1 -1
- package/templates/react-sync/src/vite-env.d.ts +1 -0
- package/templates/react-sync/vite.config.ts +14 -4
- package/templates/react-tailwind/README.md.hbs +1 -1
- package/templates/react-tailwind/src/main.tsx +1 -1
- package/templates/react-tailwind/src/vite-env.d.ts +1 -0
- package/templates/react-tailwind/vite.config.ts +7 -4
- package/templates/react-tailwind-sync/README.md.hbs +6 -5
- package/templates/react-tailwind-sync/server.ts +46 -3
- package/templates/react-tailwind-sync/src/main.tsx +1 -1
- package/templates/react-tailwind-sync/src/vite-env.d.ts +1 -0
- package/templates/react-tailwind-sync/vite.config.ts +14 -4
- package/templates/svelte-basic/README.md.hbs +1 -1
- package/templates/svelte-basic/src/main.ts +1 -1
- package/templates/svelte-basic/vite.config.ts +4 -2
- package/templates/svelte-sync/README.md.hbs +6 -5
- package/templates/svelte-sync/server.ts +46 -3
- package/templates/svelte-sync/src/main.ts +1 -1
- package/templates/svelte-sync/src/vite-env.d.ts +1 -0
- package/templates/svelte-sync/vite.config.ts +11 -2
- package/templates/svelte-tailwind/README.md.hbs +1 -1
- package/templates/svelte-tailwind/src/main.ts +1 -1
- package/templates/svelte-tailwind/vite.config.ts +4 -2
- package/templates/svelte-tailwind-sync/README.md.hbs +6 -5
- package/templates/svelte-tailwind-sync/server.ts +46 -3
- package/templates/svelte-tailwind-sync/src/main.ts +1 -1
- package/templates/svelte-tailwind-sync/src/vite-env.d.ts +1 -0
- package/templates/svelte-tailwind-sync/vite.config.ts +11 -2
- package/templates/tauri-react/server.ts +44 -1
- package/templates/tauri-react/src/AppShell.tsx +1 -1
- package/templates/tauri-react/src/vite-env.d.ts +1 -0
- package/templates/vue-basic/README.md.hbs +1 -1
- package/templates/vue-basic/src/main.ts +1 -1
- package/templates/vue-basic/vite.config.ts +4 -2
- package/templates/vue-sync/README.md.hbs +6 -5
- package/templates/vue-sync/server.ts +46 -3
- package/templates/vue-sync/src/main.ts +1 -1
- package/templates/vue-sync/src/vite-env.d.ts +1 -0
- package/templates/vue-sync/vite.config.ts +11 -2
- package/templates/vue-tailwind/README.md.hbs +1 -1
- package/templates/vue-tailwind/src/main.ts +1 -1
- package/templates/vue-tailwind/vite.config.ts +4 -2
- package/templates/vue-tailwind-sync/README.md.hbs +6 -5
- package/templates/vue-tailwind-sync/server.ts +46 -3
- package/templates/vue-tailwind-sync/src/main.ts +1 -1
- package/templates/vue-tailwind-sync/src/vite-env.d.ts +1 -0
- package/templates/vue-tailwind-sync/vite.config.ts +11 -2
- package/dist/chunk-BWTKRKNJ.js.map +0 -1
- package/dist/chunk-EOWLAAIV.js.map +0 -1
- package/dist/spectator-manager-E2LH2P54.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AGENTS_FRAMEWORKS: () => AGENTS_FRAMEWORKS,
|
|
33
34
|
ClackPromptClient: () => ClackPromptClient,
|
|
34
35
|
CliError: () => CliError,
|
|
35
36
|
DEPLOY_PLATFORMS: () => DEPLOY_PLATFORMS,
|
|
@@ -48,13 +49,16 @@ __export(index_exports, {
|
|
|
48
49
|
StubDeployAdapter: () => StubDeployAdapter,
|
|
49
50
|
TEMPLATES: () => TEMPLATES,
|
|
50
51
|
TEMPLATE_INFO: () => TEMPLATE_INFO,
|
|
52
|
+
agentsCommand: () => agentsCommand,
|
|
51
53
|
applySyncProviderPreset: () => applySyncProviderPreset,
|
|
52
54
|
buildClient: () => buildClient,
|
|
53
55
|
bundleServer: () => bundleServer,
|
|
54
56
|
createDeployAdapter: () => createDeployAdapter,
|
|
55
57
|
createPromptClient: () => createPromptClient,
|
|
56
58
|
deployCommand: () => deployCommand,
|
|
59
|
+
detectFrameworkFromManifest: () => detectFrameworkFromManifest,
|
|
57
60
|
determineTemplateFromSelections: () => determineTemplateFromSelections,
|
|
61
|
+
generateAgentsMd: () => generateAgentsMd,
|
|
58
62
|
generateDeployPackageJson: () => generateDeployPackageJson,
|
|
59
63
|
generateDockerIgnore: () => generateDockerIgnore,
|
|
60
64
|
generateDockerfile: () => generateDockerfile,
|
|
@@ -63,6 +67,7 @@ __export(index_exports, {
|
|
|
63
67
|
generateTypes: () => generateTypes,
|
|
64
68
|
getCreatePreferencesOrDefault: () => getCreatePreferencesOrDefault,
|
|
65
69
|
getDefaultCreatePreferences: () => getDefaultCreatePreferences,
|
|
70
|
+
isAgentsFramework: () => isAgentsFramework,
|
|
66
71
|
isAuthValue: () => isAuthValue,
|
|
67
72
|
isDatabaseProviderValue: () => isDatabaseProviderValue,
|
|
68
73
|
isDatabaseValue: () => isDatabaseValue,
|
|
@@ -229,6 +234,311 @@ var DevServerError = class extends import_core.KoraError {
|
|
|
229
234
|
searchPath;
|
|
230
235
|
};
|
|
231
236
|
|
|
237
|
+
// src/commands/agents/agents-command.ts
|
|
238
|
+
var import_promises2 = require("fs/promises");
|
|
239
|
+
var import_node_path2 = require("path");
|
|
240
|
+
var import_citty = require("citty");
|
|
241
|
+
|
|
242
|
+
// src/utils/fs-helpers.ts
|
|
243
|
+
var import_promises = require("fs/promises");
|
|
244
|
+
var import_node_path = require("path");
|
|
245
|
+
async function findProjectRoot(startDir) {
|
|
246
|
+
let current = (0, import_node_path.resolve)(startDir ?? process.cwd());
|
|
247
|
+
for (; ; ) {
|
|
248
|
+
const pkgPath = (0, import_node_path.join)(current, "package.json");
|
|
249
|
+
try {
|
|
250
|
+
const content = await (0, import_promises.readFile)(pkgPath, "utf-8");
|
|
251
|
+
const pkg = JSON.parse(content);
|
|
252
|
+
if (isKoraProject(pkg)) {
|
|
253
|
+
return current;
|
|
254
|
+
}
|
|
255
|
+
} catch {
|
|
256
|
+
}
|
|
257
|
+
const parent = (0, import_node_path.dirname)(current);
|
|
258
|
+
if (parent === current) break;
|
|
259
|
+
current = parent;
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
async function resolveProjectBinaryEntryPoint(projectRoot, packageName, binaryName) {
|
|
264
|
+
const pkgJsonPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, "package.json");
|
|
265
|
+
try {
|
|
266
|
+
const content = await (0, import_promises.readFile)(pkgJsonPath, "utf-8");
|
|
267
|
+
const pkg = JSON.parse(content);
|
|
268
|
+
let binPath;
|
|
269
|
+
if (typeof pkg.bin === "string") {
|
|
270
|
+
binPath = pkg.bin;
|
|
271
|
+
} else if (typeof pkg.bin === "object" && pkg.bin !== null) {
|
|
272
|
+
binPath = pkg.bin[binaryName];
|
|
273
|
+
}
|
|
274
|
+
if (!binPath) return null;
|
|
275
|
+
const fullPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, binPath);
|
|
276
|
+
await (0, import_promises.access)(fullPath);
|
|
277
|
+
return fullPath;
|
|
278
|
+
} catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function isKoraProject(pkg) {
|
|
283
|
+
if (typeof pkg !== "object" || pkg === null) return false;
|
|
284
|
+
const record = pkg;
|
|
285
|
+
return hasKoraDep(record.dependencies) || hasKoraDep(record.devDependencies);
|
|
286
|
+
}
|
|
287
|
+
function hasKoraDep(deps) {
|
|
288
|
+
if (typeof deps !== "object" || deps === null) return false;
|
|
289
|
+
return Object.keys(deps).some((key) => key === "kora" || key.startsWith("@korajs/"));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// src/utils/logger.ts
|
|
293
|
+
var RESET = "\x1B[0m";
|
|
294
|
+
var BOLD = "\x1B[1m";
|
|
295
|
+
var DIM = "\x1B[2m";
|
|
296
|
+
var GREEN = "\x1B[32m";
|
|
297
|
+
var YELLOW = "\x1B[33m";
|
|
298
|
+
var RED = "\x1B[31m";
|
|
299
|
+
var CYAN = "\x1B[36m";
|
|
300
|
+
function createLogger(options) {
|
|
301
|
+
const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
|
|
302
|
+
function color(code, text) {
|
|
303
|
+
return colorDisabled ? text : `${code}${text}${RESET}`;
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
info(message) {
|
|
307
|
+
console.log(color(CYAN, message));
|
|
308
|
+
},
|
|
309
|
+
success(message) {
|
|
310
|
+
console.log(color(GREEN, ` \u2713 ${message}`));
|
|
311
|
+
},
|
|
312
|
+
warn(message) {
|
|
313
|
+
console.warn(color(YELLOW, ` \u26A0 ${message}`));
|
|
314
|
+
},
|
|
315
|
+
error(message) {
|
|
316
|
+
console.error(color(RED, ` \u2717 ${message}`));
|
|
317
|
+
},
|
|
318
|
+
step(message) {
|
|
319
|
+
console.log(color(DIM, ` ${message}`));
|
|
320
|
+
},
|
|
321
|
+
blank() {
|
|
322
|
+
console.log();
|
|
323
|
+
},
|
|
324
|
+
banner() {
|
|
325
|
+
console.log();
|
|
326
|
+
console.log(
|
|
327
|
+
color(BOLD + CYAN, " Kora.js") + color(DIM, ", the offline-first application framework")
|
|
328
|
+
);
|
|
329
|
+
console.log();
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// src/commands/agents/agents-md-content.ts
|
|
335
|
+
var AGENTS_FRAMEWORKS = ["react", "vue", "svelte"];
|
|
336
|
+
function isAgentsFramework(value) {
|
|
337
|
+
return AGENTS_FRAMEWORKS.includes(value);
|
|
338
|
+
}
|
|
339
|
+
function detectFrameworkFromManifest(manifest) {
|
|
340
|
+
if (typeof manifest !== "object" || manifest === null) return null;
|
|
341
|
+
const record = manifest;
|
|
342
|
+
const deps = collectDependencyNames(record.dependencies, record.devDependencies);
|
|
343
|
+
if (deps.has("@korajs/react")) return "react";
|
|
344
|
+
if (deps.has("@korajs/vue")) return "vue";
|
|
345
|
+
if (deps.has("@korajs/svelte")) return "svelte";
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
function collectDependencyNames(...groups) {
|
|
349
|
+
const names = /* @__PURE__ */ new Set();
|
|
350
|
+
for (const group of groups) {
|
|
351
|
+
if (typeof group !== "object" || group === null) continue;
|
|
352
|
+
for (const name of Object.keys(group)) {
|
|
353
|
+
names.add(name);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return names;
|
|
357
|
+
}
|
|
358
|
+
var FRAMEWORK_BINDINGS = {
|
|
359
|
+
react: `## React bindings
|
|
360
|
+
|
|
361
|
+
\`\`\`tsx
|
|
362
|
+
import { KoraProvider, useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/react'
|
|
363
|
+
|
|
364
|
+
// Wrap the tree once near your app entry: <KoraProvider app={app}><App /></KoraProvider>
|
|
365
|
+
|
|
366
|
+
const todos = useCollection('todos')
|
|
367
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt'))
|
|
368
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
369
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
370
|
+
await addTodo.mutateAsync({ title: 'x' }) // resolves with the result; throws on failure
|
|
371
|
+
const status = useSyncStatus() // status.status, status.pendingOperations
|
|
372
|
+
\`\`\`
|
|
373
|
+
|
|
374
|
+
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.`,
|
|
375
|
+
vue: `## Vue bindings
|
|
376
|
+
|
|
377
|
+
\`\`\`ts
|
|
378
|
+
import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/vue'
|
|
379
|
+
|
|
380
|
+
const todos = useCollection('todos')
|
|
381
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // readonly reactive ref
|
|
382
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
383
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
384
|
+
const status = useSyncStatus() // status.status, status.pendingOperations
|
|
385
|
+
\`\`\`
|
|
386
|
+
|
|
387
|
+
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\`).`,
|
|
388
|
+
svelte: `## Svelte bindings
|
|
389
|
+
|
|
390
|
+
Kora's Svelte bindings from \`@korajs/svelte\` expose \`useCollection\`, \`useQuery\`, \`useMutation\`, and \`useSyncStatus\`, wired through the provider set up in your app entry.
|
|
391
|
+
|
|
392
|
+
\`\`\`ts
|
|
393
|
+
import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/svelte'
|
|
394
|
+
|
|
395
|
+
const todos = useCollection('todos')
|
|
396
|
+
const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // reactive store
|
|
397
|
+
const addTodo = useMutation((data) => todos.insert(data))
|
|
398
|
+
addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
|
|
399
|
+
const status = useSyncStatus() // readable store; read $status.status in markup
|
|
400
|
+
\`\`\`
|
|
401
|
+
|
|
402
|
+
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.`
|
|
403
|
+
};
|
|
404
|
+
function generateAgentsMd(framework) {
|
|
405
|
+
return `# AGENTS.md
|
|
406
|
+
|
|
407
|
+
Guidance for AI coding agents working in this project. Humans: this is useful for you too.
|
|
408
|
+
|
|
409
|
+
## What this project is
|
|
410
|
+
|
|
411
|
+
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.
|
|
412
|
+
|
|
413
|
+
## Golden rules
|
|
414
|
+
|
|
415
|
+
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.
|
|
416
|
+
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.
|
|
417
|
+
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.
|
|
418
|
+
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.
|
|
419
|
+
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.
|
|
420
|
+
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.
|
|
421
|
+
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.
|
|
422
|
+
|
|
423
|
+
## Data API cheat sheet
|
|
424
|
+
|
|
425
|
+
\`\`\`ts
|
|
426
|
+
await app.ready
|
|
427
|
+
const rec = await app.todos.insert({ title: 'x' }) // defaults and .auto() fields applied
|
|
428
|
+
await app.todos.update(rec.id, { completed: true }) // partial update, changed fields only
|
|
429
|
+
await app.todos.delete(rec.id)
|
|
430
|
+
const one = await app.todos.findById(rec.id)
|
|
431
|
+
const unsubscribe = app.todos
|
|
432
|
+
.where({ completed: false })
|
|
433
|
+
.orderBy('createdAt', 'desc')
|
|
434
|
+
.subscribe((rows) => {/* fires immediately, then on every change */})
|
|
435
|
+
\`\`\`
|
|
436
|
+
|
|
437
|
+
Schema example (\`src/schema.ts\`):
|
|
438
|
+
|
|
439
|
+
\`\`\`ts
|
|
440
|
+
import { defineSchema, t } from 'korajs'
|
|
441
|
+
|
|
442
|
+
export default defineSchema({
|
|
443
|
+
version: 1,
|
|
444
|
+
collections: {
|
|
445
|
+
todos: {
|
|
446
|
+
fields: {
|
|
447
|
+
title: t.string(),
|
|
448
|
+
completed: t.boolean().default(false),
|
|
449
|
+
tags: t.array(t.string()).default([]),
|
|
450
|
+
priority: t.enum(['low', 'medium', 'high']).default('medium'),
|
|
451
|
+
createdAt: t.timestamp().auto(), // set automatically; never pass it on insert
|
|
452
|
+
},
|
|
453
|
+
indexes: ['completed', 'createdAt'],
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
})
|
|
457
|
+
\`\`\`
|
|
458
|
+
|
|
459
|
+
If you change collection shapes, increment \`version\` and run \`npx kora migrate\`.
|
|
460
|
+
|
|
461
|
+
## Conflict handling
|
|
462
|
+
|
|
463
|
+
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.
|
|
464
|
+
|
|
465
|
+
## Sync and auth
|
|
466
|
+
|
|
467
|
+
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.
|
|
468
|
+
|
|
469
|
+
${FRAMEWORK_BINDINGS[framework]}
|
|
470
|
+
|
|
471
|
+
## Commands
|
|
472
|
+
|
|
473
|
+
- \`npx kora dev\` runs the dev environment (app server, local sync server when configured, schema watcher).
|
|
474
|
+
- \`npx kora doctor\` diagnoses a broken setup.
|
|
475
|
+
- \`npx kora migrate\` applies a schema change to the local store.
|
|
476
|
+
- In a running app, the DevTools overlay (Ctrl+Shift+K, Cmd+Shift+K on macOS) inspects operations, merges, and sync status.
|
|
477
|
+
`;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/commands/agents/agents-command.ts
|
|
481
|
+
async function fileExists(path) {
|
|
482
|
+
try {
|
|
483
|
+
await (0, import_promises2.access)(path);
|
|
484
|
+
return true;
|
|
485
|
+
} catch {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
async function readManifest(root) {
|
|
490
|
+
try {
|
|
491
|
+
return JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.join)(root, "package.json"), "utf-8"));
|
|
492
|
+
} catch {
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function resolveFramework(override, manifest) {
|
|
497
|
+
if (override !== void 0 && isAgentsFramework(override)) return override;
|
|
498
|
+
return detectFrameworkFromManifest(manifest) ?? "react";
|
|
499
|
+
}
|
|
500
|
+
var agentsCommand = (0, import_citty.defineCommand)({
|
|
501
|
+
meta: {
|
|
502
|
+
name: "agents-md",
|
|
503
|
+
description: "Write an AGENTS.md with Kora rules for AI coding agents into this project"
|
|
504
|
+
},
|
|
505
|
+
args: {
|
|
506
|
+
force: {
|
|
507
|
+
type: "boolean",
|
|
508
|
+
description: "Overwrite an existing AGENTS.md",
|
|
509
|
+
default: false
|
|
510
|
+
},
|
|
511
|
+
framework: {
|
|
512
|
+
type: "string",
|
|
513
|
+
description: "Override framework detection (react, vue, or svelte)"
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
async run({ args }) {
|
|
517
|
+
const logger = createLogger();
|
|
518
|
+
const projectRoot = await findProjectRoot() ?? process.cwd();
|
|
519
|
+
const manifest = await readManifest(projectRoot);
|
|
520
|
+
const override = typeof args.framework === "string" ? args.framework : void 0;
|
|
521
|
+
if (override !== void 0 && !isAgentsFramework(override)) {
|
|
522
|
+
logger.error(`Unknown framework "${override}". Use one of: react, vue, svelte.`);
|
|
523
|
+
process.exitCode = 1;
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const framework = resolveFramework(override, manifest);
|
|
527
|
+
const target = (0, import_node_path2.join)(projectRoot, "AGENTS.md");
|
|
528
|
+
const force = args.force === true;
|
|
529
|
+
if (await fileExists(target) && !force) {
|
|
530
|
+
logger.warn("AGENTS.md already exists. Re-run with --force to overwrite it.");
|
|
531
|
+
process.exitCode = 1;
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
await (0, import_promises2.writeFile)(target, generateAgentsMd(framework), "utf-8");
|
|
535
|
+
logger.banner();
|
|
536
|
+
logger.success(`Wrote AGENTS.md (${framework} bindings) to ${target}`);
|
|
537
|
+
logger.step("Commit it so coding agents pick up Kora conventions automatically.");
|
|
538
|
+
logger.blank();
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
|
|
232
542
|
// src/commands/generate/type-generator.ts
|
|
233
543
|
function generateTypes(schema) {
|
|
234
544
|
const lines = [
|
|
@@ -328,8 +638,8 @@ function toPascalCase(name) {
|
|
|
328
638
|
|
|
329
639
|
// src/commands/deploy/deploy-command.ts
|
|
330
640
|
var import_node_fs2 = require("fs");
|
|
331
|
-
var
|
|
332
|
-
var
|
|
641
|
+
var import_node_path13 = require("path");
|
|
642
|
+
var import_citty2 = require("citty");
|
|
333
643
|
|
|
334
644
|
// src/prompts/prompt-client.ts
|
|
335
645
|
var import_prompts = require("@clack/prompts");
|
|
@@ -499,98 +809,6 @@ var ClackPromptClient = class {
|
|
|
499
809
|
}
|
|
500
810
|
};
|
|
501
811
|
|
|
502
|
-
// src/utils/fs-helpers.ts
|
|
503
|
-
var import_promises = require("fs/promises");
|
|
504
|
-
var import_node_path = require("path");
|
|
505
|
-
async function findProjectRoot(startDir) {
|
|
506
|
-
let current = (0, import_node_path.resolve)(startDir ?? process.cwd());
|
|
507
|
-
for (; ; ) {
|
|
508
|
-
const pkgPath = (0, import_node_path.join)(current, "package.json");
|
|
509
|
-
try {
|
|
510
|
-
const content = await (0, import_promises.readFile)(pkgPath, "utf-8");
|
|
511
|
-
const pkg = JSON.parse(content);
|
|
512
|
-
if (isKoraProject(pkg)) {
|
|
513
|
-
return current;
|
|
514
|
-
}
|
|
515
|
-
} catch {
|
|
516
|
-
}
|
|
517
|
-
const parent = (0, import_node_path.dirname)(current);
|
|
518
|
-
if (parent === current) break;
|
|
519
|
-
current = parent;
|
|
520
|
-
}
|
|
521
|
-
return null;
|
|
522
|
-
}
|
|
523
|
-
async function resolveProjectBinaryEntryPoint(projectRoot, packageName, binaryName) {
|
|
524
|
-
const pkgJsonPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, "package.json");
|
|
525
|
-
try {
|
|
526
|
-
const content = await (0, import_promises.readFile)(pkgJsonPath, "utf-8");
|
|
527
|
-
const pkg = JSON.parse(content);
|
|
528
|
-
let binPath;
|
|
529
|
-
if (typeof pkg.bin === "string") {
|
|
530
|
-
binPath = pkg.bin;
|
|
531
|
-
} else if (typeof pkg.bin === "object" && pkg.bin !== null) {
|
|
532
|
-
binPath = pkg.bin[binaryName];
|
|
533
|
-
}
|
|
534
|
-
if (!binPath) return null;
|
|
535
|
-
const fullPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, binPath);
|
|
536
|
-
await (0, import_promises.access)(fullPath);
|
|
537
|
-
return fullPath;
|
|
538
|
-
} catch {
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
function isKoraProject(pkg) {
|
|
543
|
-
if (typeof pkg !== "object" || pkg === null) return false;
|
|
544
|
-
const record = pkg;
|
|
545
|
-
return hasKoraDep(record.dependencies) || hasKoraDep(record.devDependencies);
|
|
546
|
-
}
|
|
547
|
-
function hasKoraDep(deps) {
|
|
548
|
-
if (typeof deps !== "object" || deps === null) return false;
|
|
549
|
-
return Object.keys(deps).some((key) => key === "kora" || key.startsWith("@korajs/"));
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// src/utils/logger.ts
|
|
553
|
-
var RESET = "\x1B[0m";
|
|
554
|
-
var BOLD = "\x1B[1m";
|
|
555
|
-
var DIM = "\x1B[2m";
|
|
556
|
-
var GREEN = "\x1B[32m";
|
|
557
|
-
var YELLOW = "\x1B[33m";
|
|
558
|
-
var RED = "\x1B[31m";
|
|
559
|
-
var CYAN = "\x1B[36m";
|
|
560
|
-
function createLogger(options) {
|
|
561
|
-
const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
|
|
562
|
-
function color(code, text) {
|
|
563
|
-
return colorDisabled ? text : `${code}${text}${RESET}`;
|
|
564
|
-
}
|
|
565
|
-
return {
|
|
566
|
-
info(message) {
|
|
567
|
-
console.log(color(CYAN, message));
|
|
568
|
-
},
|
|
569
|
-
success(message) {
|
|
570
|
-
console.log(color(GREEN, ` \u2713 ${message}`));
|
|
571
|
-
},
|
|
572
|
-
warn(message) {
|
|
573
|
-
console.warn(color(YELLOW, ` \u26A0 ${message}`));
|
|
574
|
-
},
|
|
575
|
-
error(message) {
|
|
576
|
-
console.error(color(RED, ` \u2717 ${message}`));
|
|
577
|
-
},
|
|
578
|
-
step(message) {
|
|
579
|
-
console.log(color(DIM, ` ${message}`));
|
|
580
|
-
},
|
|
581
|
-
blank() {
|
|
582
|
-
console.log();
|
|
583
|
-
},
|
|
584
|
-
banner() {
|
|
585
|
-
console.log();
|
|
586
|
-
console.log(
|
|
587
|
-
color(BOLD + CYAN, " Kora.js") + color(DIM, " \u2014 Offline-first application framework")
|
|
588
|
-
);
|
|
589
|
-
console.log();
|
|
590
|
-
}
|
|
591
|
-
};
|
|
592
|
-
}
|
|
593
|
-
|
|
594
812
|
// src/commands/deploy/adapters/adapter.ts
|
|
595
813
|
var DEPLOY_PLATFORMS = [
|
|
596
814
|
"fly",
|
|
@@ -607,13 +825,13 @@ function isDeployPlatform(value) {
|
|
|
607
825
|
|
|
608
826
|
// src/commands/deploy/adapters/aws-ecs-adapter.ts
|
|
609
827
|
var import_node_child_process2 = require("child_process");
|
|
610
|
-
var
|
|
828
|
+
var import_node_path5 = require("path");
|
|
611
829
|
|
|
612
830
|
// src/commands/deploy/builder/client-builder.ts
|
|
613
831
|
var import_node_child_process = require("child_process");
|
|
614
832
|
var import_node_fs = require("fs");
|
|
615
|
-
var
|
|
616
|
-
var
|
|
833
|
+
var import_promises3 = require("fs/promises");
|
|
834
|
+
var import_node_path3 = require("path");
|
|
617
835
|
async function buildClient(options) {
|
|
618
836
|
const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
|
|
619
837
|
if (!viteEntryPoint) {
|
|
@@ -634,15 +852,15 @@ async function buildClient(options) {
|
|
|
634
852
|
return { outDir: options.outDir };
|
|
635
853
|
}
|
|
636
854
|
async function patchSqliteWasmAssets(projectRoot, outDir) {
|
|
637
|
-
const assetsDir = (0,
|
|
855
|
+
const assetsDir = (0, import_node_path3.join)(outDir, "assets");
|
|
638
856
|
if (!(0, import_node_fs.existsSync)(assetsDir)) return;
|
|
639
|
-
const files = await (0,
|
|
857
|
+
const files = await (0, import_promises3.readdir)(assetsDir);
|
|
640
858
|
const hashedWasm = files.find((f) => /^sqlite3-.+\.wasm$/.test(f));
|
|
641
859
|
if (hashedWasm && !files.includes("sqlite3.wasm")) {
|
|
642
|
-
await (0,
|
|
860
|
+
await (0, import_promises3.copyFile)((0, import_node_path3.join)(assetsDir, hashedWasm), (0, import_node_path3.join)(assetsDir, "sqlite3.wasm"));
|
|
643
861
|
}
|
|
644
862
|
if (!files.includes("sqlite3-opfs-async-proxy.js")) {
|
|
645
|
-
const proxyFile = (0,
|
|
863
|
+
const proxyFile = (0, import_node_path3.resolve)(
|
|
646
864
|
projectRoot,
|
|
647
865
|
"node_modules",
|
|
648
866
|
"@sqlite.org",
|
|
@@ -652,7 +870,7 @@ async function patchSqliteWasmAssets(projectRoot, outDir) {
|
|
|
652
870
|
"sqlite3-opfs-async-proxy.js"
|
|
653
871
|
);
|
|
654
872
|
if ((0, import_node_fs.existsSync)(proxyFile)) {
|
|
655
|
-
await (0,
|
|
873
|
+
await (0, import_promises3.copyFile)(proxyFile, (0, import_node_path3.join)(assetsDir, "sqlite3-opfs-async-proxy.js"));
|
|
656
874
|
}
|
|
657
875
|
}
|
|
658
876
|
}
|
|
@@ -677,9 +895,9 @@ async function runProcess(command, args, cwd) {
|
|
|
677
895
|
}
|
|
678
896
|
|
|
679
897
|
// src/commands/deploy/builder/server-bundler.ts
|
|
680
|
-
var import_promises3 = require("fs/promises");
|
|
681
898
|
var import_promises4 = require("fs/promises");
|
|
682
|
-
var
|
|
899
|
+
var import_promises5 = require("fs/promises");
|
|
900
|
+
var import_node_path4 = require("path");
|
|
683
901
|
var import_esbuild = require("esbuild");
|
|
684
902
|
var DEFAULT_ENTRY_CANDIDATES = [
|
|
685
903
|
"server.ts",
|
|
@@ -695,8 +913,8 @@ async function bundleServer(options) {
|
|
|
695
913
|
`Could not find a server entry file in ${options.projectRoot}. Looked for: ${candidates.join(", ")}`
|
|
696
914
|
);
|
|
697
915
|
}
|
|
698
|
-
await (0,
|
|
699
|
-
const outputFilePath = (0,
|
|
916
|
+
await (0, import_promises4.mkdir)(options.deployDirectory, { recursive: true });
|
|
917
|
+
const outputFilePath = (0, import_node_path4.join)(options.deployDirectory, "server-bundled.js");
|
|
700
918
|
await (0, import_esbuild.build)({
|
|
701
919
|
entryPoints: [entryFilePath],
|
|
702
920
|
outfile: outputFilePath,
|
|
@@ -718,9 +936,9 @@ async function bundleServer(options) {
|
|
|
718
936
|
}
|
|
719
937
|
async function resolveServerEntry(projectRoot, candidates) {
|
|
720
938
|
for (const candidate of candidates) {
|
|
721
|
-
const fullPath = (0,
|
|
939
|
+
const fullPath = (0, import_node_path4.join)(projectRoot, candidate);
|
|
722
940
|
try {
|
|
723
|
-
await (0,
|
|
941
|
+
await (0, import_promises5.access)(fullPath);
|
|
724
942
|
return fullPath;
|
|
725
943
|
} catch {
|
|
726
944
|
}
|
|
@@ -822,19 +1040,19 @@ var AwsEcsAdapter = class {
|
|
|
822
1040
|
appName: config.appName,
|
|
823
1041
|
region: config.region
|
|
824
1042
|
};
|
|
825
|
-
const deployDirectory = (0,
|
|
1043
|
+
const deployDirectory = (0, import_node_path5.join)(config.projectRoot, ".kora", "deploy");
|
|
826
1044
|
await bundleServer({
|
|
827
1045
|
projectRoot: config.projectRoot,
|
|
828
1046
|
deployDirectory
|
|
829
1047
|
});
|
|
830
1048
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
831
1049
|
projectRoot: config.projectRoot,
|
|
832
|
-
outDir: (0,
|
|
1050
|
+
outDir: (0, import_node_path5.join)(deployDirectory, "dist"),
|
|
833
1051
|
mode: "production"
|
|
834
1052
|
});
|
|
835
1053
|
return {
|
|
836
1054
|
clientDirectory: client?.outDir ?? null,
|
|
837
|
-
serverBundlePath: (0,
|
|
1055
|
+
serverBundlePath: (0, import_node_path5.join)(deployDirectory, "server-bundled.js"),
|
|
838
1056
|
deployDirectory
|
|
839
1057
|
};
|
|
840
1058
|
}
|
|
@@ -1100,7 +1318,7 @@ function inferLogLevel(line) {
|
|
|
1100
1318
|
|
|
1101
1319
|
// src/commands/deploy/adapters/aws-lightsail-adapter.ts
|
|
1102
1320
|
var import_node_child_process3 = require("child_process");
|
|
1103
|
-
var
|
|
1321
|
+
var import_node_path6 = require("path");
|
|
1104
1322
|
var AwsLightsailAdapter = class {
|
|
1105
1323
|
name = "aws-lightsail";
|
|
1106
1324
|
logger = createLogger();
|
|
@@ -1173,19 +1391,19 @@ var AwsLightsailAdapter = class {
|
|
|
1173
1391
|
appName: config.appName,
|
|
1174
1392
|
region: config.region
|
|
1175
1393
|
};
|
|
1176
|
-
const deployDirectory = (0,
|
|
1394
|
+
const deployDirectory = (0, import_node_path6.join)(config.projectRoot, ".kora", "deploy");
|
|
1177
1395
|
await bundleServer({
|
|
1178
1396
|
projectRoot: config.projectRoot,
|
|
1179
1397
|
deployDirectory
|
|
1180
1398
|
});
|
|
1181
1399
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
1182
1400
|
projectRoot: config.projectRoot,
|
|
1183
|
-
outDir: (0,
|
|
1401
|
+
outDir: (0, import_node_path6.join)(deployDirectory, "dist"),
|
|
1184
1402
|
mode: "production"
|
|
1185
1403
|
});
|
|
1186
1404
|
return {
|
|
1187
1405
|
clientDirectory: client?.outDir ?? null,
|
|
1188
|
-
serverBundlePath: (0,
|
|
1406
|
+
serverBundlePath: (0, import_node_path6.join)(deployDirectory, "server-bundled.js"),
|
|
1189
1407
|
deployDirectory
|
|
1190
1408
|
};
|
|
1191
1409
|
}
|
|
@@ -1485,11 +1703,11 @@ function inferLogLevel2(line) {
|
|
|
1485
1703
|
|
|
1486
1704
|
// src/commands/deploy/adapters/fly-adapter.ts
|
|
1487
1705
|
var import_node_child_process4 = require("child_process");
|
|
1488
|
-
var
|
|
1706
|
+
var import_node_path8 = require("path");
|
|
1489
1707
|
|
|
1490
1708
|
// src/commands/deploy/artifacts/fly-toml-generator.ts
|
|
1491
|
-
var
|
|
1492
|
-
var
|
|
1709
|
+
var import_promises6 = require("fs/promises");
|
|
1710
|
+
var import_node_path7 = require("path");
|
|
1493
1711
|
var GENERATED_HEADER = "# Generated by kora deploy \u2014 do not edit manually";
|
|
1494
1712
|
function generateFlyToml(options) {
|
|
1495
1713
|
const internalPort = options.internalPort ?? 3e3;
|
|
@@ -1519,9 +1737,9 @@ function generateFlyToml(options) {
|
|
|
1519
1737
|
].join("\n");
|
|
1520
1738
|
}
|
|
1521
1739
|
async function writeFlyTomlArtifact(deployDirectory, options) {
|
|
1522
|
-
await (0,
|
|
1523
|
-
const filePath = (0,
|
|
1524
|
-
await (0,
|
|
1740
|
+
await (0, import_promises6.mkdir)(deployDirectory, { recursive: true });
|
|
1741
|
+
const filePath = (0, import_node_path7.join)(deployDirectory, "fly.toml");
|
|
1742
|
+
await (0, import_promises6.writeFile)(filePath, generateFlyToml(options), "utf-8");
|
|
1525
1743
|
return filePath;
|
|
1526
1744
|
}
|
|
1527
1745
|
|
|
@@ -1615,7 +1833,7 @@ var FlyAdapter = class {
|
|
|
1615
1833
|
appName: config.appName,
|
|
1616
1834
|
region: config.region
|
|
1617
1835
|
};
|
|
1618
|
-
const deployDirectory = (0,
|
|
1836
|
+
const deployDirectory = (0, import_node_path8.join)(config.projectRoot, ".kora", "deploy");
|
|
1619
1837
|
await writeFlyTomlArtifact(deployDirectory, {
|
|
1620
1838
|
appName: config.appName,
|
|
1621
1839
|
region: config.region ?? "iad"
|
|
@@ -1626,12 +1844,12 @@ var FlyAdapter = class {
|
|
|
1626
1844
|
});
|
|
1627
1845
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
1628
1846
|
projectRoot: config.projectRoot,
|
|
1629
|
-
outDir: (0,
|
|
1847
|
+
outDir: (0, import_node_path8.join)(deployDirectory, "dist"),
|
|
1630
1848
|
mode: "production"
|
|
1631
1849
|
});
|
|
1632
1850
|
return {
|
|
1633
1851
|
clientDirectory: client?.outDir ?? null,
|
|
1634
|
-
serverBundlePath: (0,
|
|
1852
|
+
serverBundlePath: (0, import_node_path8.join)(deployDirectory, "server-bundled.js"),
|
|
1635
1853
|
deployDirectory
|
|
1636
1854
|
};
|
|
1637
1855
|
}
|
|
@@ -1853,11 +2071,11 @@ ${stdout}`.toLowerCase();
|
|
|
1853
2071
|
|
|
1854
2072
|
// src/commands/deploy/adapters/railway-adapter.ts
|
|
1855
2073
|
var import_node_child_process5 = require("child_process");
|
|
1856
|
-
var
|
|
2074
|
+
var import_node_path10 = require("path");
|
|
1857
2075
|
|
|
1858
2076
|
// src/commands/deploy/artifacts/railway-json-generator.ts
|
|
1859
|
-
var
|
|
1860
|
-
var
|
|
2077
|
+
var import_promises7 = require("fs/promises");
|
|
2078
|
+
var import_node_path9 = require("path");
|
|
1861
2079
|
var GENERATED_HEADER2 = "Generated by kora deploy - do not edit manually.";
|
|
1862
2080
|
function generateRailwayJson(options) {
|
|
1863
2081
|
const file = {
|
|
@@ -1882,9 +2100,9 @@ function generateRailwayJson(options) {
|
|
|
1882
2100
|
`;
|
|
1883
2101
|
}
|
|
1884
2102
|
async function writeRailwayJsonArtifact(deployDirectory, options) {
|
|
1885
|
-
await (0,
|
|
1886
|
-
const filePath = (0,
|
|
1887
|
-
await (0,
|
|
2103
|
+
await (0, import_promises7.mkdir)(deployDirectory, { recursive: true });
|
|
2104
|
+
const filePath = (0, import_node_path9.join)(deployDirectory, "railway.json");
|
|
2105
|
+
await (0, import_promises7.writeFile)(filePath, generateRailwayJson(options), "utf-8");
|
|
1888
2106
|
return filePath;
|
|
1889
2107
|
}
|
|
1890
2108
|
|
|
@@ -1973,7 +2191,7 @@ var RailwayAdapter = class {
|
|
|
1973
2191
|
appName: config.appName,
|
|
1974
2192
|
region: config.region
|
|
1975
2193
|
};
|
|
1976
|
-
const deployDirectory = (0,
|
|
2194
|
+
const deployDirectory = (0, import_node_path10.join)(config.projectRoot, ".kora", "deploy");
|
|
1977
2195
|
await writeRailwayJsonArtifact(deployDirectory, {
|
|
1978
2196
|
appName: config.appName,
|
|
1979
2197
|
environment: config.environment
|
|
@@ -1984,12 +2202,12 @@ var RailwayAdapter = class {
|
|
|
1984
2202
|
});
|
|
1985
2203
|
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
1986
2204
|
projectRoot: config.projectRoot,
|
|
1987
|
-
outDir: (0,
|
|
2205
|
+
outDir: (0, import_node_path10.join)(deployDirectory, "dist"),
|
|
1988
2206
|
mode: "production"
|
|
1989
2207
|
});
|
|
1990
2208
|
return {
|
|
1991
2209
|
clientDirectory: client?.outDir ?? null,
|
|
1992
|
-
serverBundlePath: (0,
|
|
2210
|
+
serverBundlePath: (0, import_node_path10.join)(deployDirectory, "server-bundled.js"),
|
|
1993
2211
|
deployDirectory
|
|
1994
2212
|
};
|
|
1995
2213
|
}
|
|
@@ -2274,8 +2492,8 @@ function createDeployAdapter(platform) {
|
|
|
2274
2492
|
}
|
|
2275
2493
|
|
|
2276
2494
|
// src/commands/deploy/artifacts/dockerfile-generator.ts
|
|
2277
|
-
var
|
|
2278
|
-
var
|
|
2495
|
+
var import_promises8 = require("fs/promises");
|
|
2496
|
+
var import_node_path11 = require("path");
|
|
2279
2497
|
var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually";
|
|
2280
2498
|
function generateDockerfile(options = {}) {
|
|
2281
2499
|
const nodeVersion = options.nodeVersion ?? "20-alpine";
|
|
@@ -2341,37 +2559,37 @@ function generateDockerIgnore() {
|
|
|
2341
2559
|
].join("\n");
|
|
2342
2560
|
}
|
|
2343
2561
|
async function writeDockerfileArtifact(deployDirectory, options = {}) {
|
|
2344
|
-
await (0,
|
|
2345
|
-
const dockerfilePath = (0,
|
|
2346
|
-
await (0,
|
|
2562
|
+
await (0, import_promises8.mkdir)(deployDirectory, { recursive: true });
|
|
2563
|
+
const dockerfilePath = (0, import_node_path11.join)(deployDirectory, "Dockerfile");
|
|
2564
|
+
await (0, import_promises8.writeFile)(dockerfilePath, generateDockerfile(options), "utf-8");
|
|
2347
2565
|
if (options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0) {
|
|
2348
|
-
const pkgJsonPath = (0,
|
|
2349
|
-
await (0,
|
|
2566
|
+
const pkgJsonPath = (0, import_node_path11.join)(deployDirectory, "package.json");
|
|
2567
|
+
await (0, import_promises8.writeFile)(pkgJsonPath, generateDeployPackageJson(options.nativeDependencies), "utf-8");
|
|
2350
2568
|
}
|
|
2351
2569
|
return dockerfilePath;
|
|
2352
2570
|
}
|
|
2353
2571
|
async function writeDockerIgnoreArtifact(deployDirectory) {
|
|
2354
|
-
await (0,
|
|
2355
|
-
const dockerIgnorePath = (0,
|
|
2356
|
-
await (0,
|
|
2572
|
+
await (0, import_promises8.mkdir)(deployDirectory, { recursive: true });
|
|
2573
|
+
const dockerIgnorePath = (0, import_node_path11.join)(deployDirectory, ".dockerignore");
|
|
2574
|
+
await (0, import_promises8.writeFile)(dockerIgnorePath, generateDockerIgnore(), "utf-8");
|
|
2357
2575
|
return dockerIgnorePath;
|
|
2358
2576
|
}
|
|
2359
2577
|
|
|
2360
2578
|
// src/commands/deploy/state/deploy-state.ts
|
|
2361
|
-
var
|
|
2362
|
-
var
|
|
2363
|
-
var KORA_DEPLOY_DIRECTORY = (0,
|
|
2579
|
+
var import_promises9 = require("fs/promises");
|
|
2580
|
+
var import_node_path12 = require("path");
|
|
2581
|
+
var KORA_DEPLOY_DIRECTORY = (0, import_node_path12.join)(".kora", "deploy");
|
|
2364
2582
|
var DEPLOY_STATE_FILENAME = "deploy.json";
|
|
2365
2583
|
function resolveDeployDirectory(projectRoot) {
|
|
2366
|
-
return (0,
|
|
2584
|
+
return (0, import_node_path12.join)(projectRoot, KORA_DEPLOY_DIRECTORY);
|
|
2367
2585
|
}
|
|
2368
2586
|
function resolveDeployStatePath(projectRoot) {
|
|
2369
|
-
return (0,
|
|
2587
|
+
return (0, import_node_path12.join)(resolveDeployDirectory(projectRoot), DEPLOY_STATE_FILENAME);
|
|
2370
2588
|
}
|
|
2371
2589
|
async function readDeployState(projectRoot) {
|
|
2372
2590
|
const statePath = resolveDeployStatePath(projectRoot);
|
|
2373
2591
|
try {
|
|
2374
|
-
const source = await (0,
|
|
2592
|
+
const source = await (0, import_promises9.readFile)(statePath, "utf-8");
|
|
2375
2593
|
const parsed = JSON.parse(source);
|
|
2376
2594
|
return parseDeployState(parsed);
|
|
2377
2595
|
} catch (error) {
|
|
@@ -2418,13 +2636,13 @@ async function updateDeployState(projectRoot, patch, now = /* @__PURE__ */ new D
|
|
|
2418
2636
|
return nextState;
|
|
2419
2637
|
}
|
|
2420
2638
|
async function resetDeployState(projectRoot) {
|
|
2421
|
-
await (0,
|
|
2639
|
+
await (0, import_promises9.rm)(resolveDeployDirectory(projectRoot), { recursive: true, force: true });
|
|
2422
2640
|
}
|
|
2423
2641
|
async function persistDeployState(projectRoot, state) {
|
|
2424
2642
|
const deployDir = resolveDeployDirectory(projectRoot);
|
|
2425
2643
|
const statePath = resolveDeployStatePath(projectRoot);
|
|
2426
|
-
await (0,
|
|
2427
|
-
await (0,
|
|
2644
|
+
await (0, import_promises9.mkdir)(deployDir, { recursive: true });
|
|
2645
|
+
await (0, import_promises9.writeFile)(statePath, `${JSON.stringify(state, null, 2)}
|
|
2428
2646
|
`, "utf-8");
|
|
2429
2647
|
}
|
|
2430
2648
|
function parseDeployState(value) {
|
|
@@ -2474,7 +2692,7 @@ function readOptionalString(value, field) {
|
|
|
2474
2692
|
}
|
|
2475
2693
|
|
|
2476
2694
|
// src/commands/deploy/deploy-command.ts
|
|
2477
|
-
var deployCommand = (0,
|
|
2695
|
+
var deployCommand = (0, import_citty2.defineCommand)({
|
|
2478
2696
|
meta: {
|
|
2479
2697
|
name: "deploy",
|
|
2480
2698
|
description: "Deploy a Kora project to your selected platform"
|
|
@@ -2509,7 +2727,7 @@ var deployCommand = (0, import_citty.defineCommand)({
|
|
|
2509
2727
|
}
|
|
2510
2728
|
},
|
|
2511
2729
|
subCommands: {
|
|
2512
|
-
status: (0,
|
|
2730
|
+
status: (0, import_citty2.defineCommand)({
|
|
2513
2731
|
meta: {
|
|
2514
2732
|
name: "status",
|
|
2515
2733
|
description: "Show current deployment status"
|
|
@@ -2540,7 +2758,7 @@ var deployCommand = (0, import_citty.defineCommand)({
|
|
|
2540
2758
|
logger.step(`Sync URL: ${state.syncUrl ?? "n/a"}`);
|
|
2541
2759
|
}
|
|
2542
2760
|
}),
|
|
2543
|
-
rollback: (0,
|
|
2761
|
+
rollback: (0, import_citty2.defineCommand)({
|
|
2544
2762
|
meta: {
|
|
2545
2763
|
name: "rollback",
|
|
2546
2764
|
description: "Rollback the current deployment"
|
|
@@ -2571,7 +2789,7 @@ var deployCommand = (0, import_citty.defineCommand)({
|
|
|
2571
2789
|
logger.success(`Rolled back ${state.platform} deployment to ${deploymentId}.`);
|
|
2572
2790
|
}
|
|
2573
2791
|
}),
|
|
2574
|
-
logs: (0,
|
|
2792
|
+
logs: (0, import_citty2.defineCommand)({
|
|
2575
2793
|
meta: {
|
|
2576
2794
|
name: "logs",
|
|
2577
2795
|
description: "Read deployment logs"
|
|
@@ -2758,7 +2976,7 @@ function resolveAppName(argValue, storedValue, projectRoot, confirm) {
|
|
|
2758
2976
|
"Missing app name in --confirm mode. Provide --app or run an interactive deploy first."
|
|
2759
2977
|
);
|
|
2760
2978
|
}
|
|
2761
|
-
return sanitizeAppName((0,
|
|
2979
|
+
return sanitizeAppName((0, import_node_path13.basename)(projectRoot));
|
|
2762
2980
|
}
|
|
2763
2981
|
function resolveRegion(argValue, storedValue, confirm) {
|
|
2764
2982
|
if (typeof argValue === "string" && argValue.length > 0) return argValue;
|
|
@@ -2793,7 +3011,7 @@ function configureAdapterContext(adapter, context) {
|
|
|
2793
3011
|
}
|
|
2794
3012
|
}
|
|
2795
3013
|
function detectDeployTarget(projectRoot) {
|
|
2796
|
-
return (0, import_node_fs2.existsSync)((0,
|
|
3014
|
+
return (0, import_node_fs2.existsSync)((0, import_node_path13.join)(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
|
|
2797
3015
|
}
|
|
2798
3016
|
function hasContextSetter(adapter) {
|
|
2799
3017
|
return typeof adapter.setContext === "function";
|
|
@@ -3104,8 +3322,8 @@ function formatStoredPreferenceLabel(preferences) {
|
|
|
3104
3322
|
}
|
|
3105
3323
|
|
|
3106
3324
|
// src/commands/create/sync-provider-preset.ts
|
|
3107
|
-
var
|
|
3108
|
-
var
|
|
3325
|
+
var import_promises10 = require("fs/promises");
|
|
3326
|
+
var import_node_path14 = require("path");
|
|
3109
3327
|
async function applySyncProviderPreset(options) {
|
|
3110
3328
|
if (!isSyncTemplate(options.template)) {
|
|
3111
3329
|
return;
|
|
@@ -3115,10 +3333,10 @@ async function applySyncProviderPreset(options) {
|
|
|
3115
3333
|
}
|
|
3116
3334
|
const providerName = getProviderDisplayName(options.dbProvider);
|
|
3117
3335
|
const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
|
|
3118
|
-
const envPath = (0,
|
|
3119
|
-
const readmePath = (0,
|
|
3120
|
-
const existingReadme = await (0,
|
|
3121
|
-
const existingEnv = await (0,
|
|
3336
|
+
const envPath = (0, import_node_path14.join)(options.targetDir, ".env.example");
|
|
3337
|
+
const readmePath = (0, import_node_path14.join)(options.targetDir, "README.md");
|
|
3338
|
+
const existingReadme = await (0, import_promises10.readFile)(readmePath, "utf-8");
|
|
3339
|
+
const existingEnv = await (0, import_promises10.readFile)(envPath, "utf-8");
|
|
3122
3340
|
const trimmedReadme = existingReadme.trimEnd();
|
|
3123
3341
|
const trimmedEnv = existingEnv.trimEnd();
|
|
3124
3342
|
const envSuffix = [
|
|
@@ -3138,9 +3356,9 @@ async function applySyncProviderPreset(options) {
|
|
|
3138
3356
|
""
|
|
3139
3357
|
].join("\n");
|
|
3140
3358
|
const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
|
|
3141
|
-
await (0,
|
|
3359
|
+
await (0, import_promises10.writeFile)(envPath, `${trimmedEnv}${envSuffix}
|
|
3142
3360
|
`, "utf-8");
|
|
3143
|
-
await (0,
|
|
3361
|
+
await (0, import_promises10.writeFile)(readmePath, readmeTemplate, "utf-8");
|
|
3144
3362
|
}
|
|
3145
3363
|
function isSyncTemplate(template) {
|
|
3146
3364
|
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";
|
|
@@ -3183,6 +3401,7 @@ function getProviderConnectionStringExample(provider) {
|
|
|
3183
3401
|
}
|
|
3184
3402
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3185
3403
|
0 && (module.exports = {
|
|
3404
|
+
AGENTS_FRAMEWORKS,
|
|
3186
3405
|
ClackPromptClient,
|
|
3187
3406
|
CliError,
|
|
3188
3407
|
DEPLOY_PLATFORMS,
|
|
@@ -3201,13 +3420,16 @@ function getProviderConnectionStringExample(provider) {
|
|
|
3201
3420
|
StubDeployAdapter,
|
|
3202
3421
|
TEMPLATES,
|
|
3203
3422
|
TEMPLATE_INFO,
|
|
3423
|
+
agentsCommand,
|
|
3204
3424
|
applySyncProviderPreset,
|
|
3205
3425
|
buildClient,
|
|
3206
3426
|
bundleServer,
|
|
3207
3427
|
createDeployAdapter,
|
|
3208
3428
|
createPromptClient,
|
|
3209
3429
|
deployCommand,
|
|
3430
|
+
detectFrameworkFromManifest,
|
|
3210
3431
|
determineTemplateFromSelections,
|
|
3432
|
+
generateAgentsMd,
|
|
3211
3433
|
generateDeployPackageJson,
|
|
3212
3434
|
generateDockerIgnore,
|
|
3213
3435
|
generateDockerfile,
|
|
@@ -3216,6 +3438,7 @@ function getProviderConnectionStringExample(provider) {
|
|
|
3216
3438
|
generateTypes,
|
|
3217
3439
|
getCreatePreferencesOrDefault,
|
|
3218
3440
|
getDefaultCreatePreferences,
|
|
3441
|
+
isAgentsFramework,
|
|
3219
3442
|
isAuthValue,
|
|
3220
3443
|
isDatabaseProviderValue,
|
|
3221
3444
|
isDatabaseValue,
|