@korajs/cli 0.3.4 → 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.
Files changed (104) hide show
  1. package/dist/bin.cjs +1839 -829
  2. package/dist/bin.cjs.map +1 -1
  3. package/dist/bin.js +1107 -146
  4. package/dist/bin.js.map +1 -1
  5. package/dist/{chunk-HNVCNPER.js → chunk-3WNFM3QB.js} +107 -97
  6. package/dist/chunk-3WNFM3QB.js.map +1 -0
  7. package/dist/{chunk-ULTO5NFA.js → chunk-PSRM56B7.js} +2 -2
  8. package/dist/chunk-PSRM56B7.js.map +1 -0
  9. package/dist/{chunk-MIMLCXSX.js → chunk-SOTZIWIF.js} +267 -228
  10. package/dist/chunk-SOTZIWIF.js.map +1 -0
  11. package/dist/create.cjs +58 -48
  12. package/dist/create.cjs.map +1 -1
  13. package/dist/create.js +2 -2
  14. package/dist/index.cjs +322 -273
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +31 -29
  17. package/dist/index.d.ts +31 -29
  18. package/dist/index.js +2 -2
  19. package/package.json +9 -3
  20. package/templates/react-basic/README.md.hbs +10 -1
  21. package/templates/react-basic/src/App.tsx +112 -126
  22. package/templates/react-basic/src/index.css +165 -159
  23. package/templates/react-basic/src/kora-worker.ts +0 -1
  24. package/templates/react-basic/src/main.tsx +12 -12
  25. package/templates/react-basic/src/modules/todos/todo.mutations.ts +25 -0
  26. package/templates/react-basic/src/modules/todos/todo.queries.ts +5 -0
  27. package/templates/react-basic/src/modules/todos/todo.schema.ts +10 -0
  28. package/templates/react-basic/src/modules/todos/useTodos.ts +31 -0
  29. package/templates/react-basic/src/schema.ts +6 -12
  30. package/templates/react-basic/src/vite-env.d.ts +17 -0
  31. package/templates/react-basic/{tsconfig.json → tsconfig.json.hbs} +1 -2
  32. package/templates/react-basic/vite.config.ts +57 -50
  33. package/templates/react-sync/.env.example +19 -0
  34. package/templates/react-sync/README.md.hbs +43 -1
  35. package/templates/react-sync/package.json.hbs +3 -0
  36. package/templates/react-sync/server.ts +90 -26
  37. package/templates/react-sync/src/App.tsx +132 -130
  38. package/templates/react-sync/src/auth.ts +25 -0
  39. package/templates/react-sync/src/index.css +212 -165
  40. package/templates/react-sync/src/kora-worker.ts +0 -1
  41. package/templates/react-sync/src/main.tsx +34 -18
  42. package/templates/react-sync/src/modules/todos/todo.mutations.ts +25 -0
  43. package/templates/react-sync/src/modules/todos/todo.queries.ts +5 -0
  44. package/templates/react-sync/src/modules/todos/todo.schema.ts +10 -0
  45. package/templates/react-sync/src/modules/todos/useTodos.ts +31 -0
  46. package/templates/react-sync/src/schema.ts +6 -12
  47. package/templates/react-sync/src/vite-env.d.ts +17 -0
  48. package/templates/react-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
  49. package/templates/react-sync/vite.config.ts +67 -60
  50. package/templates/react-tailwind/README.md.hbs +10 -1
  51. package/templates/react-tailwind/src/App.tsx +186 -197
  52. package/templates/react-tailwind/src/index.css +3 -3
  53. package/templates/react-tailwind/src/kora-worker.ts +0 -1
  54. package/templates/react-tailwind/src/main.tsx +19 -12
  55. package/templates/react-tailwind/src/modules/todos/todo.mutations.ts +25 -0
  56. package/templates/react-tailwind/src/modules/todos/todo.queries.ts +5 -0
  57. package/templates/react-tailwind/src/modules/todos/todo.schema.ts +10 -0
  58. package/templates/react-tailwind/src/modules/todos/useTodos.ts +31 -0
  59. package/templates/react-tailwind/src/schema.ts +6 -12
  60. package/templates/react-tailwind/src/vite-env.d.ts +17 -0
  61. package/templates/react-tailwind/{tsconfig.json → tsconfig.json.hbs} +1 -2
  62. package/templates/react-tailwind/vite.config.ts +57 -50
  63. package/templates/react-tailwind-sync/.env.example +19 -0
  64. package/templates/react-tailwind-sync/README.md.hbs +43 -1
  65. package/templates/react-tailwind-sync/package.json.hbs +3 -0
  66. package/templates/react-tailwind-sync/server.ts +90 -26
  67. package/templates/react-tailwind-sync/src/App.tsx +246 -222
  68. package/templates/react-tailwind-sync/src/auth.ts +25 -0
  69. package/templates/react-tailwind-sync/src/index.css +3 -3
  70. package/templates/react-tailwind-sync/src/kora-worker.ts +0 -1
  71. package/templates/react-tailwind-sync/src/main.tsx +48 -18
  72. package/templates/react-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
  73. package/templates/react-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
  74. package/templates/react-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
  75. package/templates/react-tailwind-sync/src/modules/todos/useTodos.ts +31 -0
  76. package/templates/react-tailwind-sync/src/schema.ts +6 -12
  77. package/templates/react-tailwind-sync/src/vite-env.d.ts +17 -0
  78. package/templates/react-tailwind-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
  79. package/templates/react-tailwind-sync/vite.config.ts +67 -60
  80. package/templates/tauri-react/.env.example +20 -0
  81. package/templates/tauri-react/README.md.hbs +36 -1
  82. package/templates/tauri-react/dev.ts +11 -11
  83. package/templates/tauri-react/package.json.hbs +2 -0
  84. package/templates/tauri-react/server.ts +86 -12
  85. package/templates/tauri-react/src/App.tsx +769 -544
  86. package/templates/tauri-react/src/AppShell.tsx +125 -83
  87. package/templates/tauri-react/src/SetupScreen.tsx +257 -208
  88. package/templates/tauri-react/src/auth.ts +45 -0
  89. package/templates/tauri-react/src/main.tsx +3 -3
  90. package/templates/tauri-react/src/modules/todos/todo.mutations.ts +25 -0
  91. package/templates/tauri-react/src/modules/todos/todo.queries.ts +5 -0
  92. package/templates/tauri-react/src/modules/todos/todo.schema.ts +10 -0
  93. package/templates/tauri-react/src/modules/todos/useTodos.ts +31 -0
  94. package/templates/tauri-react/src/schema.ts +6 -12
  95. package/templates/tauri-react/src/sync-config.ts +47 -47
  96. package/templates/tauri-react/src/updater.ts +15 -15
  97. package/templates/tauri-react/src/vite-env.d.ts +17 -0
  98. package/templates/tauri-react/src-tauri/tauri.conf.json +2 -2
  99. package/templates/tauri-react/tsconfig.json.hbs +14 -0
  100. package/templates/tauri-react/vite.config.ts +9 -9
  101. package/dist/chunk-HNVCNPER.js.map +0 -1
  102. package/dist/chunk-MIMLCXSX.js.map +0 -1
  103. package/dist/chunk-ULTO5NFA.js.map +0 -1
  104. package/templates/tauri-react/tsconfig.json +0 -15
