@korajs/cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +1609 -643
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1086 -139
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-CMSX76KM.js → chunk-3WNFM3QB.js} +103 -96
- package/dist/chunk-3WNFM3QB.js.map +1 -0
- package/dist/{chunk-MVP5PDT4.js → chunk-PSRM56B7.js} +2 -2
- package/dist/{chunk-YGVO4POI.js → chunk-SOTZIWIF.js} +27 -15
- package/dist/chunk-SOTZIWIF.js.map +1 -0
- package/dist/create.cjs +54 -47
- package/dist/create.cjs.map +1 -1
- package/dist/create.js +2 -2
- package/dist/index.cjs +78 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -2
- package/package.json +9 -3
- package/templates/react-basic/README.md.hbs +10 -1
- package/templates/react-basic/src/App.tsx +112 -126
- package/templates/react-basic/src/index.css +165 -159
- package/templates/react-basic/src/kora-worker.ts +0 -1
- package/templates/react-basic/src/main.tsx +12 -12
- package/templates/react-basic/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-basic/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-basic/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-basic/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-basic/src/schema.ts +6 -12
- package/templates/react-basic/src/vite-env.d.ts +17 -0
- package/templates/react-basic/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-basic/vite.config.ts +57 -50
- package/templates/react-sync/.env.example +19 -0
- package/templates/react-sync/README.md.hbs +43 -1
- package/templates/react-sync/package.json.hbs +3 -0
- package/templates/react-sync/server.ts +90 -26
- package/templates/react-sync/src/App.tsx +132 -130
- package/templates/react-sync/src/auth.ts +25 -0
- package/templates/react-sync/src/index.css +212 -165
- package/templates/react-sync/src/kora-worker.ts +0 -1
- package/templates/react-sync/src/main.tsx +34 -18
- package/templates/react-sync/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-sync/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-sync/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-sync/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-sync/src/schema.ts +6 -12
- package/templates/react-sync/src/vite-env.d.ts +17 -0
- package/templates/react-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-sync/vite.config.ts +67 -60
- package/templates/react-tailwind/README.md.hbs +10 -1
- package/templates/react-tailwind/src/App.tsx +186 -197
- package/templates/react-tailwind/src/index.css +3 -3
- package/templates/react-tailwind/src/kora-worker.ts +0 -1
- package/templates/react-tailwind/src/main.tsx +19 -12
- package/templates/react-tailwind/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-tailwind/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-tailwind/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-tailwind/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-tailwind/src/schema.ts +6 -12
- package/templates/react-tailwind/src/vite-env.d.ts +17 -0
- package/templates/react-tailwind/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-tailwind/vite.config.ts +57 -50
- package/templates/react-tailwind-sync/.env.example +19 -0
- package/templates/react-tailwind-sync/README.md.hbs +43 -1
- package/templates/react-tailwind-sync/package.json.hbs +3 -0
- package/templates/react-tailwind-sync/server.ts +90 -26
- package/templates/react-tailwind-sync/src/App.tsx +246 -222
- package/templates/react-tailwind-sync/src/auth.ts +25 -0
- package/templates/react-tailwind-sync/src/index.css +3 -3
- package/templates/react-tailwind-sync/src/kora-worker.ts +0 -1
- package/templates/react-tailwind-sync/src/main.tsx +48 -18
- package/templates/react-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-tailwind-sync/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-tailwind-sync/src/schema.ts +6 -12
- package/templates/react-tailwind-sync/src/vite-env.d.ts +17 -0
- package/templates/react-tailwind-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-tailwind-sync/vite.config.ts +67 -60
- package/templates/tauri-react/.env.example +20 -0
- package/templates/tauri-react/README.md.hbs +36 -1
- package/templates/tauri-react/dev.ts +11 -11
- package/templates/tauri-react/package.json.hbs +2 -0
- package/templates/tauri-react/server.ts +86 -12
- package/templates/tauri-react/src/App.tsx +769 -544
- package/templates/tauri-react/src/AppShell.tsx +125 -83
- package/templates/tauri-react/src/SetupScreen.tsx +257 -208
- package/templates/tauri-react/src/auth.ts +45 -0
- package/templates/tauri-react/src/main.tsx +3 -3
- package/templates/tauri-react/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/tauri-react/src/modules/todos/todo.queries.ts +5 -0
- package/templates/tauri-react/src/modules/todos/todo.schema.ts +10 -0
- package/templates/tauri-react/src/modules/todos/useTodos.ts +31 -0
- package/templates/tauri-react/src/schema.ts +6 -12
- package/templates/tauri-react/src/sync-config.ts +47 -47
- package/templates/tauri-react/src/updater.ts +15 -15
- package/templates/tauri-react/src/vite-env.d.ts +17 -0
- package/templates/tauri-react/src-tauri/tauri.conf.json +1 -1
- package/templates/tauri-react/tsconfig.json.hbs +14 -0
- package/templates/tauri-react/vite.config.ts +9 -9
- package/dist/chunk-CMSX76KM.js.map +0 -1
- package/dist/chunk-YGVO4POI.js.map +0 -1
- package/templates/tauri-react/tsconfig.json +0 -15
- /package/dist/{chunk-MVP5PDT4.js.map → chunk-PSRM56B7.js.map} +0 -0
|
@@ -372,10 +372,49 @@ async function resolveCreatePreferencesFlow(params) {
|
|
|
372
372
|
if (isTauri) {
|
|
373
373
|
effective.framework = "react";
|
|
374
374
|
effective.tailwind = false;
|
|
375
|
-
effective.sync = true;
|
|
376
|
-
effective.db = "sqlite";
|
|
377
|
-
effective.dbProvider = "none";
|
|
378
375
|
effective.auth = "none";
|
|
376
|
+
if (flags.sync !== void 0) {
|
|
377
|
+
effective.sync = flags.sync;
|
|
378
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
379
|
+
effective.sync = await prompts.confirm("Enable multi-device sync?", true);
|
|
380
|
+
}
|
|
381
|
+
if (flags.db !== void 0) {
|
|
382
|
+
if (!isDatabaseValue(flags.db)) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
effective.db = flags.db;
|
|
388
|
+
} else if (!effective.sync) {
|
|
389
|
+
effective.db = "none";
|
|
390
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
391
|
+
effective.db = await prompts.select("Sync server database:", [
|
|
392
|
+
{ label: "SQLite (zero-config; local, LAN, small teams)", value: "sqlite" },
|
|
393
|
+
{ label: "PostgreSQL (production-scale)", value: "postgres" }
|
|
394
|
+
]);
|
|
395
|
+
}
|
|
396
|
+
if (effective.db === "none") {
|
|
397
|
+
effective.sync = false;
|
|
398
|
+
}
|
|
399
|
+
if (effective.db !== "postgres") {
|
|
400
|
+
effective.dbProvider = "none";
|
|
401
|
+
} else if (flags.dbProvider !== void 0) {
|
|
402
|
+
if (!isDatabaseProviderValue(flags.dbProvider)) {
|
|
403
|
+
throw new Error(
|
|
404
|
+
`Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
effective.dbProvider = flags.dbProvider;
|
|
408
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
409
|
+
effective.dbProvider = await prompts.select("Database provider:", [
|
|
410
|
+
{ label: "Local Postgres", value: "local" },
|
|
411
|
+
{ label: "Supabase", value: "supabase" },
|
|
412
|
+
{ label: "Neon", value: "neon" },
|
|
413
|
+
{ label: "Railway", value: "railway" },
|
|
414
|
+
{ label: "Vercel Postgres", value: "vercel-postgres" },
|
|
415
|
+
{ label: "Custom connection string", value: "custom" }
|
|
416
|
+
]);
|
|
417
|
+
}
|
|
379
418
|
} else {
|
|
380
419
|
if (flags.framework !== void 0) {
|
|
381
420
|
if (!isFrameworkValue(flags.framework)) {
|
|
@@ -535,63 +574,31 @@ async function applySyncProviderPreset(options) {
|
|
|
535
574
|
}
|
|
536
575
|
const providerName = getProviderDisplayName(options.dbProvider);
|
|
537
576
|
const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
|
|
538
|
-
const serverPath = join(options.targetDir, "server.ts");
|
|
539
577
|
const envPath = join(options.targetDir, ".env.example");
|
|
540
578
|
const readmePath = join(options.targetDir, "README.md");
|
|
541
|
-
const serverTemplate = [
|
|
542
|
-
"import { createPostgresServerStore, createProductionServer } from '@korajs/server'",
|
|
543
|
-
"",
|
|
544
|
-
`// PostgreSQL provider preset: ${providerName}`,
|
|
545
|
-
"// Ensure DATABASE_URL is set in your environment.",
|
|
546
|
-
"",
|
|
547
|
-
"async function start(): Promise<void> {",
|
|
548
|
-
" const connectionString = process.env.DATABASE_URL || ''",
|
|
549
|
-
" if (connectionString.length === 0) {",
|
|
550
|
-
" throw new Error('DATABASE_URL is required for PostgreSQL sync server store.')",
|
|
551
|
-
" }",
|
|
552
|
-
"",
|
|
553
|
-
" const store = await createPostgresServerStore({ connectionString })",
|
|
554
|
-
" const server = createProductionServer({",
|
|
555
|
-
" store,",
|
|
556
|
-
" port: Number(process.env.PORT) || 3001,",
|
|
557
|
-
" staticDir: './dist',",
|
|
558
|
-
" syncPath: '/kora-sync',",
|
|
559
|
-
" })",
|
|
560
|
-
"",
|
|
561
|
-
" const url = await server.start()",
|
|
562
|
-
" console.log(`Kora app running at ${url}`)",
|
|
563
|
-
"}",
|
|
564
|
-
"",
|
|
565
|
-
"void start()",
|
|
566
|
-
""
|
|
567
|
-
].join("\n");
|
|
568
|
-
const envTemplate = [
|
|
569
|
-
"# Kora Sync Server",
|
|
570
|
-
"# WebSocket URL for the sync server (used by the client)",
|
|
571
|
-
"VITE_SYNC_URL=ws://localhost:3001",
|
|
572
|
-
"",
|
|
573
|
-
"# Sync server port",
|
|
574
|
-
"PORT=3001",
|
|
575
|
-
"",
|
|
576
|
-
`# PostgreSQL connection string (${providerName})`,
|
|
577
|
-
`# Example: ${providerConnectionString}`,
|
|
578
|
-
"DATABASE_URL=",
|
|
579
|
-
""
|
|
580
|
-
].join("\n");
|
|
581
579
|
const existingReadme = await readFile(readmePath, "utf-8");
|
|
580
|
+
const existingEnv = await readFile(envPath, "utf-8");
|
|
582
581
|
const trimmedReadme = existingReadme.trimEnd();
|
|
582
|
+
const trimmedEnv = existingEnv.trimEnd();
|
|
583
|
+
const envSuffix = [
|
|
584
|
+
"",
|
|
585
|
+
`# PostgreSQL provider preset: ${providerName}`,
|
|
586
|
+
`# Example: ${providerConnectionString}`
|
|
587
|
+
].join("\n");
|
|
583
588
|
const readmeSuffix = [
|
|
584
589
|
"",
|
|
585
590
|
"## PostgreSQL Provider Preset",
|
|
586
591
|
"",
|
|
587
592
|
`Selected DB provider: ${options.dbProvider}`,
|
|
588
593
|
"",
|
|
589
|
-
"This scaffold
|
|
594
|
+
"This scaffold keeps one sync server entrypoint. When `DATABASE_URL` is set, `server.ts` uses PostgreSQL. When it is empty, the same server uses SQLite at `KORA_SERVER_DB`.",
|
|
595
|
+
"",
|
|
596
|
+
"The generated server uses `createPostgresServerStore` automatically when `DATABASE_URL` is present.",
|
|
590
597
|
""
|
|
591
598
|
].join("\n");
|
|
592
599
|
const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
|
|
593
|
-
await writeFile(
|
|
594
|
-
|
|
600
|
+
await writeFile(envPath, `${trimmedEnv}${envSuffix}
|
|
601
|
+
`, "utf-8");
|
|
595
602
|
await writeFile(readmePath, readmeTemplate, "utf-8");
|
|
596
603
|
}
|
|
597
604
|
function isSyncTemplate(template) {
|
|
@@ -634,6 +641,48 @@ function getProviderConnectionStringExample(provider) {
|
|
|
634
641
|
}
|
|
635
642
|
}
|
|
636
643
|
|
|
644
|
+
// src/utils/logger.ts
|
|
645
|
+
var RESET = "\x1B[0m";
|
|
646
|
+
var BOLD = "\x1B[1m";
|
|
647
|
+
var DIM = "\x1B[2m";
|
|
648
|
+
var GREEN = "\x1B[32m";
|
|
649
|
+
var YELLOW = "\x1B[33m";
|
|
650
|
+
var RED = "\x1B[31m";
|
|
651
|
+
var CYAN = "\x1B[36m";
|
|
652
|
+
function createLogger(options) {
|
|
653
|
+
const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
|
|
654
|
+
function color(code, text) {
|
|
655
|
+
return colorDisabled ? text : `${code}${text}${RESET}`;
|
|
656
|
+
}
|
|
657
|
+
return {
|
|
658
|
+
info(message) {
|
|
659
|
+
console.log(color(CYAN, message));
|
|
660
|
+
},
|
|
661
|
+
success(message) {
|
|
662
|
+
console.log(color(GREEN, ` \u2713 ${message}`));
|
|
663
|
+
},
|
|
664
|
+
warn(message) {
|
|
665
|
+
console.warn(color(YELLOW, ` \u26A0 ${message}`));
|
|
666
|
+
},
|
|
667
|
+
error(message) {
|
|
668
|
+
console.error(color(RED, ` \u2717 ${message}`));
|
|
669
|
+
},
|
|
670
|
+
step(message) {
|
|
671
|
+
console.log(color(DIM, ` ${message}`));
|
|
672
|
+
},
|
|
673
|
+
blank() {
|
|
674
|
+
console.log();
|
|
675
|
+
},
|
|
676
|
+
banner() {
|
|
677
|
+
console.log();
|
|
678
|
+
console.log(
|
|
679
|
+
color(BOLD + CYAN, " Kora.js") + color(DIM, " \u2014 Offline-first application framework")
|
|
680
|
+
);
|
|
681
|
+
console.log();
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
637
686
|
// src/utils/fs-helpers.ts
|
|
638
687
|
import { access, readFile as readFile2 } from "fs/promises";
|
|
639
688
|
import { dirname, join as join2, resolve } from "path";
|
|
@@ -716,54 +765,18 @@ function hasKoraDep(deps) {
|
|
|
716
765
|
return Object.keys(deps).some((key) => key === "kora" || key.startsWith("@korajs/"));
|
|
717
766
|
}
|
|
718
767
|
|
|
719
|
-
// src/utils/logger.ts
|
|
720
|
-
var RESET = "\x1B[0m";
|
|
721
|
-
var BOLD = "\x1B[1m";
|
|
722
|
-
var DIM = "\x1B[2m";
|
|
723
|
-
var GREEN = "\x1B[32m";
|
|
724
|
-
var YELLOW = "\x1B[33m";
|
|
725
|
-
var RED = "\x1B[31m";
|
|
726
|
-
var CYAN = "\x1B[36m";
|
|
727
|
-
function createLogger(options) {
|
|
728
|
-
const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
|
|
729
|
-
function color(code, text) {
|
|
730
|
-
return colorDisabled ? text : `${code}${text}${RESET}`;
|
|
731
|
-
}
|
|
732
|
-
return {
|
|
733
|
-
info(message) {
|
|
734
|
-
console.log(color(CYAN, message));
|
|
735
|
-
},
|
|
736
|
-
success(message) {
|
|
737
|
-
console.log(color(GREEN, ` \u2713 ${message}`));
|
|
738
|
-
},
|
|
739
|
-
warn(message) {
|
|
740
|
-
console.warn(color(YELLOW, ` \u26A0 ${message}`));
|
|
741
|
-
},
|
|
742
|
-
error(message) {
|
|
743
|
-
console.error(color(RED, ` \u2717 ${message}`));
|
|
744
|
-
},
|
|
745
|
-
step(message) {
|
|
746
|
-
console.log(color(DIM, ` ${message}`));
|
|
747
|
-
},
|
|
748
|
-
blank() {
|
|
749
|
-
console.log();
|
|
750
|
-
},
|
|
751
|
-
banner() {
|
|
752
|
-
console.log();
|
|
753
|
-
console.log(
|
|
754
|
-
color(BOLD + CYAN, " Kora.js") + color(DIM, " \u2014 Offline-first application framework")
|
|
755
|
-
);
|
|
756
|
-
console.log();
|
|
757
|
-
}
|
|
758
|
-
};
|
|
759
|
-
}
|
|
760
|
-
|
|
761
768
|
export {
|
|
769
|
+
createLogger,
|
|
762
770
|
CliError,
|
|
763
771
|
ProjectExistsError,
|
|
764
772
|
SchemaNotFoundError,
|
|
765
773
|
InvalidProjectError,
|
|
766
774
|
DevServerError,
|
|
775
|
+
directoryExists,
|
|
776
|
+
findProjectRoot,
|
|
777
|
+
findSchemaFile,
|
|
778
|
+
hasTsxInstalled,
|
|
779
|
+
resolveProjectBinaryEntryPoint,
|
|
767
780
|
PreferenceStore,
|
|
768
781
|
getCreatePreferencesOrDefault,
|
|
769
782
|
getDefaultCreatePreferences,
|
|
@@ -775,12 +788,6 @@ export {
|
|
|
775
788
|
PACKAGE_MANAGERS,
|
|
776
789
|
TEMPLATES,
|
|
777
790
|
TEMPLATE_INFO,
|
|
778
|
-
directoryExists,
|
|
779
|
-
findProjectRoot,
|
|
780
|
-
findSchemaFile,
|
|
781
|
-
hasTsxInstalled,
|
|
782
|
-
resolveProjectBinaryEntryPoint,
|
|
783
|
-
createLogger,
|
|
784
791
|
determineTemplateFromSelections,
|
|
785
792
|
isFrameworkValue,
|
|
786
793
|
isAuthValue,
|
|
@@ -792,4 +799,4 @@ export {
|
|
|
792
799
|
validateProjectName,
|
|
793
800
|
applySyncProviderPreset
|
|
794
801
|
};
|
|
795
|
-
//# sourceMappingURL=chunk-
|
|
802
|
+
//# sourceMappingURL=chunk-3WNFM3QB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/prompts/preferences.ts","../src/prompts/prompt-client.ts","../src/utils/prompt.ts","../src/types.ts","../src/commands/create/options.ts","../src/commands/create/preferences-flow.ts","../src/commands/create/project-name.ts","../src/commands/create/sync-provider-preset.ts","../src/utils/logger.ts","../src/utils/fs-helpers.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\n\n/**\n * Base error class for all CLI errors.\n */\nexport class CliError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(message, 'CLI_ERROR', context)\n\t\tthis.name = 'CliError'\n\t}\n}\n\n/**\n * Thrown when the target project directory already exists.\n */\nexport class ProjectExistsError extends KoraError {\n\tconstructor(public readonly directory: string) {\n\t\tsuper(\n\t\t\t`Directory \"${directory}\" already exists. Choose a different name or remove the existing directory.`,\n\t\t\t'PROJECT_EXISTS',\n\t\t\t{ directory },\n\t\t)\n\t\tthis.name = 'ProjectExistsError'\n\t}\n}\n\n/**\n * Thrown when a schema file cannot be found in the project.\n */\nexport class SchemaNotFoundError extends KoraError {\n\tconstructor(public readonly searchedPaths: string[]) {\n\t\tsuper(\n\t\t\t`Could not find a schema file. Searched: ${searchedPaths.join(', ')}. Create a schema file using defineSchema() from @korajs/core.`,\n\t\t\t'SCHEMA_NOT_FOUND',\n\t\t\t{ searchedPaths },\n\t\t)\n\t\tthis.name = 'SchemaNotFoundError'\n\t}\n}\n\n/**\n * Thrown when a command is run outside a valid Kora project.\n */\nexport class InvalidProjectError extends KoraError {\n\tconstructor(public readonly directory: string) {\n\t\tsuper(\n\t\t\t`\"${directory}\" is not a valid Kora project. No package.json with a kora dependency found. Run this command from inside a Kora project.`,\n\t\t\t'INVALID_PROJECT',\n\t\t\t{ directory },\n\t\t)\n\t\tthis.name = 'InvalidProjectError'\n\t}\n}\n\n/**\n * Thrown when a required local dev server binary cannot be found.\n */\nexport class DevServerError extends KoraError {\n\tconstructor(\n\t\tpublic readonly binary: string,\n\t\tpublic readonly searchPath: string,\n\t) {\n\t\tsuper(\n\t\t\t`Could not find required binary \"${binary}\" at ${searchPath}. Install project dependencies and try again.`,\n\t\t\t'DEV_SERVER_ERROR',\n\t\t\t{ binary, searchPath },\n\t\t)\n\t\tthis.name = 'DevServerError'\n\t}\n}\n","import Conf from 'conf'\nimport type {\n\tAuthOption,\n\tDatabaseOption,\n\tDatabaseProviderOption,\n\tFrameworkOption,\n\tPlatformOption,\n} from '../commands/create/options'\nimport type { PackageManager } from '../types'\n\nexport interface CreatePreferences {\n\tplatform: PlatformOption\n\tframework: FrameworkOption\n\ttailwind: boolean\n\tsync: boolean\n\tdb: DatabaseOption\n\tdbProvider: DatabaseProviderOption\n\tauth: AuthOption\n\tpackageManager: PackageManager\n}\n\nconst DEFAULT_PREFERENCES: CreatePreferences = {\n\tplatform: 'web',\n\tframework: 'react',\n\ttailwind: true,\n\tsync: true,\n\tdb: 'sqlite',\n\tdbProvider: 'none',\n\tauth: 'none',\n\tpackageManager: 'pnpm',\n}\n\nconst PREFERENCES_KEY = 'create.defaults'\n\n/**\n * Preference store for scaffold-time defaults in `create-kora-app`.\n */\nexport class PreferenceStore {\n\tprivate readonly store: Conf<{ [PREFERENCES_KEY]?: CreatePreferences }>\n\n\tpublic constructor() {\n\t\tthis.store = new Conf<{ [PREFERENCES_KEY]?: CreatePreferences }>({\n\t\t\tprojectName: 'korajs-cli',\n\t\t})\n\t}\n\n\tpublic getCreatePreferences(): CreatePreferences | null {\n\t\treturn this.store.get(PREFERENCES_KEY) ?? null\n\t}\n\n\tpublic saveCreatePreferences(preferences: CreatePreferences): void {\n\t\tthis.store.set(PREFERENCES_KEY, preferences)\n\t}\n\n\tpublic clearCreatePreferences(): void {\n\t\tthis.store.delete(PREFERENCES_KEY)\n\t}\n}\n\n/**\n * Gets preferences from storage or returns defaults when not available.\n */\nexport function getCreatePreferencesOrDefault(store: PreferenceStore): CreatePreferences {\n\treturn store.getCreatePreferences() ?? DEFAULT_PREFERENCES\n}\n\nexport function getDefaultCreatePreferences(): CreatePreferences {\n\treturn { ...DEFAULT_PREFERENCES }\n}\n","import {\n\tcancel as clackCancel,\n\tconfirm as clackConfirm,\n\tintro as clackIntro,\n\tisCancel as clackIsCancel,\n\toutro as clackOutro,\n\tselect as clackSelect,\n\ttext as clackText,\n} from '@clack/prompts'\nimport { promptConfirm, promptSelect, promptText } from '../utils/prompt'\n\nexport interface SelectOption<T extends string> {\n\tlabel: string\n\tvalue: T\n\thint?: string\n\tdisabled?: boolean\n}\n\ntype ClackSelectOption<T extends string> = {\n\tvalue: T\n\tlabel?: string\n\thint?: string\n\tdisabled?: boolean\n}\n\nexport interface PromptClient {\n\ttext(message: string, defaultValue?: string): Promise<string>\n\tselect<T extends string>(message: string, options: readonly SelectOption<T>[]): Promise<T>\n\tconfirm(message: string, defaultValue?: boolean): Promise<boolean>\n\tintro(message: string): void\n\toutro(message: string): void\n}\n\nexport class PromptCancelledError extends Error {\n\tpublic constructor(message = 'Prompt cancelled by user') {\n\t\tsuper(message)\n\t\tthis.name = 'PromptCancelledError'\n\t}\n}\n\n/**\n * Prompt client backed by the current readline helpers.\n *\n * Phase 12 will introduce a richer prompt backend. This adapter keeps command\n * logic decoupled from the prompt implementation so we can migrate without\n * reshaping command behavior.\n */\nexport class ReadlinePromptClient implements PromptClient {\n\tpublic async text(message: string, defaultValue?: string): Promise<string> {\n\t\treturn promptText(message, defaultValue)\n\t}\n\n\tpublic async select<T extends string>(\n\t\tmessage: string,\n\t\toptions: readonly SelectOption<T>[],\n\t): Promise<T> {\n\t\treturn promptSelect(\n\t\t\tmessage,\n\t\t\toptions\n\t\t\t\t.filter((option) => option.disabled !== true)\n\t\t\t\t.map((option) => ({ label: option.label, value: option.value })),\n\t\t)\n\t}\n\n\tpublic async confirm(message: string, defaultValue = false): Promise<boolean> {\n\t\treturn promptConfirm(message, defaultValue)\n\t}\n\n\tpublic intro(message: string): void {\n\t\t// The readline backend does not provide intro/outro framing.\n\t\t// Keep no-op semantics for compatibility.\n\t\tvoid message\n\t}\n\n\tpublic outro(message: string): void {\n\t\t// The readline backend does not provide intro/outro framing.\n\t\t// Keep no-op semantics for compatibility.\n\t\tvoid message\n\t}\n}\n\n/**\n * Returns the default prompt client for interactive CLI flows.\n */\nexport function createPromptClient(): PromptClient {\n\tconst canUseInteractiveClack =\n\t\ttypeof process !== 'undefined' && process.stdin.isTTY && process.stdout.isTTY\n\tif (canUseInteractiveClack) {\n\t\treturn new ClackPromptClient()\n\t}\n\treturn new ReadlinePromptClient()\n}\n\n/**\n * Prompt client backed by @clack/prompts for richer interactive UX.\n * Falls back to readline in non-interactive contexts.\n */\nexport class ClackPromptClient implements PromptClient {\n\tpublic async text(message: string, defaultValue?: string): Promise<string> {\n\t\tconst result = await clackText({\n\t\t\tmessage,\n\t\t\tplaceholder: defaultValue,\n\t\t\tdefaultValue,\n\t\t})\n\t\tif (clackIsCancel(result)) {\n\t\t\tclackCancel('Operation cancelled.')\n\t\t\tthrow new PromptCancelledError()\n\t\t}\n\t\tconst value = result.trim()\n\t\tif (value.length > 0) return value\n\t\treturn defaultValue ?? ''\n\t}\n\n\tpublic async select<T extends string>(\n\t\tmessage: string,\n\t\toptions: readonly SelectOption<T>[],\n\t): Promise<T> {\n\t\tconst mappedOptions: ClackSelectOption<T>[] = options.map((option) => ({\n\t\t\tlabel: option.label,\n\t\t\tvalue: option.value,\n\t\t\thint: option.hint,\n\t\t\tdisabled: option.disabled,\n\t\t}))\n\t\tconst result = await clackSelect({\n\t\t\tmessage,\n\t\t\toptions: mappedOptions as unknown as Parameters<typeof clackSelect>[0]['options'],\n\t\t})\n\t\tif (clackIsCancel(result)) {\n\t\t\tclackCancel('Operation cancelled.')\n\t\t\tthrow new PromptCancelledError()\n\t\t}\n\t\treturn result as T\n\t}\n\n\tpublic async confirm(message: string, defaultValue = false): Promise<boolean> {\n\t\tconst result = await clackConfirm({\n\t\t\tmessage,\n\t\t\tinitialValue: defaultValue,\n\t\t})\n\t\tif (clackIsCancel(result)) {\n\t\t\tclackCancel('Operation cancelled.')\n\t\t\tthrow new PromptCancelledError()\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic intro(message: string): void {\n\t\tclackIntro(message)\n\t}\n\n\tpublic outro(message: string): void {\n\t\tclackOutro(message)\n\t}\n}\n","import { type Interface as ReadlineInterface, createInterface } from 'node:readline'\n\nexport interface PromptOptions {\n\t/** Input stream (defaults to process.stdin) */\n\tinput?: NodeJS.ReadableStream\n\t/** Output stream (defaults to process.stdout) */\n\toutput?: NodeJS.WritableStream\n}\n\n/**\n * Prompts the user for text input.\n *\n * @param message - The prompt message to display\n * @param defaultValue - Optional default value shown in brackets\n * @param options - Optional input/output streams for testing\n */\nexport function promptText(\n\tmessage: string,\n\tdefaultValue?: string,\n\toptions?: PromptOptions,\n): Promise<string> {\n\treturn new Promise((resolve) => {\n\t\tconst rl = createReadline(options)\n\t\tconst suffix = defaultValue !== undefined ? ` (${defaultValue})` : ''\n\t\trl.question(` ? ${message}${suffix}: `, (answer) => {\n\t\t\trl.close()\n\t\t\tconst trimmed = answer.trim()\n\t\t\tresolve(trimmed || defaultValue || '')\n\t\t})\n\t})\n}\n\n/**\n * Prompts the user to select from a numbered list of options.\n *\n * @param message - The prompt message to display\n * @param choices - Array of { label, value } options\n * @param options - Optional input/output streams for testing\n */\nexport function promptSelect<T extends string>(\n\tmessage: string,\n\tchoices: readonly { label: string; value: T }[],\n\toptions?: PromptOptions,\n): Promise<T> {\n\treturn new Promise((resolve) => {\n\t\tconst rl = createReadline(options)\n\t\tconst out = options?.output ?? process.stdout\n\n\t\tout.write(` ? ${message}\\n`)\n\t\tfor (let i = 0; i < choices.length; i++) {\n\t\t\tconst choice = choices[i]\n\t\t\tif (choice) {\n\t\t\t\tout.write(` ${i + 1}) ${choice.label}\\n`)\n\t\t\t}\n\t\t}\n\n\t\tconst ask = (): void => {\n\t\t\trl.question(' > ', (answer) => {\n\t\t\t\tconst index = Number.parseInt(answer.trim(), 10) - 1\n\t\t\t\tconst selected = choices[index]\n\t\t\t\tif (selected) {\n\t\t\t\t\trl.close()\n\t\t\t\t\tresolve(selected.value)\n\t\t\t\t} else {\n\t\t\t\t\tout.write(` Please enter a number between 1 and ${choices.length}\\n`)\n\t\t\t\t\task()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\task()\n\t})\n}\n\n/**\n * Prompts the user with a yes/no confirmation.\n *\n * @param message - The prompt message to display\n * @param defaultValue - Default when input is empty (true => yes)\n * @param options - Optional input/output streams for testing\n */\nexport function promptConfirm(\n\tmessage: string,\n\tdefaultValue = false,\n\toptions?: PromptOptions,\n): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst rl = createReadline(options)\n\t\tconst suffix = defaultValue ? 'Y/n' : 'y/N'\n\n\t\tconst ask = (): void => {\n\t\t\trl.question(` ? ${message} (${suffix}): `, (answer) => {\n\t\t\t\tconst normalized = answer.trim().toLowerCase()\n\t\t\t\tif (normalized.length === 0) {\n\t\t\t\t\trl.close()\n\t\t\t\t\tresolve(defaultValue)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (normalized === 'y' || normalized === 'yes') {\n\t\t\t\t\trl.close()\n\t\t\t\t\tresolve(true)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (normalized === 'n' || normalized === 'no') {\n\t\t\t\t\trl.close()\n\t\t\t\t\tresolve(false)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t;(options?.output ?? process.stdout).write(' Please answer with y or n\\n')\n\t\t\t\task()\n\t\t\t})\n\t\t}\n\n\t\task()\n\t})\n}\n\nfunction createReadline(options?: PromptOptions): ReadlineInterface {\n\treturn createInterface({\n\t\tinput: options?.input ?? process.stdin,\n\t\toutput: options?.output ?? process.stdout,\n\t})\n}\n","/** Supported package managers */\nexport const PACKAGE_MANAGERS = ['pnpm', 'npm', 'yarn', 'bun'] as const\nexport type PackageManager = (typeof PACKAGE_MANAGERS)[number]\n\n/** Available project templates */\nexport const TEMPLATES = [\n\t'react-tailwind-sync',\n\t'react-tailwind',\n\t'react-sync',\n\t'react-basic',\n\t'tauri-react',\n] as const\nexport type TemplateName = (typeof TEMPLATES)[number]\n\n/** Metadata for a project template */\nexport interface TemplateInfo {\n\tname: TemplateName\n\tlabel: string\n\tdescription: string\n}\n\n/** Available templates with their descriptions */\nexport const TEMPLATE_INFO: readonly TemplateInfo[] = [\n\t{\n\t\tname: 'react-tailwind-sync',\n\t\tlabel: 'React + Tailwind (with sync)',\n\t\tdescription: 'Polished dark-themed app with Tailwind CSS and sync server (Recommended)',\n\t},\n\t{\n\t\tname: 'react-tailwind',\n\t\tlabel: 'React + Tailwind (local-only)',\n\t\tdescription: 'Polished dark-themed app with Tailwind CSS — no sync server',\n\t},\n\t{\n\t\tname: 'react-sync',\n\t\tlabel: 'React + CSS (with sync)',\n\t\tdescription: 'Clean CSS app with sync server included',\n\t},\n\t{\n\t\tname: 'react-basic',\n\t\tlabel: 'React + CSS (local-only)',\n\t\tdescription: 'Clean CSS app — no sync server',\n\t},\n\t{\n\t\tname: 'tauri-react',\n\t\tlabel: 'Tauri Desktop (native SQLite)',\n\t\tdescription: 'Desktop app with native SQLite — no WASM, includes sync server',\n\t},\n] as const\n\n/** Variables available for template substitution */\nexport interface TemplateContext {\n\tprojectName: string\n\tpackageManager: PackageManager\n\tkoraVersion: string\n\tdbProvider?: string\n}\n","import type { TemplateName } from '../../types'\n\nexport type PlatformOption = 'web' | 'desktop-tauri'\nexport type FrameworkOption = 'react' | 'vue' | 'svelte' | 'solid'\nexport type AuthOption = 'none' | 'email-password' | 'oauth'\nexport type DatabaseOption = 'none' | 'sqlite' | 'postgres'\nexport type DatabaseProviderOption =\n\t| 'none'\n\t| 'local'\n\t| 'supabase'\n\t| 'neon'\n\t| 'railway'\n\t| 'vercel-postgres'\n\t| 'custom'\n\nexport interface TemplateSelectionInput {\n\tplatform: PlatformOption\n\ttailwind: boolean\n\tsync: boolean\n\tdb: DatabaseOption\n}\n\n/**\n * Converts high-level scaffold selections into the currently supported\n * concrete template names.\n */\nexport function determineTemplateFromSelections(input: TemplateSelectionInput): TemplateName {\n\tif (input.platform === 'desktop-tauri') return 'tauri-react'\n\tconst shouldSync = input.sync && input.db !== 'none'\n\tif (input.tailwind && shouldSync) return 'react-tailwind-sync'\n\tif (input.tailwind && !shouldSync) return 'react-tailwind'\n\tif (!input.tailwind && shouldSync) return 'react-sync'\n\treturn 'react-basic'\n}\n\nexport function isPlatformValue(value: string): value is PlatformOption {\n\treturn value === 'web' || value === 'desktop-tauri'\n}\n\nexport function isFrameworkValue(value: string): value is FrameworkOption {\n\treturn value === 'react' || value === 'vue' || value === 'svelte' || value === 'solid'\n}\n\nexport function isAuthValue(value: string): value is AuthOption {\n\treturn value === 'none' || value === 'email-password' || value === 'oauth'\n}\n\nexport function isDatabaseValue(value: string): value is DatabaseOption {\n\treturn value === 'none' || value === 'sqlite' || value === 'postgres'\n}\n\nexport function isDatabaseProviderValue(value: string): value is DatabaseProviderOption {\n\treturn (\n\t\tvalue === 'none' ||\n\t\tvalue === 'local' ||\n\t\tvalue === 'supabase' ||\n\t\tvalue === 'neon' ||\n\t\tvalue === 'railway' ||\n\t\tvalue === 'vercel-postgres' ||\n\t\tvalue === 'custom'\n\t)\n}\n","import {\n\ttype CreatePreferences,\n\ttype PreferenceStore,\n\tgetCreatePreferencesOrDefault,\n\tgetDefaultCreatePreferences,\n} from '../../prompts/preferences'\nimport type { PromptClient } from '../../prompts/prompt-client'\nimport {\n\ttype AuthOption,\n\ttype DatabaseOption,\n\ttype DatabaseProviderOption,\n\ttype FrameworkOption,\n\ttype PlatformOption,\n\tdetermineTemplateFromSelections,\n\tisAuthValue,\n\tisDatabaseProviderValue,\n\tisDatabaseValue,\n\tisFrameworkValue,\n\tisPlatformValue,\n} from './options'\n\nexport interface CreateFlags {\n\tplatform?: string\n\tframework?: string\n\tauth?: string\n\tdb?: string\n\tdbProvider?: string\n\ttailwind?: boolean\n\tsync?: boolean\n\tuseDefaults: boolean\n}\n\nexport interface PreferenceResolutionResult {\n\tplatform: PlatformOption\n\tframework: FrameworkOption\n\tauth: AuthOption\n\tdb: DatabaseOption\n\tdbProvider: DatabaseProviderOption\n\ttailwind: boolean\n\tsync: boolean\n\ttemplate: ReturnType<typeof determineTemplateFromSelections>\n\tusedStoredPreferences: boolean\n}\n\n/**\n * Resolves scaffold options with precedence:\n * CLI flags > --yes defaults > stored preferences > interactive prompts.\n */\nexport async function resolveCreatePreferencesFlow(params: {\n\tflags: CreateFlags\n\tprompts: PromptClient\n\tstore: PreferenceStore\n}): Promise<PreferenceResolutionResult> {\n\tconst { flags, prompts, store } = params\n\tconst stored = store.getCreatePreferences()\n\tconst base = getCreatePreferencesOrDefault(store)\n\tconst hasExplicitFlags = hasExplicitPreferenceFlags(flags)\n\tconst canOfferStored =\n\t\t!flags.useDefaults && !hasExplicitFlags && stored !== null && promptSupportsRichOptions()\n\n\tlet effective: CreatePreferences = { ...base }\n\tlet usedStoredPreferences = false\n\n\tif (flags.useDefaults) {\n\t\teffective = getDefaultCreatePreferences()\n\t} else if (canOfferStored && stored !== null) {\n\t\tconst reuseStored = await prompts.select('Welcome back! Choose setup mode:', [\n\t\t\t{ label: formatStoredPreferenceLabel(stored), value: 'reuse' },\n\t\t\t{ label: 'Customize', value: 'customize' },\n\t\t])\n\t\tif (reuseStored === 'reuse') {\n\t\t\teffective = { ...stored }\n\t\t\tusedStoredPreferences = true\n\t\t}\n\t}\n\n\tif (flags.platform !== undefined) {\n\t\tif (!isPlatformValue(flags.platform)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid --platform value \"${flags.platform}\". Expected one of: web, desktop-tauri.`,\n\t\t\t)\n\t\t}\n\t\teffective.platform = flags.platform\n\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\teffective.platform = await prompts.select('Platform:', [\n\t\t\t{ label: 'Web (browser)', value: 'web' },\n\t\t\t{ label: 'Desktop (Tauri — native SQLite)', value: 'desktop-tauri' },\n\t\t])\n\t}\n\n\tconst isTauri = effective.platform === 'desktop-tauri'\n\n\tif (isTauri) {\n\t\t// Tauri currently uses React and native SQLite on the client.\n\t\t// The sync server remains configurable so the same desktop scaffold can\n\t\t// run local-only, LAN sync, or cloud sync without switching templates.\n\t\teffective.framework = 'react'\n\t\teffective.tailwind = false\n\t\teffective.auth = 'none'\n\n\t\tif (flags.sync !== undefined) {\n\t\t\teffective.sync = flags.sync\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.sync = await prompts.confirm('Enable multi-device sync?', true)\n\t\t}\n\n\t\tif (flags.db !== undefined) {\n\t\t\tif (!isDatabaseValue(flags.db)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid --db value \"${flags.db}\". Expected one of: none, sqlite, postgres.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\teffective.db = flags.db\n\t\t} else if (!effective.sync) {\n\t\t\teffective.db = 'none'\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.db = await prompts.select('Sync server database:', [\n\t\t\t\t{ label: 'SQLite (zero-config; local, LAN, small teams)', value: 'sqlite' },\n\t\t\t\t{ label: 'PostgreSQL (production-scale)', value: 'postgres' },\n\t\t\t])\n\t\t}\n\n\t\tif (effective.db === 'none') {\n\t\t\teffective.sync = false\n\t\t}\n\n\t\tif (effective.db !== 'postgres') {\n\t\t\teffective.dbProvider = 'none'\n\t\t} else if (flags.dbProvider !== undefined) {\n\t\t\tif (!isDatabaseProviderValue(flags.dbProvider)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid --db-provider value \"${flags.dbProvider}\". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\teffective.dbProvider = flags.dbProvider\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.dbProvider = await prompts.select('Database provider:', [\n\t\t\t\t{ label: 'Local Postgres', value: 'local' },\n\t\t\t\t{ label: 'Supabase', value: 'supabase' },\n\t\t\t\t{ label: 'Neon', value: 'neon' },\n\t\t\t\t{ label: 'Railway', value: 'railway' },\n\t\t\t\t{ label: 'Vercel Postgres', value: 'vercel-postgres' },\n\t\t\t\t{ label: 'Custom connection string', value: 'custom' },\n\t\t\t])\n\t\t}\n\t} else {\n\t\tif (flags.framework !== undefined) {\n\t\t\tif (!isFrameworkValue(flags.framework)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid --framework value \"${flags.framework}\". Expected one of: react, vue, svelte, solid.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\teffective.framework = flags.framework\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.framework = await prompts.select('UI framework:', [\n\t\t\t\t{ label: 'React', value: 'react' },\n\t\t\t\t{ label: 'Vue (coming soon)', value: 'vue', disabled: true },\n\t\t\t\t{ label: 'Svelte (coming soon)', value: 'svelte', disabled: true },\n\t\t\t\t{ label: 'Solid (coming soon)', value: 'solid', disabled: true },\n\t\t\t])\n\t\t}\n\n\t\tif (flags.auth !== undefined) {\n\t\t\tif (!isAuthValue(flags.auth)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid --auth value \"${flags.auth}\". Expected one of: none, email-password, oauth.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\teffective.auth = flags.auth\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.auth = await prompts.select('Authentication:', [\n\t\t\t\t{ label: 'None', value: 'none' },\n\t\t\t\t{ label: 'Email + Password (coming soon)', value: 'email-password', disabled: true },\n\t\t\t\t{ label: 'OAuth (coming soon)', value: 'oauth', disabled: true },\n\t\t\t])\n\t\t}\n\n\t\tif (flags.tailwind !== undefined) {\n\t\t\teffective.tailwind = flags.tailwind\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.tailwind = await prompts.confirm('Use Tailwind CSS?', true)\n\t\t}\n\n\t\tif (flags.sync !== undefined) {\n\t\t\teffective.sync = flags.sync\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.sync = await prompts.confirm('Enable multi-device sync?', true)\n\t\t}\n\n\t\tif (flags.db !== undefined) {\n\t\t\tif (!isDatabaseValue(flags.db)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid --db value \"${flags.db}\". Expected one of: none, sqlite, postgres.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\teffective.db = flags.db\n\t\t} else if (!effective.sync) {\n\t\t\teffective.db = 'none'\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.db = await prompts.select('Server-side database:', [\n\t\t\t\t{ label: 'SQLite (zero-config)', value: 'sqlite' },\n\t\t\t\t{ label: 'PostgreSQL (production-scale)', value: 'postgres' },\n\t\t\t])\n\t\t}\n\n\t\tif (effective.db !== 'postgres') {\n\t\t\teffective.dbProvider = 'none'\n\t\t} else if (flags.dbProvider !== undefined) {\n\t\t\tif (!isDatabaseProviderValue(flags.dbProvider)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid --db-provider value \"${flags.dbProvider}\". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\teffective.dbProvider = flags.dbProvider\n\t\t} else if (!flags.useDefaults && !usedStoredPreferences) {\n\t\t\teffective.dbProvider = await prompts.select('Database provider:', [\n\t\t\t\t{ label: 'Local Postgres', value: 'local' },\n\t\t\t\t{ label: 'Supabase', value: 'supabase' },\n\t\t\t\t{ label: 'Neon', value: 'neon' },\n\t\t\t\t{ label: 'Railway', value: 'railway' },\n\t\t\t\t{ label: 'Vercel Postgres', value: 'vercel-postgres' },\n\t\t\t\t{ label: 'Custom connection string', value: 'custom' },\n\t\t\t])\n\t\t}\n\t}\n\n\tconst template = determineTemplateFromSelections({\n\t\tplatform: effective.platform,\n\t\ttailwind: effective.tailwind,\n\t\tsync: effective.sync,\n\t\tdb: effective.db,\n\t})\n\n\treturn {\n\t\tplatform: effective.platform,\n\t\tframework: effective.framework,\n\t\tauth: effective.auth,\n\t\tdb: effective.db,\n\t\tdbProvider: effective.dbProvider,\n\t\ttailwind: effective.tailwind,\n\t\tsync: effective.sync,\n\t\ttemplate,\n\t\tusedStoredPreferences,\n\t}\n}\n\nexport function shouldSavePreferences(flags: CreateFlags): boolean {\n\treturn !flags.useDefaults\n}\n\nexport function saveResolvedPreferences(\n\tstore: PreferenceStore,\n\tresolution: Omit<PreferenceResolutionResult, 'template' | 'usedStoredPreferences'> & {\n\t\tpackageManager: CreatePreferences['packageManager']\n\t},\n): void {\n\tstore.saveCreatePreferences({\n\t\tplatform: resolution.platform,\n\t\tframework: resolution.framework,\n\t\ttailwind: resolution.tailwind,\n\t\tsync: resolution.sync,\n\t\tdb: resolution.db,\n\t\tdbProvider: resolution.dbProvider,\n\t\tauth: resolution.auth,\n\t\tpackageManager: resolution.packageManager,\n\t})\n}\n\nfunction hasExplicitPreferenceFlags(flags: CreateFlags): boolean {\n\treturn (\n\t\tflags.platform !== undefined ||\n\t\tflags.framework !== undefined ||\n\t\tflags.auth !== undefined ||\n\t\tflags.db !== undefined ||\n\t\tflags.dbProvider !== undefined ||\n\t\tflags.tailwind !== undefined ||\n\t\tflags.sync !== undefined\n\t)\n}\n\nfunction promptSupportsRichOptions(): boolean {\n\treturn typeof process !== 'undefined' && process.stdin.isTTY && process.stdout.isTTY\n}\n\nfunction formatStoredPreferenceLabel(preferences: CreatePreferences): string {\n\tif (preferences.platform === 'desktop-tauri') {\n\t\treturn `Use previous settings (tauri-desktop + ${preferences.packageManager})`\n\t}\n\tconst syncLabel = preferences.sync ? `sync/${preferences.db}` : 'local-only'\n\tconst styleLabel = preferences.tailwind ? 'tailwind' : 'css'\n\treturn `Use previous settings (${preferences.framework} + ${styleLabel} + ${syncLabel} + ${preferences.packageManager})`\n}\n","import validateNpmPackageName from 'validate-npm-package-name'\n\nexport interface ProjectNameValidationResult {\n\tvalid: boolean\n\tissues: readonly string[]\n}\n\n/**\n * Validates a project name for scaffolded package creation.\n *\n * The create command uses this validation before writing files so users get a\n * clear, early error if the name cannot be used as an npm package name.\n */\nexport function validateProjectName(name: string): ProjectNameValidationResult {\n\tconst trimmedName = name.trim()\n\tif (trimmedName.length === 0) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: ['Project name cannot be empty.'],\n\t\t}\n\t}\n\n\tconst validation = validateNpmPackageName(trimmedName)\n\tconst issues = [...(validation.errors ?? []), ...(validation.warnings ?? [])]\n\tif (!validation.validForNewPackages && issues.length === 0) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: ['Project name is not a valid npm package name.'],\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: validation.validForNewPackages,\n\t\tissues,\n\t}\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { TemplateName } from '../../types'\nimport type { DatabaseOption, DatabaseProviderOption } from './options'\n\ninterface SyncProviderPresetOptions {\n\ttargetDir: string\n\ttemplate: TemplateName\n\tdb: DatabaseOption\n\tdbProvider: DatabaseProviderOption\n}\n\n/**\n * Applies provider-specific sync scaffolding adjustments after template copy.\n *\n * The sync server template is environment-driven: SQLite is used when\n * DATABASE_URL is absent, and PostgreSQL is used when DATABASE_URL is present.\n * Provider presets only add provider-specific guidance.\n */\nexport async function applySyncProviderPreset(options: SyncProviderPresetOptions): Promise<void> {\n\tif (!isSyncTemplate(options.template)) {\n\t\treturn\n\t}\n\tif (options.db !== 'postgres') {\n\t\treturn\n\t}\n\n\tconst providerName = getProviderDisplayName(options.dbProvider)\n\tconst providerConnectionString = getProviderConnectionStringExample(options.dbProvider)\n\tconst envPath = join(options.targetDir, '.env.example')\n\tconst readmePath = join(options.targetDir, 'README.md')\n\n\tconst existingReadme = await readFile(readmePath, 'utf-8')\n\tconst existingEnv = await readFile(envPath, 'utf-8')\n\tconst trimmedReadme = existingReadme.trimEnd()\n\tconst trimmedEnv = existingEnv.trimEnd()\n\tconst envSuffix = [\n\t\t'',\n\t\t`# PostgreSQL provider preset: ${providerName}`,\n\t\t`# Example: ${providerConnectionString}`,\n\t].join('\\n')\n\tconst readmeSuffix = [\n\t\t'',\n\t\t'## PostgreSQL Provider Preset',\n\t\t'',\n\t\t`Selected DB provider: ${options.dbProvider}`,\n\t\t'',\n\t\t'This scaffold keeps one sync server entrypoint. When `DATABASE_URL` is set, `server.ts` uses PostgreSQL. When it is empty, the same server uses SQLite at `KORA_SERVER_DB`.',\n\t\t'',\n\t\t'The generated server uses `createPostgresServerStore` automatically when `DATABASE_URL` is present.',\n\t\t'',\n\t].join('\\n')\n\tconst readmeTemplate = `${trimmedReadme}${readmeSuffix}`\n\n\tawait writeFile(envPath, `${trimmedEnv}${envSuffix}\\n`, 'utf-8')\n\tawait writeFile(readmePath, readmeTemplate, 'utf-8')\n}\n\nfunction isSyncTemplate(template: TemplateName): boolean {\n\treturn (\n\t\ttemplate === 'react-sync' || template === 'react-tailwind-sync' || template === 'tauri-react'\n\t)\n}\n\nfunction getProviderDisplayName(provider: DatabaseProviderOption): string {\n\tswitch (provider) {\n\t\tcase 'supabase':\n\t\t\treturn 'Supabase'\n\t\tcase 'neon':\n\t\t\treturn 'Neon'\n\t\tcase 'railway':\n\t\t\treturn 'Railway'\n\t\tcase 'vercel-postgres':\n\t\t\treturn 'Vercel Postgres'\n\t\tcase 'custom':\n\t\t\treturn 'Custom'\n\t\tcase 'local':\n\t\t\treturn 'Local Postgres'\n\t\tcase 'none':\n\t\t\treturn 'PostgreSQL'\n\t}\n}\n\nfunction getProviderConnectionStringExample(provider: DatabaseProviderOption): string {\n\tswitch (provider) {\n\t\tcase 'supabase':\n\t\t\treturn 'postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require'\n\t\tcase 'neon':\n\t\t\treturn 'postgresql://<user>:<password>@<branch>.<project>.neon.tech/neondb?sslmode=require'\n\t\tcase 'railway':\n\t\t\treturn 'postgresql://postgres:<password>@<host>.railway.app:<port>/railway?sslmode=require'\n\t\tcase 'vercel-postgres':\n\t\t\treturn 'postgresql://<user>:<password>@<host>.pooler.vercel-storage.com:5432/verceldb?sslmode=require'\n\t\tcase 'custom':\n\t\t\treturn 'postgresql://<user>:<password>@<host>:5432/<database>'\n\t\tcase 'local':\n\t\t\treturn 'postgresql://postgres:postgres@localhost:5432/kora'\n\t\tcase 'none':\n\t\t\treturn 'postgresql://postgres:postgres@localhost:5432/kora'\n\t}\n}\n","/** ANSI escape codes for terminal colors */\nconst RESET = '\\x1b[0m'\nconst BOLD = '\\x1b[1m'\nconst DIM = '\\x1b[2m'\nconst GREEN = '\\x1b[32m'\nconst YELLOW = '\\x1b[33m'\nconst RED = '\\x1b[31m'\nconst CYAN = '\\x1b[36m'\n\nexport interface LoggerOptions {\n\t/** Disable ANSI colors */\n\tnoColor?: boolean\n}\n\nexport interface Logger {\n\tinfo(message: string): void\n\tsuccess(message: string): void\n\twarn(message: string): void\n\terror(message: string): void\n\tstep(message: string): void\n\tblank(): void\n\tbanner(): void\n}\n\n/**\n * Creates a logger with optional ANSI color support.\n * Respects the NO_COLOR environment variable and TTY detection.\n */\nexport function createLogger(options?: LoggerOptions): Logger {\n\tconst colorDisabled =\n\t\toptions?.noColor === true || process.env.NO_COLOR !== undefined || !process.stdout.isTTY\n\n\tfunction color(code: string, text: string): string {\n\t\treturn colorDisabled ? text : `${code}${text}${RESET}`\n\t}\n\n\treturn {\n\t\tinfo(message: string): void {\n\t\t\tconsole.log(color(CYAN, message))\n\t\t},\n\t\tsuccess(message: string): void {\n\t\t\tconsole.log(color(GREEN, ` ✓ ${message}`))\n\t\t},\n\t\twarn(message: string): void {\n\t\t\tconsole.warn(color(YELLOW, ` ⚠ ${message}`))\n\t\t},\n\t\terror(message: string): void {\n\t\t\tconsole.error(color(RED, ` ✗ ${message}`))\n\t\t},\n\t\tstep(message: string): void {\n\t\t\tconsole.log(color(DIM, ` ${message}`))\n\t\t},\n\t\tblank(): void {\n\t\t\tconsole.log()\n\t\t},\n\t\tbanner(): void {\n\t\t\tconsole.log()\n\t\t\tconsole.log(\n\t\t\t\tcolor(BOLD + CYAN, ' Kora.js') + color(DIM, ' — Offline-first application framework'),\n\t\t\t)\n\t\t\tconsole.log()\n\t\t},\n\t}\n}\n","import { access, readFile } from 'node:fs/promises'\nimport { dirname, join, resolve } from 'node:path'\n\n/** Checks if a directory exists at the given path */\nexport async function directoryExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Walks up the directory tree from startDir looking for a package.json\n * that contains a kora or @korajs/* dependency.\n *\n * @param startDir - Directory to start searching from (defaults to cwd)\n * @returns Absolute path to the project root, or null if not found\n */\nexport async function findProjectRoot(startDir?: string): Promise<string | null> {\n\tlet current = resolve(startDir ?? process.cwd())\n\n\t// Walk up until the filesystem root (where dirname(x) === x)\n\tfor (;;) {\n\t\tconst pkgPath = join(current, 'package.json')\n\t\ttry {\n\t\t\tconst content = await readFile(pkgPath, 'utf-8')\n\t\t\tconst pkg: unknown = JSON.parse(content)\n\t\t\tif (isKoraProject(pkg)) {\n\t\t\t\treturn current\n\t\t\t}\n\t\t} catch {\n\t\t\t// No package.json at this level, keep walking up\n\t\t}\n\t\tconst parent = dirname(current)\n\t\tif (parent === current) break\n\t\tcurrent = parent\n\t}\n\n\treturn null\n}\n\n/**\n * Searches for a schema file in common locations within a project.\n *\n * @param projectRoot - The project root directory\n * @returns Absolute path to the schema file, or null if not found\n */\nexport async function findSchemaFile(projectRoot: string): Promise<string | null> {\n\tconst candidates = [\n\t\tjoin(projectRoot, 'src', 'schema.ts'),\n\t\tjoin(projectRoot, 'schema.ts'),\n\t\tjoin(projectRoot, 'src', 'schema.js'),\n\t\tjoin(projectRoot, 'schema.js'),\n\t]\n\n\tfor (const candidate of candidates) {\n\t\ttry {\n\t\t\tawait access(candidate)\n\t\t\treturn candidate\n\t\t} catch {\n\t\t\t// Not found, try next\n\t\t}\n\t}\n\n\treturn null\n}\n\n/**\n * Resolves a binary from a project's local node_modules/.bin directory.\n * On Windows, npm creates .cmd shims instead of extensionless files.\n *\n * @param projectRoot - The project root directory\n * @param binaryName - Binary filename (for example: vite, tsx, kora)\n * @returns Absolute path to the binary, or null if not found\n */\nexport async function resolveProjectBinary(\n\tprojectRoot: string,\n\tbinaryName: string,\n): Promise<string | null> {\n\tconst binDir = join(projectRoot, 'node_modules', '.bin')\n\t// On Windows, try .cmd first (npm/pnpm create .cmd shims)\n\tconst candidates =\n\t\tprocess.platform === 'win32'\n\t\t\t? [join(binDir, `${binaryName}.cmd`), join(binDir, binaryName)]\n\t\t\t: [join(binDir, binaryName)]\n\n\tfor (const candidate of candidates) {\n\t\ttry {\n\t\t\tawait access(candidate)\n\t\t\treturn candidate\n\t\t} catch {\n\t\t\t// continue\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Checks whether the `tsx` package is installed in the project's node_modules.\n * Used to determine if we can use `--import tsx` with process.execPath.\n */\nexport async function hasTsxInstalled(projectRoot: string): Promise<boolean> {\n\ttry {\n\t\tawait access(join(projectRoot, 'node_modules', 'tsx', 'package.json'))\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Resolves the JS entry point for a package binary.\n * Reads the package.json bin field to find the actual JS file,\n * avoiding .cmd shims and shell:true on Windows.\n *\n * @returns Absolute path to the JS entry point, or null if not found\n */\nexport async function resolveProjectBinaryEntryPoint(\n\tprojectRoot: string,\n\tpackageName: string,\n\tbinaryName: string,\n): Promise<string | null> {\n\tconst pkgJsonPath = join(projectRoot, 'node_modules', packageName, 'package.json')\n\ttry {\n\t\tconst content = await readFile(pkgJsonPath, 'utf-8')\n\t\tconst pkg = JSON.parse(content) as { bin?: string | Record<string, string> }\n\t\tlet binPath: string | undefined\n\t\tif (typeof pkg.bin === 'string') {\n\t\t\tbinPath = pkg.bin\n\t\t} else if (typeof pkg.bin === 'object' && pkg.bin !== null) {\n\t\t\tbinPath = pkg.bin[binaryName]\n\t\t}\n\t\tif (!binPath) return null\n\t\tconst fullPath = join(projectRoot, 'node_modules', packageName, binPath)\n\t\tawait access(fullPath)\n\t\treturn fullPath\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction isKoraProject(pkg: unknown): boolean {\n\tif (typeof pkg !== 'object' || pkg === null) return false\n\tconst record = pkg as Record<string, unknown>\n\treturn hasKoraDep(record.dependencies) || hasKoraDep(record.devDependencies)\n}\n\nfunction hasKoraDep(deps: unknown): boolean {\n\tif (typeof deps !== 'object' || deps === null) return false\n\treturn Object.keys(deps).some((key) => key === 'kora' || key.startsWith('@korajs/'))\n}\n"],"mappings":"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","names":["resolve","readFile","join","join","readFile"]}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
saveResolvedPreferences,
|
|
14
14
|
shouldSavePreferences,
|
|
15
15
|
validateProjectName
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3WNFM3QB.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/create/create-command.ts
|
|
19
19
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -624,4 +624,4 @@ function resolveKoraVersion() {
|
|
|
624
624
|
export {
|
|
625
625
|
createCommand
|
|
626
626
|
};
|
|
627
|
-
//# sourceMappingURL=chunk-
|
|
627
|
+
//# sourceMappingURL=chunk-PSRM56B7.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
createPromptClient,
|
|
6
6
|
findProjectRoot,
|
|
7
7
|
resolveProjectBinaryEntryPoint
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3WNFM3QB.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/deploy/adapters/adapter.ts
|
|
11
11
|
var DEPLOY_PLATFORMS = [
|
|
@@ -167,7 +167,7 @@ function generateFlyToml(options) {
|
|
|
167
167
|
' interval = "30s"',
|
|
168
168
|
' method = "GET"',
|
|
169
169
|
' timeout = "5s"',
|
|
170
|
-
' path = "/"',
|
|
170
|
+
' path = "/health"',
|
|
171
171
|
""
|
|
172
172
|
].join("\n");
|
|
173
173
|
}
|
|
@@ -279,13 +279,13 @@ var FlyAdapter = class {
|
|
|
279
279
|
projectRoot: config.projectRoot,
|
|
280
280
|
deployDirectory
|
|
281
281
|
});
|
|
282
|
-
const client = await buildClient({
|
|
282
|
+
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
283
283
|
projectRoot: config.projectRoot,
|
|
284
284
|
outDir: join4(deployDirectory, "dist"),
|
|
285
285
|
mode: "production"
|
|
286
286
|
});
|
|
287
287
|
return {
|
|
288
|
-
clientDirectory: client
|
|
288
|
+
clientDirectory: client?.outDir ?? null,
|
|
289
289
|
serverBundlePath: join4(deployDirectory, "server-bundled.js"),
|
|
290
290
|
deployDirectory
|
|
291
291
|
};
|
|
@@ -635,13 +635,13 @@ var RailwayAdapter = class {
|
|
|
635
635
|
projectRoot: config.projectRoot,
|
|
636
636
|
deployDirectory
|
|
637
637
|
});
|
|
638
|
-
const client = await buildClient({
|
|
638
|
+
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
639
639
|
projectRoot: config.projectRoot,
|
|
640
640
|
outDir: join6(deployDirectory, "dist"),
|
|
641
641
|
mode: "production"
|
|
642
642
|
});
|
|
643
643
|
return {
|
|
644
|
-
clientDirectory: client
|
|
644
|
+
clientDirectory: client?.outDir ?? null,
|
|
645
645
|
serverBundlePath: join6(deployDirectory, "server-bundled.js"),
|
|
646
646
|
deployDirectory
|
|
647
647
|
};
|
|
@@ -1005,13 +1005,13 @@ var AwsEcsAdapter = class {
|
|
|
1005
1005
|
projectRoot: config.projectRoot,
|
|
1006
1006
|
deployDirectory
|
|
1007
1007
|
});
|
|
1008
|
-
const client = await buildClient({
|
|
1008
|
+
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
1009
1009
|
projectRoot: config.projectRoot,
|
|
1010
1010
|
outDir: join7(deployDirectory, "dist"),
|
|
1011
1011
|
mode: "production"
|
|
1012
1012
|
});
|
|
1013
1013
|
return {
|
|
1014
|
-
clientDirectory: client
|
|
1014
|
+
clientDirectory: client?.outDir ?? null,
|
|
1015
1015
|
serverBundlePath: join7(deployDirectory, "server-bundled.js"),
|
|
1016
1016
|
deployDirectory
|
|
1017
1017
|
};
|
|
@@ -1356,13 +1356,13 @@ var AwsLightsailAdapter = class {
|
|
|
1356
1356
|
projectRoot: config.projectRoot,
|
|
1357
1357
|
deployDirectory
|
|
1358
1358
|
});
|
|
1359
|
-
const client = await buildClient({
|
|
1359
|
+
const client = config.deployTarget === "sync-server" ? null : await buildClient({
|
|
1360
1360
|
projectRoot: config.projectRoot,
|
|
1361
1361
|
outDir: join8(deployDirectory, "dist"),
|
|
1362
1362
|
mode: "production"
|
|
1363
1363
|
});
|
|
1364
1364
|
return {
|
|
1365
|
-
clientDirectory: client
|
|
1365
|
+
clientDirectory: client?.outDir ?? null,
|
|
1366
1366
|
serverBundlePath: join8(deployDirectory, "server-bundled.js"),
|
|
1367
1367
|
deployDirectory
|
|
1368
1368
|
};
|
|
@@ -1690,7 +1690,7 @@ var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually"
|
|
|
1690
1690
|
function generateDockerfile(options = {}) {
|
|
1691
1691
|
const nodeVersion = options.nodeVersion ?? "20-alpine";
|
|
1692
1692
|
const port = options.port ?? 3e3;
|
|
1693
|
-
const clientDirectory = options.clientDirectory
|
|
1693
|
+
const clientDirectory = options.clientDirectory === void 0 ? "dist" : options.clientDirectory;
|
|
1694
1694
|
const serverBundleFile = options.serverBundleFile ?? "server-bundled.js";
|
|
1695
1695
|
const hasNativeDeps = options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0;
|
|
1696
1696
|
const lines = [
|
|
@@ -1710,7 +1710,9 @@ function generateDockerfile(options = {}) {
|
|
|
1710
1710
|
lines.push("RUN npm install --omit=dev");
|
|
1711
1711
|
lines.push("");
|
|
1712
1712
|
}
|
|
1713
|
-
|
|
1713
|
+
if (clientDirectory !== null) {
|
|
1714
|
+
lines.push(`COPY ${clientDirectory} ./dist`);
|
|
1715
|
+
}
|
|
1714
1716
|
lines.push(`COPY ${serverBundleFile} ./server-bundled.js`);
|
|
1715
1717
|
lines.push("");
|
|
1716
1718
|
lines.push(`EXPOSE ${String(port)}`);
|
|
@@ -1882,7 +1884,8 @@ function readOptionalString(value, field) {
|
|
|
1882
1884
|
}
|
|
1883
1885
|
|
|
1884
1886
|
// src/commands/deploy/deploy-command.ts
|
|
1885
|
-
import {
|
|
1887
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1888
|
+
import { basename, join as join11 } from "path";
|
|
1886
1889
|
import { defineCommand } from "citty";
|
|
1887
1890
|
var deployCommand = defineCommand({
|
|
1888
1891
|
meta: {
|
|
@@ -2037,12 +2040,14 @@ var deployCommand = defineCommand({
|
|
|
2037
2040
|
const region = resolveRegion(args.region, existingState?.region, confirmMode);
|
|
2038
2041
|
const deployDirectory = resolveDeployDirectory(projectRoot);
|
|
2039
2042
|
const environment = args.prod === true ? "production" : "preview";
|
|
2043
|
+
const deployTarget = detectDeployTarget(projectRoot);
|
|
2040
2044
|
const config = {
|
|
2041
2045
|
projectRoot,
|
|
2042
2046
|
appName,
|
|
2043
2047
|
region,
|
|
2044
2048
|
environment,
|
|
2045
|
-
confirm: confirmMode
|
|
2049
|
+
confirm: confirmMode,
|
|
2050
|
+
deployTarget
|
|
2046
2051
|
};
|
|
2047
2052
|
const adapter = createDeployAdapter(platform);
|
|
2048
2053
|
configureAdapterContext(adapter, {
|
|
@@ -2054,10 +2059,14 @@ var deployCommand = defineCommand({
|
|
|
2054
2059
|
logger.info(
|
|
2055
2060
|
`Deploying to ${platform} (${appName}${region ? `, ${region}` : ""}, ${environment})`
|
|
2056
2061
|
);
|
|
2062
|
+
if (deployTarget === "sync-server") {
|
|
2063
|
+
logger.step("Detected Tauri project. Deploying the sync server only.");
|
|
2064
|
+
}
|
|
2057
2065
|
if (confirmMode) {
|
|
2058
2066
|
logger.step("Running in --confirm mode (non-interactive, fail-fast).");
|
|
2059
2067
|
}
|
|
2060
2068
|
await writeDockerfileArtifact(deployDirectory, {
|
|
2069
|
+
clientDirectory: deployTarget === "sync-server" ? null : void 0,
|
|
2061
2070
|
nativeDependencies: {
|
|
2062
2071
|
"better-sqlite3": "^11.0.0",
|
|
2063
2072
|
"drizzle-orm": "^0.45.2",
|
|
@@ -2196,6 +2205,9 @@ function configureAdapterContext(adapter, context) {
|
|
|
2196
2205
|
adapter.setContext(context);
|
|
2197
2206
|
}
|
|
2198
2207
|
}
|
|
2208
|
+
function detectDeployTarget(projectRoot) {
|
|
2209
|
+
return existsSync2(join11(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
|
|
2210
|
+
}
|
|
2199
2211
|
function hasContextSetter(adapter) {
|
|
2200
2212
|
return typeof adapter.setContext === "function";
|
|
2201
2213
|
}
|
|
@@ -2326,4 +2338,4 @@ export {
|
|
|
2326
2338
|
deployCommand,
|
|
2327
2339
|
generateTypes
|
|
2328
2340
|
};
|
|
2329
|
-
//# sourceMappingURL=chunk-
|
|
2341
|
+
//# sourceMappingURL=chunk-SOTZIWIF.js.map
|