@soapjs/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/LICENSE +21 -0
- package/README.md +360 -0
- package/build/cli.d.ts +3 -0
- package/build/cli.js +50 -0
- package/build/commands/add/add.command.d.ts +2 -0
- package/build/commands/add/add.command.js +709 -0
- package/build/commands/add/command-plan.d.ts +15 -0
- package/build/commands/add/command-plan.js +182 -0
- package/build/commands/add/entity-plan.d.ts +7 -0
- package/build/commands/add/entity-plan.js +106 -0
- package/build/commands/add/event-plan.d.ts +8 -0
- package/build/commands/add/event-plan.js +59 -0
- package/build/commands/add/query-plan.d.ts +10 -0
- package/build/commands/add/query-plan.js +156 -0
- package/build/commands/add/repository-plan.d.ts +11 -0
- package/build/commands/add/repository-plan.js +252 -0
- package/build/commands/add/resource-plan.d.ts +52 -0
- package/build/commands/add/resource-plan.js +2031 -0
- package/build/commands/add/route-plan.d.ts +24 -0
- package/build/commands/add/route-plan.js +256 -0
- package/build/commands/add/socket-plan.d.ts +9 -0
- package/build/commands/add/socket-plan.js +81 -0
- package/build/commands/add/use-case-plan.d.ts +7 -0
- package/build/commands/add/use-case-plan.js +86 -0
- package/build/commands/check/check.command.d.ts +2 -0
- package/build/commands/check/check.command.js +113 -0
- package/build/commands/create/create.command.d.ts +2 -0
- package/build/commands/create/create.command.js +234 -0
- package/build/commands/create/project-plan.d.ts +44 -0
- package/build/commands/create/project-plan.js +1430 -0
- package/build/commands/doctor/doctor.command.d.ts +2 -0
- package/build/commands/doctor/doctor.command.js +38 -0
- package/build/commands/generate/bruno-analysis.d.ts +19 -0
- package/build/commands/generate/bruno-analysis.js +51 -0
- package/build/commands/generate/bruno-plan.d.ts +6 -0
- package/build/commands/generate/bruno-plan.js +326 -0
- package/build/commands/generate/generate.command.d.ts +2 -0
- package/build/commands/generate/generate.command.js +130 -0
- package/build/commands/info/info.command.d.ts +2 -0
- package/build/commands/info/info.command.js +26 -0
- package/build/commands/remove/remove.command.d.ts +2 -0
- package/build/commands/remove/remove.command.js +328 -0
- package/build/commands/shared/common-options.d.ts +10 -0
- package/build/commands/shared/common-options.js +23 -0
- package/build/commands/update/update.command.d.ts +2 -0
- package/build/commands/update/update.command.js +155 -0
- package/build/config/auth-policy.d.ts +4 -0
- package/build/config/auth-policy.js +54 -0
- package/build/config/find-soap-root.d.ts +1 -0
- package/build/config/find-soap-root.js +22 -0
- package/build/config/load-soap-config.d.ts +2 -0
- package/build/config/load-soap-config.js +30 -0
- package/build/config/schemas/types.d.ts +127 -0
- package/build/config/schemas/types.js +2 -0
- package/build/config/schemas/validation.d.ts +5 -0
- package/build/config/schemas/validation.js +130 -0
- package/build/config/soap-config.service.d.ts +4 -0
- package/build/config/soap-config.service.js +24 -0
- package/build/config/write-soap-config.d.ts +8 -0
- package/build/config/write-soap-config.js +25 -0
- package/build/core/command-context.d.ts +20 -0
- package/build/core/command-context.js +30 -0
- package/build/core/errors.d.ts +6 -0
- package/build/core/errors.js +23 -0
- package/build/core/output.d.ts +12 -0
- package/build/core/output.js +30 -0
- package/build/core/result.d.ts +9 -0
- package/build/core/result.js +11 -0
- package/build/dependencies/dependency-resolver.d.ts +6 -0
- package/build/dependencies/dependency-resolver.js +68 -0
- package/build/dependencies/package-manager.d.ts +7 -0
- package/build/dependencies/package-manager.js +54 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +9 -0
- package/build/io/conflict-policy.d.ts +10 -0
- package/build/io/conflict-policy.js +32 -0
- package/build/io/file-writer.d.ts +19 -0
- package/build/io/file-writer.js +65 -0
- package/build/io/format-file.d.ts +1 -0
- package/build/io/format-file.js +13 -0
- package/build/presets/create-presets.d.ts +4 -0
- package/build/presets/create-presets.js +97 -0
- package/build/presets/index.d.ts +2 -0
- package/build/presets/index.js +18 -0
- package/build/presets/preset.types.d.ts +6 -0
- package/build/presets/preset.types.js +2 -0
- package/build/prompts/add-resource.prompt.d.ts +13 -0
- package/build/prompts/add-resource.prompt.js +80 -0
- package/build/prompts/add-route.prompt.d.ts +16 -0
- package/build/prompts/add-route.prompt.js +140 -0
- package/build/prompts/create-project.prompt.d.ts +11 -0
- package/build/prompts/create-project.prompt.js +156 -0
- package/build/prompts/generate-bruno.prompt.d.ts +7 -0
- package/build/prompts/generate-bruno.prompt.js +21 -0
- package/build/prompts/index.d.ts +8 -0
- package/build/prompts/index.js +24 -0
- package/build/prompts/inquirer-prompt-adapter.d.ts +8 -0
- package/build/prompts/inquirer-prompt-adapter.js +52 -0
- package/build/prompts/mock-prompt-adapter.d.ts +13 -0
- package/build/prompts/mock-prompt-adapter.js +60 -0
- package/build/prompts/prompt-adapter.d.ts +7 -0
- package/build/prompts/prompt-adapter.js +2 -0
- package/build/prompts/prompt.types.d.ts +26 -0
- package/build/prompts/prompt.types.js +2 -0
- package/build/registry/registry.service.d.ts +19 -0
- package/build/registry/registry.service.js +68 -0
- package/build/resolvers/add-resource.resolver.d.ts +23 -0
- package/build/resolvers/add-resource.resolver.js +73 -0
- package/build/resolvers/add-route.resolver.d.ts +34 -0
- package/build/resolvers/add-route.resolver.js +83 -0
- package/build/resolvers/create-config.resolver.d.ts +32 -0
- package/build/resolvers/create-config.resolver.js +57 -0
- package/build/resolvers/generate-bruno.resolver.d.ts +17 -0
- package/build/resolvers/generate-bruno.resolver.js +23 -0
- package/build/resolvers/index.d.ts +5 -0
- package/build/resolvers/index.js +21 -0
- package/build/resolvers/resolver.types.d.ts +8 -0
- package/build/resolvers/resolver.types.js +2 -0
- package/build/summary/create-summary.d.ts +2 -0
- package/build/summary/create-summary.js +24 -0
- package/build/summary/index.d.ts +1 -0
- package/build/summary/index.js +17 -0
- package/build/templates/naming.d.ts +11 -0
- package/build/templates/naming.js +30 -0
- package/build/templates/template-context.d.ts +6 -0
- package/build/templates/template-context.js +2 -0
- package/build/templates/template-engine.d.ts +1 -0
- package/build/templates/template-engine.js +10 -0
- package/build/templates/template-resolver.d.ts +2 -0
- package/build/templates/template-resolver.js +17 -0
- package/build/terminal/terminal-capabilities.d.ts +6 -0
- package/build/terminal/terminal-capabilities.js +14 -0
- package/docs/adr/0001-soap-cli-project-aware-generator.md +108 -0
- package/docs/cli/add-resource.md +127 -0
- package/docs/cli/add-route.md +79 -0
- package/docs/cli/bruno.md +58 -0
- package/docs/cli/create.md +73 -0
- package/docs/cli/index.md +92 -0
- package/docs/cli/interactive-mode.md +61 -0
- package/docs/cli/remove.md +45 -0
- package/docs/guides/auth.md +90 -0
- package/docs/guides/cqrs-events-realtime.md +100 -0
- package/docs/guides/index.md +24 -0
- package/docs/guides/quality-and-safety.md +88 -0
- package/docs/guides/regular-api.md +119 -0
- package/docs/guides/storage.md +101 -0
- package/docs/plans/interactive-mode-plan.md +601 -0
- package/package.json +44 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.conflictPolicyHelp = exports.resolveConflictPolicy = exports.parseConflictPolicy = void 0;
|
|
4
|
+
const errors_1 = require("../core/errors");
|
|
5
|
+
const conflictPolicies = ["ask", "skip", "overwrite", "new", "abort"];
|
|
6
|
+
function parseConflictPolicy(value) {
|
|
7
|
+
if (!conflictPolicies.includes(value)) {
|
|
8
|
+
throw new errors_1.CliError(`Unsupported conflict policy "${value}". Allowed values: ${conflictPolicies.join(", ")}.`);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
exports.parseConflictPolicy = parseConflictPolicy;
|
|
13
|
+
function resolveConflictPolicy(options = {}) {
|
|
14
|
+
if (options.onConflict) {
|
|
15
|
+
return parseConflictPolicy(options.onConflict);
|
|
16
|
+
}
|
|
17
|
+
if (options.force) {
|
|
18
|
+
return "overwrite";
|
|
19
|
+
}
|
|
20
|
+
if (options.writeNew) {
|
|
21
|
+
return "new";
|
|
22
|
+
}
|
|
23
|
+
if (options.skipModified) {
|
|
24
|
+
return "skip";
|
|
25
|
+
}
|
|
26
|
+
return "abort";
|
|
27
|
+
}
|
|
28
|
+
exports.resolveConflictPolicy = resolveConflictPolicy;
|
|
29
|
+
function conflictPolicyHelp() {
|
|
30
|
+
return conflictPolicies.join(", ");
|
|
31
|
+
}
|
|
32
|
+
exports.conflictPolicyHelp = conflictPolicyHelp;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CommandContext } from "../core/command-context";
|
|
2
|
+
import { GeneratedFileType, SoapRegistryConfig } from "../config/schemas/types";
|
|
3
|
+
export interface PlannedFile {
|
|
4
|
+
path: string;
|
|
5
|
+
type: GeneratedFileType;
|
|
6
|
+
content: string;
|
|
7
|
+
owner?: string;
|
|
8
|
+
executable?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface WriteFilesOptions {
|
|
11
|
+
root: string;
|
|
12
|
+
files: PlannedFile[];
|
|
13
|
+
registry: SoapRegistryConfig;
|
|
14
|
+
force?: boolean;
|
|
15
|
+
writeNew?: boolean;
|
|
16
|
+
skipModified?: boolean;
|
|
17
|
+
onConflict?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function writePlannedFiles(options: WriteFilesOptions, context: CommandContext): Promise<void>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.writePlannedFiles = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const registry_service_1 = require("../registry/registry.service");
|
|
10
|
+
const errors_1 = require("../core/errors");
|
|
11
|
+
const conflict_policy_1 = require("./conflict-policy");
|
|
12
|
+
const format_file_1 = require("./format-file");
|
|
13
|
+
async function writePlannedFiles(options, context) {
|
|
14
|
+
const conflictPolicy = (0, conflict_policy_1.resolveConflictPolicy)(options);
|
|
15
|
+
for (const file of options.files) {
|
|
16
|
+
const formatted = (0, format_file_1.formatFile)(file.path, file.content);
|
|
17
|
+
let targetPath;
|
|
18
|
+
try {
|
|
19
|
+
targetPath = await (0, registry_service_1.assertCanWriteGeneratedFile)(options.root, file.path, options.registry, {
|
|
20
|
+
force: conflictPolicy === "overwrite",
|
|
21
|
+
writeNew: conflictPolicy === "new",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (conflictPolicy === "skip" && error instanceof errors_1.CliError) {
|
|
26
|
+
context.output.warn(`Skipped modified file ${file.path}. Use --force to overwrite or --write-new to write ${file.path}.new.`);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (conflictPolicy === "ask" && error instanceof errors_1.CliError) {
|
|
30
|
+
throw new errors_1.CliError(`Interactive conflict resolution is not available yet for ${file.path}. Use --on-conflict skip, overwrite, new, or abort.`);
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
const originalPath = path_1.default.join(options.root, file.path);
|
|
35
|
+
const writesOriginalPath = targetPath === originalPath;
|
|
36
|
+
if (context.dryRun) {
|
|
37
|
+
context.output.info(`[dry-run] write ${targetPath}`);
|
|
38
|
+
if (writesOriginalPath) {
|
|
39
|
+
await (0, registry_service_1.registerGeneratedFile)({
|
|
40
|
+
root: options.root,
|
|
41
|
+
relativePath: file.path,
|
|
42
|
+
type: file.type,
|
|
43
|
+
owner: file.owner,
|
|
44
|
+
registry: options.registry,
|
|
45
|
+
}, formatted, context);
|
|
46
|
+
}
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
await promises_1.default.mkdir(path_1.default.dirname(targetPath), { recursive: true });
|
|
50
|
+
await promises_1.default.writeFile(targetPath, formatted, "utf8");
|
|
51
|
+
if (file.executable) {
|
|
52
|
+
await promises_1.default.chmod(targetPath, 0o755);
|
|
53
|
+
}
|
|
54
|
+
if (writesOriginalPath) {
|
|
55
|
+
await (0, registry_service_1.registerGeneratedFile)({
|
|
56
|
+
root: options.root,
|
|
57
|
+
relativePath: file.path,
|
|
58
|
+
type: file.type,
|
|
59
|
+
owner: file.owner,
|
|
60
|
+
registry: options.registry,
|
|
61
|
+
}, formatted, context);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.writePlannedFiles = writePlannedFiles;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatFile(filePath: string, content: string): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatFile = void 0;
|
|
4
|
+
function formatFile(filePath, content) {
|
|
5
|
+
if (filePath.endsWith(".json")) {
|
|
6
|
+
return `${JSON.stringify(JSON.parse(content), null, 2)}\n`;
|
|
7
|
+
}
|
|
8
|
+
if (filePath.endsWith(".md") || filePath.endsWith(".ts") || filePath.endsWith(".js")) {
|
|
9
|
+
return content.endsWith("\n") ? content : `${content}\n`;
|
|
10
|
+
}
|
|
11
|
+
return content.endsWith("\n") ? content : `${content}\n`;
|
|
12
|
+
}
|
|
13
|
+
exports.formatFile = formatFile;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatCreatePresetNames = exports.resolveCreatePreset = exports.createPresets = void 0;
|
|
4
|
+
const errors_1 = require("../core/errors");
|
|
5
|
+
exports.createPresets = [
|
|
6
|
+
{
|
|
7
|
+
name: "express-mongo-api",
|
|
8
|
+
description: "Express API with MongoDB, JWT auth, OpenAPI docs, and Bruno requests.",
|
|
9
|
+
config: {
|
|
10
|
+
framework: "express",
|
|
11
|
+
architecture: "regular",
|
|
12
|
+
capabilities: {
|
|
13
|
+
databases: ["mongo"],
|
|
14
|
+
auth: ["jwt"],
|
|
15
|
+
messaging: ["in-memory"],
|
|
16
|
+
realtime: [],
|
|
17
|
+
telemetry: ["logs"],
|
|
18
|
+
docs: ["openapi"],
|
|
19
|
+
contracts: [],
|
|
20
|
+
apiClient: ["bruno"],
|
|
21
|
+
},
|
|
22
|
+
zones: ["public", "private", "admin"],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "express-postgres-api",
|
|
27
|
+
description: "Express API with PostgreSQL, JWT auth, OpenAPI docs, and Bruno requests.",
|
|
28
|
+
config: {
|
|
29
|
+
framework: "express",
|
|
30
|
+
architecture: "regular",
|
|
31
|
+
capabilities: {
|
|
32
|
+
databases: ["postgres"],
|
|
33
|
+
auth: ["jwt"],
|
|
34
|
+
messaging: ["in-memory"],
|
|
35
|
+
realtime: [],
|
|
36
|
+
telemetry: ["logs"],
|
|
37
|
+
docs: ["openapi"],
|
|
38
|
+
contracts: [],
|
|
39
|
+
apiClient: ["bruno"],
|
|
40
|
+
},
|
|
41
|
+
zones: ["public", "private", "admin"],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "express-cqrs-kafka-api",
|
|
46
|
+
description: "Express CQRS API with PostgreSQL, Kafka, JWT auth, OpenAPI docs, and Bruno requests.",
|
|
47
|
+
config: {
|
|
48
|
+
framework: "express",
|
|
49
|
+
architecture: "cqrs",
|
|
50
|
+
capabilities: {
|
|
51
|
+
databases: ["postgres"],
|
|
52
|
+
auth: ["jwt"],
|
|
53
|
+
messaging: ["kafka"],
|
|
54
|
+
realtime: [],
|
|
55
|
+
telemetry: ["logs"],
|
|
56
|
+
docs: ["openapi"],
|
|
57
|
+
contracts: [],
|
|
58
|
+
apiClient: ["bruno"],
|
|
59
|
+
},
|
|
60
|
+
zones: ["public", "private", "admin"],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "express-full-demo",
|
|
65
|
+
description: "Express demo API with MongoDB, PostgreSQL, JWT, API key, Kafka, WebSocket, OpenAPI, and Bruno.",
|
|
66
|
+
config: {
|
|
67
|
+
framework: "express",
|
|
68
|
+
architecture: "cqrs",
|
|
69
|
+
capabilities: {
|
|
70
|
+
databases: ["mongo", "postgres"],
|
|
71
|
+
auth: ["jwt", "api-key"],
|
|
72
|
+
messaging: ["kafka"],
|
|
73
|
+
realtime: ["ws"],
|
|
74
|
+
telemetry: ["logs", "otel-noop"],
|
|
75
|
+
docs: ["openapi"],
|
|
76
|
+
contracts: [],
|
|
77
|
+
apiClient: ["bruno"],
|
|
78
|
+
},
|
|
79
|
+
zones: ["public", "private", "admin"],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
function resolveCreatePreset(name) {
|
|
84
|
+
if (!name) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const preset = exports.createPresets.find((candidate) => candidate.name === name);
|
|
88
|
+
if (!preset) {
|
|
89
|
+
throw new errors_1.CliError(`Unknown create preset "${name}". Available presets: ${formatCreatePresetNames()}.`);
|
|
90
|
+
}
|
|
91
|
+
return preset;
|
|
92
|
+
}
|
|
93
|
+
exports.resolveCreatePreset = resolveCreatePreset;
|
|
94
|
+
function formatCreatePresetNames() {
|
|
95
|
+
return exports.createPresets.map((preset) => preset.name).join(", ");
|
|
96
|
+
}
|
|
97
|
+
exports.formatCreatePresetNames = formatCreatePresetNames;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./create-presets"), exports);
|
|
18
|
+
__exportStar(require("./preset.types"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SoapConfig } from "../config/schemas/types";
|
|
2
|
+
import { AddResourceInput } from "../resolvers/add-resource.resolver";
|
|
3
|
+
import { PromptAdapter } from "./prompt-adapter";
|
|
4
|
+
export interface AddResourcePromptAnswers extends AddResourceInput {
|
|
5
|
+
bruno?: boolean;
|
|
6
|
+
enableBruno?: boolean;
|
|
7
|
+
dryRunFirst?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AddResourcePromptOptions {
|
|
10
|
+
config: SoapConfig;
|
|
11
|
+
provided: Partial<Record<keyof AddResourcePromptAnswers, boolean>>;
|
|
12
|
+
}
|
|
13
|
+
export declare function promptAddResource(prompt: PromptAdapter, options: AddResourcePromptOptions): Promise<AddResourcePromptAnswers>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptAddResource = void 0;
|
|
4
|
+
async function promptAddResource(prompt, options) {
|
|
5
|
+
const answers = {};
|
|
6
|
+
const config = options.config;
|
|
7
|
+
if (!options.provided.crud) {
|
|
8
|
+
answers.crud = await prompt.confirm({
|
|
9
|
+
message: "Generate CRUD routes",
|
|
10
|
+
defaultValue: true,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
if (!options.provided.db) {
|
|
14
|
+
answers.db = await prompt.select({
|
|
15
|
+
message: "Storage",
|
|
16
|
+
choices: createDatabaseChoices(config),
|
|
17
|
+
defaultValue: config.project.capabilities.databases[0] ?? "none",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (!options.provided.auth) {
|
|
21
|
+
answers.auth = await prompt.select({
|
|
22
|
+
message: "Route auth",
|
|
23
|
+
choices: createAuthChoices(config),
|
|
24
|
+
defaultValue: defaultRouteAuth(config.project.capabilities.auth),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (!options.provided.zone) {
|
|
28
|
+
answers.zone = await prompt.select({
|
|
29
|
+
message: "API zone",
|
|
30
|
+
choices: config.project.zones.map((zone) => ({ label: zone, value: zone })),
|
|
31
|
+
defaultValue: config.project.zones.includes("public") ? "public" : config.project.zones[0],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const brunoEnabled = config.project.capabilities.apiClient.includes("bruno") || config.api.bruno.enabled;
|
|
35
|
+
if (brunoEnabled && !options.provided.bruno) {
|
|
36
|
+
answers.bruno = await prompt.confirm({
|
|
37
|
+
message: "Generate Bruno requests",
|
|
38
|
+
defaultValue: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (!brunoEnabled && !options.provided.enableBruno) {
|
|
42
|
+
answers.enableBruno = await prompt.confirm({
|
|
43
|
+
message: "Enable Bruno now",
|
|
44
|
+
defaultValue: false,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (!options.provided.dryRunFirst) {
|
|
48
|
+
answers.dryRunFirst = await prompt.confirm({
|
|
49
|
+
message: "Run as dry-run first",
|
|
50
|
+
defaultValue: false,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return answers;
|
|
54
|
+
}
|
|
55
|
+
exports.promptAddResource = promptAddResource;
|
|
56
|
+
function createDatabaseChoices(config) {
|
|
57
|
+
return [
|
|
58
|
+
{ label: "None", value: "none" },
|
|
59
|
+
...config.project.capabilities.databases.map((database) => ({ label: database, value: database })),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
function createAuthChoices(config) {
|
|
63
|
+
const choices = [{ label: "None", value: "none" }];
|
|
64
|
+
if (config.project.capabilities.auth.includes("jwt") || config.project.capabilities.auth.includes("local")) {
|
|
65
|
+
choices.push({ label: "JWT", value: "jwt" });
|
|
66
|
+
}
|
|
67
|
+
if (config.project.capabilities.auth.includes("api-key")) {
|
|
68
|
+
choices.push({ label: "API key", value: "api-key" });
|
|
69
|
+
}
|
|
70
|
+
return choices;
|
|
71
|
+
}
|
|
72
|
+
function defaultRouteAuth(values) {
|
|
73
|
+
if (values.includes("jwt") || values.includes("local")) {
|
|
74
|
+
return "jwt";
|
|
75
|
+
}
|
|
76
|
+
if (values.includes("api-key")) {
|
|
77
|
+
return "api-key";
|
|
78
|
+
}
|
|
79
|
+
return "none";
|
|
80
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ResourceRegistryEntry, SoapConfig } from "../config/schemas/types";
|
|
2
|
+
import { AddRouteInput } from "../resolvers/add-route.resolver";
|
|
3
|
+
import { PromptAdapter } from "./prompt-adapter";
|
|
4
|
+
export interface AddRoutePromptAnswers extends AddRouteInput {
|
|
5
|
+
resourceName?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
bruno?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AddRoutePromptOptions {
|
|
10
|
+
config: SoapConfig;
|
|
11
|
+
resource?: ResourceRegistryEntry;
|
|
12
|
+
resourceName?: string;
|
|
13
|
+
routeName?: string;
|
|
14
|
+
provided: Partial<Record<keyof AddRoutePromptAnswers, boolean>>;
|
|
15
|
+
}
|
|
16
|
+
export declare function promptAddRoute(prompt: PromptAdapter, options: AddRoutePromptOptions): Promise<AddRoutePromptAnswers>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptAddRoute = void 0;
|
|
4
|
+
const route_plan_1 = require("../commands/add/route-plan");
|
|
5
|
+
const naming_1 = require("../templates/naming");
|
|
6
|
+
async function promptAddRoute(prompt, options) {
|
|
7
|
+
const answers = {};
|
|
8
|
+
const config = options.config;
|
|
9
|
+
const resource = options.resource ?? await promptForResource(prompt, config, options.provided.resourceName);
|
|
10
|
+
const routeName = options.routeName ?? await promptForRouteName(prompt, options.provided.name);
|
|
11
|
+
if (!options.resourceName) {
|
|
12
|
+
answers.resourceName = resource.name;
|
|
13
|
+
}
|
|
14
|
+
if (!options.routeName) {
|
|
15
|
+
answers.name = routeName;
|
|
16
|
+
}
|
|
17
|
+
if (!options.provided.method) {
|
|
18
|
+
answers.method = await prompt.select({
|
|
19
|
+
message: "HTTP method",
|
|
20
|
+
choices: route_plan_1.routeMethods.map((method) => ({ label: method.toUpperCase(), value: method })),
|
|
21
|
+
defaultValue: "get",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (!options.provided.path) {
|
|
25
|
+
answers.path = await prompt.input({
|
|
26
|
+
message: "Route path",
|
|
27
|
+
defaultValue: (0, naming_1.createNameVariants)(routeName).kebabName,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (!options.provided.zone) {
|
|
31
|
+
answers.zone = await prompt.select({
|
|
32
|
+
message: "API zone",
|
|
33
|
+
choices: config.project.zones.map((zone) => ({ label: zone, value: zone })),
|
|
34
|
+
defaultValue: resource.zone,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (!options.provided.auth) {
|
|
38
|
+
answers.auth = await prompt.select({
|
|
39
|
+
message: "Route auth",
|
|
40
|
+
choices: createAuthChoices(config),
|
|
41
|
+
defaultValue: defaultRouteAuth(resource.auth, config.project.capabilities.auth),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (!options.provided.useCase && !options.provided.command && !options.provided.query) {
|
|
45
|
+
const target = await prompt.select({
|
|
46
|
+
message: "Route target",
|
|
47
|
+
choices: createTargetChoices(config),
|
|
48
|
+
defaultValue: "direct",
|
|
49
|
+
});
|
|
50
|
+
if (target === "use-case") {
|
|
51
|
+
answers.useCase = await prompt.input({
|
|
52
|
+
message: "Use case name",
|
|
53
|
+
defaultValue: routeName,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (target === "command") {
|
|
57
|
+
answers.command = await prompt.input({
|
|
58
|
+
message: "Command name",
|
|
59
|
+
defaultValue: routeName,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (target === "query") {
|
|
63
|
+
answers.query = await prompt.input({
|
|
64
|
+
message: "Query name",
|
|
65
|
+
defaultValue: routeName,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const brunoEnabled = config.project.capabilities.apiClient.includes("bruno") || config.api.bruno.enabled;
|
|
70
|
+
if (brunoEnabled && !options.provided.bruno) {
|
|
71
|
+
answers.bruno = await prompt.confirm({
|
|
72
|
+
message: "Generate Bruno request",
|
|
73
|
+
defaultValue: true,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return answers;
|
|
77
|
+
}
|
|
78
|
+
exports.promptAddRoute = promptAddRoute;
|
|
79
|
+
async function promptForResource(prompt, config, provided) {
|
|
80
|
+
if (provided) {
|
|
81
|
+
throw new Error("Resource was marked as provided but no resource entry was passed.");
|
|
82
|
+
}
|
|
83
|
+
const value = await prompt.select({
|
|
84
|
+
message: "Resource",
|
|
85
|
+
choices: config.registry.resources.map((resource) => ({
|
|
86
|
+
label: `${resource.name} (${resource.path})`,
|
|
87
|
+
value: resource.name,
|
|
88
|
+
})),
|
|
89
|
+
});
|
|
90
|
+
const resource = config.registry.resources.find((entry) => entry.name === value);
|
|
91
|
+
if (!resource) {
|
|
92
|
+
throw new Error(`Selected resource "${value}" was not found.`);
|
|
93
|
+
}
|
|
94
|
+
return resource;
|
|
95
|
+
}
|
|
96
|
+
async function promptForRouteName(prompt, provided) {
|
|
97
|
+
if (provided) {
|
|
98
|
+
throw new Error("Route name was marked as provided but no route name was passed.");
|
|
99
|
+
}
|
|
100
|
+
return prompt.input({
|
|
101
|
+
message: "Route name",
|
|
102
|
+
required: true,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function createAuthChoices(config) {
|
|
106
|
+
const choices = [{ label: "None", value: "none" }];
|
|
107
|
+
if (config.project.capabilities.auth.includes("jwt") || config.project.capabilities.auth.includes("local")) {
|
|
108
|
+
choices.push({ label: "JWT", value: "jwt" });
|
|
109
|
+
}
|
|
110
|
+
if (config.project.capabilities.auth.includes("api-key")) {
|
|
111
|
+
choices.push({ label: "API key", value: "api-key" });
|
|
112
|
+
}
|
|
113
|
+
return choices;
|
|
114
|
+
}
|
|
115
|
+
function defaultRouteAuth(resourceAuth, projectAuth) {
|
|
116
|
+
if (resourceAuth === "local" || resourceAuth === "jwt") {
|
|
117
|
+
return "jwt";
|
|
118
|
+
}
|
|
119
|
+
if (resourceAuth === "api-key") {
|
|
120
|
+
return "api-key";
|
|
121
|
+
}
|
|
122
|
+
if (projectAuth.includes("jwt") || projectAuth.includes("local")) {
|
|
123
|
+
return "jwt";
|
|
124
|
+
}
|
|
125
|
+
if (projectAuth.includes("api-key")) {
|
|
126
|
+
return "api-key";
|
|
127
|
+
}
|
|
128
|
+
return "none";
|
|
129
|
+
}
|
|
130
|
+
function createTargetChoices(config) {
|
|
131
|
+
const choices = [
|
|
132
|
+
{ label: "Direct controller", value: "direct" },
|
|
133
|
+
{ label: "Use case", value: "use-case" },
|
|
134
|
+
];
|
|
135
|
+
if (config.project.architecture === "cqrs") {
|
|
136
|
+
choices.push({ label: "CQRS command", value: "command" });
|
|
137
|
+
choices.push({ label: "CQRS query", value: "query" });
|
|
138
|
+
}
|
|
139
|
+
return choices;
|
|
140
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PromptAdapter } from "./prompt-adapter";
|
|
2
|
+
import { CreateConfigInput, CreateConfigResult } from "../resolvers/create-config.resolver";
|
|
3
|
+
export interface CreateProjectPromptAnswers extends CreateConfigInput {
|
|
4
|
+
install?: boolean;
|
|
5
|
+
gitInit?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface CreateProjectPromptOptions {
|
|
8
|
+
provided: Partial<Record<keyof CreateProjectPromptAnswers, boolean>>;
|
|
9
|
+
preset?: Partial<CreateConfigResult>;
|
|
10
|
+
}
|
|
11
|
+
export declare function promptCreateProject(prompt: PromptAdapter, options: CreateProjectPromptOptions): Promise<CreateProjectPromptAnswers>;
|