@@ -16,26 +16,26 @@ const SYNC_CONFIGURED_KEY = 'kora-sync-configured'
16
16
  * Priority: localStorage → VITE_SYNC_URL env var → null (needs setup).
17
17
  */
18
18
  export function getSyncUrl(): string | null {
19
- const stored = localStorage.getItem(SYNC_URL_KEY)
20
- if (stored) return stored
19
+ const stored = localStorage.getItem(SYNC_URL_KEY)
20
+ if (stored) return stored
21
21
 
22
- // Compile-time default (set via VITE_SYNC_URL when building)
23
- const envUrl = import.meta.env.VITE_SYNC_URL
24
- if (envUrl) return envUrl
22
+ // Compile-time default (set via VITE_SYNC_URL when building)
23
+ const envUrl = import.meta.env.VITE_SYNC_URL
24
+ if (envUrl) return envUrl
25
25
 
26
- return null
26
+ return null
27
27
  }
28
28
 
29
29
  /** Save a sync server URL to persistent local config. */
30
30
  export function setSyncUrl(url: string): void {
31
- localStorage.setItem(SYNC_URL_KEY, url)
32
- localStorage.setItem(SYNC_CONFIGURED_KEY, 'true')
31
+ localStorage.setItem(SYNC_URL_KEY, url)
32
+ localStorage.setItem(SYNC_CONFIGURED_KEY, 'true')
33
33
  }
