@igniter-js/cli 0.4.91 → 0.4.93
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 +19 -0
- package/dist/index.mjs +490 -71
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
10
|
-
import { Command as
|
|
10
|
+
import { Command as Command10 } from "commander";
|
|
11
11
|
|
|
12
12
|
// src/commands/init/index.ts
|
|
13
13
|
import { Command } from "commander";
|
|
@@ -94,10 +94,10 @@ import { execa } from "execa";
|
|
|
94
94
|
import { existsSync } from "fs";
|
|
95
95
|
import { readFile, writeFile } from "fs/promises";
|
|
96
96
|
import { join as join2 } from "path";
|
|
97
|
-
import
|
|
97
|
+
import handlebars2 from "handlebars";
|
|
98
98
|
|
|
99
99
|
// src/core/handlebars-helpers.ts
|
|
100
|
-
import
|
|
100
|
+
import handlebars from "handlebars";
|
|
101
101
|
function registerHandlebarsHelpers() {
|
|
102
102
|
handlebars.registerHelper("includes", function(array, value) {
|
|
103
103
|
if (!Array.isArray(array)) {
|
|
@@ -123,11 +123,11 @@ function registerHandlebarsHelpers() {
|
|
|
123
123
|
handlebars.registerHelper("capitalizeSlug", function(slug) {
|
|
124
124
|
return slug.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
125
125
|
});
|
|
126
|
-
handlebars.registerHelper("get", function(obj,
|
|
127
|
-
if (!
|
|
126
|
+
handlebars.registerHelper("get", function(obj, path25) {
|
|
127
|
+
if (!path25 || typeof path25 !== "string") {
|
|
128
128
|
return void 0;
|
|
129
129
|
}
|
|
130
|
-
const pathArray =
|
|
130
|
+
const pathArray = path25.split(".");
|
|
131
131
|
let current = obj;
|
|
132
132
|
for (let i = 0; i < pathArray.length; i++) {
|
|
133
133
|
if (current === null || current === void 0) {
|
|
@@ -148,7 +148,7 @@ function registerHandlebarsHelpers() {
|
|
|
148
148
|
});
|
|
149
149
|
handlebars.registerHelper("filterPlugins", function(plugins = []) {
|
|
150
150
|
if (!Array.isArray(plugins)) return [];
|
|
151
|
-
return plugins.filter((
|
|
151
|
+
return plugins.filter((p14) => p14 !== "next-cookies");
|
|
152
152
|
});
|
|
153
153
|
handlebars.registerHelper(
|
|
154
154
|
"generatePluginImports",
|
|
@@ -162,7 +162,7 @@ function registerHandlebarsHelpers() {
|
|
|
162
162
|
if (str === "open-api") return "openAPI";
|
|
163
163
|
return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
164
164
|
};
|
|
165
|
-
const regularPlugins = plugins.filter((
|
|
165
|
+
const regularPlugins = plugins.filter((p14) => p14 !== "next-cookies").map(camelCase);
|
|
166
166
|
const hasNextCookies = plugins.includes("next-cookies");
|
|
167
167
|
const importStatements = [];
|
|
168
168
|
if (regularPlugins.length > 0) {
|
|
@@ -334,9 +334,9 @@ var BaseStarter = class {
|
|
|
334
334
|
}
|
|
335
335
|
const outputPath = join2(projectDir, template.outputPath);
|
|
336
336
|
const outputDir = join2(outputPath, "..");
|
|
337
|
-
await import("fs").then((
|
|
338
|
-
if (!
|
|
339
|
-
|
|
337
|
+
await import("fs").then((fs9) => {
|
|
338
|
+
if (!fs9.existsSync(outputDir)) {
|
|
339
|
+
fs9.mkdirSync(outputDir, { recursive: true });
|
|
340
340
|
}
|
|
341
341
|
});
|
|
342
342
|
await writeFile(outputPath, renderedContent);
|
|
@@ -676,7 +676,7 @@ import path4 from "path";
|
|
|
676
676
|
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
677
677
|
import { existsSync as existsSync2 } from "fs";
|
|
678
678
|
import { join as join3 } from "path";
|
|
679
|
-
import
|
|
679
|
+
import handlebars3 from "handlebars";
|
|
680
680
|
var BaseAddOn = class {
|
|
681
681
|
async runSetup(projectDir, config) {
|
|
682
682
|
await this.addToPackageJson(projectDir, config);
|
|
@@ -971,9 +971,9 @@ var BaseAddOn = class {
|
|
|
971
971
|
}
|
|
972
972
|
const outputPath = join3(projectDir, template.outputPath);
|
|
973
973
|
const outputDir = join3(outputPath, "..");
|
|
974
|
-
await import("fs").then((
|
|
975
|
-
if (!
|
|
976
|
-
|
|
974
|
+
await import("fs").then((fs9) => {
|
|
975
|
+
if (!fs9.existsSync(outputDir)) {
|
|
976
|
+
fs9.mkdirSync(outputDir, { recursive: true });
|
|
977
977
|
}
|
|
978
978
|
});
|
|
979
979
|
await writeFile2(outputPath, renderedContent);
|
|
@@ -1838,9 +1838,9 @@ var addOnRegistry = AddOnRegistry.create().register(new RedisStoreAddOn()).regis
|
|
|
1838
1838
|
|
|
1839
1839
|
// src/core/file-system.ts
|
|
1840
1840
|
import * as fs2 from "fs/promises";
|
|
1841
|
-
async function isPathEmpty(
|
|
1841
|
+
async function isPathEmpty(path25) {
|
|
1842
1842
|
try {
|
|
1843
|
-
const files = await fs2.readdir(
|
|
1843
|
+
const files = await fs2.readdir(path25);
|
|
1844
1844
|
return files.length === 0;
|
|
1845
1845
|
} catch (error) {
|
|
1846
1846
|
if (error.code === "ENOENT") {
|
|
@@ -2173,14 +2173,14 @@ var ProjectGenerator = class {
|
|
|
2173
2173
|
dockerSetup.message(
|
|
2174
2174
|
`Checking and stopping currently running containers...`
|
|
2175
2175
|
);
|
|
2176
|
-
const
|
|
2177
|
-
const
|
|
2178
|
-
const
|
|
2179
|
-
const composeFilePath =
|
|
2176
|
+
const fs9 = await import("fs/promises");
|
|
2177
|
+
const path25 = await import("path");
|
|
2178
|
+
const yaml2 = await import("js-yaml");
|
|
2179
|
+
const composeFilePath = path25.join(this.targetDir, "docker-compose.yml");
|
|
2180
2180
|
let ports = [];
|
|
2181
2181
|
try {
|
|
2182
|
-
const composeContent = await
|
|
2183
|
-
const doc =
|
|
2182
|
+
const composeContent = await fs9.readFile(composeFilePath, "utf8");
|
|
2183
|
+
const doc = yaml2.load(composeContent);
|
|
2184
2184
|
const services = doc?.services || {};
|
|
2185
2185
|
for (const svcKey of Object.keys(services)) {
|
|
2186
2186
|
const service = services[svcKey];
|
|
@@ -2287,7 +2287,7 @@ var initCommand = new Command().command("init").description("Create a new Ignite
|
|
|
2287
2287
|
).option("--no-git", "Skip git repository initialization").option("--no-install", "Skip automatic dependency installation").option("--no-docker", "Skip Docker Compose setup").action(handleInitAction);
|
|
2288
2288
|
|
|
2289
2289
|
// src/commands/generate/index.ts
|
|
2290
|
-
import { Command as
|
|
2290
|
+
import { Command as Command8 } from "commander";
|
|
2291
2291
|
|
|
2292
2292
|
// src/commands/generate/feature/index.ts
|
|
2293
2293
|
import { Command as Command2 } from "commander";
|
|
@@ -2302,7 +2302,7 @@ import { writeFile as writeFile5 } from "fs/promises";
|
|
|
2302
2302
|
import { mkdirSync, existsSync as existsSync3 } from "fs";
|
|
2303
2303
|
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
2304
2304
|
import * as path14 from "path";
|
|
2305
|
-
import
|
|
2305
|
+
import handlebars4 from "handlebars";
|
|
2306
2306
|
import { fileURLToPath } from "url";
|
|
2307
2307
|
var __filename = fileURLToPath(import.meta?.url);
|
|
2308
2308
|
var __dirname = path14.dirname(__filename);
|
|
@@ -2900,8 +2900,8 @@ async function handleGenerateFeatureAction(name, options) {
|
|
|
2900
2900
|
p7.outro("Nothing to do.");
|
|
2901
2901
|
process.exit(1);
|
|
2902
2902
|
}
|
|
2903
|
-
const
|
|
2904
|
-
|
|
2903
|
+
const spinner8 = p7.spinner();
|
|
2904
|
+
spinner8.start(`Scaffolding feature '${featureSlug}'...`);
|
|
2905
2905
|
try {
|
|
2906
2906
|
if (provider && selection) {
|
|
2907
2907
|
await FeatureWorkspace.ensureStructure(featureDir);
|
|
@@ -2914,13 +2914,13 @@ async function handleGenerateFeatureAction(name, options) {
|
|
|
2914
2914
|
await FeatureWorkspace.ensureStructure(featureDir);
|
|
2915
2915
|
await generateEmptyFeature(featureSlug, featureDir, templateEngine);
|
|
2916
2916
|
}
|
|
2917
|
-
|
|
2917
|
+
spinner8.stop(`Feature '${featureSlug}' created successfully!`);
|
|
2918
2918
|
p7.log.success(
|
|
2919
2919
|
`Scaffolded feature '${featureSlug}'. Remember to register the controller in your router.`
|
|
2920
2920
|
);
|
|
2921
2921
|
p7.outro("Feature generation complete!");
|
|
2922
2922
|
} catch (error) {
|
|
2923
|
-
|
|
2923
|
+
spinner8.stop("Failed to scaffold the feature.");
|
|
2924
2924
|
const message = error instanceof Error ? error.message : String(error);
|
|
2925
2925
|
p7.log.error(`Feature generation failed: ${message}`);
|
|
2926
2926
|
process.exit(1);
|
|
@@ -2929,7 +2929,7 @@ async function handleGenerateFeatureAction(name, options) {
|
|
|
2929
2929
|
async function resolveSchemaProvider({
|
|
2930
2930
|
registry,
|
|
2931
2931
|
options,
|
|
2932
|
-
cancel:
|
|
2932
|
+
cancel: cancel5
|
|
2933
2933
|
}) {
|
|
2934
2934
|
if (options.schema) {
|
|
2935
2935
|
const provider2 = registry.findBySchemaOption(options.schema);
|
|
@@ -2962,7 +2962,7 @@ async function resolveSchemaProvider({
|
|
|
2962
2962
|
initialValue: "none"
|
|
2963
2963
|
});
|
|
2964
2964
|
if (p7.isCancel(choice)) {
|
|
2965
|
-
|
|
2965
|
+
cancel5("Feature generation cancelled.");
|
|
2966
2966
|
}
|
|
2967
2967
|
if (choice === "none") {
|
|
2968
2968
|
return { provider: null, selection: null };
|
|
@@ -3063,13 +3063,13 @@ var OpenAPIGenerator = class _OpenAPIGenerator {
|
|
|
3063
3063
|
for (const [controllerKey, controller] of Object.entries(router.controllers)) {
|
|
3064
3064
|
for (const [actionKey, action] of Object.entries(controller.actions)) {
|
|
3065
3065
|
const actionName = action.name || actionKey;
|
|
3066
|
-
let
|
|
3067
|
-
|
|
3068
|
-
if (
|
|
3069
|
-
|
|
3066
|
+
let path25 = `/${controller.path}/${action.path}`;
|
|
3067
|
+
path25 = path25.replace(/\/{2,}/g, "/");
|
|
3068
|
+
if (path25.length > 1 && path25.endsWith("/")) {
|
|
3069
|
+
path25 = path25.slice(0, -1);
|
|
3070
3070
|
}
|
|
3071
|
-
if (!paths[
|
|
3072
|
-
paths[
|
|
3071
|
+
if (!paths[path25]) {
|
|
3072
|
+
paths[path25] = {};
|
|
3073
3073
|
}
|
|
3074
3074
|
const operation = {
|
|
3075
3075
|
summary: action.description || actionName,
|
|
@@ -3131,7 +3131,7 @@ var OpenAPIGenerator = class _OpenAPIGenerator {
|
|
|
3131
3131
|
if (action.isStream) {
|
|
3132
3132
|
operation.description = (operation.description ? operation.description + "\n\n" : "") + "This endpoint supports Server-Sent Events (SSE) for real-time updates. It functions as a standard GET request initially, then maintains an open connection for streaming data.";
|
|
3133
3133
|
}
|
|
3134
|
-
paths[
|
|
3134
|
+
paths[path25][action.method.toLowerCase()] = operation;
|
|
3135
3135
|
}
|
|
3136
3136
|
}
|
|
3137
3137
|
return paths;
|
|
@@ -3307,10 +3307,10 @@ async function generateDocsWatchMode(routerPath, outputDir) {
|
|
|
3307
3307
|
async function handleGenerateDocsAction(options) {
|
|
3308
3308
|
try {
|
|
3309
3309
|
p9.intro("Generate OpenAPI documentation");
|
|
3310
|
-
const
|
|
3311
|
-
|
|
3310
|
+
const spinner8 = p9.spinner();
|
|
3311
|
+
spinner8.start("Generating OpenAPI documentation...");
|
|
3312
3312
|
const result = await generateDocsWatchMode(options.router, options.output);
|
|
3313
|
-
|
|
3313
|
+
spinner8.stop("OpenAPI documentation generated successfully.");
|
|
3314
3314
|
p9.log.success(
|
|
3315
3315
|
`Docs generated in ${(result.durationMs / 1e3).toFixed(2)}s (${result.sizeKb.toFixed(1)} KB)`
|
|
3316
3316
|
);
|
|
@@ -3354,10 +3354,10 @@ async function generateSchemaWatchMode(routerPath, outputPath) {
|
|
|
3354
3354
|
async function handleGenerateSchemaAction({ router: routerPath, output: outputPath }) {
|
|
3355
3355
|
try {
|
|
3356
3356
|
p10.intro("Generate Igniter.js Client Schema");
|
|
3357
|
-
const
|
|
3358
|
-
|
|
3357
|
+
const spinner8 = p10.spinner();
|
|
3358
|
+
spinner8.start("Generating schema...");
|
|
3359
3359
|
const result = await generateSchemaWatchMode(routerPath, outputPath);
|
|
3360
|
-
|
|
3360
|
+
spinner8.stop("Schema generated successfully.");
|
|
3361
3361
|
p10.log.success(
|
|
3362
3362
|
`Schema generated in ${(result.durationMs / 1e3).toFixed(2)}s (${result.controllers} controllers, ${result.actions} actions).`
|
|
3363
3363
|
);
|
|
@@ -3432,8 +3432,8 @@ async function handleGenerateControllerAction(name, options) {
|
|
|
3432
3432
|
"feature",
|
|
3433
3433
|
"empty.controller.hbs"
|
|
3434
3434
|
);
|
|
3435
|
-
const
|
|
3436
|
-
|
|
3435
|
+
const spinner8 = p11.spinner();
|
|
3436
|
+
spinner8.start(
|
|
3437
3437
|
`Creating controller '${controllerSlug}' inside feature '${featureSlug}'...`
|
|
3438
3438
|
);
|
|
3439
3439
|
try {
|
|
@@ -3446,13 +3446,13 @@ async function handleGenerateControllerAction(name, options) {
|
|
|
3446
3446
|
},
|
|
3447
3447
|
controllerPath
|
|
3448
3448
|
);
|
|
3449
|
-
|
|
3449
|
+
spinner8.stop("Controller created successfully!");
|
|
3450
3450
|
p11.log.success(
|
|
3451
3451
|
`Created controller '${controllerSlug}' in feature '${featureSlug}'.`
|
|
3452
3452
|
);
|
|
3453
3453
|
p11.outro("Controller generation complete!");
|
|
3454
3454
|
} catch (error) {
|
|
3455
|
-
|
|
3455
|
+
spinner8.stop("Failed to create the controller.");
|
|
3456
3456
|
const message = error instanceof Error ? error.message : String(error);
|
|
3457
3457
|
p11.log.error(`Controller generation failed: ${message}`);
|
|
3458
3458
|
process.exit(1);
|
|
@@ -3510,8 +3510,8 @@ async function handleGenerateProcedureAction(name, options) {
|
|
|
3510
3510
|
"feature",
|
|
3511
3511
|
"procedure.hbs"
|
|
3512
3512
|
);
|
|
3513
|
-
const
|
|
3514
|
-
|
|
3513
|
+
const spinner8 = p12.spinner();
|
|
3514
|
+
spinner8.start(
|
|
3515
3515
|
`Creating procedure '${procedureSlug}' inside feature '${featureSlug}'...`
|
|
3516
3516
|
);
|
|
3517
3517
|
if (await FeatureWorkspace.fileExists(path22.join(featureDir, "procedures", ".gitkeep"))) {
|
|
@@ -3527,13 +3527,13 @@ async function handleGenerateProcedureAction(name, options) {
|
|
|
3527
3527
|
},
|
|
3528
3528
|
procedurePath
|
|
3529
3529
|
);
|
|
3530
|
-
|
|
3530
|
+
spinner8.stop("Procedure created successfully!");
|
|
3531
3531
|
p12.log.success(
|
|
3532
3532
|
`Created procedure '${procedureSlug}' in feature '${featureSlug}'.`
|
|
3533
3533
|
);
|
|
3534
3534
|
p12.outro("Procedure generation complete!");
|
|
3535
3535
|
} catch (error) {
|
|
3536
|
-
|
|
3536
|
+
spinner8.stop("Failed to create the procedure.");
|
|
3537
3537
|
const message = error instanceof Error ? error.message : String(error);
|
|
3538
3538
|
p12.log.error(`Procedure generation failed: ${message}`);
|
|
3539
3539
|
process.exit(1);
|
|
@@ -3543,15 +3543,434 @@ async function handleGenerateProcedureAction(name, options) {
|
|
|
3543
3543
|
// src/commands/generate/procedure/index.ts
|
|
3544
3544
|
var procedureCommand = new Command6().command("procedure").description("Scaffold a new procedure within a feature").argument("[name]", "Name of the procedure (e.g., 'profile')").option("-f, --feature <feature>", "Target feature name").action(handleGenerateProcedureAction);
|
|
3545
3545
|
|
|
3546
|
+
// src/commands/generate/caller/index.ts
|
|
3547
|
+
import { Command as Command7 } from "commander";
|
|
3548
|
+
|
|
3549
|
+
// src/commands/generate/caller/action.ts
|
|
3550
|
+
import { promises as fs7 } from "fs";
|
|
3551
|
+
import path23 from "path";
|
|
3552
|
+
import * as p13 from "@clack/prompts";
|
|
3553
|
+
import yaml from "js-yaml";
|
|
3554
|
+
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
3555
|
+
var SUPPORTED_METHODS = ["get", "post", "put", "patch", "delete"];
|
|
3556
|
+
async function handleGenerateCallerAction(options) {
|
|
3557
|
+
p13.intro("Generate Igniter Caller");
|
|
3558
|
+
try {
|
|
3559
|
+
const callerName = await resolveCallerName(options.name);
|
|
3560
|
+
const source = await resolveSource(options);
|
|
3561
|
+
const spinner8 = p13.spinner();
|
|
3562
|
+
spinner8.start("Loading OpenAPI spec...");
|
|
3563
|
+
const parsedDoc = await loadOpenApiDocument(source);
|
|
3564
|
+
const host = deriveHostname(source, parsedDoc) || "api";
|
|
3565
|
+
const outputDir = path23.resolve(
|
|
3566
|
+
process.cwd(),
|
|
3567
|
+
options.output ?? path23.join("src", "callers", host)
|
|
3568
|
+
);
|
|
3569
|
+
const prefix = Casing.toPascalCase(callerName);
|
|
3570
|
+
const converter = new SchemaConverter(prefix, parsedDoc.components);
|
|
3571
|
+
const pathsCode = buildSchemasObject(parsedDoc, converter);
|
|
3572
|
+
const componentsCode = converter.renderComponentSchemas();
|
|
3573
|
+
const schemaConstName = `${prefix}Schema`;
|
|
3574
|
+
const schemaTypeName = `${prefix}SchemaType`;
|
|
3575
|
+
const schemaFileContents = [
|
|
3576
|
+
"/* eslint-disable */",
|
|
3577
|
+
"/* prettier-ignore */",
|
|
3578
|
+
"",
|
|
3579
|
+
"/**",
|
|
3580
|
+
" * @generated by @igniter-js/cli",
|
|
3581
|
+
" * This file was automatically created from your OpenAPI spec.",
|
|
3582
|
+
" * Do not edit manually; regenerate via `igniter generate caller`.",
|
|
3583
|
+
" */",
|
|
3584
|
+
"",
|
|
3585
|
+
'import { z } from "zod";',
|
|
3586
|
+
componentsCode,
|
|
3587
|
+
`const schemas = ${pathsCode};`,
|
|
3588
|
+
"",
|
|
3589
|
+
`export const ${schemaConstName} = schemas;`,
|
|
3590
|
+
`export type ${schemaTypeName} = typeof ${schemaConstName};`,
|
|
3591
|
+
""
|
|
3592
|
+
].filter(Boolean).join("\n");
|
|
3593
|
+
const baseUrl = inferBaseUrl(source, parsedDoc);
|
|
3594
|
+
const callerVar = `${Casing.toCamelCase(callerName)}Caller`;
|
|
3595
|
+
const callerFileContents = [
|
|
3596
|
+
"/**",
|
|
3597
|
+
` * Preconfigured IgniterCaller for ${prefix}.`,
|
|
3598
|
+
" * Regenerate via `igniter generate caller` when the OpenAPI spec changes.",
|
|
3599
|
+
" */",
|
|
3600
|
+
'import { IgniterCaller } from "@igniter-js/caller";',
|
|
3601
|
+
`import { ${schemaConstName} } from "./schema";`,
|
|
3602
|
+
"",
|
|
3603
|
+
"export const " + callerVar + " = IgniterCaller.create()",
|
|
3604
|
+
baseUrl ? ` .withBaseUrl("${baseUrl}")` : "",
|
|
3605
|
+
" .withSchemas(" + schemaConstName + ', { mode: "strict" })',
|
|
3606
|
+
" .build();",
|
|
3607
|
+
""
|
|
3608
|
+
].filter(Boolean).join("\n");
|
|
3609
|
+
await fs7.mkdir(outputDir, { recursive: true });
|
|
3610
|
+
await fs7.writeFile(path23.join(outputDir, "schema.ts"), schemaFileContents, "utf8");
|
|
3611
|
+
await fs7.writeFile(path23.join(outputDir, "index.ts"), callerFileContents, "utf8");
|
|
3612
|
+
spinner8.stop("Caller generated successfully.");
|
|
3613
|
+
p13.log.success(
|
|
3614
|
+
`Schemas and caller created at ${path23.relative(process.cwd(), outputDir)}`
|
|
3615
|
+
);
|
|
3616
|
+
p13.log.info(
|
|
3617
|
+
`Exported caller: ${callerVar} (schemas: ${schemaConstName})`
|
|
3618
|
+
);
|
|
3619
|
+
} catch (error) {
|
|
3620
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3621
|
+
p13.log.error(message);
|
|
3622
|
+
process.exit(1);
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
async function resolveCallerName(name) {
|
|
3626
|
+
if (name) {
|
|
3627
|
+
return name.trim();
|
|
3628
|
+
}
|
|
3629
|
+
const answer = await p13.text({
|
|
3630
|
+
message: "Caller name (e.g., facebook, billing)",
|
|
3631
|
+
validate: (value) => value && value.trim().length > 0 ? void 0 : "Name is required"
|
|
3632
|
+
});
|
|
3633
|
+
if (p13.isCancel(answer)) {
|
|
3634
|
+
p13.cancel("Caller generation cancelled.");
|
|
3635
|
+
process.exit(0);
|
|
3636
|
+
}
|
|
3637
|
+
return String(answer);
|
|
3638
|
+
}
|
|
3639
|
+
async function resolveSource(options) {
|
|
3640
|
+
if (options.url && options.path) {
|
|
3641
|
+
throw new Error("Use either --url or --path, not both.");
|
|
3642
|
+
}
|
|
3643
|
+
if (options.url) {
|
|
3644
|
+
return { type: "url", url: options.url };
|
|
3645
|
+
}
|
|
3646
|
+
if (options.path) {
|
|
3647
|
+
return { type: "path", path: options.path };
|
|
3648
|
+
}
|
|
3649
|
+
const sourceChoice = await p13.select({
|
|
3650
|
+
message: "Where is your OpenAPI spec?",
|
|
3651
|
+
options: [
|
|
3652
|
+
{ label: "Remote URL", value: "url" },
|
|
3653
|
+
{ label: "Local file path", value: "path" }
|
|
3654
|
+
],
|
|
3655
|
+
initialValue: "url"
|
|
3656
|
+
});
|
|
3657
|
+
if (p13.isCancel(sourceChoice)) {
|
|
3658
|
+
p13.cancel("Caller generation cancelled.");
|
|
3659
|
+
process.exit(0);
|
|
3660
|
+
}
|
|
3661
|
+
if (sourceChoice === "url") {
|
|
3662
|
+
const url = await p13.text({
|
|
3663
|
+
message: "OpenAPI URL",
|
|
3664
|
+
placeholder: "https://api.example.com/openapi.json",
|
|
3665
|
+
validate: (value) => !value ? "URL is required" : void 0
|
|
3666
|
+
});
|
|
3667
|
+
if (p13.isCancel(url)) {
|
|
3668
|
+
p13.cancel("Caller generation cancelled.");
|
|
3669
|
+
process.exit(0);
|
|
3670
|
+
}
|
|
3671
|
+
return { type: "url", url: String(url) };
|
|
3672
|
+
}
|
|
3673
|
+
const filePath = await p13.text({
|
|
3674
|
+
message: "Path to OpenAPI file",
|
|
3675
|
+
placeholder: "./openapi.json",
|
|
3676
|
+
validate: (value) => !value ? "Path is required" : void 0
|
|
3677
|
+
});
|
|
3678
|
+
if (p13.isCancel(filePath)) {
|
|
3679
|
+
p13.cancel("Caller generation cancelled.");
|
|
3680
|
+
process.exit(0);
|
|
3681
|
+
}
|
|
3682
|
+
return { type: "path", path: String(filePath) };
|
|
3683
|
+
}
|
|
3684
|
+
async function loadOpenApiDocument(source) {
|
|
3685
|
+
const raw = await loadRawContent(source);
|
|
3686
|
+
const parsed = parseOpenApi(raw);
|
|
3687
|
+
if (!parsed.openapi || !parsed.openapi.startsWith("3.")) {
|
|
3688
|
+
throw new Error("Only OpenAPI 3.x documents are supported.");
|
|
3689
|
+
}
|
|
3690
|
+
const dereferenced = await SwaggerParser.dereference(
|
|
3691
|
+
parsed
|
|
3692
|
+
);
|
|
3693
|
+
return dereferenced;
|
|
3694
|
+
}
|
|
3695
|
+
async function loadRawContent(source) {
|
|
3696
|
+
if (source.type === "url") {
|
|
3697
|
+
const response = await fetch(source.url);
|
|
3698
|
+
if (!response.ok) {
|
|
3699
|
+
throw new Error(
|
|
3700
|
+
`Failed to fetch OpenAPI document: ${response.status} ${response.statusText}`
|
|
3701
|
+
);
|
|
3702
|
+
}
|
|
3703
|
+
return await response.text();
|
|
3704
|
+
}
|
|
3705
|
+
const filePath = path23.resolve(process.cwd(), source.path);
|
|
3706
|
+
return await fs7.readFile(filePath, "utf8");
|
|
3707
|
+
}
|
|
3708
|
+
function parseOpenApi(content) {
|
|
3709
|
+
try {
|
|
3710
|
+
return JSON.parse(content);
|
|
3711
|
+
} catch {
|
|
3712
|
+
const parsed = yaml.load(content);
|
|
3713
|
+
if (!parsed || typeof parsed !== "object") {
|
|
3714
|
+
throw new Error("Could not parse OpenAPI document (JSON/YAML).");
|
|
3715
|
+
}
|
|
3716
|
+
return parsed;
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
function deriveHostname(source, doc) {
|
|
3720
|
+
if (source.type === "url") {
|
|
3721
|
+
try {
|
|
3722
|
+
const url = new URL(source.url);
|
|
3723
|
+
return url.hostname.replace(/[^a-zA-Z0-9.-]/g, "") || null;
|
|
3724
|
+
} catch {
|
|
3725
|
+
return null;
|
|
3726
|
+
}
|
|
3727
|
+
}
|
|
3728
|
+
const serverUrl = doc.servers?.[0]?.url;
|
|
3729
|
+
if (serverUrl) {
|
|
3730
|
+
try {
|
|
3731
|
+
const url = new URL(serverUrl);
|
|
3732
|
+
return url.hostname.replace(/[^a-zA-Z0-9.-]/g, "") || null;
|
|
3733
|
+
} catch {
|
|
3734
|
+
return null;
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
return null;
|
|
3738
|
+
}
|
|
3739
|
+
function inferBaseUrl(source, doc) {
|
|
3740
|
+
if (source.type === "url") {
|
|
3741
|
+
const serverUrl2 = doc.servers?.[0]?.url;
|
|
3742
|
+
if (serverUrl2) {
|
|
3743
|
+
return serverUrl2;
|
|
3744
|
+
}
|
|
3745
|
+
return new URL(source.url).origin;
|
|
3746
|
+
}
|
|
3747
|
+
const serverUrl = doc.servers?.[0]?.url;
|
|
3748
|
+
return serverUrl ?? null;
|
|
3749
|
+
}
|
|
3750
|
+
var SchemaConverter = class {
|
|
3751
|
+
constructor(prefix, components) {
|
|
3752
|
+
this.generated = /* @__PURE__ */ new Map();
|
|
3753
|
+
this.inProgress = /* @__PURE__ */ new Set();
|
|
3754
|
+
this.prefix = prefix;
|
|
3755
|
+
this.components = components;
|
|
3756
|
+
}
|
|
3757
|
+
renderComponentSchemas() {
|
|
3758
|
+
const entries = [];
|
|
3759
|
+
const names = Object.keys(this.components?.schemas ?? {}).sort();
|
|
3760
|
+
for (const name of names) {
|
|
3761
|
+
const identifier = this.componentIdentifier(name);
|
|
3762
|
+
const expression = this.convertWithCache(name);
|
|
3763
|
+
entries.push(`const ${identifier} = ${expression};`);
|
|
3764
|
+
}
|
|
3765
|
+
return entries.length ? `${entries.join("\n")}
|
|
3766
|
+
` : "";
|
|
3767
|
+
}
|
|
3768
|
+
convert(schema) {
|
|
3769
|
+
if ("$ref" in schema) {
|
|
3770
|
+
const refName = this.refName(schema.$ref);
|
|
3771
|
+
const identifier = this.componentIdentifier(refName);
|
|
3772
|
+
this.convertWithCache(refName);
|
|
3773
|
+
return this.wrapLazyIfNeeded(refName, identifier);
|
|
3774
|
+
}
|
|
3775
|
+
if (schema.oneOf?.length) {
|
|
3776
|
+
const parts = schema.oneOf.map((item) => this.convert(item));
|
|
3777
|
+
return `z.union([${parts.join(", ")}])${schema.nullable ? ".nullable()" : ""}`;
|
|
3778
|
+
}
|
|
3779
|
+
if (schema.anyOf?.length) {
|
|
3780
|
+
const parts = schema.anyOf.map((item) => this.convert(item));
|
|
3781
|
+
return `z.union([${parts.join(", ")}])${schema.nullable ? ".nullable()" : ""}`;
|
|
3782
|
+
}
|
|
3783
|
+
if (schema.allOf?.length) {
|
|
3784
|
+
const [first, ...rest] = schema.allOf;
|
|
3785
|
+
let expr = this.convert(first);
|
|
3786
|
+
for (const part of rest) {
|
|
3787
|
+
expr = `z.intersection(${expr}, ${this.convert(part)})`;
|
|
3788
|
+
}
|
|
3789
|
+
return schema.nullable ? `${expr}.nullable()` : expr;
|
|
3790
|
+
}
|
|
3791
|
+
switch (schema.type) {
|
|
3792
|
+
case "string":
|
|
3793
|
+
if (schema.enum) {
|
|
3794
|
+
const values = schema.enum.map((v) => JSON.stringify(String(v)));
|
|
3795
|
+
return `z.enum([${values.join(", ")}])${schema.nullable ? ".nullable()" : ""}`;
|
|
3796
|
+
}
|
|
3797
|
+
return `z.string()${schema.nullable ? ".nullable()" : ""}`;
|
|
3798
|
+
case "number":
|
|
3799
|
+
case "integer": {
|
|
3800
|
+
let expr = "z.number()";
|
|
3801
|
+
if (schema.type === "integer") {
|
|
3802
|
+
expr = `${expr}.int()`;
|
|
3803
|
+
}
|
|
3804
|
+
if (schema.nullable) {
|
|
3805
|
+
expr = `${expr}.nullable()`;
|
|
3806
|
+
}
|
|
3807
|
+
return expr;
|
|
3808
|
+
}
|
|
3809
|
+
case "boolean":
|
|
3810
|
+
return `z.boolean()${schema.nullable ? ".nullable()" : ""}`;
|
|
3811
|
+
case "array": {
|
|
3812
|
+
const items = schema.items ? this.convert(schema.items) : "z.unknown()";
|
|
3813
|
+
return `z.array(${items})${schema.nullable ? ".nullable()" : ""}`;
|
|
3814
|
+
}
|
|
3815
|
+
case "object": {
|
|
3816
|
+
const properties = schema.properties ?? {};
|
|
3817
|
+
const required = new Set(schema.required ?? []);
|
|
3818
|
+
const entries = Object.entries(properties).map(([key, value]) => {
|
|
3819
|
+
const valueExpr = this.convert(value);
|
|
3820
|
+
return `${JSON.stringify(key)}: ${required.has(key) ? valueExpr : `${valueExpr}.optional()`}`;
|
|
3821
|
+
});
|
|
3822
|
+
let base = `z.object({${entries.length ? ` ${entries.join(", ")} ` : ""}})`;
|
|
3823
|
+
if (schema.additionalProperties) {
|
|
3824
|
+
const apValue = schema.additionalProperties === true ? "z.unknown()" : this.convert(schema.additionalProperties);
|
|
3825
|
+
base = `${base}.catchall(${apValue})`;
|
|
3826
|
+
}
|
|
3827
|
+
if (schema.nullable) {
|
|
3828
|
+
base = `${base}.nullable()`;
|
|
3829
|
+
}
|
|
3830
|
+
return base;
|
|
3831
|
+
}
|
|
3832
|
+
default:
|
|
3833
|
+
return "z.unknown()";
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
convertWithCache(name) {
|
|
3837
|
+
const identifier = this.componentIdentifier(name);
|
|
3838
|
+
if (this.generated.has(name)) {
|
|
3839
|
+
return this.generated.get(name);
|
|
3840
|
+
}
|
|
3841
|
+
if (this.inProgress.has(name)) {
|
|
3842
|
+
return `z.lazy(() => ${identifier})`;
|
|
3843
|
+
}
|
|
3844
|
+
const schema = this.components?.schemas?.[name];
|
|
3845
|
+
if (!schema) {
|
|
3846
|
+
return "z.unknown()";
|
|
3847
|
+
}
|
|
3848
|
+
this.inProgress.add(name);
|
|
3849
|
+
const expression = this.convert(schema);
|
|
3850
|
+
this.inProgress.delete(name);
|
|
3851
|
+
const finalized = expression.startsWith("z.lazy(") ? expression : expression;
|
|
3852
|
+
this.generated.set(name, finalized);
|
|
3853
|
+
return finalized;
|
|
3854
|
+
}
|
|
3855
|
+
componentIdentifier(name) {
|
|
3856
|
+
return `${this.prefix}${Casing.toPascalCase(name)}Schema`;
|
|
3857
|
+
}
|
|
3858
|
+
refName(ref) {
|
|
3859
|
+
const [, component] = ref.split("#/components/schemas/");
|
|
3860
|
+
if (!component) {
|
|
3861
|
+
return "UnknownSchema";
|
|
3862
|
+
}
|
|
3863
|
+
return component;
|
|
3864
|
+
}
|
|
3865
|
+
wrapLazyIfNeeded(name, identifier) {
|
|
3866
|
+
if (this.inProgress.has(name)) {
|
|
3867
|
+
return `z.lazy(() => ${identifier})`;
|
|
3868
|
+
}
|
|
3869
|
+
return identifier;
|
|
3870
|
+
}
|
|
3871
|
+
};
|
|
3872
|
+
function buildSchemasObject(doc, converter) {
|
|
3873
|
+
const pathEntries = [];
|
|
3874
|
+
const sortedPaths = Object.keys(doc.paths || {}).sort();
|
|
3875
|
+
for (const rawPath of sortedPaths) {
|
|
3876
|
+
const pathItem = doc.paths?.[rawPath];
|
|
3877
|
+
if (!pathItem) continue;
|
|
3878
|
+
const methodEntries = [];
|
|
3879
|
+
for (const method of SUPPORTED_METHODS) {
|
|
3880
|
+
const operation = pathItem[method];
|
|
3881
|
+
if (!operation) continue;
|
|
3882
|
+
const responses = buildResponses(operation.responses, converter);
|
|
3883
|
+
const requestBody = buildRequestBody(operation.requestBody, converter);
|
|
3884
|
+
const segments = [];
|
|
3885
|
+
if (requestBody) {
|
|
3886
|
+
segments.push(`request: ${requestBody}`);
|
|
3887
|
+
}
|
|
3888
|
+
segments.push(`responses: ${responses}`);
|
|
3889
|
+
const methodBlock = [
|
|
3890
|
+
`${method.toUpperCase()}: {`,
|
|
3891
|
+
indentLines(segments.join(",\n"), 2),
|
|
3892
|
+
"}"
|
|
3893
|
+
].join("\n");
|
|
3894
|
+
methodEntries.push(indentLines(methodBlock, 2));
|
|
3895
|
+
}
|
|
3896
|
+
if (!methodEntries.length) continue;
|
|
3897
|
+
const normalizedPath = normalizePath(rawPath);
|
|
3898
|
+
const pathBlock = [
|
|
3899
|
+
`${JSON.stringify(normalizedPath)}: {`,
|
|
3900
|
+
methodEntries.join(",\n"),
|
|
3901
|
+
"}"
|
|
3902
|
+
].join("\n");
|
|
3903
|
+
pathEntries.push(indentLines(pathBlock, 1));
|
|
3904
|
+
}
|
|
3905
|
+
return `{
|
|
3906
|
+
${pathEntries.join(",\n")}
|
|
3907
|
+
}`;
|
|
3908
|
+
}
|
|
3909
|
+
function buildResponses(responses, converter) {
|
|
3910
|
+
if (!responses || !Object.keys(responses).length) {
|
|
3911
|
+
return "{ }";
|
|
3912
|
+
}
|
|
3913
|
+
const entries = [];
|
|
3914
|
+
const sorted = Object.keys(responses).sort();
|
|
3915
|
+
for (const status of sorted) {
|
|
3916
|
+
const responseOrRef = responses[status];
|
|
3917
|
+
if (!responseOrRef) continue;
|
|
3918
|
+
const response = "$ref" in responseOrRef ? void 0 : responseOrRef;
|
|
3919
|
+
const schema = resolveSchemaFromResponse(response);
|
|
3920
|
+
const expression = schema ? converter.convert(schema) : "z.unknown()";
|
|
3921
|
+
entries.push(`${status}: ${expression}`);
|
|
3922
|
+
}
|
|
3923
|
+
if (!entries.length) {
|
|
3924
|
+
return "{ }";
|
|
3925
|
+
}
|
|
3926
|
+
return `{
|
|
3927
|
+
${indentLines(entries.join(",\n"), 2)}
|
|
3928
|
+
}`;
|
|
3929
|
+
}
|
|
3930
|
+
function buildRequestBody(requestBody, converter) {
|
|
3931
|
+
if (!requestBody) return null;
|
|
3932
|
+
const resolved = "$ref" in requestBody ? null : requestBody;
|
|
3933
|
+
if (!resolved?.content) return null;
|
|
3934
|
+
const schema = selectJsonSchema(resolved.content);
|
|
3935
|
+
if (!schema) return null;
|
|
3936
|
+
return converter.convert(schema);
|
|
3937
|
+
}
|
|
3938
|
+
function selectJsonSchema(content) {
|
|
3939
|
+
if (content["application/json"]?.schema) {
|
|
3940
|
+
return content["application/json"].schema;
|
|
3941
|
+
}
|
|
3942
|
+
const first = Object.values(content)[0];
|
|
3943
|
+
return first?.schema;
|
|
3944
|
+
}
|
|
3945
|
+
function resolveSchemaFromResponse(response) {
|
|
3946
|
+
if (!response?.content) {
|
|
3947
|
+
return void 0;
|
|
3948
|
+
}
|
|
3949
|
+
return selectJsonSchema(response.content);
|
|
3950
|
+
}
|
|
3951
|
+
function normalizePath(pathname) {
|
|
3952
|
+
return pathname.replace(/{(.*?)}/g, ":$1");
|
|
3953
|
+
}
|
|
3954
|
+
function indentLines(value, depth) {
|
|
3955
|
+
const pad = " ".repeat(depth);
|
|
3956
|
+
return value.split("\n").map((line) => line ? pad + line : line).join("\n");
|
|
3957
|
+
}
|
|
3958
|
+
|
|
3959
|
+
// src/commands/generate/caller/index.ts
|
|
3960
|
+
var callerCommand = new Command7().command("caller").description("Generate Igniter Caller schemas from an OpenAPI spec").option("--name <name>", "Name used to prefix generated schemas and caller export").option("--url <url>", "URL to the OpenAPI document").option("--path <path>", "Local path to the OpenAPI document").option(
|
|
3961
|
+
"--output <path>",
|
|
3962
|
+
"Output directory (defaults to src/callers/<hostname>)"
|
|
3963
|
+
).action(handleGenerateCallerAction);
|
|
3964
|
+
|
|
3546
3965
|
// src/commands/generate/index.ts
|
|
3547
|
-
var generateCommand = new
|
|
3966
|
+
var generateCommand = new Command8().command("generate").description("Scaffold new features or generate client schema").addCommand(featureCommand).addCommand(controllerCommand).addCommand(procedureCommand).addCommand(docsCommand).addCommand(schemaCommand).addCommand(callerCommand);
|
|
3548
3967
|
|
|
3549
3968
|
// src/commands/dev/index.ts
|
|
3550
|
-
import { Command as
|
|
3969
|
+
import { Command as Command9 } from "commander";
|
|
3551
3970
|
|
|
3552
3971
|
// src/commands/dev/action.ts
|
|
3553
|
-
import * as
|
|
3554
|
-
import * as
|
|
3972
|
+
import * as path24 from "path";
|
|
3973
|
+
import * as fs8 from "fs";
|
|
3555
3974
|
import { spawn as spawn2 } from "child_process";
|
|
3556
3975
|
import chokidar from "chokidar";
|
|
3557
3976
|
import { render } from "ink";
|
|
@@ -3586,14 +4005,14 @@ function DevUI({ igniterLogs, appLogs, onExit }) {
|
|
|
3586
4005
|
};
|
|
3587
4006
|
const renderLogs = (logs, maxLines = 50) => {
|
|
3588
4007
|
const visibleLogs = logs.slice(-maxLines);
|
|
3589
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleLogs.length === 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "No logs yet...") : visibleLogs.map((
|
|
4008
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleLogs.length === 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "No logs yet...") : visibleLogs.map((log12, index) => {
|
|
3590
4009
|
const color2 = {
|
|
3591
4010
|
info: "cyan",
|
|
3592
4011
|
success: "green",
|
|
3593
4012
|
error: "red",
|
|
3594
4013
|
warn: "yellow"
|
|
3595
|
-
}[
|
|
3596
|
-
return /* @__PURE__ */ React.createElement(Text, { key: `${
|
|
4014
|
+
}[log12.type];
|
|
4015
|
+
return /* @__PURE__ */ React.createElement(Text, { key: `${log12.timestamp.getTime()}-${index}`, color: color2 }, formatLogEntry(log12));
|
|
3597
4016
|
}));
|
|
3598
4017
|
};
|
|
3599
4018
|
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Igniter.js Development Mode")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(
|
|
@@ -3655,19 +4074,19 @@ async function regenerateSchemaAndDocs(routerPath, outputPath, docsOutputDir, ad
|
|
|
3655
4074
|
}
|
|
3656
4075
|
async function handleDevAction(options) {
|
|
3657
4076
|
const packageManager = detectPackageManager();
|
|
3658
|
-
const routerPath =
|
|
4077
|
+
const routerPath = path24.resolve(process.cwd(), options.router || "src/igniter.router.ts");
|
|
3659
4078
|
const outputPath = options.output || "src/igniter.schema.ts";
|
|
3660
4079
|
const docsOutputDir = options.docsOutput || "./src/docs";
|
|
3661
4080
|
const devCommand2 = options.cmd || getDefaultDevCommand(packageManager);
|
|
3662
|
-
if (!
|
|
4081
|
+
if (!fs8.existsSync(routerPath)) {
|
|
3663
4082
|
console.error(`Router file not found: ${routerPath}`);
|
|
3664
4083
|
process.exit(1);
|
|
3665
4084
|
}
|
|
3666
4085
|
const igniterLogs = [];
|
|
3667
4086
|
const appLogs = [];
|
|
3668
4087
|
let rerenderFn = null;
|
|
3669
|
-
const addIgniterLog = (
|
|
3670
|
-
igniterLogs.push(
|
|
4088
|
+
const addIgniterLog = (log12) => {
|
|
4089
|
+
igniterLogs.push(log12);
|
|
3671
4090
|
if (igniterLogs.length > 1e3) {
|
|
3672
4091
|
igniterLogs.shift();
|
|
3673
4092
|
}
|
|
@@ -3675,8 +4094,8 @@ async function handleDevAction(options) {
|
|
|
3675
4094
|
rerenderFn();
|
|
3676
4095
|
}
|
|
3677
4096
|
};
|
|
3678
|
-
const addAppLog = (
|
|
3679
|
-
appLogs.push(
|
|
4097
|
+
const addAppLog = (log12) => {
|
|
4098
|
+
appLogs.push(log12);
|
|
3680
4099
|
if (appLogs.length > 1e3) {
|
|
3681
4100
|
appLogs.shift();
|
|
3682
4101
|
}
|
|
@@ -3706,13 +4125,13 @@ async function handleDevAction(options) {
|
|
|
3706
4125
|
});
|
|
3707
4126
|
process.exit(1);
|
|
3708
4127
|
}
|
|
3709
|
-
const featuresDir =
|
|
4128
|
+
const featuresDir = path24.join(process.cwd(), "src", "features");
|
|
3710
4129
|
const watchPaths = [
|
|
3711
4130
|
routerPath,
|
|
3712
4131
|
// Watch router file directly
|
|
3713
4132
|
featuresDir
|
|
3714
4133
|
// Watch features directory recursively
|
|
3715
|
-
].filter((
|
|
4134
|
+
].filter((p14) => fs8.existsSync(p14));
|
|
3716
4135
|
if (watchPaths.length === 0) {
|
|
3717
4136
|
addIgniterLog({
|
|
3718
4137
|
type: "warn",
|
|
@@ -3723,7 +4142,7 @@ async function handleDevAction(options) {
|
|
|
3723
4142
|
}
|
|
3724
4143
|
addIgniterLog({
|
|
3725
4144
|
type: "info",
|
|
3726
|
-
message: `Watching for changes in: ${watchPaths.map((
|
|
4145
|
+
message: `Watching for changes in: ${watchPaths.map((p14) => path24.relative(process.cwd(), p14)).join(", ")}`,
|
|
3727
4146
|
timestamp: /* @__PURE__ */ new Date()
|
|
3728
4147
|
});
|
|
3729
4148
|
let regenerateTimeout = null;
|
|
@@ -3743,7 +4162,7 @@ async function handleDevAction(options) {
|
|
|
3743
4162
|
ignoreInitial: true
|
|
3744
4163
|
});
|
|
3745
4164
|
watcher.on("change", (filePath) => {
|
|
3746
|
-
const relativePath =
|
|
4165
|
+
const relativePath = path24.relative(process.cwd(), filePath);
|
|
3747
4166
|
if (regenerateTimeout) {
|
|
3748
4167
|
clearTimeout(regenerateTimeout);
|
|
3749
4168
|
}
|
|
@@ -3867,10 +4286,10 @@ async function handleDevAction(options) {
|
|
|
3867
4286
|
}
|
|
3868
4287
|
|
|
3869
4288
|
// src/commands/dev/index.ts
|
|
3870
|
-
var devCommand = new
|
|
4289
|
+
var devCommand = new Command9().command("dev").description("Start development mode with automatic schema and docs regeneration").option("--router <path>", "Path to the router file", "src/igniter.router.ts").option("--output <path>", "Output path for the schema file", "src/igniter.schema.ts").option("--docs-output <dir>", "Output directory for the OpenAPI spec", "./src/docs").option("--cmd <command>", "Custom command to start the development server").action(handleDevAction);
|
|
3871
4290
|
|
|
3872
4291
|
// src/index.ts
|
|
3873
|
-
var program = new
|
|
4292
|
+
var program = new Command10();
|
|
3874
4293
|
program.name("igniter").description("The next-generation command-line interface for Igniter.js").version("0.0.1");
|
|
3875
4294
|
program.addCommand(initCommand);
|
|
3876
4295
|
program.addCommand(generateCommand);
|