zuro-cli 0.0.2-beta.0 → 0.0.2-beta.2
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/README.md +40 -0
- package/dist/index.js +58 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +58 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# zuro-cli
|
|
2
|
+
|
|
3
|
+
The backend builder for busy developers.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx zuro-cli@beta init
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Add modules:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx zuro-cli@beta add database
|
|
15
|
+
npx zuro-cli@beta add auth
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Docs
|
|
19
|
+
|
|
20
|
+
- https://zuro-cli.devbybriyan.com/docs
|
|
21
|
+
|
|
22
|
+
## Registry
|
|
23
|
+
|
|
24
|
+
Default registry:
|
|
25
|
+
|
|
26
|
+
- https://registry.devbybriyan.com/channels/stable.json
|
|
27
|
+
|
|
28
|
+
Override for local testing:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
export ZURO_REGISTRY_URL=http://127.0.0.1:8787
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Development
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
corepack pnpm install
|
|
38
|
+
corepack pnpm --filter zuro-cli build
|
|
39
|
+
corepack pnpm --filter zuro-cli lint
|
|
40
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ var import_prompts = __toESM(require("prompts"));
|
|
|
35
35
|
|
|
36
36
|
// src/utils/registry.ts
|
|
37
37
|
var import_node_crypto = require("crypto");
|
|
38
|
-
var DEFAULT_REGISTRY_BASE_URL = "https://
|
|
38
|
+
var DEFAULT_REGISTRY_BASE_URL = "https://registry.devbybriyan.com";
|
|
39
39
|
var DEFAULT_REGISTRY_ENTRY_URL = `${DEFAULT_REGISTRY_BASE_URL}/channels/stable.json`;
|
|
40
40
|
var REGISTRY_ENV_VAR = "ZURO_REGISTRY_URL";
|
|
41
41
|
var REQUEST_TIMEOUT_MS = 8e3;
|
|
@@ -189,15 +189,28 @@ async function fetchFile(filePath, options) {
|
|
|
189
189
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
190
190
|
var import_path = __toESM(require("path"));
|
|
191
191
|
var import_execa = require("execa");
|
|
192
|
-
|
|
192
|
+
function normalizePackageName(name) {
|
|
193
|
+
const normalized = name.trim().toLowerCase().replace(/[^a-z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
|
|
194
|
+
return normalized || "zuro-app";
|
|
195
|
+
}
|
|
196
|
+
async function ensurePackageManagerAvailable(pm) {
|
|
197
|
+
try {
|
|
198
|
+
await (0, import_execa.execa)(pm, ["--version"], { stdio: "ignore" });
|
|
199
|
+
} catch {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Package manager '${pm}' is not installed or not available in PATH. Install it or choose npm.`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function initPackageJson(cwd, force = false, packageName = "zuro-app", srcDir = "src") {
|
|
193
206
|
const pkgPath = import_path.default.join(cwd, "package.json");
|
|
194
207
|
if (force || !await import_fs_extra.default.pathExists(pkgPath)) {
|
|
195
208
|
await import_fs_extra.default.writeJson(pkgPath, {
|
|
196
|
-
name:
|
|
209
|
+
name: normalizePackageName(packageName),
|
|
197
210
|
version: "0.0.1",
|
|
198
211
|
private: true,
|
|
199
212
|
scripts: {
|
|
200
|
-
"dev":
|
|
213
|
+
"dev": `tsx watch ${srcDir}/server.ts`,
|
|
201
214
|
"build": "tsc",
|
|
202
215
|
"start": "node dist/server.js"
|
|
203
216
|
}
|
|
@@ -391,6 +404,21 @@ function resolveSafeTargetPath(projectRoot, srcDir, file) {
|
|
|
391
404
|
targetPath
|
|
392
405
|
};
|
|
393
406
|
}
|
|
407
|
+
async function ensureSafeTargetDirectory(targetDir, cwd, projectName) {
|
|
408
|
+
await import_fs_extra4.default.ensureDir(targetDir);
|
|
409
|
+
const entries = await import_fs_extra4.default.readdir(targetDir);
|
|
410
|
+
if (entries.length === 0) {
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
const isCurrentFolder = targetDir === cwd;
|
|
414
|
+
const response = await (0, import_prompts.default)({
|
|
415
|
+
type: "confirm",
|
|
416
|
+
name: "proceed",
|
|
417
|
+
message: isCurrentFolder ? `Current folder '${projectName}' is not empty. Continue anyway?` : `Target folder '${projectName}' already exists and is not empty. Continue anyway?`,
|
|
418
|
+
initial: false
|
|
419
|
+
});
|
|
420
|
+
return response.proceed === true;
|
|
421
|
+
}
|
|
394
422
|
async function init() {
|
|
395
423
|
const cwd = process.cwd();
|
|
396
424
|
const isExistingProject = await import_fs_extra4.default.pathExists(import_path4.default.join(cwd, "package.json"));
|
|
@@ -455,7 +483,11 @@ async function init() {
|
|
|
455
483
|
} else {
|
|
456
484
|
projectName = response.path.trim();
|
|
457
485
|
targetDir = import_path4.default.resolve(cwd, projectName);
|
|
458
|
-
|
|
486
|
+
}
|
|
487
|
+
const isSafeTarget = await ensureSafeTargetDirectory(targetDir, cwd, projectName);
|
|
488
|
+
if (!isSafeTarget) {
|
|
489
|
+
console.log(import_chalk2.default.red("Operation cancelled."));
|
|
490
|
+
return;
|
|
459
491
|
}
|
|
460
492
|
}
|
|
461
493
|
const existingConfig = targetDir === cwd ? existingZuroConfig : await readZuroConfig(targetDir);
|
|
@@ -464,20 +496,26 @@ async function init() {
|
|
|
464
496
|
pm,
|
|
465
497
|
srcDir: srcDir || existingConfig?.srcDir || "src"
|
|
466
498
|
};
|
|
467
|
-
await writeZuroConfig(targetDir, zuroConfig);
|
|
468
499
|
const spinner = (0, import_ora.default)("Connecting to Zuro Registry...").start();
|
|
500
|
+
let currentStep = "package manager preflight";
|
|
469
501
|
try {
|
|
502
|
+
spinner.text = `Checking ${pm} availability...`;
|
|
503
|
+
await ensurePackageManagerAvailable(pm);
|
|
504
|
+
currentStep = "registry fetch";
|
|
505
|
+
spinner.text = "Connecting to Zuro Registry...";
|
|
470
506
|
const registryContext = await fetchRegistry();
|
|
471
507
|
const coreModule = registryContext.manifest.modules.core;
|
|
472
508
|
if (!coreModule) {
|
|
473
509
|
spinner.fail("Core module not found in registry.");
|
|
474
510
|
return;
|
|
475
511
|
}
|
|
512
|
+
currentStep = "project initialization";
|
|
476
513
|
spinner.text = "Initializing project...";
|
|
477
514
|
const hasPackageJson = await import_fs_extra4.default.pathExists(import_path4.default.join(targetDir, "package.json"));
|
|
478
515
|
if (!hasPackageJson) {
|
|
479
|
-
await initPackageJson(targetDir, true);
|
|
516
|
+
await initPackageJson(targetDir, true, projectName, srcDir);
|
|
480
517
|
}
|
|
518
|
+
currentStep = "dependency installation";
|
|
481
519
|
spinner.text = `Installing dependencies using ${pm}...`;
|
|
482
520
|
let runtimeDeps = [];
|
|
483
521
|
let devDeps = [];
|
|
@@ -492,6 +530,7 @@ async function init() {
|
|
|
492
530
|
}
|
|
493
531
|
await installDependencies(pm, runtimeDeps, targetDir);
|
|
494
532
|
await installDependencies(pm, devDeps, targetDir, { dev: true });
|
|
533
|
+
currentStep = "module file generation";
|
|
495
534
|
spinner.text = "Fetching core module files...";
|
|
496
535
|
for (const file of coreModule.files) {
|
|
497
536
|
const { relativeTargetPath, targetPath } = resolveSafeTargetPath(targetDir, srcDir, file);
|
|
@@ -514,7 +553,10 @@ async function init() {
|
|
|
514
553
|
await import_fs_extra4.default.ensureDir(import_path4.default.dirname(targetPath));
|
|
515
554
|
await import_fs_extra4.default.writeFile(targetPath, content);
|
|
516
555
|
}
|
|
556
|
+
currentStep = "environment file setup";
|
|
517
557
|
await createInitialEnv(targetDir);
|
|
558
|
+
currentStep = "config write";
|
|
559
|
+
await writeZuroConfig(targetDir, zuroConfig);
|
|
518
560
|
spinner.succeed(import_chalk2.default.green("Project initialized successfully!"));
|
|
519
561
|
console.log(`
|
|
520
562
|
${import_chalk2.default.bold("Next steps:")}`);
|
|
@@ -525,8 +567,15 @@ ${import_chalk2.default.bold("Next steps:")}`);
|
|
|
525
567
|
console.log(`
|
|
526
568
|
${import_chalk2.default.dim("Add modules: zuro-cli add database, zuro-cli add auth")}`);
|
|
527
569
|
} catch (error) {
|
|
528
|
-
spinner.fail(import_chalk2.default.red(
|
|
529
|
-
|
|
570
|
+
spinner.fail(import_chalk2.default.red(`Failed during ${currentStep}.`));
|
|
571
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
572
|
+
console.error(import_chalk2.default.red(errorMessage));
|
|
573
|
+
console.log(`
|
|
574
|
+
${import_chalk2.default.bold("Retry:")}`);
|
|
575
|
+
if (targetDir !== cwd) {
|
|
576
|
+
console.log(import_chalk2.default.cyan(` cd ${projectName}`));
|
|
577
|
+
}
|
|
578
|
+
console.log(import_chalk2.default.cyan(" npx zuro-cli init"));
|
|
530
579
|
}
|
|
531
580
|
}
|
|
532
581
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/registry.ts","../src/utils/pm.ts","../src/utils/env-manager.ts","../src/utils/config.ts","../src/utils/project-guard.ts","../src/commands/add.ts","../src/utils/dependency.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init\";\nimport { add } from \"./commands/add\";\n\nconst program = new Command();\n\nprogram\n .name(\"zuro-cli\")\n .description(\"Zuro CLI tool\")\n .version(\"0.0.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new Zuro project\")\n .action(init);\n\nprogram\n .command(\"add <module>\")\n .description(\"Add a module to your project\")\n .action(add);\n\nprogram.parse(process.argv);\n","import ora from \"ora\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport prompts from \"prompts\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { initPackageJson, installDependencies } from \"../utils/pm\";\nimport { createInitialEnv } from \"../utils/env-manager\";\nimport { readZuroConfig, writeZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\nimport type { ZuroConfig } from \"../utils/config\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const relativeTargetPath = path.join(srcDir, file.target);\n const targetPath = path.resolve(projectRoot, relativeTargetPath);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return {\n relativeTargetPath,\n targetPath,\n };\n}\n\nexport async function init() {\n const cwd = process.cwd();\n const isExistingProject = await fs.pathExists(path.join(cwd, \"package.json\"));\n const existingZuroConfig = await readZuroConfig(cwd);\n\n if (isExistingProject && !existingZuroConfig) {\n showNonZuroProjectMessage();\n return;\n }\n\n let targetDir = cwd;\n let pm = \"npm\";\n let srcDir = \"src\";\n let projectName = path.basename(cwd);\n\n if (isExistingProject) {\n console.log(chalk.blue(\"ℹ Existing project detected.\"));\n\n projectName = path.basename(cwd);\n\n if (await fs.pathExists(path.join(cwd, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (await fs.pathExists(path.join(cwd, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (await fs.pathExists(path.join(cwd, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n const response = await prompts({\n type: \"text\",\n name: \"srcDir\",\n message: \"Where is your source code located?\",\n initial: \"src\",\n });\n\n srcDir = response.srcDir || \"src\";\n } else {\n console.log(chalk.dim(` Tip: Leave blank to use current folder (${path.basename(cwd)})\\n`));\n\n const response = await prompts([\n {\n type: \"text\",\n name: \"path\",\n message: \"Project name (blank for current folder)\",\n initial: \"\",\n },\n {\n type: \"select\",\n name: \"pm\",\n message: \"Package Manager?\",\n choices: [\n { title: \"npm\", value: \"npm\" },\n { title: \"pnpm\", value: \"pnpm\" },\n { title: \"bun\", value: \"bun\" },\n ],\n initial: 0,\n },\n ]);\n\n if (response.pm === undefined) {\n console.log(chalk.red(\"Operation cancelled.\"));\n return;\n }\n\n pm = response.pm;\n srcDir = \"src\";\n\n if (!response.path || response.path.trim() === \"\") {\n projectName = path.basename(cwd);\n targetDir = cwd;\n console.log(chalk.blue(`ℹ Using current folder: ${projectName}`));\n } else {\n projectName = response.path.trim();\n targetDir = path.resolve(cwd, projectName);\n await fs.ensureDir(targetDir);\n }\n }\n\n const existingConfig = targetDir === cwd ? existingZuroConfig : await readZuroConfig(targetDir);\n\n const zuroConfig: ZuroConfig = {\n name: projectName,\n pm,\n srcDir: srcDir || existingConfig?.srcDir || \"src\",\n };\n\n await writeZuroConfig(targetDir, zuroConfig);\n\n const spinner = ora(\"Connecting to Zuro Registry...\").start();\n\n try {\n const registryContext = await fetchRegistry();\n\n const coreModule = registryContext.manifest.modules.core;\n\n if (!coreModule) {\n spinner.fail(\"Core module not found in registry.\");\n return;\n }\n\n spinner.text = \"Initializing project...\";\n\n const hasPackageJson = await fs.pathExists(path.join(targetDir, \"package.json\"));\n if (!hasPackageJson) {\n await initPackageJson(targetDir, true);\n }\n\n spinner.text = `Installing dependencies using ${pm}...`;\n\n let runtimeDeps: string[] = [];\n let devDeps: string[] = [];\n\n if (isExistingProject) {\n const safeDeps = [\"zod\", \"dotenv\"];\n const coreDeps = coreModule.dependencies || [];\n runtimeDeps = coreDeps.filter((dependency) => safeDeps.includes(dependency));\n devDeps = coreModule.devDependencies || [];\n } else {\n runtimeDeps = coreModule.dependencies || [];\n devDeps = coreModule.devDependencies || [];\n }\n\n await installDependencies(pm, runtimeDeps, targetDir);\n await installDependencies(pm, devDeps, targetDir, { dev: true });\n\n spinner.text = \"Fetching core module files...\";\n\n for (const file of coreModule.files) {\n const { relativeTargetPath, targetPath } = resolveSafeTargetPath(targetDir, srcDir, file);\n const fileName = path.basename(targetPath);\n\n if (isExistingProject) {\n if (fileName === \"app.ts\" || fileName === \"server.ts\") {\n continue;\n }\n\n const relativeParts = relativeTargetPath.split(path.sep);\n const isSafe = fileName === \"env.ts\" || relativeParts.includes(\"lib\");\n if (!isSafe) {\n continue;\n }\n }\n\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n await createInitialEnv(targetDir);\n\n spinner.succeed(chalk.green(\"Project initialized successfully!\"));\n\n console.log(`\\n${chalk.bold(\"Next steps:\")}`);\n if (targetDir !== cwd) {\n console.log(chalk.cyan(` cd ${projectName}`));\n }\n console.log(chalk.cyan(` ${pm} run dev`));\n console.log(`\\n${chalk.dim(\"Add modules: zuro-cli add database, zuro-cli add auth\")}`);\n } catch (error) {\n spinner.fail(chalk.red(\"Failed to initialize project.\"));\n console.error(error);\n }\n}\n","import { createHash } from \"node:crypto\";\n\nconst DEFAULT_REGISTRY_BASE_URL = \"https://zuro-cli.devbybriyan.com/registry\";\nconst DEFAULT_REGISTRY_ENTRY_URL = `${DEFAULT_REGISTRY_BASE_URL}/channels/stable.json`;\nconst REGISTRY_ENV_VAR = \"ZURO_REGISTRY_URL\";\nconst REQUEST_TIMEOUT_MS = 8000;\nconst MAX_RETRIES = 2;\n\nexport interface RegistryFile {\n path: string;\n target: string;\n type: string;\n sha256?: string;\n size?: number;\n}\n\nexport interface RegistryModule {\n type: string;\n files: RegistryFile[];\n moduleDependencies?: string[];\n dependencies?: string[];\n devDependencies?: string[];\n}\n\nexport interface RegistryManifest {\n schemaVersion?: number;\n status?: string;\n templateVersion?: string;\n generatedAt?: string;\n modules: Record<string, RegistryModule>;\n}\n\ninterface RegistryChannelPointer {\n schemaVersion?: number;\n channel?: string;\n templateVersion?: string;\n generatedAt?: string;\n indexPath?: string;\n indexUrl?: string;\n}\n\nexport interface RegistryContext {\n manifest: RegistryManifest;\n manifestUrl: string;\n fileBaseUrl: string;\n}\n\ninterface FetchFileOptions {\n baseUrl: string;\n expectedSha256?: string;\n expectedSize?: number;\n}\n\nexport function getRegistryUrl() {\n return resolveRegistryEntryUrl();\n}\n\nfunction withTrailingSlash(url: string) {\n return url.endsWith(\"/\") ? url : `${url}/`;\n}\n\nfunction resolveRegistryEntryUrl() {\n const override = process.env[REGISTRY_ENV_VAR]?.trim();\n\n if (!override) {\n return DEFAULT_REGISTRY_ENTRY_URL;\n }\n\n let parsed: URL;\n\n try {\n parsed = new URL(override);\n } catch {\n throw new Error(\n `Invalid ${REGISTRY_ENV_VAR} value '${override}'. Expected a valid http(s) URL.`\n );\n }\n\n if (parsed.pathname.endsWith(\".json\")) {\n return parsed.toString();\n }\n\n return new URL(\"channels/stable.json\", withTrailingSlash(parsed.toString())).toString();\n}\n\nfunction isRegistryManifest(data: unknown): data is RegistryManifest {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryManifest>;\n return !!candidate.modules && typeof candidate.modules === \"object\";\n}\n\nfunction isChannelPointer(data: unknown): data is RegistryChannelPointer {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryChannelPointer>;\n return typeof candidate.indexPath === \"string\" || typeof candidate.indexUrl === \"string\";\n}\n\nfunction delay(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function fetchWithRetry(url: string): Promise<Response> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n headers: { Accept: \"application/json, text/plain, */*\" },\n signal: controller.signal,\n });\n\n if (response.ok) {\n return response;\n }\n\n const shouldRetry = response.status >= 500 && attempt < MAX_RETRIES;\n if (shouldRetry) {\n await delay(250 * (attempt + 1));\n continue;\n }\n\n throw new Error(`Request failed (${response.status} ${response.statusText}) for ${url}`);\n } catch (error) {\n lastError = error;\n\n if (attempt === MAX_RETRIES) {\n break;\n }\n\n await delay(250 * (attempt + 1));\n } finally {\n clearTimeout(timeout);\n }\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n\n throw new Error(`Failed to fetch ${url}`);\n}\n\nasync function fetchJson<T>(url: string): Promise<{ data: T; resolvedUrl: string }> {\n const response = await fetchWithRetry(url);\n const data = (await response.json()) as T;\n\n return {\n data,\n resolvedUrl: response.url || url,\n };\n}\n\nfunction resolveManifestUrl(pointer: RegistryChannelPointer, pointerUrl: string): string {\n const explicit = pointer.indexUrl || pointer.indexPath;\n\n if (!explicit) {\n throw new Error(\"Registry channel pointer is missing indexUrl/indexPath\");\n }\n\n return new URL(explicit, pointerUrl).toString();\n}\n\nexport async function fetchRegistry(): Promise<RegistryContext> {\n const registryEntryUrl = resolveRegistryEntryUrl();\n let entry: { data: unknown; resolvedUrl: string };\n\n try {\n entry = await fetchJson<unknown>(registryEntryUrl);\n } catch (error) {\n throw new Error(\n `Unable to fetch registry from ${registryEntryUrl}. For local testing set ${REGISTRY_ENV_VAR}=http://127.0.0.1:8787.`,\n { cause: error as Error }\n );\n }\n\n if (isRegistryManifest(entry.data)) {\n return {\n manifest: entry.data,\n manifestUrl: entry.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", entry.resolvedUrl).toString()),\n };\n }\n\n if (!isChannelPointer(entry.data)) {\n throw new Error(\n `Invalid registry payload at ${registryEntryUrl}. Expected manifest or channel pointer.`\n );\n }\n\n const manifestUrl = resolveManifestUrl(entry.data, entry.resolvedUrl);\n const manifestResult = await fetchJson<unknown>(manifestUrl);\n\n if (!isRegistryManifest(manifestResult.data)) {\n throw new Error(`Invalid manifest payload at ${manifestUrl}.`);\n }\n\n return {\n manifest: manifestResult.data,\n manifestUrl: manifestResult.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", manifestResult.resolvedUrl).toString()),\n };\n}\n\nexport async function fetchFile(filePath: string, options: FetchFileOptions) {\n const normalizedPath = filePath.replace(/^\\//, \"\");\n const fileUrl = new URL(normalizedPath, withTrailingSlash(options.baseUrl)).toString();\n const response = await fetchWithRetry(fileUrl);\n const content = await response.text();\n\n if (typeof options.expectedSize === \"number\") {\n const actualSize = Buffer.byteLength(content, \"utf8\");\n if (actualSize !== options.expectedSize) {\n throw new Error(\n `Size mismatch for ${filePath}. Expected ${options.expectedSize}, got ${actualSize}.`\n );\n }\n }\n\n if (options.expectedSha256) {\n const actualSha256 = createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n if (actualSha256 !== options.expectedSha256) {\n throw new Error(\n `Checksum mismatch for ${filePath}. Expected ${options.expectedSha256}, got ${actualSha256}.`\n );\n }\n }\n\n return content;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { execa } from \"execa\";\n\nexport async function initPackageJson(cwd: string, force: boolean = false) {\n const pkgPath = path.join(cwd, \"package.json\");\n if (force || !await fs.pathExists(pkgPath)) {\n await fs.writeJson(pkgPath, {\n name: \"zuro-app\",\n version: \"0.0.1\",\n private: true,\n scripts: {\n \"dev\": \"tsx watch src/server.ts\",\n \"build\": \"tsc\",\n \"start\": \"node dist/server.js\"\n }\n }, { spaces: 2 });\n }\n}\n\ninterface InstallOptions {\n dev?: boolean;\n}\n\nexport async function installDependencies(\n pm: string,\n deps: string[],\n cwd: string,\n options: InstallOptions = {}\n) {\n const uniqueDeps = [...new Set(deps)].filter(Boolean);\n\n if (uniqueDeps.length === 0) {\n return;\n }\n\n const isDev = options.dev ?? false;\n\n if (pm === \"npm\") {\n const args = [\"install\", ...(isDev ? [\"--save-dev\"] : []), ...uniqueDeps];\n await execa(\"npm\", args, { cwd });\n return;\n }\n\n if (pm === \"pnpm\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"pnpm\", args, { cwd });\n return;\n }\n\n if (pm === \"yarn\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"yarn\", args, { cwd });\n return;\n }\n\n if (pm === \"bun\") {\n const args = [\"add\", ...(isDev ? [\"-d\"] : []), ...uniqueDeps];\n await execa(\"bun\", args, { cwd });\n return;\n }\n\n throw new Error(`Unsupported package manager: ${pm}`);\n}\n","import fs from \"fs-extra\";\r\nimport path from \"path\";\r\nimport os from \"os\";\r\n\r\n/**\r\n * Creates or updates .env file with new variables\r\n */\r\nexport const updateEnvFile = async (\r\n cwd: string,\r\n variables: Record<string, string>,\r\n createIfMissing = true\r\n) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n let content = \"\";\r\n if (fs.existsSync(envPath)) {\r\n content = await fs.readFile(envPath, \"utf-8\");\r\n } else if (!createIfMissing) {\r\n return;\r\n }\r\n\r\n let modified = false;\r\n\r\n for (const [key, value] of Object.entries(variables)) {\r\n // Check if key already exists\r\n const regex = new RegExp(`^${key}=`, \"m\");\r\n if (!regex.test(content)) {\r\n // Add newline if content doesn't end with one\r\n if (content && !content.endsWith(\"\\n\")) {\r\n content += os.EOL;\r\n }\r\n content += `${key}=${value}${os.EOL}`;\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified || !fs.existsSync(envPath)) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n};\r\n\r\n/**\r\n * Updates env.ts to add new schema fields\r\n */\r\nexport const updateEnvSchema = async (\r\n cwd: string,\r\n srcDir: string,\r\n fields: Array<{ name: string; schema: string }>\r\n) => {\r\n const envPath = path.join(cwd, srcDir, \"env.ts\");\r\n\r\n if (!fs.existsSync(envPath)) {\r\n return false;\r\n }\r\n\r\n let content = await fs.readFile(envPath, \"utf-8\");\r\n let modified = false;\r\n\r\n for (const field of fields) {\r\n // Check if field already exists in schema\r\n if (content.includes(`${field.name}:`)) {\r\n continue;\r\n }\r\n\r\n // Find the closing of envSchema z.object({ ... })\r\n // Insert before the closing });\r\n const schemaEndRegex = /(\\n\\s*)(}\\);?\\s*\\n\\s*export const env)/;\r\n const match = content.match(schemaEndRegex);\r\n\r\n if (match) {\r\n const indent = \" \"; // 4 spaces\r\n const newField = `${indent}${field.name}: ${field.schema},\\n`;\r\n content = content.replace(\r\n schemaEndRegex,\r\n `\\n${newField}$1$2`\r\n );\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n\r\n return modified;\r\n};\r\n\r\n/**\r\n * Creates initial .env file for new projects\r\n */\r\nexport const createInitialEnv = async (cwd: string) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n if (fs.existsSync(envPath)) {\r\n return; // Don't overwrite existing\r\n }\r\n\r\n const content = `# Environment Variables\r\nPORT=3000\r\nNODE_ENV=development\r\n`;\r\n\r\n await fs.writeFile(envPath, content);\r\n};\r\n\r\n/**\r\n * Module-specific env configurations\r\n */\r\nexport const ENV_CONFIGS = {\r\n \"database-pg\": {\r\n envVars: {\r\n DATABASE_URL: \"postgresql://postgres@localhost:5432/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n \"database-mysql\": {\r\n envVars: {\r\n DATABASE_URL: \"mysql://root@localhost:3306/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n auth: {\r\n envVars: {\r\n BETTER_AUTH_SECRET: \"your-secret-key-at-least-32-characters-long\",\r\n BETTER_AUTH_URL: \"http://localhost:3000\",\r\n },\r\n schemaFields: [\r\n { name: \"BETTER_AUTH_SECRET\", schema: \"z.string().min(32)\" },\r\n { name: \"BETTER_AUTH_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n};\r\n","import fs from \"fs-extra\";\nimport path from \"path\";\n\nexport interface ZuroConfig {\n name?: string;\n pm?: string;\n srcDir?: string;\n}\n\nfunction sanitizeConfig(input: unknown): ZuroConfig {\n if (!input || typeof input !== \"object\") {\n return {};\n }\n\n const raw = input as Record<string, unknown>;\n const config: ZuroConfig = {};\n\n if (typeof raw.name === \"string\") {\n config.name = raw.name;\n }\n\n if (typeof raw.pm === \"string\") {\n config.pm = raw.pm;\n }\n\n if (typeof raw.srcDir === \"string\") {\n config.srcDir = raw.srcDir;\n }\n\n return config;\n}\n\nexport function getConfigPath(cwd: string) {\n return path.join(cwd, \"zuro.json\");\n}\n\nexport async function readZuroConfig(cwd: string): Promise<ZuroConfig | null> {\n const configPath = getConfigPath(cwd);\n\n if (!(await fs.pathExists(configPath))) {\n return null;\n }\n\n const raw = await fs.readJson(configPath);\n return sanitizeConfig(raw);\n}\n\nexport async function writeZuroConfig(cwd: string, config: ZuroConfig) {\n const configPath = getConfigPath(cwd);\n await fs.writeJson(configPath, sanitizeConfig(config), { spaces: 2 });\n}\n","import chalk from \"chalk\";\n\nexport function showNonZuroProjectMessage() {\n console.log(chalk.yellow(\"This directory looks like an existing project that wasn't created with Zuro CLI.\"));\n console.log(\"\");\n console.log(chalk.yellow(\"We stopped here because we don't want to make unnecessary changes to your project.\"));\n console.log(\"\");\n console.log(\"Zuro CLI works in:\");\n console.log(\"- a fresh/empty directory, or\");\n console.log(\"- an existing project already managed by Zuro CLI.\");\n}\n","import prompts from \"prompts\";\nimport ora from \"ora\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { installDependencies } from \"../utils/pm\";\nimport { resolveDependencies } from \"../utils/dependency\";\nimport { updateEnvFile, updateEnvSchema, ENV_CONFIGS } from \"../utils/env-manager\";\nimport chalk from \"chalk\";\nimport { readZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const targetPath = path.resolve(projectRoot, srcDir, file.target);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return targetPath;\n}\n\n/**\n * Modifies app.ts to include error handler middleware\n */\nasync function injectErrorHandler(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"errorHandler\")) {\n return true;\n }\n\n const errorImport = `import { errorHandler, notFoundHandler } from \"./middleware/error-handler\";`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${errorImport}` + content.slice(lastImportIndex);\n }\n\n const errorSetup = `\\n// Error handling (must be last)\\napp.use(notFoundHandler);\\napp.use(errorHandler);\\n`;\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + errorSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\n/**\n * Modifies app.ts to include auth routes\n */\nasync function injectAuthRoutes(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"routes/auth.routes\")) {\n return true;\n }\n\n const authImport = `import authRoutes from \"./routes/auth.routes\";`;\n const userImport = `import userRoutes from \"./routes/user.routes\";`;\n const routeSetup = `\\n// Auth routes\\napp.use(authRoutes);\\napp.use(\"/api/users\", userRoutes);\\n`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${authImport}\\n${userImport}` + content.slice(lastImportIndex);\n }\n\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + routeSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\nexport const add = async (moduleName: string) => {\n const projectRoot = process.cwd();\n const projectConfig = await readZuroConfig(projectRoot);\n if (!projectConfig) {\n showNonZuroProjectMessage();\n return;\n }\n let srcDir = projectConfig.srcDir || \"src\";\n\n let customDbUrl: string | undefined;\n\n const DEFAULT_URLS = {\n \"database-pg\": \"postgresql://root@localhost:5432/mydb\",\n \"database-mysql\": \"mysql://root@localhost:3306/mydb\",\n };\n\n if (moduleName === \"database\") {\n const variantResponse = await prompts({\n type: \"select\",\n name: \"variant\",\n message: \"Which database dialect?\",\n choices: [\n { title: \"PostgreSQL\", value: \"database-pg\" },\n { title: \"MySQL\", value: \"database-mysql\" },\n ],\n });\n\n if (!variantResponse.variant) {\n process.exit(0);\n }\n\n moduleName = variantResponse.variant;\n\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const urlResponse = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = urlResponse.dbUrl?.trim() || defaultUrl;\n }\n\n if ((moduleName === \"database-pg\" || moduleName === \"database-mysql\") && customDbUrl === undefined) {\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const response = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = response.dbUrl?.trim() || defaultUrl;\n }\n\n const spinner = ora(`Checking registry for ${moduleName}...`).start();\n\n try {\n const registryContext = await fetchRegistry();\n const module = registryContext.manifest.modules[moduleName];\n\n if (!module) {\n spinner.fail(`Module '${moduleName}' not found.`);\n return;\n }\n\n spinner.succeed(`Found module: ${chalk.cyan(moduleName)}`);\n\n const moduleDeps = module.moduleDependencies || [];\n await resolveDependencies(moduleDeps, projectRoot);\n\n spinner.start(\"Installing dependencies...\");\n\n let pm = \"npm\";\n if (fs.existsSync(path.join(projectRoot, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (fs.existsSync(path.join(projectRoot, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (fs.existsSync(path.join(projectRoot, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n await installDependencies(pm, module.dependencies || [], projectRoot);\n await installDependencies(pm, module.devDependencies || [], projectRoot, { dev: true });\n\n spinner.succeed(\"Dependencies installed\");\n\n spinner.start(\"Scaffolding files...\");\n\n for (const file of module.files) {\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n const targetPath = resolveSafeTargetPath(projectRoot, srcDir, file);\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n spinner.succeed(\"Files generated\");\n\n if (moduleName === \"auth\") {\n spinner.start(\"Configuring routes in app.ts...\");\n const injected = await injectAuthRoutes(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Routes configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - routes need manual setup\");\n }\n }\n\n if (moduleName === \"error-handler\") {\n spinner.start(\"Configuring error handler in app.ts...\");\n const injected = await injectErrorHandler(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Error handler configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - error handler needs manual setup\");\n }\n }\n\n const envConfig = ENV_CONFIGS[moduleName as keyof typeof ENV_CONFIGS];\n if (envConfig) {\n spinner.start(\"Updating environment configuration...\");\n\n const envVars: Record<string, string> = { ...envConfig.envVars };\n if (customDbUrl && (moduleName === \"database-pg\" || moduleName === \"database-mysql\")) {\n envVars.DATABASE_URL = customDbUrl;\n }\n\n await updateEnvFile(projectRoot, envVars);\n await updateEnvSchema(projectRoot, srcDir, envConfig.schemaFields);\n\n spinner.succeed(\"Environment configured\");\n }\n\n console.log(chalk.green(`\\n✔ ${moduleName} added successfully!\\n`));\n\n if (moduleName === \"auth\") {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n console.log(chalk.yellow(\"1. Update your .env file:\"));\n console.log(\n chalk.dim(\" We added placeholder values. Update BETTER_AUTH_SECRET with a secure key.\\n\")\n );\n console.log(chalk.yellow(\"2. Run database migrations:\"));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n console.log(chalk.yellow(\"3. Available endpoints:\"));\n console.log(chalk.dim(\" POST /auth/sign-up/email - Register\"));\n console.log(chalk.dim(\" POST /auth/sign-in/email - Login\"));\n console.log(chalk.dim(\" POST /auth/sign-out - Logout\"));\n console.log(chalk.dim(\" GET /api/users/me - Current user\\n\"));\n } else if (moduleName === \"error-handler\") {\n console.log(chalk.bold(\"📋 Usage:\\n\"));\n console.log(chalk.yellow(\"Throw errors in your controllers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { UnauthorizedError, NotFoundError } from \"./lib/errors\";`));\n console.log(\"\");\n console.log(chalk.white(` throw new UnauthorizedError(\"Invalid credentials\");`));\n console.log(chalk.white(` throw new NotFoundError(\"User not found\");`));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n console.log(chalk.yellow(\"Available error classes:\"));\n console.log(chalk.dim(\" BadRequestError (400)\"));\n console.log(chalk.dim(\" UnauthorizedError (401)\"));\n console.log(chalk.dim(\" ForbiddenError (403)\"));\n console.log(chalk.dim(\" NotFoundError (404)\"));\n console.log(chalk.dim(\" ConflictError (409)\"));\n console.log(chalk.dim(\" ValidationError (422)\"));\n console.log(chalk.dim(\" InternalServerError (500)\\n\"));\n console.log(chalk.yellow(\"Wrap async handlers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { asyncHandler } from \"./middleware/error-handler\";`));\n console.log(\"\");\n console.log(chalk.white(` router.get(\"/users\", asyncHandler(async (req, res) => {`));\n console.log(chalk.white(\" // errors auto-caught\"));\n console.log(chalk.white(\" }));\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n } else if (moduleName.includes(\"database\")) {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n let stepNum = 1;\n\n if (!customDbUrl) {\n console.log(chalk.yellow(`${stepNum}. Update DATABASE_URL in .env:`));\n console.log(\n chalk.dim(\" We added a placeholder. Update with your actual database credentials.\\n\")\n );\n stepNum++;\n }\n\n console.log(chalk.yellow(`${stepNum}. Create schemas in src/db/schema/:`));\n console.log(chalk.dim(\" Add table files and export from index.ts\\n\"));\n stepNum++;\n\n console.log(chalk.yellow(`${stepNum}. Run migrations:`));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n }\n } catch (error) {\n spinner.fail(`Failed to add module: ${(error as Error).message}`);\n }\n};\n","import { add } from \"../commands/add\";\nimport { readZuroConfig } from \"./config\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport chalk from \"chalk\";\n\n// Signature files to check if a Zuro module is installed\nconst BLOCK_SIGNATURES: Record<string, string> = {\n core: \"env.ts\",\n \"database-pg\": \"db/index.ts\",\n \"database-mysql\": \"db/index.ts\",\n validator: \"middleware/validate.ts\",\n \"error-handler\": \"lib/errors.ts\",\n logger: \"lib/logger.ts\",\n auth: \"lib/auth.ts\",\n};\n\n/**\n * Resolves Zuro module dependencies (NOT npm packages).\n * Only handles module dependencies like \"core\", \"database\", \"validator\", \"auth\".\n */\nexport const resolveDependencies = async (\n moduleDependencies: string[] | undefined,\n cwd: string\n) => {\n if (!moduleDependencies || moduleDependencies.length === 0) {\n return;\n }\n\n const config = await readZuroConfig(cwd);\n const srcDir = config?.srcDir || \"src\";\n\n for (const dep of moduleDependencies) {\n if (dep === \"database\") {\n const pgExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-pg\"]));\n const mysqlExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-mysql\"]));\n\n if (pgExists || mysqlExists) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Dependency '${dep}' is missing. Triggering install...`));\n await add(\"database\");\n continue;\n }\n\n const signature = BLOCK_SIGNATURES[dep];\n if (!signature) {\n continue;\n }\n\n if (fs.existsSync(path.join(cwd, srcDir, signature))) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Installing missing dependency: ${dep}...`));\n await add(dep);\n }\n};\n"],"mappings":"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","names":["import_chalk","import_fs_extra","import_path","path","fs","import_fs_extra","import_path","path","fs","os","import_fs_extra","import_path","path","fs","chalk","path","fs","chalk","prompts","ora","import_prompts","import_ora","import_path","import_fs_extra","import_fs_extra","import_path","import_chalk","fs","path","chalk","import_chalk","resolveSafeTargetPath","path","fs","prompts","chalk","ora","module"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/registry.ts","../src/utils/pm.ts","../src/utils/env-manager.ts","../src/utils/config.ts","../src/utils/project-guard.ts","../src/commands/add.ts","../src/utils/dependency.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init\";\nimport { add } from \"./commands/add\";\n\nconst program = new Command();\n\nprogram\n .name(\"zuro-cli\")\n .description(\"Zuro CLI tool\")\n .version(\"0.0.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new Zuro project\")\n .action(init);\n\nprogram\n .command(\"add <module>\")\n .description(\"Add a module to your project\")\n .action(add);\n\nprogram.parse(process.argv);\n","import ora from \"ora\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport prompts from \"prompts\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { initPackageJson, installDependencies, ensurePackageManagerAvailable } from \"../utils/pm\";\nimport { createInitialEnv } from \"../utils/env-manager\";\nimport { readZuroConfig, writeZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\nimport type { ZuroConfig } from \"../utils/config\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const relativeTargetPath = path.join(srcDir, file.target);\n const targetPath = path.resolve(projectRoot, relativeTargetPath);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return {\n relativeTargetPath,\n targetPath,\n };\n}\n\nasync function ensureSafeTargetDirectory(targetDir: string, cwd: string, projectName: string) {\n await fs.ensureDir(targetDir);\n const entries = await fs.readdir(targetDir);\n\n if (entries.length === 0) {\n return true;\n }\n\n const isCurrentFolder = targetDir === cwd;\n const response = await prompts({\n type: \"confirm\",\n name: \"proceed\",\n message: isCurrentFolder\n ? `Current folder '${projectName}' is not empty. Continue anyway?`\n : `Target folder '${projectName}' already exists and is not empty. Continue anyway?`,\n initial: false,\n });\n\n return response.proceed === true;\n}\n\nexport async function init() {\n const cwd = process.cwd();\n const isExistingProject = await fs.pathExists(path.join(cwd, \"package.json\"));\n const existingZuroConfig = await readZuroConfig(cwd);\n\n if (isExistingProject && !existingZuroConfig) {\n showNonZuroProjectMessage();\n return;\n }\n\n let targetDir = cwd;\n let pm = \"npm\";\n let srcDir = \"src\";\n let projectName = path.basename(cwd);\n\n if (isExistingProject) {\n console.log(chalk.blue(\"ℹ Existing project detected.\"));\n\n projectName = path.basename(cwd);\n\n if (await fs.pathExists(path.join(cwd, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (await fs.pathExists(path.join(cwd, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (await fs.pathExists(path.join(cwd, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n const response = await prompts({\n type: \"text\",\n name: \"srcDir\",\n message: \"Where is your source code located?\",\n initial: \"src\",\n });\n\n srcDir = response.srcDir || \"src\";\n } else {\n console.log(chalk.dim(` Tip: Leave blank to use current folder (${path.basename(cwd)})\\n`));\n\n const response = await prompts([\n {\n type: \"text\",\n name: \"path\",\n message: \"Project name (blank for current folder)\",\n initial: \"\",\n },\n {\n type: \"select\",\n name: \"pm\",\n message: \"Package Manager?\",\n choices: [\n { title: \"npm\", value: \"npm\" },\n { title: \"pnpm\", value: \"pnpm\" },\n { title: \"bun\", value: \"bun\" },\n ],\n initial: 0,\n },\n ]);\n\n if (response.pm === undefined) {\n console.log(chalk.red(\"Operation cancelled.\"));\n return;\n }\n\n pm = response.pm;\n srcDir = \"src\";\n\n if (!response.path || response.path.trim() === \"\") {\n projectName = path.basename(cwd);\n targetDir = cwd;\n console.log(chalk.blue(`ℹ Using current folder: ${projectName}`));\n } else {\n projectName = response.path.trim();\n targetDir = path.resolve(cwd, projectName);\n }\n\n const isSafeTarget = await ensureSafeTargetDirectory(targetDir, cwd, projectName);\n if (!isSafeTarget) {\n console.log(chalk.red(\"Operation cancelled.\"));\n return;\n }\n }\n\n const existingConfig = targetDir === cwd ? existingZuroConfig : await readZuroConfig(targetDir);\n\n const zuroConfig: ZuroConfig = {\n name: projectName,\n pm,\n srcDir: srcDir || existingConfig?.srcDir || \"src\",\n };\n\n const spinner = ora(\"Connecting to Zuro Registry...\").start();\n let currentStep = \"package manager preflight\";\n\n try {\n spinner.text = `Checking ${pm} availability...`;\n await ensurePackageManagerAvailable(pm);\n\n currentStep = \"registry fetch\";\n spinner.text = \"Connecting to Zuro Registry...\";\n const registryContext = await fetchRegistry();\n\n const coreModule = registryContext.manifest.modules.core;\n\n if (!coreModule) {\n spinner.fail(\"Core module not found in registry.\");\n return;\n }\n\n currentStep = \"project initialization\";\n spinner.text = \"Initializing project...\";\n\n const hasPackageJson = await fs.pathExists(path.join(targetDir, \"package.json\"));\n if (!hasPackageJson) {\n await initPackageJson(targetDir, true, projectName, srcDir);\n }\n\n currentStep = \"dependency installation\";\n spinner.text = `Installing dependencies using ${pm}...`;\n\n let runtimeDeps: string[] = [];\n let devDeps: string[] = [];\n\n if (isExistingProject) {\n const safeDeps = [\"zod\", \"dotenv\"];\n const coreDeps = coreModule.dependencies || [];\n runtimeDeps = coreDeps.filter((dependency) => safeDeps.includes(dependency));\n devDeps = coreModule.devDependencies || [];\n } else {\n runtimeDeps = coreModule.dependencies || [];\n devDeps = coreModule.devDependencies || [];\n }\n\n await installDependencies(pm, runtimeDeps, targetDir);\n await installDependencies(pm, devDeps, targetDir, { dev: true });\n\n currentStep = \"module file generation\";\n spinner.text = \"Fetching core module files...\";\n\n for (const file of coreModule.files) {\n const { relativeTargetPath, targetPath } = resolveSafeTargetPath(targetDir, srcDir, file);\n const fileName = path.basename(targetPath);\n\n if (isExistingProject) {\n if (fileName === \"app.ts\" || fileName === \"server.ts\") {\n continue;\n }\n\n const relativeParts = relativeTargetPath.split(path.sep);\n const isSafe = fileName === \"env.ts\" || relativeParts.includes(\"lib\");\n if (!isSafe) {\n continue;\n }\n }\n\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n currentStep = \"environment file setup\";\n await createInitialEnv(targetDir);\n\n currentStep = \"config write\";\n await writeZuroConfig(targetDir, zuroConfig);\n\n spinner.succeed(chalk.green(\"Project initialized successfully!\"));\n\n console.log(`\\n${chalk.bold(\"Next steps:\")}`);\n if (targetDir !== cwd) {\n console.log(chalk.cyan(` cd ${projectName}`));\n }\n console.log(chalk.cyan(` ${pm} run dev`));\n console.log(`\\n${chalk.dim(\"Add modules: zuro-cli add database, zuro-cli add auth\")}`);\n } catch (error) {\n spinner.fail(chalk.red(`Failed during ${currentStep}.`));\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(errorMessage));\n console.log(`\\n${chalk.bold(\"Retry:\")}`);\n if (targetDir !== cwd) {\n console.log(chalk.cyan(` cd ${projectName}`));\n }\n console.log(chalk.cyan(\" npx zuro-cli init\"));\n }\n}\n","import { createHash } from \"node:crypto\";\n\nconst DEFAULT_REGISTRY_BASE_URL = \"https://registry.devbybriyan.com\";\nconst DEFAULT_REGISTRY_ENTRY_URL = `${DEFAULT_REGISTRY_BASE_URL}/channels/stable.json`;\nconst REGISTRY_ENV_VAR = \"ZURO_REGISTRY_URL\";\nconst REQUEST_TIMEOUT_MS = 8000;\nconst MAX_RETRIES = 2;\n\nexport interface RegistryFile {\n path: string;\n target: string;\n type: string;\n sha256?: string;\n size?: number;\n}\n\nexport interface RegistryModule {\n type: string;\n files: RegistryFile[];\n moduleDependencies?: string[];\n dependencies?: string[];\n devDependencies?: string[];\n}\n\nexport interface RegistryManifest {\n schemaVersion?: number;\n status?: string;\n templateVersion?: string;\n generatedAt?: string;\n modules: Record<string, RegistryModule>;\n}\n\ninterface RegistryChannelPointer {\n schemaVersion?: number;\n channel?: string;\n templateVersion?: string;\n generatedAt?: string;\n indexPath?: string;\n indexUrl?: string;\n}\n\nexport interface RegistryContext {\n manifest: RegistryManifest;\n manifestUrl: string;\n fileBaseUrl: string;\n}\n\ninterface FetchFileOptions {\n baseUrl: string;\n expectedSha256?: string;\n expectedSize?: number;\n}\n\nexport function getRegistryUrl() {\n return resolveRegistryEntryUrl();\n}\n\nfunction withTrailingSlash(url: string) {\n return url.endsWith(\"/\") ? url : `${url}/`;\n}\n\nfunction resolveRegistryEntryUrl() {\n const override = process.env[REGISTRY_ENV_VAR]?.trim();\n\n if (!override) {\n return DEFAULT_REGISTRY_ENTRY_URL;\n }\n\n let parsed: URL;\n\n try {\n parsed = new URL(override);\n } catch {\n throw new Error(\n `Invalid ${REGISTRY_ENV_VAR} value '${override}'. Expected a valid http(s) URL.`\n );\n }\n\n if (parsed.pathname.endsWith(\".json\")) {\n return parsed.toString();\n }\n\n return new URL(\"channels/stable.json\", withTrailingSlash(parsed.toString())).toString();\n}\n\nfunction isRegistryManifest(data: unknown): data is RegistryManifest {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryManifest>;\n return !!candidate.modules && typeof candidate.modules === \"object\";\n}\n\nfunction isChannelPointer(data: unknown): data is RegistryChannelPointer {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryChannelPointer>;\n return typeof candidate.indexPath === \"string\" || typeof candidate.indexUrl === \"string\";\n}\n\nfunction delay(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function fetchWithRetry(url: string): Promise<Response> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n headers: { Accept: \"application/json, text/plain, */*\" },\n signal: controller.signal,\n });\n\n if (response.ok) {\n return response;\n }\n\n const shouldRetry = response.status >= 500 && attempt < MAX_RETRIES;\n if (shouldRetry) {\n await delay(250 * (attempt + 1));\n continue;\n }\n\n throw new Error(`Request failed (${response.status} ${response.statusText}) for ${url}`);\n } catch (error) {\n lastError = error;\n\n if (attempt === MAX_RETRIES) {\n break;\n }\n\n await delay(250 * (attempt + 1));\n } finally {\n clearTimeout(timeout);\n }\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n\n throw new Error(`Failed to fetch ${url}`);\n}\n\nasync function fetchJson<T>(url: string): Promise<{ data: T; resolvedUrl: string }> {\n const response = await fetchWithRetry(url);\n const data = (await response.json()) as T;\n\n return {\n data,\n resolvedUrl: response.url || url,\n };\n}\n\nfunction resolveManifestUrl(pointer: RegistryChannelPointer, pointerUrl: string): string {\n const explicit = pointer.indexUrl || pointer.indexPath;\n\n if (!explicit) {\n throw new Error(\"Registry channel pointer is missing indexUrl/indexPath\");\n }\n\n return new URL(explicit, pointerUrl).toString();\n}\n\nexport async function fetchRegistry(): Promise<RegistryContext> {\n const registryEntryUrl = resolveRegistryEntryUrl();\n let entry: { data: unknown; resolvedUrl: string };\n\n try {\n entry = await fetchJson<unknown>(registryEntryUrl);\n } catch (error) {\n throw new Error(\n `Unable to fetch registry from ${registryEntryUrl}. For local testing set ${REGISTRY_ENV_VAR}=http://127.0.0.1:8787.`,\n { cause: error as Error }\n );\n }\n\n if (isRegistryManifest(entry.data)) {\n return {\n manifest: entry.data,\n manifestUrl: entry.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", entry.resolvedUrl).toString()),\n };\n }\n\n if (!isChannelPointer(entry.data)) {\n throw new Error(\n `Invalid registry payload at ${registryEntryUrl}. Expected manifest or channel pointer.`\n );\n }\n\n const manifestUrl = resolveManifestUrl(entry.data, entry.resolvedUrl);\n const manifestResult = await fetchJson<unknown>(manifestUrl);\n\n if (!isRegistryManifest(manifestResult.data)) {\n throw new Error(`Invalid manifest payload at ${manifestUrl}.`);\n }\n\n return {\n manifest: manifestResult.data,\n manifestUrl: manifestResult.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", manifestResult.resolvedUrl).toString()),\n };\n}\n\nexport async function fetchFile(filePath: string, options: FetchFileOptions) {\n const normalizedPath = filePath.replace(/^\\//, \"\");\n const fileUrl = new URL(normalizedPath, withTrailingSlash(options.baseUrl)).toString();\n const response = await fetchWithRetry(fileUrl);\n const content = await response.text();\n\n if (typeof options.expectedSize === \"number\") {\n const actualSize = Buffer.byteLength(content, \"utf8\");\n if (actualSize !== options.expectedSize) {\n throw new Error(\n `Size mismatch for ${filePath}. Expected ${options.expectedSize}, got ${actualSize}.`\n );\n }\n }\n\n if (options.expectedSha256) {\n const actualSha256 = createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n if (actualSha256 !== options.expectedSha256) {\n throw new Error(\n `Checksum mismatch for ${filePath}. Expected ${options.expectedSha256}, got ${actualSha256}.`\n );\n }\n }\n\n return content;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { execa } from \"execa\";\n\nfunction normalizePackageName(name: string) {\n const normalized = name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^[._-]+|[._-]+$/g, \"\");\n\n return normalized || \"zuro-app\";\n}\n\nexport async function ensurePackageManagerAvailable(pm: string) {\n try {\n await execa(pm, [\"--version\"], { stdio: \"ignore\" });\n } catch {\n throw new Error(\n `Package manager '${pm}' is not installed or not available in PATH. Install it or choose npm.`\n );\n }\n}\n\nexport async function initPackageJson(\n cwd: string,\n force: boolean = false,\n packageName = \"zuro-app\",\n srcDir = \"src\"\n) {\n const pkgPath = path.join(cwd, \"package.json\");\n if (force || !await fs.pathExists(pkgPath)) {\n await fs.writeJson(pkgPath, {\n name: normalizePackageName(packageName),\n version: \"0.0.1\",\n private: true,\n scripts: {\n \"dev\": `tsx watch ${srcDir}/server.ts`,\n \"build\": \"tsc\",\n \"start\": \"node dist/server.js\"\n }\n }, { spaces: 2 });\n }\n}\n\ninterface InstallOptions {\n dev?: boolean;\n}\n\nexport async function installDependencies(\n pm: string,\n deps: string[],\n cwd: string,\n options: InstallOptions = {}\n) {\n const uniqueDeps = [...new Set(deps)].filter(Boolean);\n\n if (uniqueDeps.length === 0) {\n return;\n }\n\n const isDev = options.dev ?? false;\n\n if (pm === \"npm\") {\n const args = [\"install\", ...(isDev ? [\"--save-dev\"] : []), ...uniqueDeps];\n await execa(\"npm\", args, { cwd });\n return;\n }\n\n if (pm === \"pnpm\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"pnpm\", args, { cwd });\n return;\n }\n\n if (pm === \"yarn\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"yarn\", args, { cwd });\n return;\n }\n\n if (pm === \"bun\") {\n const args = [\"add\", ...(isDev ? [\"-d\"] : []), ...uniqueDeps];\n await execa(\"bun\", args, { cwd });\n return;\n }\n\n throw new Error(`Unsupported package manager: ${pm}`);\n}\n","import fs from \"fs-extra\";\r\nimport path from \"path\";\r\nimport os from \"os\";\r\n\r\n/**\r\n * Creates or updates .env file with new variables\r\n */\r\nexport const updateEnvFile = async (\r\n cwd: string,\r\n variables: Record<string, string>,\r\n createIfMissing = true\r\n) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n let content = \"\";\r\n if (fs.existsSync(envPath)) {\r\n content = await fs.readFile(envPath, \"utf-8\");\r\n } else if (!createIfMissing) {\r\n return;\r\n }\r\n\r\n let modified = false;\r\n\r\n for (const [key, value] of Object.entries(variables)) {\r\n // Check if key already exists\r\n const regex = new RegExp(`^${key}=`, \"m\");\r\n if (!regex.test(content)) {\r\n // Add newline if content doesn't end with one\r\n if (content && !content.endsWith(\"\\n\")) {\r\n content += os.EOL;\r\n }\r\n content += `${key}=${value}${os.EOL}`;\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified || !fs.existsSync(envPath)) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n};\r\n\r\n/**\r\n * Updates env.ts to add new schema fields\r\n */\r\nexport const updateEnvSchema = async (\r\n cwd: string,\r\n srcDir: string,\r\n fields: Array<{ name: string; schema: string }>\r\n) => {\r\n const envPath = path.join(cwd, srcDir, \"env.ts\");\r\n\r\n if (!fs.existsSync(envPath)) {\r\n return false;\r\n }\r\n\r\n let content = await fs.readFile(envPath, \"utf-8\");\r\n let modified = false;\r\n\r\n for (const field of fields) {\r\n // Check if field already exists in schema\r\n if (content.includes(`${field.name}:`)) {\r\n continue;\r\n }\r\n\r\n // Find the closing of envSchema z.object({ ... })\r\n // Insert before the closing });\r\n const schemaEndRegex = /(\\n\\s*)(}\\);?\\s*\\n\\s*export const env)/;\r\n const match = content.match(schemaEndRegex);\r\n\r\n if (match) {\r\n const indent = \" \"; // 4 spaces\r\n const newField = `${indent}${field.name}: ${field.schema},\\n`;\r\n content = content.replace(\r\n schemaEndRegex,\r\n `\\n${newField}$1$2`\r\n );\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n\r\n return modified;\r\n};\r\n\r\n/**\r\n * Creates initial .env file for new projects\r\n */\r\nexport const createInitialEnv = async (cwd: string) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n if (fs.existsSync(envPath)) {\r\n return; // Don't overwrite existing\r\n }\r\n\r\n const content = `# Environment Variables\r\nPORT=3000\r\nNODE_ENV=development\r\n`;\r\n\r\n await fs.writeFile(envPath, content);\r\n};\r\n\r\n/**\r\n * Module-specific env configurations\r\n */\r\nexport const ENV_CONFIGS = {\r\n \"database-pg\": {\r\n envVars: {\r\n DATABASE_URL: \"postgresql://postgres@localhost:5432/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n \"database-mysql\": {\r\n envVars: {\r\n DATABASE_URL: \"mysql://root@localhost:3306/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n auth: {\r\n envVars: {\r\n BETTER_AUTH_SECRET: \"your-secret-key-at-least-32-characters-long\",\r\n BETTER_AUTH_URL: \"http://localhost:3000\",\r\n },\r\n schemaFields: [\r\n { name: \"BETTER_AUTH_SECRET\", schema: \"z.string().min(32)\" },\r\n { name: \"BETTER_AUTH_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n};\r\n","import fs from \"fs-extra\";\nimport path from \"path\";\n\nexport interface ZuroConfig {\n name?: string;\n pm?: string;\n srcDir?: string;\n}\n\nfunction sanitizeConfig(input: unknown): ZuroConfig {\n if (!input || typeof input !== \"object\") {\n return {};\n }\n\n const raw = input as Record<string, unknown>;\n const config: ZuroConfig = {};\n\n if (typeof raw.name === \"string\") {\n config.name = raw.name;\n }\n\n if (typeof raw.pm === \"string\") {\n config.pm = raw.pm;\n }\n\n if (typeof raw.srcDir === \"string\") {\n config.srcDir = raw.srcDir;\n }\n\n return config;\n}\n\nexport function getConfigPath(cwd: string) {\n return path.join(cwd, \"zuro.json\");\n}\n\nexport async function readZuroConfig(cwd: string): Promise<ZuroConfig | null> {\n const configPath = getConfigPath(cwd);\n\n if (!(await fs.pathExists(configPath))) {\n return null;\n }\n\n const raw = await fs.readJson(configPath);\n return sanitizeConfig(raw);\n}\n\nexport async function writeZuroConfig(cwd: string, config: ZuroConfig) {\n const configPath = getConfigPath(cwd);\n await fs.writeJson(configPath, sanitizeConfig(config), { spaces: 2 });\n}\n","import chalk from \"chalk\";\n\nexport function showNonZuroProjectMessage() {\n console.log(chalk.yellow(\"This directory looks like an existing project that wasn't created with Zuro CLI.\"));\n console.log(\"\");\n console.log(chalk.yellow(\"We stopped here because we don't want to make unnecessary changes to your project.\"));\n console.log(\"\");\n console.log(\"Zuro CLI works in:\");\n console.log(\"- a fresh/empty directory, or\");\n console.log(\"- an existing project already managed by Zuro CLI.\");\n}\n","import prompts from \"prompts\";\nimport ora from \"ora\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { installDependencies } from \"../utils/pm\";\nimport { resolveDependencies } from \"../utils/dependency\";\nimport { updateEnvFile, updateEnvSchema, ENV_CONFIGS } from \"../utils/env-manager\";\nimport chalk from \"chalk\";\nimport { readZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const targetPath = path.resolve(projectRoot, srcDir, file.target);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return targetPath;\n}\n\n/**\n * Modifies app.ts to include error handler middleware\n */\nasync function injectErrorHandler(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"errorHandler\")) {\n return true;\n }\n\n const errorImport = `import { errorHandler, notFoundHandler } from \"./middleware/error-handler\";`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${errorImport}` + content.slice(lastImportIndex);\n }\n\n const errorSetup = `\\n// Error handling (must be last)\\napp.use(notFoundHandler);\\napp.use(errorHandler);\\n`;\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + errorSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\n/**\n * Modifies app.ts to include auth routes\n */\nasync function injectAuthRoutes(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"routes/auth.routes\")) {\n return true;\n }\n\n const authImport = `import authRoutes from \"./routes/auth.routes\";`;\n const userImport = `import userRoutes from \"./routes/user.routes\";`;\n const routeSetup = `\\n// Auth routes\\napp.use(authRoutes);\\napp.use(\"/api/users\", userRoutes);\\n`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${authImport}\\n${userImport}` + content.slice(lastImportIndex);\n }\n\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + routeSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\nexport const add = async (moduleName: string) => {\n const projectRoot = process.cwd();\n const projectConfig = await readZuroConfig(projectRoot);\n if (!projectConfig) {\n showNonZuroProjectMessage();\n return;\n }\n let srcDir = projectConfig.srcDir || \"src\";\n\n let customDbUrl: string | undefined;\n\n const DEFAULT_URLS = {\n \"database-pg\": \"postgresql://root@localhost:5432/mydb\",\n \"database-mysql\": \"mysql://root@localhost:3306/mydb\",\n };\n\n if (moduleName === \"database\") {\n const variantResponse = await prompts({\n type: \"select\",\n name: \"variant\",\n message: \"Which database dialect?\",\n choices: [\n { title: \"PostgreSQL\", value: \"database-pg\" },\n { title: \"MySQL\", value: \"database-mysql\" },\n ],\n });\n\n if (!variantResponse.variant) {\n process.exit(0);\n }\n\n moduleName = variantResponse.variant;\n\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const urlResponse = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = urlResponse.dbUrl?.trim() || defaultUrl;\n }\n\n if ((moduleName === \"database-pg\" || moduleName === \"database-mysql\") && customDbUrl === undefined) {\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const response = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = response.dbUrl?.trim() || defaultUrl;\n }\n\n const spinner = ora(`Checking registry for ${moduleName}...`).start();\n\n try {\n const registryContext = await fetchRegistry();\n const module = registryContext.manifest.modules[moduleName];\n\n if (!module) {\n spinner.fail(`Module '${moduleName}' not found.`);\n return;\n }\n\n spinner.succeed(`Found module: ${chalk.cyan(moduleName)}`);\n\n const moduleDeps = module.moduleDependencies || [];\n await resolveDependencies(moduleDeps, projectRoot);\n\n spinner.start(\"Installing dependencies...\");\n\n let pm = \"npm\";\n if (fs.existsSync(path.join(projectRoot, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (fs.existsSync(path.join(projectRoot, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (fs.existsSync(path.join(projectRoot, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n await installDependencies(pm, module.dependencies || [], projectRoot);\n await installDependencies(pm, module.devDependencies || [], projectRoot, { dev: true });\n\n spinner.succeed(\"Dependencies installed\");\n\n spinner.start(\"Scaffolding files...\");\n\n for (const file of module.files) {\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n const targetPath = resolveSafeTargetPath(projectRoot, srcDir, file);\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n spinner.succeed(\"Files generated\");\n\n if (moduleName === \"auth\") {\n spinner.start(\"Configuring routes in app.ts...\");\n const injected = await injectAuthRoutes(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Routes configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - routes need manual setup\");\n }\n }\n\n if (moduleName === \"error-handler\") {\n spinner.start(\"Configuring error handler in app.ts...\");\n const injected = await injectErrorHandler(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Error handler configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - error handler needs manual setup\");\n }\n }\n\n const envConfig = ENV_CONFIGS[moduleName as keyof typeof ENV_CONFIGS];\n if (envConfig) {\n spinner.start(\"Updating environment configuration...\");\n\n const envVars: Record<string, string> = { ...envConfig.envVars };\n if (customDbUrl && (moduleName === \"database-pg\" || moduleName === \"database-mysql\")) {\n envVars.DATABASE_URL = customDbUrl;\n }\n\n await updateEnvFile(projectRoot, envVars);\n await updateEnvSchema(projectRoot, srcDir, envConfig.schemaFields);\n\n spinner.succeed(\"Environment configured\");\n }\n\n console.log(chalk.green(`\\n✔ ${moduleName} added successfully!\\n`));\n\n if (moduleName === \"auth\") {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n console.log(chalk.yellow(\"1. Update your .env file:\"));\n console.log(\n chalk.dim(\" We added placeholder values. Update BETTER_AUTH_SECRET with a secure key.\\n\")\n );\n console.log(chalk.yellow(\"2. Run database migrations:\"));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n console.log(chalk.yellow(\"3. Available endpoints:\"));\n console.log(chalk.dim(\" POST /auth/sign-up/email - Register\"));\n console.log(chalk.dim(\" POST /auth/sign-in/email - Login\"));\n console.log(chalk.dim(\" POST /auth/sign-out - Logout\"));\n console.log(chalk.dim(\" GET /api/users/me - Current user\\n\"));\n } else if (moduleName === \"error-handler\") {\n console.log(chalk.bold(\"📋 Usage:\\n\"));\n console.log(chalk.yellow(\"Throw errors in your controllers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { UnauthorizedError, NotFoundError } from \"./lib/errors\";`));\n console.log(\"\");\n console.log(chalk.white(` throw new UnauthorizedError(\"Invalid credentials\");`));\n console.log(chalk.white(` throw new NotFoundError(\"User not found\");`));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n console.log(chalk.yellow(\"Available error classes:\"));\n console.log(chalk.dim(\" BadRequestError (400)\"));\n console.log(chalk.dim(\" UnauthorizedError (401)\"));\n console.log(chalk.dim(\" ForbiddenError (403)\"));\n console.log(chalk.dim(\" NotFoundError (404)\"));\n console.log(chalk.dim(\" ConflictError (409)\"));\n console.log(chalk.dim(\" ValidationError (422)\"));\n console.log(chalk.dim(\" InternalServerError (500)\\n\"));\n console.log(chalk.yellow(\"Wrap async handlers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { asyncHandler } from \"./middleware/error-handler\";`));\n console.log(\"\");\n console.log(chalk.white(` router.get(\"/users\", asyncHandler(async (req, res) => {`));\n console.log(chalk.white(\" // errors auto-caught\"));\n console.log(chalk.white(\" }));\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n } else if (moduleName.includes(\"database\")) {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n let stepNum = 1;\n\n if (!customDbUrl) {\n console.log(chalk.yellow(`${stepNum}. Update DATABASE_URL in .env:`));\n console.log(\n chalk.dim(\" We added a placeholder. Update with your actual database credentials.\\n\")\n );\n stepNum++;\n }\n\n console.log(chalk.yellow(`${stepNum}. Create schemas in src/db/schema/:`));\n console.log(chalk.dim(\" Add table files and export from index.ts\\n\"));\n stepNum++;\n\n console.log(chalk.yellow(`${stepNum}. Run migrations:`));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n }\n } catch (error) {\n spinner.fail(`Failed to add module: ${(error as Error).message}`);\n }\n};\n","import { add } from \"../commands/add\";\nimport { readZuroConfig } from \"./config\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport chalk from \"chalk\";\n\n// Signature files to check if a Zuro module is installed\nconst BLOCK_SIGNATURES: Record<string, string> = {\n core: \"env.ts\",\n \"database-pg\": \"db/index.ts\",\n \"database-mysql\": \"db/index.ts\",\n validator: \"middleware/validate.ts\",\n \"error-handler\": \"lib/errors.ts\",\n logger: \"lib/logger.ts\",\n auth: \"lib/auth.ts\",\n};\n\n/**\n * Resolves Zuro module dependencies (NOT npm packages).\n * Only handles module dependencies like \"core\", \"database\", \"validator\", \"auth\".\n */\nexport const resolveDependencies = async (\n moduleDependencies: string[] | undefined,\n cwd: string\n) => {\n if (!moduleDependencies || moduleDependencies.length === 0) {\n return;\n }\n\n const config = await readZuroConfig(cwd);\n const srcDir = config?.srcDir || \"src\";\n\n for (const dep of moduleDependencies) {\n if (dep === \"database\") {\n const pgExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-pg\"]));\n const mysqlExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-mysql\"]));\n\n if (pgExists || mysqlExists) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Dependency '${dep}' is missing. Triggering install...`));\n await add(\"database\");\n continue;\n }\n\n const signature = BLOCK_SIGNATURES[dep];\n if (!signature) {\n continue;\n }\n\n if (fs.existsSync(path.join(cwd, srcDir, signature))) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Installing missing dependency: ${dep}...`));\n await add(dep);\n }\n};\n"],"mappings":"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","names":["import_chalk","import_fs_extra","import_path","path","fs","import_fs_extra","import_path","path","fs","os","import_fs_extra","import_path","path","fs","chalk","path","fs","prompts","chalk","ora","import_prompts","import_ora","import_path","import_fs_extra","import_fs_extra","import_path","import_chalk","fs","path","chalk","import_chalk","resolveSafeTargetPath","path","fs","prompts","chalk","ora","module"]}
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import prompts from "prompts";
|
|
|
12
12
|
|
|
13
13
|
// src/utils/registry.ts
|
|
14
14
|
import { createHash } from "crypto";
|
|
15
|
-
var DEFAULT_REGISTRY_BASE_URL = "https://
|
|
15
|
+
var DEFAULT_REGISTRY_BASE_URL = "https://registry.devbybriyan.com";
|
|
16
16
|
var DEFAULT_REGISTRY_ENTRY_URL = `${DEFAULT_REGISTRY_BASE_URL}/channels/stable.json`;
|
|
17
17
|
var REGISTRY_ENV_VAR = "ZURO_REGISTRY_URL";
|
|
18
18
|
var REQUEST_TIMEOUT_MS = 8e3;
|
|
@@ -166,15 +166,28 @@ async function fetchFile(filePath, options) {
|
|
|
166
166
|
import fs from "fs-extra";
|
|
167
167
|
import path from "path";
|
|
168
168
|
import { execa } from "execa";
|
|
169
|
-
|
|
169
|
+
function normalizePackageName(name) {
|
|
170
|
+
const normalized = name.trim().toLowerCase().replace(/[^a-z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
|
|
171
|
+
return normalized || "zuro-app";
|
|
172
|
+
}
|
|
173
|
+
async function ensurePackageManagerAvailable(pm) {
|
|
174
|
+
try {
|
|
175
|
+
await execa(pm, ["--version"], { stdio: "ignore" });
|
|
176
|
+
} catch {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Package manager '${pm}' is not installed or not available in PATH. Install it or choose npm.`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function initPackageJson(cwd, force = false, packageName = "zuro-app", srcDir = "src") {
|
|
170
183
|
const pkgPath = path.join(cwd, "package.json");
|
|
171
184
|
if (force || !await fs.pathExists(pkgPath)) {
|
|
172
185
|
await fs.writeJson(pkgPath, {
|
|
173
|
-
name:
|
|
186
|
+
name: normalizePackageName(packageName),
|
|
174
187
|
version: "0.0.1",
|
|
175
188
|
private: true,
|
|
176
189
|
scripts: {
|
|
177
|
-
"dev":
|
|
190
|
+
"dev": `tsx watch ${srcDir}/server.ts`,
|
|
178
191
|
"build": "tsc",
|
|
179
192
|
"start": "node dist/server.js"
|
|
180
193
|
}
|
|
@@ -368,6 +381,21 @@ function resolveSafeTargetPath(projectRoot, srcDir, file) {
|
|
|
368
381
|
targetPath
|
|
369
382
|
};
|
|
370
383
|
}
|
|
384
|
+
async function ensureSafeTargetDirectory(targetDir, cwd, projectName) {
|
|
385
|
+
await fs4.ensureDir(targetDir);
|
|
386
|
+
const entries = await fs4.readdir(targetDir);
|
|
387
|
+
if (entries.length === 0) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
const isCurrentFolder = targetDir === cwd;
|
|
391
|
+
const response = await prompts({
|
|
392
|
+
type: "confirm",
|
|
393
|
+
name: "proceed",
|
|
394
|
+
message: isCurrentFolder ? `Current folder '${projectName}' is not empty. Continue anyway?` : `Target folder '${projectName}' already exists and is not empty. Continue anyway?`,
|
|
395
|
+
initial: false
|
|
396
|
+
});
|
|
397
|
+
return response.proceed === true;
|
|
398
|
+
}
|
|
371
399
|
async function init() {
|
|
372
400
|
const cwd = process.cwd();
|
|
373
401
|
const isExistingProject = await fs4.pathExists(path4.join(cwd, "package.json"));
|
|
@@ -432,7 +460,11 @@ async function init() {
|
|
|
432
460
|
} else {
|
|
433
461
|
projectName = response.path.trim();
|
|
434
462
|
targetDir = path4.resolve(cwd, projectName);
|
|
435
|
-
|
|
463
|
+
}
|
|
464
|
+
const isSafeTarget = await ensureSafeTargetDirectory(targetDir, cwd, projectName);
|
|
465
|
+
if (!isSafeTarget) {
|
|
466
|
+
console.log(chalk2.red("Operation cancelled."));
|
|
467
|
+
return;
|
|
436
468
|
}
|
|
437
469
|
}
|
|
438
470
|
const existingConfig = targetDir === cwd ? existingZuroConfig : await readZuroConfig(targetDir);
|
|
@@ -441,20 +473,26 @@ async function init() {
|
|
|
441
473
|
pm,
|
|
442
474
|
srcDir: srcDir || existingConfig?.srcDir || "src"
|
|
443
475
|
};
|
|
444
|
-
await writeZuroConfig(targetDir, zuroConfig);
|
|
445
476
|
const spinner = ora("Connecting to Zuro Registry...").start();
|
|
477
|
+
let currentStep = "package manager preflight";
|
|
446
478
|
try {
|
|
479
|
+
spinner.text = `Checking ${pm} availability...`;
|
|
480
|
+
await ensurePackageManagerAvailable(pm);
|
|
481
|
+
currentStep = "registry fetch";
|
|
482
|
+
spinner.text = "Connecting to Zuro Registry...";
|
|
447
483
|
const registryContext = await fetchRegistry();
|
|
448
484
|
const coreModule = registryContext.manifest.modules.core;
|
|
449
485
|
if (!coreModule) {
|
|
450
486
|
spinner.fail("Core module not found in registry.");
|
|
451
487
|
return;
|
|
452
488
|
}
|
|
489
|
+
currentStep = "project initialization";
|
|
453
490
|
spinner.text = "Initializing project...";
|
|
454
491
|
const hasPackageJson = await fs4.pathExists(path4.join(targetDir, "package.json"));
|
|
455
492
|
if (!hasPackageJson) {
|
|
456
|
-
await initPackageJson(targetDir, true);
|
|
493
|
+
await initPackageJson(targetDir, true, projectName, srcDir);
|
|
457
494
|
}
|
|
495
|
+
currentStep = "dependency installation";
|
|
458
496
|
spinner.text = `Installing dependencies using ${pm}...`;
|
|
459
497
|
let runtimeDeps = [];
|
|
460
498
|
let devDeps = [];
|
|
@@ -469,6 +507,7 @@ async function init() {
|
|
|
469
507
|
}
|
|
470
508
|
await installDependencies(pm, runtimeDeps, targetDir);
|
|
471
509
|
await installDependencies(pm, devDeps, targetDir, { dev: true });
|
|
510
|
+
currentStep = "module file generation";
|
|
472
511
|
spinner.text = "Fetching core module files...";
|
|
473
512
|
for (const file of coreModule.files) {
|
|
474
513
|
const { relativeTargetPath, targetPath } = resolveSafeTargetPath(targetDir, srcDir, file);
|
|
@@ -491,7 +530,10 @@ async function init() {
|
|
|
491
530
|
await fs4.ensureDir(path4.dirname(targetPath));
|
|
492
531
|
await fs4.writeFile(targetPath, content);
|
|
493
532
|
}
|
|
533
|
+
currentStep = "environment file setup";
|
|
494
534
|
await createInitialEnv(targetDir);
|
|
535
|
+
currentStep = "config write";
|
|
536
|
+
await writeZuroConfig(targetDir, zuroConfig);
|
|
495
537
|
spinner.succeed(chalk2.green("Project initialized successfully!"));
|
|
496
538
|
console.log(`
|
|
497
539
|
${chalk2.bold("Next steps:")}`);
|
|
@@ -502,8 +544,15 @@ ${chalk2.bold("Next steps:")}`);
|
|
|
502
544
|
console.log(`
|
|
503
545
|
${chalk2.dim("Add modules: zuro-cli add database, zuro-cli add auth")}`);
|
|
504
546
|
} catch (error) {
|
|
505
|
-
spinner.fail(chalk2.red(
|
|
506
|
-
|
|
547
|
+
spinner.fail(chalk2.red(`Failed during ${currentStep}.`));
|
|
548
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
549
|
+
console.error(chalk2.red(errorMessage));
|
|
550
|
+
console.log(`
|
|
551
|
+
${chalk2.bold("Retry:")}`);
|
|
552
|
+
if (targetDir !== cwd) {
|
|
553
|
+
console.log(chalk2.cyan(` cd ${projectName}`));
|
|
554
|
+
}
|
|
555
|
+
console.log(chalk2.cyan(" npx zuro-cli init"));
|
|
507
556
|
}
|
|
508
557
|
}
|
|
509
558
|
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/registry.ts","../src/utils/pm.ts","../src/utils/env-manager.ts","../src/utils/config.ts","../src/utils/project-guard.ts","../src/commands/add.ts","../src/utils/dependency.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init\";\nimport { add } from \"./commands/add\";\n\nconst program = new Command();\n\nprogram\n .name(\"zuro-cli\")\n .description(\"Zuro CLI tool\")\n .version(\"0.0.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new Zuro project\")\n .action(init);\n\nprogram\n .command(\"add <module>\")\n .description(\"Add a module to your project\")\n .action(add);\n\nprogram.parse(process.argv);\n","import ora from \"ora\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport prompts from \"prompts\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { initPackageJson, installDependencies } from \"../utils/pm\";\nimport { createInitialEnv } from \"../utils/env-manager\";\nimport { readZuroConfig, writeZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\nimport type { ZuroConfig } from \"../utils/config\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const relativeTargetPath = path.join(srcDir, file.target);\n const targetPath = path.resolve(projectRoot, relativeTargetPath);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return {\n relativeTargetPath,\n targetPath,\n };\n}\n\nexport async function init() {\n const cwd = process.cwd();\n const isExistingProject = await fs.pathExists(path.join(cwd, \"package.json\"));\n const existingZuroConfig = await readZuroConfig(cwd);\n\n if (isExistingProject && !existingZuroConfig) {\n showNonZuroProjectMessage();\n return;\n }\n\n let targetDir = cwd;\n let pm = \"npm\";\n let srcDir = \"src\";\n let projectName = path.basename(cwd);\n\n if (isExistingProject) {\n console.log(chalk.blue(\"ℹ Existing project detected.\"));\n\n projectName = path.basename(cwd);\n\n if (await fs.pathExists(path.join(cwd, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (await fs.pathExists(path.join(cwd, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (await fs.pathExists(path.join(cwd, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n const response = await prompts({\n type: \"text\",\n name: \"srcDir\",\n message: \"Where is your source code located?\",\n initial: \"src\",\n });\n\n srcDir = response.srcDir || \"src\";\n } else {\n console.log(chalk.dim(` Tip: Leave blank to use current folder (${path.basename(cwd)})\\n`));\n\n const response = await prompts([\n {\n type: \"text\",\n name: \"path\",\n message: \"Project name (blank for current folder)\",\n initial: \"\",\n },\n {\n type: \"select\",\n name: \"pm\",\n message: \"Package Manager?\",\n choices: [\n { title: \"npm\", value: \"npm\" },\n { title: \"pnpm\", value: \"pnpm\" },\n { title: \"bun\", value: \"bun\" },\n ],\n initial: 0,\n },\n ]);\n\n if (response.pm === undefined) {\n console.log(chalk.red(\"Operation cancelled.\"));\n return;\n }\n\n pm = response.pm;\n srcDir = \"src\";\n\n if (!response.path || response.path.trim() === \"\") {\n projectName = path.basename(cwd);\n targetDir = cwd;\n console.log(chalk.blue(`ℹ Using current folder: ${projectName}`));\n } else {\n projectName = response.path.trim();\n targetDir = path.resolve(cwd, projectName);\n await fs.ensureDir(targetDir);\n }\n }\n\n const existingConfig = targetDir === cwd ? existingZuroConfig : await readZuroConfig(targetDir);\n\n const zuroConfig: ZuroConfig = {\n name: projectName,\n pm,\n srcDir: srcDir || existingConfig?.srcDir || \"src\",\n };\n\n await writeZuroConfig(targetDir, zuroConfig);\n\n const spinner = ora(\"Connecting to Zuro Registry...\").start();\n\n try {\n const registryContext = await fetchRegistry();\n\n const coreModule = registryContext.manifest.modules.core;\n\n if (!coreModule) {\n spinner.fail(\"Core module not found in registry.\");\n return;\n }\n\n spinner.text = \"Initializing project...\";\n\n const hasPackageJson = await fs.pathExists(path.join(targetDir, \"package.json\"));\n if (!hasPackageJson) {\n await initPackageJson(targetDir, true);\n }\n\n spinner.text = `Installing dependencies using ${pm}...`;\n\n let runtimeDeps: string[] = [];\n let devDeps: string[] = [];\n\n if (isExistingProject) {\n const safeDeps = [\"zod\", \"dotenv\"];\n const coreDeps = coreModule.dependencies || [];\n runtimeDeps = coreDeps.filter((dependency) => safeDeps.includes(dependency));\n devDeps = coreModule.devDependencies || [];\n } else {\n runtimeDeps = coreModule.dependencies || [];\n devDeps = coreModule.devDependencies || [];\n }\n\n await installDependencies(pm, runtimeDeps, targetDir);\n await installDependencies(pm, devDeps, targetDir, { dev: true });\n\n spinner.text = \"Fetching core module files...\";\n\n for (const file of coreModule.files) {\n const { relativeTargetPath, targetPath } = resolveSafeTargetPath(targetDir, srcDir, file);\n const fileName = path.basename(targetPath);\n\n if (isExistingProject) {\n if (fileName === \"app.ts\" || fileName === \"server.ts\") {\n continue;\n }\n\n const relativeParts = relativeTargetPath.split(path.sep);\n const isSafe = fileName === \"env.ts\" || relativeParts.includes(\"lib\");\n if (!isSafe) {\n continue;\n }\n }\n\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n await createInitialEnv(targetDir);\n\n spinner.succeed(chalk.green(\"Project initialized successfully!\"));\n\n console.log(`\\n${chalk.bold(\"Next steps:\")}`);\n if (targetDir !== cwd) {\n console.log(chalk.cyan(` cd ${projectName}`));\n }\n console.log(chalk.cyan(` ${pm} run dev`));\n console.log(`\\n${chalk.dim(\"Add modules: zuro-cli add database, zuro-cli add auth\")}`);\n } catch (error) {\n spinner.fail(chalk.red(\"Failed to initialize project.\"));\n console.error(error);\n }\n}\n","import { createHash } from \"node:crypto\";\n\nconst DEFAULT_REGISTRY_BASE_URL = \"https://zuro-cli.devbybriyan.com/registry\";\nconst DEFAULT_REGISTRY_ENTRY_URL = `${DEFAULT_REGISTRY_BASE_URL}/channels/stable.json`;\nconst REGISTRY_ENV_VAR = \"ZURO_REGISTRY_URL\";\nconst REQUEST_TIMEOUT_MS = 8000;\nconst MAX_RETRIES = 2;\n\nexport interface RegistryFile {\n path: string;\n target: string;\n type: string;\n sha256?: string;\n size?: number;\n}\n\nexport interface RegistryModule {\n type: string;\n files: RegistryFile[];\n moduleDependencies?: string[];\n dependencies?: string[];\n devDependencies?: string[];\n}\n\nexport interface RegistryManifest {\n schemaVersion?: number;\n status?: string;\n templateVersion?: string;\n generatedAt?: string;\n modules: Record<string, RegistryModule>;\n}\n\ninterface RegistryChannelPointer {\n schemaVersion?: number;\n channel?: string;\n templateVersion?: string;\n generatedAt?: string;\n indexPath?: string;\n indexUrl?: string;\n}\n\nexport interface RegistryContext {\n manifest: RegistryManifest;\n manifestUrl: string;\n fileBaseUrl: string;\n}\n\ninterface FetchFileOptions {\n baseUrl: string;\n expectedSha256?: string;\n expectedSize?: number;\n}\n\nexport function getRegistryUrl() {\n return resolveRegistryEntryUrl();\n}\n\nfunction withTrailingSlash(url: string) {\n return url.endsWith(\"/\") ? url : `${url}/`;\n}\n\nfunction resolveRegistryEntryUrl() {\n const override = process.env[REGISTRY_ENV_VAR]?.trim();\n\n if (!override) {\n return DEFAULT_REGISTRY_ENTRY_URL;\n }\n\n let parsed: URL;\n\n try {\n parsed = new URL(override);\n } catch {\n throw new Error(\n `Invalid ${REGISTRY_ENV_VAR} value '${override}'. Expected a valid http(s) URL.`\n );\n }\n\n if (parsed.pathname.endsWith(\".json\")) {\n return parsed.toString();\n }\n\n return new URL(\"channels/stable.json\", withTrailingSlash(parsed.toString())).toString();\n}\n\nfunction isRegistryManifest(data: unknown): data is RegistryManifest {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryManifest>;\n return !!candidate.modules && typeof candidate.modules === \"object\";\n}\n\nfunction isChannelPointer(data: unknown): data is RegistryChannelPointer {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryChannelPointer>;\n return typeof candidate.indexPath === \"string\" || typeof candidate.indexUrl === \"string\";\n}\n\nfunction delay(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function fetchWithRetry(url: string): Promise<Response> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n headers: { Accept: \"application/json, text/plain, */*\" },\n signal: controller.signal,\n });\n\n if (response.ok) {\n return response;\n }\n\n const shouldRetry = response.status >= 500 && attempt < MAX_RETRIES;\n if (shouldRetry) {\n await delay(250 * (attempt + 1));\n continue;\n }\n\n throw new Error(`Request failed (${response.status} ${response.statusText}) for ${url}`);\n } catch (error) {\n lastError = error;\n\n if (attempt === MAX_RETRIES) {\n break;\n }\n\n await delay(250 * (attempt + 1));\n } finally {\n clearTimeout(timeout);\n }\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n\n throw new Error(`Failed to fetch ${url}`);\n}\n\nasync function fetchJson<T>(url: string): Promise<{ data: T; resolvedUrl: string }> {\n const response = await fetchWithRetry(url);\n const data = (await response.json()) as T;\n\n return {\n data,\n resolvedUrl: response.url || url,\n };\n}\n\nfunction resolveManifestUrl(pointer: RegistryChannelPointer, pointerUrl: string): string {\n const explicit = pointer.indexUrl || pointer.indexPath;\n\n if (!explicit) {\n throw new Error(\"Registry channel pointer is missing indexUrl/indexPath\");\n }\n\n return new URL(explicit, pointerUrl).toString();\n}\n\nexport async function fetchRegistry(): Promise<RegistryContext> {\n const registryEntryUrl = resolveRegistryEntryUrl();\n let entry: { data: unknown; resolvedUrl: string };\n\n try {\n entry = await fetchJson<unknown>(registryEntryUrl);\n } catch (error) {\n throw new Error(\n `Unable to fetch registry from ${registryEntryUrl}. For local testing set ${REGISTRY_ENV_VAR}=http://127.0.0.1:8787.`,\n { cause: error as Error }\n );\n }\n\n if (isRegistryManifest(entry.data)) {\n return {\n manifest: entry.data,\n manifestUrl: entry.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", entry.resolvedUrl).toString()),\n };\n }\n\n if (!isChannelPointer(entry.data)) {\n throw new Error(\n `Invalid registry payload at ${registryEntryUrl}. Expected manifest or channel pointer.`\n );\n }\n\n const manifestUrl = resolveManifestUrl(entry.data, entry.resolvedUrl);\n const manifestResult = await fetchJson<unknown>(manifestUrl);\n\n if (!isRegistryManifest(manifestResult.data)) {\n throw new Error(`Invalid manifest payload at ${manifestUrl}.`);\n }\n\n return {\n manifest: manifestResult.data,\n manifestUrl: manifestResult.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", manifestResult.resolvedUrl).toString()),\n };\n}\n\nexport async function fetchFile(filePath: string, options: FetchFileOptions) {\n const normalizedPath = filePath.replace(/^\\//, \"\");\n const fileUrl = new URL(normalizedPath, withTrailingSlash(options.baseUrl)).toString();\n const response = await fetchWithRetry(fileUrl);\n const content = await response.text();\n\n if (typeof options.expectedSize === \"number\") {\n const actualSize = Buffer.byteLength(content, \"utf8\");\n if (actualSize !== options.expectedSize) {\n throw new Error(\n `Size mismatch for ${filePath}. Expected ${options.expectedSize}, got ${actualSize}.`\n );\n }\n }\n\n if (options.expectedSha256) {\n const actualSha256 = createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n if (actualSha256 !== options.expectedSha256) {\n throw new Error(\n `Checksum mismatch for ${filePath}. Expected ${options.expectedSha256}, got ${actualSha256}.`\n );\n }\n }\n\n return content;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { execa } from \"execa\";\n\nexport async function initPackageJson(cwd: string, force: boolean = false) {\n const pkgPath = path.join(cwd, \"package.json\");\n if (force || !await fs.pathExists(pkgPath)) {\n await fs.writeJson(pkgPath, {\n name: \"zuro-app\",\n version: \"0.0.1\",\n private: true,\n scripts: {\n \"dev\": \"tsx watch src/server.ts\",\n \"build\": \"tsc\",\n \"start\": \"node dist/server.js\"\n }\n }, { spaces: 2 });\n }\n}\n\ninterface InstallOptions {\n dev?: boolean;\n}\n\nexport async function installDependencies(\n pm: string,\n deps: string[],\n cwd: string,\n options: InstallOptions = {}\n) {\n const uniqueDeps = [...new Set(deps)].filter(Boolean);\n\n if (uniqueDeps.length === 0) {\n return;\n }\n\n const isDev = options.dev ?? false;\n\n if (pm === \"npm\") {\n const args = [\"install\", ...(isDev ? [\"--save-dev\"] : []), ...uniqueDeps];\n await execa(\"npm\", args, { cwd });\n return;\n }\n\n if (pm === \"pnpm\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"pnpm\", args, { cwd });\n return;\n }\n\n if (pm === \"yarn\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"yarn\", args, { cwd });\n return;\n }\n\n if (pm === \"bun\") {\n const args = [\"add\", ...(isDev ? [\"-d\"] : []), ...uniqueDeps];\n await execa(\"bun\", args, { cwd });\n return;\n }\n\n throw new Error(`Unsupported package manager: ${pm}`);\n}\n","import fs from \"fs-extra\";\r\nimport path from \"path\";\r\nimport os from \"os\";\r\n\r\n/**\r\n * Creates or updates .env file with new variables\r\n */\r\nexport const updateEnvFile = async (\r\n cwd: string,\r\n variables: Record<string, string>,\r\n createIfMissing = true\r\n) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n let content = \"\";\r\n if (fs.existsSync(envPath)) {\r\n content = await fs.readFile(envPath, \"utf-8\");\r\n } else if (!createIfMissing) {\r\n return;\r\n }\r\n\r\n let modified = false;\r\n\r\n for (const [key, value] of Object.entries(variables)) {\r\n // Check if key already exists\r\n const regex = new RegExp(`^${key}=`, \"m\");\r\n if (!regex.test(content)) {\r\n // Add newline if content doesn't end with one\r\n if (content && !content.endsWith(\"\\n\")) {\r\n content += os.EOL;\r\n }\r\n content += `${key}=${value}${os.EOL}`;\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified || !fs.existsSync(envPath)) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n};\r\n\r\n/**\r\n * Updates env.ts to add new schema fields\r\n */\r\nexport const updateEnvSchema = async (\r\n cwd: string,\r\n srcDir: string,\r\n fields: Array<{ name: string; schema: string }>\r\n) => {\r\n const envPath = path.join(cwd, srcDir, \"env.ts\");\r\n\r\n if (!fs.existsSync(envPath)) {\r\n return false;\r\n }\r\n\r\n let content = await fs.readFile(envPath, \"utf-8\");\r\n let modified = false;\r\n\r\n for (const field of fields) {\r\n // Check if field already exists in schema\r\n if (content.includes(`${field.name}:`)) {\r\n continue;\r\n }\r\n\r\n // Find the closing of envSchema z.object({ ... })\r\n // Insert before the closing });\r\n const schemaEndRegex = /(\\n\\s*)(}\\);?\\s*\\n\\s*export const env)/;\r\n const match = content.match(schemaEndRegex);\r\n\r\n if (match) {\r\n const indent = \" \"; // 4 spaces\r\n const newField = `${indent}${field.name}: ${field.schema},\\n`;\r\n content = content.replace(\r\n schemaEndRegex,\r\n `\\n${newField}$1$2`\r\n );\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n\r\n return modified;\r\n};\r\n\r\n/**\r\n * Creates initial .env file for new projects\r\n */\r\nexport const createInitialEnv = async (cwd: string) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n if (fs.existsSync(envPath)) {\r\n return; // Don't overwrite existing\r\n }\r\n\r\n const content = `# Environment Variables\r\nPORT=3000\r\nNODE_ENV=development\r\n`;\r\n\r\n await fs.writeFile(envPath, content);\r\n};\r\n\r\n/**\r\n * Module-specific env configurations\r\n */\r\nexport const ENV_CONFIGS = {\r\n \"database-pg\": {\r\n envVars: {\r\n DATABASE_URL: \"postgresql://postgres@localhost:5432/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n \"database-mysql\": {\r\n envVars: {\r\n DATABASE_URL: \"mysql://root@localhost:3306/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n auth: {\r\n envVars: {\r\n BETTER_AUTH_SECRET: \"your-secret-key-at-least-32-characters-long\",\r\n BETTER_AUTH_URL: \"http://localhost:3000\",\r\n },\r\n schemaFields: [\r\n { name: \"BETTER_AUTH_SECRET\", schema: \"z.string().min(32)\" },\r\n { name: \"BETTER_AUTH_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n};\r\n","import fs from \"fs-extra\";\nimport path from \"path\";\n\nexport interface ZuroConfig {\n name?: string;\n pm?: string;\n srcDir?: string;\n}\n\nfunction sanitizeConfig(input: unknown): ZuroConfig {\n if (!input || typeof input !== \"object\") {\n return {};\n }\n\n const raw = input as Record<string, unknown>;\n const config: ZuroConfig = {};\n\n if (typeof raw.name === \"string\") {\n config.name = raw.name;\n }\n\n if (typeof raw.pm === \"string\") {\n config.pm = raw.pm;\n }\n\n if (typeof raw.srcDir === \"string\") {\n config.srcDir = raw.srcDir;\n }\n\n return config;\n}\n\nexport function getConfigPath(cwd: string) {\n return path.join(cwd, \"zuro.json\");\n}\n\nexport async function readZuroConfig(cwd: string): Promise<ZuroConfig | null> {\n const configPath = getConfigPath(cwd);\n\n if (!(await fs.pathExists(configPath))) {\n return null;\n }\n\n const raw = await fs.readJson(configPath);\n return sanitizeConfig(raw);\n}\n\nexport async function writeZuroConfig(cwd: string, config: ZuroConfig) {\n const configPath = getConfigPath(cwd);\n await fs.writeJson(configPath, sanitizeConfig(config), { spaces: 2 });\n}\n","import chalk from \"chalk\";\n\nexport function showNonZuroProjectMessage() {\n console.log(chalk.yellow(\"This directory looks like an existing project that wasn't created with Zuro CLI.\"));\n console.log(\"\");\n console.log(chalk.yellow(\"We stopped here because we don't want to make unnecessary changes to your project.\"));\n console.log(\"\");\n console.log(\"Zuro CLI works in:\");\n console.log(\"- a fresh/empty directory, or\");\n console.log(\"- an existing project already managed by Zuro CLI.\");\n}\n","import prompts from \"prompts\";\nimport ora from \"ora\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { installDependencies } from \"../utils/pm\";\nimport { resolveDependencies } from \"../utils/dependency\";\nimport { updateEnvFile, updateEnvSchema, ENV_CONFIGS } from \"../utils/env-manager\";\nimport chalk from \"chalk\";\nimport { readZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const targetPath = path.resolve(projectRoot, srcDir, file.target);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return targetPath;\n}\n\n/**\n * Modifies app.ts to include error handler middleware\n */\nasync function injectErrorHandler(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"errorHandler\")) {\n return true;\n }\n\n const errorImport = `import { errorHandler, notFoundHandler } from \"./middleware/error-handler\";`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${errorImport}` + content.slice(lastImportIndex);\n }\n\n const errorSetup = `\\n// Error handling (must be last)\\napp.use(notFoundHandler);\\napp.use(errorHandler);\\n`;\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + errorSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\n/**\n * Modifies app.ts to include auth routes\n */\nasync function injectAuthRoutes(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"routes/auth.routes\")) {\n return true;\n }\n\n const authImport = `import authRoutes from \"./routes/auth.routes\";`;\n const userImport = `import userRoutes from \"./routes/user.routes\";`;\n const routeSetup = `\\n// Auth routes\\napp.use(authRoutes);\\napp.use(\"/api/users\", userRoutes);\\n`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${authImport}\\n${userImport}` + content.slice(lastImportIndex);\n }\n\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + routeSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\nexport const add = async (moduleName: string) => {\n const projectRoot = process.cwd();\n const projectConfig = await readZuroConfig(projectRoot);\n if (!projectConfig) {\n showNonZuroProjectMessage();\n return;\n }\n let srcDir = projectConfig.srcDir || \"src\";\n\n let customDbUrl: string | undefined;\n\n const DEFAULT_URLS = {\n \"database-pg\": \"postgresql://root@localhost:5432/mydb\",\n \"database-mysql\": \"mysql://root@localhost:3306/mydb\",\n };\n\n if (moduleName === \"database\") {\n const variantResponse = await prompts({\n type: \"select\",\n name: \"variant\",\n message: \"Which database dialect?\",\n choices: [\n { title: \"PostgreSQL\", value: \"database-pg\" },\n { title: \"MySQL\", value: \"database-mysql\" },\n ],\n });\n\n if (!variantResponse.variant) {\n process.exit(0);\n }\n\n moduleName = variantResponse.variant;\n\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const urlResponse = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = urlResponse.dbUrl?.trim() || defaultUrl;\n }\n\n if ((moduleName === \"database-pg\" || moduleName === \"database-mysql\") && customDbUrl === undefined) {\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const response = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = response.dbUrl?.trim() || defaultUrl;\n }\n\n const spinner = ora(`Checking registry for ${moduleName}...`).start();\n\n try {\n const registryContext = await fetchRegistry();\n const module = registryContext.manifest.modules[moduleName];\n\n if (!module) {\n spinner.fail(`Module '${moduleName}' not found.`);\n return;\n }\n\n spinner.succeed(`Found module: ${chalk.cyan(moduleName)}`);\n\n const moduleDeps = module.moduleDependencies || [];\n await resolveDependencies(moduleDeps, projectRoot);\n\n spinner.start(\"Installing dependencies...\");\n\n let pm = \"npm\";\n if (fs.existsSync(path.join(projectRoot, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (fs.existsSync(path.join(projectRoot, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (fs.existsSync(path.join(projectRoot, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n await installDependencies(pm, module.dependencies || [], projectRoot);\n await installDependencies(pm, module.devDependencies || [], projectRoot, { dev: true });\n\n spinner.succeed(\"Dependencies installed\");\n\n spinner.start(\"Scaffolding files...\");\n\n for (const file of module.files) {\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n const targetPath = resolveSafeTargetPath(projectRoot, srcDir, file);\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n spinner.succeed(\"Files generated\");\n\n if (moduleName === \"auth\") {\n spinner.start(\"Configuring routes in app.ts...\");\n const injected = await injectAuthRoutes(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Routes configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - routes need manual setup\");\n }\n }\n\n if (moduleName === \"error-handler\") {\n spinner.start(\"Configuring error handler in app.ts...\");\n const injected = await injectErrorHandler(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Error handler configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - error handler needs manual setup\");\n }\n }\n\n const envConfig = ENV_CONFIGS[moduleName as keyof typeof ENV_CONFIGS];\n if (envConfig) {\n spinner.start(\"Updating environment configuration...\");\n\n const envVars: Record<string, string> = { ...envConfig.envVars };\n if (customDbUrl && (moduleName === \"database-pg\" || moduleName === \"database-mysql\")) {\n envVars.DATABASE_URL = customDbUrl;\n }\n\n await updateEnvFile(projectRoot, envVars);\n await updateEnvSchema(projectRoot, srcDir, envConfig.schemaFields);\n\n spinner.succeed(\"Environment configured\");\n }\n\n console.log(chalk.green(`\\n✔ ${moduleName} added successfully!\\n`));\n\n if (moduleName === \"auth\") {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n console.log(chalk.yellow(\"1. Update your .env file:\"));\n console.log(\n chalk.dim(\" We added placeholder values. Update BETTER_AUTH_SECRET with a secure key.\\n\")\n );\n console.log(chalk.yellow(\"2. Run database migrations:\"));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n console.log(chalk.yellow(\"3. Available endpoints:\"));\n console.log(chalk.dim(\" POST /auth/sign-up/email - Register\"));\n console.log(chalk.dim(\" POST /auth/sign-in/email - Login\"));\n console.log(chalk.dim(\" POST /auth/sign-out - Logout\"));\n console.log(chalk.dim(\" GET /api/users/me - Current user\\n\"));\n } else if (moduleName === \"error-handler\") {\n console.log(chalk.bold(\"📋 Usage:\\n\"));\n console.log(chalk.yellow(\"Throw errors in your controllers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { UnauthorizedError, NotFoundError } from \"./lib/errors\";`));\n console.log(\"\");\n console.log(chalk.white(` throw new UnauthorizedError(\"Invalid credentials\");`));\n console.log(chalk.white(` throw new NotFoundError(\"User not found\");`));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n console.log(chalk.yellow(\"Available error classes:\"));\n console.log(chalk.dim(\" BadRequestError (400)\"));\n console.log(chalk.dim(\" UnauthorizedError (401)\"));\n console.log(chalk.dim(\" ForbiddenError (403)\"));\n console.log(chalk.dim(\" NotFoundError (404)\"));\n console.log(chalk.dim(\" ConflictError (409)\"));\n console.log(chalk.dim(\" ValidationError (422)\"));\n console.log(chalk.dim(\" InternalServerError (500)\\n\"));\n console.log(chalk.yellow(\"Wrap async handlers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { asyncHandler } from \"./middleware/error-handler\";`));\n console.log(\"\");\n console.log(chalk.white(` router.get(\"/users\", asyncHandler(async (req, res) => {`));\n console.log(chalk.white(\" // errors auto-caught\"));\n console.log(chalk.white(\" }));\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n } else if (moduleName.includes(\"database\")) {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n let stepNum = 1;\n\n if (!customDbUrl) {\n console.log(chalk.yellow(`${stepNum}. Update DATABASE_URL in .env:`));\n console.log(\n chalk.dim(\" We added a placeholder. Update with your actual database credentials.\\n\")\n );\n stepNum++;\n }\n\n console.log(chalk.yellow(`${stepNum}. Create schemas in src/db/schema/:`));\n console.log(chalk.dim(\" Add table files and export from index.ts\\n\"));\n stepNum++;\n\n console.log(chalk.yellow(`${stepNum}. Run migrations:`));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n }\n } catch (error) {\n spinner.fail(`Failed to add module: ${(error as Error).message}`);\n }\n};\n","import { add } from \"../commands/add\";\nimport { readZuroConfig } from \"./config\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport chalk from \"chalk\";\n\n// Signature files to check if a Zuro module is installed\nconst BLOCK_SIGNATURES: Record<string, string> = {\n core: \"env.ts\",\n \"database-pg\": \"db/index.ts\",\n \"database-mysql\": \"db/index.ts\",\n validator: \"middleware/validate.ts\",\n \"error-handler\": \"lib/errors.ts\",\n logger: \"lib/logger.ts\",\n auth: \"lib/auth.ts\",\n};\n\n/**\n * Resolves Zuro module dependencies (NOT npm packages).\n * Only handles module dependencies like \"core\", \"database\", \"validator\", \"auth\".\n */\nexport const resolveDependencies = async (\n moduleDependencies: string[] | undefined,\n cwd: string\n) => {\n if (!moduleDependencies || moduleDependencies.length === 0) {\n return;\n }\n\n const config = await readZuroConfig(cwd);\n const srcDir = config?.srcDir || \"src\";\n\n for (const dep of moduleDependencies) {\n if (dep === \"database\") {\n const pgExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-pg\"]));\n const mysqlExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-mysql\"]));\n\n if (pgExists || mysqlExists) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Dependency '${dep}' is missing. Triggering install...`));\n await add(\"database\");\n continue;\n }\n\n const signature = BLOCK_SIGNATURES[dep];\n if (!signature) {\n continue;\n }\n\n if (fs.existsSync(path.join(cwd, srcDir, signature))) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Installing missing dependency: ${dep}...`));\n await add(dep);\n }\n};\n"],"mappings":"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","names":["chalk","fs","path","fs","path","fs","path","path","fs","chalk","prompts","ora","path","fs","fs","path","chalk","chalk","resolveSafeTargetPath","path","fs","prompts","chalk","ora"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/registry.ts","../src/utils/pm.ts","../src/utils/env-manager.ts","../src/utils/config.ts","../src/utils/project-guard.ts","../src/commands/add.ts","../src/utils/dependency.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init\";\nimport { add } from \"./commands/add\";\n\nconst program = new Command();\n\nprogram\n .name(\"zuro-cli\")\n .description(\"Zuro CLI tool\")\n .version(\"0.0.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new Zuro project\")\n .action(init);\n\nprogram\n .command(\"add <module>\")\n .description(\"Add a module to your project\")\n .action(add);\n\nprogram.parse(process.argv);\n","import ora from \"ora\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport prompts from \"prompts\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { initPackageJson, installDependencies, ensurePackageManagerAvailable } from \"../utils/pm\";\nimport { createInitialEnv } from \"../utils/env-manager\";\nimport { readZuroConfig, writeZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\nimport type { ZuroConfig } from \"../utils/config\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const relativeTargetPath = path.join(srcDir, file.target);\n const targetPath = path.resolve(projectRoot, relativeTargetPath);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return {\n relativeTargetPath,\n targetPath,\n };\n}\n\nasync function ensureSafeTargetDirectory(targetDir: string, cwd: string, projectName: string) {\n await fs.ensureDir(targetDir);\n const entries = await fs.readdir(targetDir);\n\n if (entries.length === 0) {\n return true;\n }\n\n const isCurrentFolder = targetDir === cwd;\n const response = await prompts({\n type: \"confirm\",\n name: \"proceed\",\n message: isCurrentFolder\n ? `Current folder '${projectName}' is not empty. Continue anyway?`\n : `Target folder '${projectName}' already exists and is not empty. Continue anyway?`,\n initial: false,\n });\n\n return response.proceed === true;\n}\n\nexport async function init() {\n const cwd = process.cwd();\n const isExistingProject = await fs.pathExists(path.join(cwd, \"package.json\"));\n const existingZuroConfig = await readZuroConfig(cwd);\n\n if (isExistingProject && !existingZuroConfig) {\n showNonZuroProjectMessage();\n return;\n }\n\n let targetDir = cwd;\n let pm = \"npm\";\n let srcDir = \"src\";\n let projectName = path.basename(cwd);\n\n if (isExistingProject) {\n console.log(chalk.blue(\"ℹ Existing project detected.\"));\n\n projectName = path.basename(cwd);\n\n if (await fs.pathExists(path.join(cwd, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (await fs.pathExists(path.join(cwd, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (await fs.pathExists(path.join(cwd, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n const response = await prompts({\n type: \"text\",\n name: \"srcDir\",\n message: \"Where is your source code located?\",\n initial: \"src\",\n });\n\n srcDir = response.srcDir || \"src\";\n } else {\n console.log(chalk.dim(` Tip: Leave blank to use current folder (${path.basename(cwd)})\\n`));\n\n const response = await prompts([\n {\n type: \"text\",\n name: \"path\",\n message: \"Project name (blank for current folder)\",\n initial: \"\",\n },\n {\n type: \"select\",\n name: \"pm\",\n message: \"Package Manager?\",\n choices: [\n { title: \"npm\", value: \"npm\" },\n { title: \"pnpm\", value: \"pnpm\" },\n { title: \"bun\", value: \"bun\" },\n ],\n initial: 0,\n },\n ]);\n\n if (response.pm === undefined) {\n console.log(chalk.red(\"Operation cancelled.\"));\n return;\n }\n\n pm = response.pm;\n srcDir = \"src\";\n\n if (!response.path || response.path.trim() === \"\") {\n projectName = path.basename(cwd);\n targetDir = cwd;\n console.log(chalk.blue(`ℹ Using current folder: ${projectName}`));\n } else {\n projectName = response.path.trim();\n targetDir = path.resolve(cwd, projectName);\n }\n\n const isSafeTarget = await ensureSafeTargetDirectory(targetDir, cwd, projectName);\n if (!isSafeTarget) {\n console.log(chalk.red(\"Operation cancelled.\"));\n return;\n }\n }\n\n const existingConfig = targetDir === cwd ? existingZuroConfig : await readZuroConfig(targetDir);\n\n const zuroConfig: ZuroConfig = {\n name: projectName,\n pm,\n srcDir: srcDir || existingConfig?.srcDir || \"src\",\n };\n\n const spinner = ora(\"Connecting to Zuro Registry...\").start();\n let currentStep = \"package manager preflight\";\n\n try {\n spinner.text = `Checking ${pm} availability...`;\n await ensurePackageManagerAvailable(pm);\n\n currentStep = \"registry fetch\";\n spinner.text = \"Connecting to Zuro Registry...\";\n const registryContext = await fetchRegistry();\n\n const coreModule = registryContext.manifest.modules.core;\n\n if (!coreModule) {\n spinner.fail(\"Core module not found in registry.\");\n return;\n }\n\n currentStep = \"project initialization\";\n spinner.text = \"Initializing project...\";\n\n const hasPackageJson = await fs.pathExists(path.join(targetDir, \"package.json\"));\n if (!hasPackageJson) {\n await initPackageJson(targetDir, true, projectName, srcDir);\n }\n\n currentStep = \"dependency installation\";\n spinner.text = `Installing dependencies using ${pm}...`;\n\n let runtimeDeps: string[] = [];\n let devDeps: string[] = [];\n\n if (isExistingProject) {\n const safeDeps = [\"zod\", \"dotenv\"];\n const coreDeps = coreModule.dependencies || [];\n runtimeDeps = coreDeps.filter((dependency) => safeDeps.includes(dependency));\n devDeps = coreModule.devDependencies || [];\n } else {\n runtimeDeps = coreModule.dependencies || [];\n devDeps = coreModule.devDependencies || [];\n }\n\n await installDependencies(pm, runtimeDeps, targetDir);\n await installDependencies(pm, devDeps, targetDir, { dev: true });\n\n currentStep = \"module file generation\";\n spinner.text = \"Fetching core module files...\";\n\n for (const file of coreModule.files) {\n const { relativeTargetPath, targetPath } = resolveSafeTargetPath(targetDir, srcDir, file);\n const fileName = path.basename(targetPath);\n\n if (isExistingProject) {\n if (fileName === \"app.ts\" || fileName === \"server.ts\") {\n continue;\n }\n\n const relativeParts = relativeTargetPath.split(path.sep);\n const isSafe = fileName === \"env.ts\" || relativeParts.includes(\"lib\");\n if (!isSafe) {\n continue;\n }\n }\n\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n currentStep = \"environment file setup\";\n await createInitialEnv(targetDir);\n\n currentStep = \"config write\";\n await writeZuroConfig(targetDir, zuroConfig);\n\n spinner.succeed(chalk.green(\"Project initialized successfully!\"));\n\n console.log(`\\n${chalk.bold(\"Next steps:\")}`);\n if (targetDir !== cwd) {\n console.log(chalk.cyan(` cd ${projectName}`));\n }\n console.log(chalk.cyan(` ${pm} run dev`));\n console.log(`\\n${chalk.dim(\"Add modules: zuro-cli add database, zuro-cli add auth\")}`);\n } catch (error) {\n spinner.fail(chalk.red(`Failed during ${currentStep}.`));\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(errorMessage));\n console.log(`\\n${chalk.bold(\"Retry:\")}`);\n if (targetDir !== cwd) {\n console.log(chalk.cyan(` cd ${projectName}`));\n }\n console.log(chalk.cyan(\" npx zuro-cli init\"));\n }\n}\n","import { createHash } from \"node:crypto\";\n\nconst DEFAULT_REGISTRY_BASE_URL = \"https://registry.devbybriyan.com\";\nconst DEFAULT_REGISTRY_ENTRY_URL = `${DEFAULT_REGISTRY_BASE_URL}/channels/stable.json`;\nconst REGISTRY_ENV_VAR = \"ZURO_REGISTRY_URL\";\nconst REQUEST_TIMEOUT_MS = 8000;\nconst MAX_RETRIES = 2;\n\nexport interface RegistryFile {\n path: string;\n target: string;\n type: string;\n sha256?: string;\n size?: number;\n}\n\nexport interface RegistryModule {\n type: string;\n files: RegistryFile[];\n moduleDependencies?: string[];\n dependencies?: string[];\n devDependencies?: string[];\n}\n\nexport interface RegistryManifest {\n schemaVersion?: number;\n status?: string;\n templateVersion?: string;\n generatedAt?: string;\n modules: Record<string, RegistryModule>;\n}\n\ninterface RegistryChannelPointer {\n schemaVersion?: number;\n channel?: string;\n templateVersion?: string;\n generatedAt?: string;\n indexPath?: string;\n indexUrl?: string;\n}\n\nexport interface RegistryContext {\n manifest: RegistryManifest;\n manifestUrl: string;\n fileBaseUrl: string;\n}\n\ninterface FetchFileOptions {\n baseUrl: string;\n expectedSha256?: string;\n expectedSize?: number;\n}\n\nexport function getRegistryUrl() {\n return resolveRegistryEntryUrl();\n}\n\nfunction withTrailingSlash(url: string) {\n return url.endsWith(\"/\") ? url : `${url}/`;\n}\n\nfunction resolveRegistryEntryUrl() {\n const override = process.env[REGISTRY_ENV_VAR]?.trim();\n\n if (!override) {\n return DEFAULT_REGISTRY_ENTRY_URL;\n }\n\n let parsed: URL;\n\n try {\n parsed = new URL(override);\n } catch {\n throw new Error(\n `Invalid ${REGISTRY_ENV_VAR} value '${override}'. Expected a valid http(s) URL.`\n );\n }\n\n if (parsed.pathname.endsWith(\".json\")) {\n return parsed.toString();\n }\n\n return new URL(\"channels/stable.json\", withTrailingSlash(parsed.toString())).toString();\n}\n\nfunction isRegistryManifest(data: unknown): data is RegistryManifest {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryManifest>;\n return !!candidate.modules && typeof candidate.modules === \"object\";\n}\n\nfunction isChannelPointer(data: unknown): data is RegistryChannelPointer {\n if (!data || typeof data !== \"object\") {\n return false;\n }\n\n const candidate = data as Partial<RegistryChannelPointer>;\n return typeof candidate.indexPath === \"string\" || typeof candidate.indexUrl === \"string\";\n}\n\nfunction delay(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function fetchWithRetry(url: string): Promise<Response> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n headers: { Accept: \"application/json, text/plain, */*\" },\n signal: controller.signal,\n });\n\n if (response.ok) {\n return response;\n }\n\n const shouldRetry = response.status >= 500 && attempt < MAX_RETRIES;\n if (shouldRetry) {\n await delay(250 * (attempt + 1));\n continue;\n }\n\n throw new Error(`Request failed (${response.status} ${response.statusText}) for ${url}`);\n } catch (error) {\n lastError = error;\n\n if (attempt === MAX_RETRIES) {\n break;\n }\n\n await delay(250 * (attempt + 1));\n } finally {\n clearTimeout(timeout);\n }\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n\n throw new Error(`Failed to fetch ${url}`);\n}\n\nasync function fetchJson<T>(url: string): Promise<{ data: T; resolvedUrl: string }> {\n const response = await fetchWithRetry(url);\n const data = (await response.json()) as T;\n\n return {\n data,\n resolvedUrl: response.url || url,\n };\n}\n\nfunction resolveManifestUrl(pointer: RegistryChannelPointer, pointerUrl: string): string {\n const explicit = pointer.indexUrl || pointer.indexPath;\n\n if (!explicit) {\n throw new Error(\"Registry channel pointer is missing indexUrl/indexPath\");\n }\n\n return new URL(explicit, pointerUrl).toString();\n}\n\nexport async function fetchRegistry(): Promise<RegistryContext> {\n const registryEntryUrl = resolveRegistryEntryUrl();\n let entry: { data: unknown; resolvedUrl: string };\n\n try {\n entry = await fetchJson<unknown>(registryEntryUrl);\n } catch (error) {\n throw new Error(\n `Unable to fetch registry from ${registryEntryUrl}. For local testing set ${REGISTRY_ENV_VAR}=http://127.0.0.1:8787.`,\n { cause: error as Error }\n );\n }\n\n if (isRegistryManifest(entry.data)) {\n return {\n manifest: entry.data,\n manifestUrl: entry.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", entry.resolvedUrl).toString()),\n };\n }\n\n if (!isChannelPointer(entry.data)) {\n throw new Error(\n `Invalid registry payload at ${registryEntryUrl}. Expected manifest or channel pointer.`\n );\n }\n\n const manifestUrl = resolveManifestUrl(entry.data, entry.resolvedUrl);\n const manifestResult = await fetchJson<unknown>(manifestUrl);\n\n if (!isRegistryManifest(manifestResult.data)) {\n throw new Error(`Invalid manifest payload at ${manifestUrl}.`);\n }\n\n return {\n manifest: manifestResult.data,\n manifestUrl: manifestResult.resolvedUrl,\n fileBaseUrl: withTrailingSlash(new URL(\".\", manifestResult.resolvedUrl).toString()),\n };\n}\n\nexport async function fetchFile(filePath: string, options: FetchFileOptions) {\n const normalizedPath = filePath.replace(/^\\//, \"\");\n const fileUrl = new URL(normalizedPath, withTrailingSlash(options.baseUrl)).toString();\n const response = await fetchWithRetry(fileUrl);\n const content = await response.text();\n\n if (typeof options.expectedSize === \"number\") {\n const actualSize = Buffer.byteLength(content, \"utf8\");\n if (actualSize !== options.expectedSize) {\n throw new Error(\n `Size mismatch for ${filePath}. Expected ${options.expectedSize}, got ${actualSize}.`\n );\n }\n }\n\n if (options.expectedSha256) {\n const actualSha256 = createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n if (actualSha256 !== options.expectedSha256) {\n throw new Error(\n `Checksum mismatch for ${filePath}. Expected ${options.expectedSha256}, got ${actualSha256}.`\n );\n }\n }\n\n return content;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { execa } from \"execa\";\n\nfunction normalizePackageName(name: string) {\n const normalized = name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^[._-]+|[._-]+$/g, \"\");\n\n return normalized || \"zuro-app\";\n}\n\nexport async function ensurePackageManagerAvailable(pm: string) {\n try {\n await execa(pm, [\"--version\"], { stdio: \"ignore\" });\n } catch {\n throw new Error(\n `Package manager '${pm}' is not installed or not available in PATH. Install it or choose npm.`\n );\n }\n}\n\nexport async function initPackageJson(\n cwd: string,\n force: boolean = false,\n packageName = \"zuro-app\",\n srcDir = \"src\"\n) {\n const pkgPath = path.join(cwd, \"package.json\");\n if (force || !await fs.pathExists(pkgPath)) {\n await fs.writeJson(pkgPath, {\n name: normalizePackageName(packageName),\n version: \"0.0.1\",\n private: true,\n scripts: {\n \"dev\": `tsx watch ${srcDir}/server.ts`,\n \"build\": \"tsc\",\n \"start\": \"node dist/server.js\"\n }\n }, { spaces: 2 });\n }\n}\n\ninterface InstallOptions {\n dev?: boolean;\n}\n\nexport async function installDependencies(\n pm: string,\n deps: string[],\n cwd: string,\n options: InstallOptions = {}\n) {\n const uniqueDeps = [...new Set(deps)].filter(Boolean);\n\n if (uniqueDeps.length === 0) {\n return;\n }\n\n const isDev = options.dev ?? false;\n\n if (pm === \"npm\") {\n const args = [\"install\", ...(isDev ? [\"--save-dev\"] : []), ...uniqueDeps];\n await execa(\"npm\", args, { cwd });\n return;\n }\n\n if (pm === \"pnpm\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"pnpm\", args, { cwd });\n return;\n }\n\n if (pm === \"yarn\") {\n const args = [\"add\", ...(isDev ? [\"-D\"] : []), ...uniqueDeps];\n await execa(\"yarn\", args, { cwd });\n return;\n }\n\n if (pm === \"bun\") {\n const args = [\"add\", ...(isDev ? [\"-d\"] : []), ...uniqueDeps];\n await execa(\"bun\", args, { cwd });\n return;\n }\n\n throw new Error(`Unsupported package manager: ${pm}`);\n}\n","import fs from \"fs-extra\";\r\nimport path from \"path\";\r\nimport os from \"os\";\r\n\r\n/**\r\n * Creates or updates .env file with new variables\r\n */\r\nexport const updateEnvFile = async (\r\n cwd: string,\r\n variables: Record<string, string>,\r\n createIfMissing = true\r\n) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n let content = \"\";\r\n if (fs.existsSync(envPath)) {\r\n content = await fs.readFile(envPath, \"utf-8\");\r\n } else if (!createIfMissing) {\r\n return;\r\n }\r\n\r\n let modified = false;\r\n\r\n for (const [key, value] of Object.entries(variables)) {\r\n // Check if key already exists\r\n const regex = new RegExp(`^${key}=`, \"m\");\r\n if (!regex.test(content)) {\r\n // Add newline if content doesn't end with one\r\n if (content && !content.endsWith(\"\\n\")) {\r\n content += os.EOL;\r\n }\r\n content += `${key}=${value}${os.EOL}`;\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified || !fs.existsSync(envPath)) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n};\r\n\r\n/**\r\n * Updates env.ts to add new schema fields\r\n */\r\nexport const updateEnvSchema = async (\r\n cwd: string,\r\n srcDir: string,\r\n fields: Array<{ name: string; schema: string }>\r\n) => {\r\n const envPath = path.join(cwd, srcDir, \"env.ts\");\r\n\r\n if (!fs.existsSync(envPath)) {\r\n return false;\r\n }\r\n\r\n let content = await fs.readFile(envPath, \"utf-8\");\r\n let modified = false;\r\n\r\n for (const field of fields) {\r\n // Check if field already exists in schema\r\n if (content.includes(`${field.name}:`)) {\r\n continue;\r\n }\r\n\r\n // Find the closing of envSchema z.object({ ... })\r\n // Insert before the closing });\r\n const schemaEndRegex = /(\\n\\s*)(}\\);?\\s*\\n\\s*export const env)/;\r\n const match = content.match(schemaEndRegex);\r\n\r\n if (match) {\r\n const indent = \" \"; // 4 spaces\r\n const newField = `${indent}${field.name}: ${field.schema},\\n`;\r\n content = content.replace(\r\n schemaEndRegex,\r\n `\\n${newField}$1$2`\r\n );\r\n modified = true;\r\n }\r\n }\r\n\r\n if (modified) {\r\n await fs.writeFile(envPath, content);\r\n }\r\n\r\n return modified;\r\n};\r\n\r\n/**\r\n * Creates initial .env file for new projects\r\n */\r\nexport const createInitialEnv = async (cwd: string) => {\r\n const envPath = path.join(cwd, \".env\");\r\n\r\n if (fs.existsSync(envPath)) {\r\n return; // Don't overwrite existing\r\n }\r\n\r\n const content = `# Environment Variables\r\nPORT=3000\r\nNODE_ENV=development\r\n`;\r\n\r\n await fs.writeFile(envPath, content);\r\n};\r\n\r\n/**\r\n * Module-specific env configurations\r\n */\r\nexport const ENV_CONFIGS = {\r\n \"database-pg\": {\r\n envVars: {\r\n DATABASE_URL: \"postgresql://postgres@localhost:5432/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n \"database-mysql\": {\r\n envVars: {\r\n DATABASE_URL: \"mysql://root@localhost:3306/mydb\",\r\n },\r\n schemaFields: [\r\n { name: \"DATABASE_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n auth: {\r\n envVars: {\r\n BETTER_AUTH_SECRET: \"your-secret-key-at-least-32-characters-long\",\r\n BETTER_AUTH_URL: \"http://localhost:3000\",\r\n },\r\n schemaFields: [\r\n { name: \"BETTER_AUTH_SECRET\", schema: \"z.string().min(32)\" },\r\n { name: \"BETTER_AUTH_URL\", schema: \"z.string().url()\" },\r\n ],\r\n },\r\n};\r\n","import fs from \"fs-extra\";\nimport path from \"path\";\n\nexport interface ZuroConfig {\n name?: string;\n pm?: string;\n srcDir?: string;\n}\n\nfunction sanitizeConfig(input: unknown): ZuroConfig {\n if (!input || typeof input !== \"object\") {\n return {};\n }\n\n const raw = input as Record<string, unknown>;\n const config: ZuroConfig = {};\n\n if (typeof raw.name === \"string\") {\n config.name = raw.name;\n }\n\n if (typeof raw.pm === \"string\") {\n config.pm = raw.pm;\n }\n\n if (typeof raw.srcDir === \"string\") {\n config.srcDir = raw.srcDir;\n }\n\n return config;\n}\n\nexport function getConfigPath(cwd: string) {\n return path.join(cwd, \"zuro.json\");\n}\n\nexport async function readZuroConfig(cwd: string): Promise<ZuroConfig | null> {\n const configPath = getConfigPath(cwd);\n\n if (!(await fs.pathExists(configPath))) {\n return null;\n }\n\n const raw = await fs.readJson(configPath);\n return sanitizeConfig(raw);\n}\n\nexport async function writeZuroConfig(cwd: string, config: ZuroConfig) {\n const configPath = getConfigPath(cwd);\n await fs.writeJson(configPath, sanitizeConfig(config), { spaces: 2 });\n}\n","import chalk from \"chalk\";\n\nexport function showNonZuroProjectMessage() {\n console.log(chalk.yellow(\"This directory looks like an existing project that wasn't created with Zuro CLI.\"));\n console.log(\"\");\n console.log(chalk.yellow(\"We stopped here because we don't want to make unnecessary changes to your project.\"));\n console.log(\"\");\n console.log(\"Zuro CLI works in:\");\n console.log(\"- a fresh/empty directory, or\");\n console.log(\"- an existing project already managed by Zuro CLI.\");\n}\n","import prompts from \"prompts\";\nimport ora from \"ora\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { fetchRegistry, fetchFile, RegistryFile } from \"../utils/registry\";\nimport { installDependencies } from \"../utils/pm\";\nimport { resolveDependencies } from \"../utils/dependency\";\nimport { updateEnvFile, updateEnvSchema, ENV_CONFIGS } from \"../utils/env-manager\";\nimport chalk from \"chalk\";\nimport { readZuroConfig } from \"../utils/config\";\nimport { showNonZuroProjectMessage } from \"../utils/project-guard\";\n\nfunction resolveSafeTargetPath(projectRoot: string, srcDir: string, file: RegistryFile) {\n const targetPath = path.resolve(projectRoot, srcDir, file.target);\n const normalizedRoot = path.resolve(projectRoot);\n\n if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {\n throw new Error(`Refusing to write outside project directory: ${file.target}`);\n }\n\n return targetPath;\n}\n\n/**\n * Modifies app.ts to include error handler middleware\n */\nasync function injectErrorHandler(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"errorHandler\")) {\n return true;\n }\n\n const errorImport = `import { errorHandler, notFoundHandler } from \"./middleware/error-handler\";`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${errorImport}` + content.slice(lastImportIndex);\n }\n\n const errorSetup = `\\n// Error handling (must be last)\\napp.use(notFoundHandler);\\napp.use(errorHandler);\\n`;\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + errorSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\n/**\n * Modifies app.ts to include auth routes\n */\nasync function injectAuthRoutes(projectRoot: string, srcDir: string): Promise<boolean> {\n const appPath = path.join(projectRoot, srcDir, \"app.ts\");\n\n if (!fs.existsSync(appPath)) {\n return false;\n }\n\n let content = await fs.readFile(appPath, \"utf-8\");\n\n if (content.includes(\"routes/auth.routes\")) {\n return true;\n }\n\n const authImport = `import authRoutes from \"./routes/auth.routes\";`;\n const userImport = `import userRoutes from \"./routes/user.routes\";`;\n const routeSetup = `\\n// Auth routes\\napp.use(authRoutes);\\napp.use(\"/api/users\", userRoutes);\\n`;\n\n const importRegex = /^import .+ from .+;?\\s*$/gm;\n let lastImportIndex = 0;\n let match;\n\n while ((match = importRegex.exec(content)) !== null) {\n lastImportIndex = match.index + match[0].length;\n }\n\n if (lastImportIndex > 0) {\n content = content.slice(0, lastImportIndex) + `\\n${authImport}\\n${userImport}` + content.slice(lastImportIndex);\n }\n\n const exportMatch = content.match(/export default app;?\\s*$/m);\n if (exportMatch && exportMatch.index !== undefined) {\n content = content.slice(0, exportMatch.index) + routeSetup + \"\\n\" + content.slice(exportMatch.index);\n }\n\n await fs.writeFile(appPath, content);\n return true;\n}\n\nexport const add = async (moduleName: string) => {\n const projectRoot = process.cwd();\n const projectConfig = await readZuroConfig(projectRoot);\n if (!projectConfig) {\n showNonZuroProjectMessage();\n return;\n }\n let srcDir = projectConfig.srcDir || \"src\";\n\n let customDbUrl: string | undefined;\n\n const DEFAULT_URLS = {\n \"database-pg\": \"postgresql://root@localhost:5432/mydb\",\n \"database-mysql\": \"mysql://root@localhost:3306/mydb\",\n };\n\n if (moduleName === \"database\") {\n const variantResponse = await prompts({\n type: \"select\",\n name: \"variant\",\n message: \"Which database dialect?\",\n choices: [\n { title: \"PostgreSQL\", value: \"database-pg\" },\n { title: \"MySQL\", value: \"database-mysql\" },\n ],\n });\n\n if (!variantResponse.variant) {\n process.exit(0);\n }\n\n moduleName = variantResponse.variant;\n\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const urlResponse = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = urlResponse.dbUrl?.trim() || defaultUrl;\n }\n\n if ((moduleName === \"database-pg\" || moduleName === \"database-mysql\") && customDbUrl === undefined) {\n const defaultUrl = DEFAULT_URLS[moduleName as keyof typeof DEFAULT_URLS];\n console.log(chalk.dim(` Tip: Leave blank to use ${defaultUrl}\\n`));\n\n const response = await prompts({\n type: \"text\",\n name: \"dbUrl\",\n message: \"Database URL\",\n initial: \"\",\n });\n customDbUrl = response.dbUrl?.trim() || defaultUrl;\n }\n\n const spinner = ora(`Checking registry for ${moduleName}...`).start();\n\n try {\n const registryContext = await fetchRegistry();\n const module = registryContext.manifest.modules[moduleName];\n\n if (!module) {\n spinner.fail(`Module '${moduleName}' not found.`);\n return;\n }\n\n spinner.succeed(`Found module: ${chalk.cyan(moduleName)}`);\n\n const moduleDeps = module.moduleDependencies || [];\n await resolveDependencies(moduleDeps, projectRoot);\n\n spinner.start(\"Installing dependencies...\");\n\n let pm = \"npm\";\n if (fs.existsSync(path.join(projectRoot, \"pnpm-lock.yaml\"))) {\n pm = \"pnpm\";\n } else if (fs.existsSync(path.join(projectRoot, \"bun.lockb\"))) {\n pm = \"bun\";\n } else if (fs.existsSync(path.join(projectRoot, \"yarn.lock\"))) {\n pm = \"yarn\";\n }\n\n await installDependencies(pm, module.dependencies || [], projectRoot);\n await installDependencies(pm, module.devDependencies || [], projectRoot, { dev: true });\n\n spinner.succeed(\"Dependencies installed\");\n\n spinner.start(\"Scaffolding files...\");\n\n for (const file of module.files) {\n const content = await fetchFile(file.path, {\n baseUrl: registryContext.fileBaseUrl,\n expectedSha256: file.sha256,\n expectedSize: file.size,\n });\n\n const targetPath = resolveSafeTargetPath(projectRoot, srcDir, file);\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content);\n }\n\n spinner.succeed(\"Files generated\");\n\n if (moduleName === \"auth\") {\n spinner.start(\"Configuring routes in app.ts...\");\n const injected = await injectAuthRoutes(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Routes configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - routes need manual setup\");\n }\n }\n\n if (moduleName === \"error-handler\") {\n spinner.start(\"Configuring error handler in app.ts...\");\n const injected = await injectErrorHandler(projectRoot, srcDir);\n if (injected) {\n spinner.succeed(\"Error handler configured in app.ts\");\n } else {\n spinner.warn(\"Could not find app.ts - error handler needs manual setup\");\n }\n }\n\n const envConfig = ENV_CONFIGS[moduleName as keyof typeof ENV_CONFIGS];\n if (envConfig) {\n spinner.start(\"Updating environment configuration...\");\n\n const envVars: Record<string, string> = { ...envConfig.envVars };\n if (customDbUrl && (moduleName === \"database-pg\" || moduleName === \"database-mysql\")) {\n envVars.DATABASE_URL = customDbUrl;\n }\n\n await updateEnvFile(projectRoot, envVars);\n await updateEnvSchema(projectRoot, srcDir, envConfig.schemaFields);\n\n spinner.succeed(\"Environment configured\");\n }\n\n console.log(chalk.green(`\\n✔ ${moduleName} added successfully!\\n`));\n\n if (moduleName === \"auth\") {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n console.log(chalk.yellow(\"1. Update your .env file:\"));\n console.log(\n chalk.dim(\" We added placeholder values. Update BETTER_AUTH_SECRET with a secure key.\\n\")\n );\n console.log(chalk.yellow(\"2. Run database migrations:\"));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n console.log(chalk.yellow(\"3. Available endpoints:\"));\n console.log(chalk.dim(\" POST /auth/sign-up/email - Register\"));\n console.log(chalk.dim(\" POST /auth/sign-in/email - Login\"));\n console.log(chalk.dim(\" POST /auth/sign-out - Logout\"));\n console.log(chalk.dim(\" GET /api/users/me - Current user\\n\"));\n } else if (moduleName === \"error-handler\") {\n console.log(chalk.bold(\"📋 Usage:\\n\"));\n console.log(chalk.yellow(\"Throw errors in your controllers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { UnauthorizedError, NotFoundError } from \"./lib/errors\";`));\n console.log(\"\");\n console.log(chalk.white(` throw new UnauthorizedError(\"Invalid credentials\");`));\n console.log(chalk.white(` throw new NotFoundError(\"User not found\");`));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n console.log(chalk.yellow(\"Available error classes:\"));\n console.log(chalk.dim(\" BadRequestError (400)\"));\n console.log(chalk.dim(\" UnauthorizedError (401)\"));\n console.log(chalk.dim(\" ForbiddenError (403)\"));\n console.log(chalk.dim(\" NotFoundError (404)\"));\n console.log(chalk.dim(\" ConflictError (409)\"));\n console.log(chalk.dim(\" ValidationError (422)\"));\n console.log(chalk.dim(\" InternalServerError (500)\\n\"));\n console.log(chalk.yellow(\"Wrap async handlers:\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\"));\n console.log(chalk.white(` import { asyncHandler } from \"./middleware/error-handler\";`));\n console.log(\"\");\n console.log(chalk.white(` router.get(\"/users\", asyncHandler(async (req, res) => {`));\n console.log(chalk.white(\" // errors auto-caught\"));\n console.log(chalk.white(\" }));\"));\n console.log(chalk.dim(\" ─────────────────────────────────────\\n\"));\n } else if (moduleName.includes(\"database\")) {\n console.log(chalk.bold(\"📋 Next Steps:\\n\"));\n let stepNum = 1;\n\n if (!customDbUrl) {\n console.log(chalk.yellow(`${stepNum}. Update DATABASE_URL in .env:`));\n console.log(\n chalk.dim(\" We added a placeholder. Update with your actual database credentials.\\n\")\n );\n stepNum++;\n }\n\n console.log(chalk.yellow(`${stepNum}. Create schemas in src/db/schema/:`));\n console.log(chalk.dim(\" Add table files and export from index.ts\\n\"));\n stepNum++;\n\n console.log(chalk.yellow(`${stepNum}. Run migrations:`));\n console.log(chalk.cyan(\" npx drizzle-kit generate\"));\n console.log(chalk.cyan(\" npx drizzle-kit migrate\\n\"));\n }\n } catch (error) {\n spinner.fail(`Failed to add module: ${(error as Error).message}`);\n }\n};\n","import { add } from \"../commands/add\";\nimport { readZuroConfig } from \"./config\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport chalk from \"chalk\";\n\n// Signature files to check if a Zuro module is installed\nconst BLOCK_SIGNATURES: Record<string, string> = {\n core: \"env.ts\",\n \"database-pg\": \"db/index.ts\",\n \"database-mysql\": \"db/index.ts\",\n validator: \"middleware/validate.ts\",\n \"error-handler\": \"lib/errors.ts\",\n logger: \"lib/logger.ts\",\n auth: \"lib/auth.ts\",\n};\n\n/**\n * Resolves Zuro module dependencies (NOT npm packages).\n * Only handles module dependencies like \"core\", \"database\", \"validator\", \"auth\".\n */\nexport const resolveDependencies = async (\n moduleDependencies: string[] | undefined,\n cwd: string\n) => {\n if (!moduleDependencies || moduleDependencies.length === 0) {\n return;\n }\n\n const config = await readZuroConfig(cwd);\n const srcDir = config?.srcDir || \"src\";\n\n for (const dep of moduleDependencies) {\n if (dep === \"database\") {\n const pgExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-pg\"]));\n const mysqlExists = fs.existsSync(path.join(cwd, srcDir, BLOCK_SIGNATURES[\"database-mysql\"]));\n\n if (pgExists || mysqlExists) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Dependency '${dep}' is missing. Triggering install...`));\n await add(\"database\");\n continue;\n }\n\n const signature = BLOCK_SIGNATURES[dep];\n if (!signature) {\n continue;\n }\n\n if (fs.existsSync(path.join(cwd, srcDir, signature))) {\n continue;\n }\n\n console.log(chalk.blue(`ℹ Installing missing dependency: ${dep}...`));\n await add(dep);\n }\n};\n"],"mappings":"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","names":["chalk","fs","path","fs","path","fs","path","path","fs","chalk","prompts","ora","path","fs","fs","path","chalk","chalk","resolveSafeTargetPath","path","fs","prompts","chalk","ora"]}
|