34
34
 
35
35
  /** Clear the stored sync server URL (returns to setup screen). */
36
36
  export function clearSyncUrl(): void {
37
- localStorage.removeItem(SYNC_URL_KEY)
38
- localStorage.removeItem(SYNC_CONFIGURED_KEY)
37
+ localStorage.removeItem(SYNC_URL_KEY)
38
+ localStorage.removeItem(SYNC_CONFIGURED_KEY)
39
39
  }
40
40
 
41
41
  /**
@@ -43,14 +43,14 @@ export function clearSyncUrl(): void {
43
43
  * This is separate from getSyncUrl() — a user who skipped still completed setup.
44
44
  */
45
45
  export function hasCompletedSetup(): boolean {
46
- // If there's a compile-time URL, setup is not needed
47
- if (import.meta.env.VITE_SYNC_URL) return true
48
- return localStorage.getItem(SYNC_CONFIGURED_KEY) === 'true'
46
+ // If there's a compile-time URL, setup is not needed
47
+ if (import.meta.env.VITE_SYNC_URL) return true
48
+ return localStorage.getItem(SYNC_CONFIGURED_KEY) === 'true'
49
49
  }
50
50
 
51
51
  /** Mark setup as completed (used when user skips sync). */
52
52
  export function markSetupComplete(): void {
53
- localStorage.setItem(SYNC_CONFIGURED_KEY, 'true')
53
+ localStorage.setItem(SYNC_CONFIGURED_KEY, 'true')
54
54
  }
55
55
 
56
56
  /**
@@ -58,46 +58,46 @@ export function markSetupComplete(): void {
58
58
  * The app reloads with a fresh state, showing the setup screen.
59
59
  */
60
60
  export function factoryReset(): void {
61
- // Clear sync config
62
- clearSyncUrl()
63
- localStorage.removeItem(SYNC_CONFIGURED_KEY)
61
+ // Clear sync config
62
+ clearSyncUrl()
63
+ localStorage.removeItem(SYNC_CONFIGURED_KEY)
64
64
 
65
- // Clear all Kora local data by removing IndexedDB databases
66
- // and any other localStorage keys the app may have set.
67
- const keysToRemove: string[] = []
68
- for (let i = 0; i < localStorage.length; i++) {
69
- const key = localStorage.key(i)
70
- if (key && key.startsWith('kora-')) {
71
- keysToRemove.push(key)
72
- }
73
- }
74
- for (const key of keysToRemove) {
75
- localStorage.removeItem(key)
76
- }
65
+ // Clear all Kora local data by removing IndexedDB databases
66
+ // and any other localStorage keys the app may have set.
67
+ const keysToRemove: string[] = []
68
+ for (let i = 0; i < localStorage.length; i++) {
69
+ const key = localStorage.key(i)
70
+ if (key?.startsWith('kora-')) {
71
+ keysToRemove.push(key)
72
+ }
73
+ }
74
+ for (const key of keysToRemove) {
75
+ localStorage.removeItem(key)
76
+ }
77
77
 
78
- // Reload to reinitialize everything from scratch
79
- window.location.reload()
78
+ // Reload to reinitialize everything from scratch
79
+ window.location.reload()
80
80
  }
81
81
 
82
82
  /** Test if a WebSocket URL is reachable by attempting a brief connection. */
83
83
  export function testConnection(url: string, timeoutMs = 5000): Promise<boolean> {
84
- return new Promise((resolve) => {
85
- const timeout = setTimeout(() => {
86
- ws.close()
87
- resolve(false)
88
- }, timeoutMs)
84
+ return new Promise((resolve) => {
85
+ const timeout = setTimeout(() => {
86
+ ws.close()
87
+ resolve(false)
88
+ }, timeoutMs)
89
89
 
90
- const ws = new WebSocket(url)
90
+ const ws = new WebSocket(url)
91
91
 
92
- ws.onopen = () => {
93
- clearTimeout(timeout)
94
- ws.close()
95
- resolve(true)
96
- }
92
+ ws.onopen = () => {
93
+ clearTimeout(timeout)
94
+ ws.close()
95
+ resolve(true)
96
+ }
97
97
 
98
- ws.onerror = () => {
99
- clearTimeout(timeout)
100
- resolve(false)
101
- }
102
- })
98
+ ws.onerror = () => {
99
+ clearTimeout(timeout)
100
+ resolve(false)
101
+ }
102
+ })
103
103
  }
@@ -19,20 +19,20 @@ let updateChecked = false
19
19
  * Silently skips if the updater is not configured (empty endpoints/pubkey).
20
20
  */
21
21
  export async function checkForUpdates(): Promise<void> {
22
- if (updateChecked) return
23
- updateChecked = true
22
+ if (updateChecked) return
23
+ updateChecked = true
24
24
 
25
- try {
26
- const { check } = await import('@tauri-apps/plugin-updater')
27
- const update = await check()
28
- if (update) {
29
- console.log(`Update available: v${update.version}`)
30
- // Download and install — the app will restart automatically
31
- await update.downloadAndInstall()
32
- }
33
- } catch (err) {
34
- // Updater not configured or network unavailable — this is fine.
35
- // The app works fully offline; updates are best-effort.
36
- console.debug('Update check skipped:', err)
37
- }
25
+ try {
26
+ const { check } = await import('@tauri-apps/plugin-updater')
27
+ const update = await check()
28
+ if (update) {
29
+ console.log(`Update available: v${update.version}`)
30
+ // Download and install — the app will restart automatically
31
+ await update.downloadAndInstall()
32
+ }
33
+ } catch (err) {
34
+ // Updater not configured or network unavailable — this is fine.
35
+ // The app works fully offline; updates are best-effort.
36
+ console.debug('Update check skipped:', err)
37
+ }
38
38
  }
@@ -0,0 +1,17 @@
1
+ interface ImportMetaEnv {
2
+ readonly VITE_SYNC_URL?: string
3
+ }
4
+
5
+ interface ImportMeta {
6
+ readonly env: ImportMetaEnv
7
+ }
8
+
9
+ declare module '*?worker&url' {
10
+ const url: string
11
+ export default url
12
+ }
13
+
14
+ declare module '*?url' {
15
+ const url: string
16
+ export default url
17
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/nicholasgriffintn/tauri/refs/heads/dev/crates/tauri-config-schema/schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json",
3
3
  "productName": "kora-app",
4
4
  "version": "0.0.1",
5
5
  "identifier": "com.kora.app",
@@ -33,7 +33,7 @@
33
33
  "icons/icon.icns",
34
34
  "icons/icon.ico"
35
35
  ],
36
- "createUpdaterArtifacts": "v2Compatible"
36
+ "createUpdaterArtifacts": false
37
37
  },
38
38
  "plugins": {
39
39
  "updater": {
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "jsx": "react-jsx",
7
+ "strict": true,
8
+ "noUncheckedIndexedAccess": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "outDir": "dist"
12
+ },
13
+ "include": ["src"]
14
+ }
@@ -3,13 +3,13 @@ import { defineConfig } from 'vite'
3
3
 
4
4
  // Tauri apps use native SQLite — no WASM, no OPFS, no cross-origin isolation needed.
5
5
  export default defineConfig({
6
- plugins: [react()],
7
- // Prevent Vite from obscuring Rust compilation errors
8
- clearScreen: false,
9
- server: {
10
- // Tauri expects a fixed port; fail if it's not available
11
- strictPort: true,
12
- },
13
- // Environment variables with this prefix are exposed to the app
14
- envPrefix: ['VITE_', 'TAURI_'],
6
+ plugins: [react()],
7
+ // Prevent Vite from obscuring Rust compilation errors
8
+ clearScreen: false,
9
+ server: {
10
+ // Tauri expects a fixed port; fail if it's not available
11
+ strictPort: true,
12
+ },
13
+ // Environment variables with this prefix are exposed to the app
14
+ envPrefix: ['VITE_', 'TAURI_'],
15
15
  })
@@ -1 +0,0 @@
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/fs-helpers.ts","../src/utils/logger.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 { AuthOption, DatabaseOption, DatabaseProviderOption, FrameworkOption, PlatformOption } 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 = typeof 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\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 type { PromptClient } from '../../prompts/prompt-client'\nimport {\n\tgetDefaultCreatePreferences,\n\tgetCreatePreferencesOrDefault,\n\ttype CreatePreferences,\n\ttype PreferenceStore,\n} from '../../prompts/preferences'\nimport {\n\tdetermineTemplateFromSelections,\n\tisAuthValue,\n\tisDatabaseProviderValue,\n\tisDatabaseValue,\n\tisFrameworkValue,\n\tisPlatformValue,\n\ttype AuthOption,\n\ttype DatabaseOption,\n\ttype DatabaseProviderOption,\n\ttype FrameworkOption,\n\ttype PlatformOption,\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 uses fixed settings: React, plain CSS, native SQLite\n\t\teffective.framework = 'react'\n\t\teffective.tailwind = false\n\t\teffective.sync = true\n\t\teffective.db = 'sqlite'\n\t\teffective.dbProvider = 'none'\n\t\teffective.auth = 'none'\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(`Invalid --db value \"${flags.db}\". Expected one of: none, sqlite, postgres.`)\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 * This is a lightweight bridge until template-layer composition lands.\n * Today we only specialize the sync server template when Postgres is selected.\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 serverPath = join(options.targetDir, 'server.ts')\n\tconst envPath = join(options.targetDir, '.env.example')\n\tconst readmePath = join(options.targetDir, 'README.md')\n\n\tconst serverTemplate = [\n\t\t\"import { createPostgresServerStore, createProductionServer } from '@korajs/server'\",\n\t\t'',\n\t\t`// PostgreSQL provider preset: ${providerName}`,\n\t\t'// Ensure DATABASE_URL is set in your environment.',\n\t\t'',\n\t\t'async function start(): Promise<void> {',\n\t\t\"\\tconst connectionString = process.env.DATABASE_URL || ''\",\n\t\t'\\tif (connectionString.length === 0) {',\n\t\t\"\\t\\tthrow new Error('DATABASE_URL is required for PostgreSQL sync server store.')\",\n\t\t'\\t}',\n\t\t'',\n\t\t'\\tconst store = await createPostgresServerStore({ connectionString })',\n\t\t'\\tconst server = createProductionServer({',\n\t\t'\\t\\tstore,',\n\t\t\"\\t\\tport: Number(process.env.PORT) || 3001,\",\n\t\t\"\\t\\tstaticDir: './dist',\",\n\t\t\"\\t\\tsyncPath: '/kora-sync',\",\n\t\t'\\t})',\n\t\t'',\n\t\t'\\tconst url = await server.start()',\n\t\t'\\tconsole.log(`Kora app running at ${url}`)',\n\t\t'}',\n\t\t'',\n\t\t'void start()',\n\t\t'',\n\t].join('\\n')\n\n\tconst envTemplate = [\n\t\t'# Kora Sync Server',\n\t\t'# WebSocket URL for the sync server (used by the client)',\n\t\t'VITE_SYNC_URL=ws://localhost:3001',\n\t\t'',\n\t\t'# Sync server port',\n\t\t'PORT=3001',\n\t\t'',\n\t\t`# PostgreSQL connection string (${providerName})`,\n\t\t`# Example: ${providerConnectionString}`,\n\t\t'DATABASE_URL=',\n\t\t'',\n\t].join('\\n')\n\n\tconst existingReadme = await readFile(readmePath, 'utf-8')\n\tconst trimmedReadme = existingReadme.trimEnd()\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 uses `createPostgresServerStore` in `server.ts` and reads `DATABASE_URL` from the environment. See `.env.example` for provider-specific examples.',\n\t\t'',\n\t].join('\\n')\n\tconst readmeTemplate = `${trimmedReadme}${readmeSuffix}`\n\n\tawait writeFile(serverPath, serverTemplate, 'utf-8')\n\tawait writeFile(envPath, envTemplate, 'utf-8')\n\tawait writeFile(readmePath, readmeTemplate, 'utf-8')\n}\n\nfunction isSyncTemplate(template: TemplateName): boolean {\n\treturn template === 'react-sync' || template === 'react-tailwind-sync' || template === 'tauri-react'\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","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","/** 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"],"mappings":"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","names":["resolve","readFile","join","join","readFile"]}