@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.
Files changed (149) hide show
  1. package/.nvmrc +1 -0
  2. package/LICENSE +21 -0
  3. package/README.md +360 -0
  4. package/build/cli.d.ts +3 -0
  5. package/build/cli.js +50 -0
  6. package/build/commands/add/add.command.d.ts +2 -0
  7. package/build/commands/add/add.command.js +709 -0
  8. package/build/commands/add/command-plan.d.ts +15 -0
  9. package/build/commands/add/command-plan.js +182 -0
  10. package/build/commands/add/entity-plan.d.ts +7 -0
  11. package/build/commands/add/entity-plan.js +106 -0
  12. package/build/commands/add/event-plan.d.ts +8 -0
  13. package/build/commands/add/event-plan.js +59 -0
  14. package/build/commands/add/query-plan.d.ts +10 -0
  15. package/build/commands/add/query-plan.js +156 -0
  16. package/build/commands/add/repository-plan.d.ts +11 -0
  17. package/build/commands/add/repository-plan.js +252 -0
  18. package/build/commands/add/resource-plan.d.ts +52 -0
  19. package/build/commands/add/resource-plan.js +2031 -0
  20. package/build/commands/add/route-plan.d.ts +24 -0
  21. package/build/commands/add/route-plan.js +256 -0
  22. package/build/commands/add/socket-plan.d.ts +9 -0
  23. package/build/commands/add/socket-plan.js +81 -0
  24. package/build/commands/add/use-case-plan.d.ts +7 -0
  25. package/build/commands/add/use-case-plan.js +86 -0
  26. package/build/commands/check/check.command.d.ts +2 -0
  27. package/build/commands/check/check.command.js +113 -0
  28. package/build/commands/create/create.command.d.ts +2 -0
  29. package/build/commands/create/create.command.js +234 -0
  30. package/build/commands/create/project-plan.d.ts +44 -0
  31. package/build/commands/create/project-plan.js +1430 -0
  32. package/build/commands/doctor/doctor.command.d.ts +2 -0
  33. package/build/commands/doctor/doctor.command.js +38 -0
  34. package/build/commands/generate/bruno-analysis.d.ts +19 -0
  35. package/build/commands/generate/bruno-analysis.js +51 -0
  36. package/build/commands/generate/bruno-plan.d.ts +6 -0
  37. package/build/commands/generate/bruno-plan.js +326 -0
  38. package/build/commands/generate/generate.command.d.ts +2 -0
  39. package/build/commands/generate/generate.command.js +130 -0
  40. package/build/commands/info/info.command.d.ts +2 -0
  41. package/build/commands/info/info.command.js +26 -0
  42. package/build/commands/remove/remove.command.d.ts +2 -0
  43. package/build/commands/remove/remove.command.js +328 -0
  44. package/build/commands/shared/common-options.d.ts +10 -0
  45. package/build/commands/shared/common-options.js +23 -0
  46. package/build/commands/update/update.command.d.ts +2 -0
  47. package/build/commands/update/update.command.js +155 -0
  48. package/build/config/auth-policy.d.ts +4 -0
  49. package/build/config/auth-policy.js +54 -0
  50. package/build/config/find-soap-root.d.ts +1 -0
  51. package/build/config/find-soap-root.js +22 -0
  52. package/build/config/load-soap-config.d.ts +2 -0
  53. package/build/config/load-soap-config.js +30 -0
  54. package/build/config/schemas/types.d.ts +127 -0
  55. package/build/config/schemas/types.js +2 -0
  56. package/build/config/schemas/validation.d.ts +5 -0
  57. package/build/config/schemas/validation.js +130 -0
  58. package/build/config/soap-config.service.d.ts +4 -0
  59. package/build/config/soap-config.service.js +24 -0
  60. package/build/config/write-soap-config.d.ts +8 -0
  61. package/build/config/write-soap-config.js +25 -0
  62. package/build/core/command-context.d.ts +20 -0
  63. package/build/core/command-context.js +30 -0
  64. package/build/core/errors.d.ts +6 -0
  65. package/build/core/errors.js +23 -0
  66. package/build/core/output.d.ts +12 -0
  67. package/build/core/output.js +30 -0
  68. package/build/core/result.d.ts +9 -0
  69. package/build/core/result.js +11 -0
  70. package/build/dependencies/dependency-resolver.d.ts +6 -0
  71. package/build/dependencies/dependency-resolver.js +68 -0
  72. package/build/dependencies/package-manager.d.ts +7 -0
  73. package/build/dependencies/package-manager.js +54 -0
  74. package/build/index.d.ts +2 -0
  75. package/build/index.js +9 -0
  76. package/build/io/conflict-policy.d.ts +10 -0
  77. package/build/io/conflict-policy.js +32 -0
  78. package/build/io/file-writer.d.ts +19 -0
  79. package/build/io/file-writer.js +65 -0
  80. package/build/io/format-file.d.ts +1 -0
  81. package/build/io/format-file.js +13 -0
  82. package/build/presets/create-presets.d.ts +4 -0
  83. package/build/presets/create-presets.js +97 -0
  84. package/build/presets/index.d.ts +2 -0
  85. package/build/presets/index.js +18 -0
  86. package/build/presets/preset.types.d.ts +6 -0
  87. package/build/presets/preset.types.js +2 -0
  88. package/build/prompts/add-resource.prompt.d.ts +13 -0
  89. package/build/prompts/add-resource.prompt.js +80 -0
  90. package/build/prompts/add-route.prompt.d.ts +16 -0
  91. package/build/prompts/add-route.prompt.js +140 -0
  92. package/build/prompts/create-project.prompt.d.ts +11 -0
  93. package/build/prompts/create-project.prompt.js +156 -0
  94. package/build/prompts/generate-bruno.prompt.d.ts +7 -0
  95. package/build/prompts/generate-bruno.prompt.js +21 -0
  96. package/build/prompts/index.d.ts +8 -0
  97. package/build/prompts/index.js +24 -0
  98. package/build/prompts/inquirer-prompt-adapter.d.ts +8 -0
  99. package/build/prompts/inquirer-prompt-adapter.js +52 -0
  100. package/build/prompts/mock-prompt-adapter.d.ts +13 -0
  101. package/build/prompts/mock-prompt-adapter.js +60 -0
  102. package/build/prompts/prompt-adapter.d.ts +7 -0
  103. package/build/prompts/prompt-adapter.js +2 -0
  104. package/build/prompts/prompt.types.d.ts +26 -0
  105. package/build/prompts/prompt.types.js +2 -0
  106. package/build/registry/registry.service.d.ts +19 -0
  107. package/build/registry/registry.service.js +68 -0
  108. package/build/resolvers/add-resource.resolver.d.ts +23 -0
  109. package/build/resolvers/add-resource.resolver.js +73 -0
  110. package/build/resolvers/add-route.resolver.d.ts +34 -0
  111. package/build/resolvers/add-route.resolver.js +83 -0
  112. package/build/resolvers/create-config.resolver.d.ts +32 -0
  113. package/build/resolvers/create-config.resolver.js +57 -0
  114. package/build/resolvers/generate-bruno.resolver.d.ts +17 -0
  115. package/build/resolvers/generate-bruno.resolver.js +23 -0
  116. package/build/resolvers/index.d.ts +5 -0
  117. package/build/resolvers/index.js +21 -0
  118. package/build/resolvers/resolver.types.d.ts +8 -0
  119. package/build/resolvers/resolver.types.js +2 -0
  120. package/build/summary/create-summary.d.ts +2 -0
  121. package/build/summary/create-summary.js +24 -0
  122. package/build/summary/index.d.ts +1 -0
  123. package/build/summary/index.js +17 -0
  124. package/build/templates/naming.d.ts +11 -0
  125. package/build/templates/naming.js +30 -0
  126. package/build/templates/template-context.d.ts +6 -0
  127. package/build/templates/template-context.js +2 -0
  128. package/build/templates/template-engine.d.ts +1 -0
  129. package/build/templates/template-engine.js +10 -0
  130. package/build/templates/template-resolver.d.ts +2 -0
  131. package/build/templates/template-resolver.js +17 -0
  132. package/build/terminal/terminal-capabilities.d.ts +6 -0
  133. package/build/terminal/terminal-capabilities.js +14 -0
  134. package/docs/adr/0001-soap-cli-project-aware-generator.md +108 -0
  135. package/docs/cli/add-resource.md +127 -0
  136. package/docs/cli/add-route.md +79 -0
  137. package/docs/cli/bruno.md +58 -0
  138. package/docs/cli/create.md +73 -0
  139. package/docs/cli/index.md +92 -0
  140. package/docs/cli/interactive-mode.md +61 -0
  141. package/docs/cli/remove.md +45 -0
  142. package/docs/guides/auth.md +90 -0
  143. package/docs/guides/cqrs-events-realtime.md +100 -0
  144. package/docs/guides/index.md +24 -0
  145. package/docs/guides/quality-and-safety.md +88 -0
  146. package/docs/guides/regular-api.md +119 -0
  147. package/docs/guides/storage.md +101 -0
  148. package/docs/plans/interactive-mode-plan.md +601 -0
  149. package/package.json +44 -0
@@ -0,0 +1,127 @@
1
+ import { PackageManager } from "../../core/command-context";
2
+ export type Framework = "express";
3
+ export type Architecture = "regular" | "cqrs";
4
+ export type Language = "typescript";
5
+ export type DatabaseCapability = "mongo" | "postgres" | "mysql" | "sqlite" | "redis";
6
+ export type AuthCapability = "jwt" | "api-key" | "local";
7
+ export type MessagingCapability = "in-memory" | "kafka";
8
+ export type RealtimeCapability = "ws";
9
+ export type TelemetryCapability = "logs" | "otel-noop";
10
+ export type ApiClientCapability = "bruno";
11
+ export type DocsCapability = "openapi";
12
+ export type ContractsCapability = "zod";
13
+ export type ApiZone = "public" | "private" | "admin";
14
+ export type ResourceFieldType = "string" | "number" | "boolean" | "date";
15
+ export interface ResourceFieldDefinition {
16
+ name: string;
17
+ type: ResourceFieldType;
18
+ required: boolean;
19
+ }
20
+ export type AuthPolicy = {
21
+ type: "admin";
22
+ } | {
23
+ type: "roles";
24
+ roles: string[];
25
+ } | {
26
+ type: "custom";
27
+ name: string;
28
+ };
29
+ export interface ProjectCapabilities {
30
+ databases: DatabaseCapability[];
31
+ auth: AuthCapability[];
32
+ messaging: MessagingCapability[];
33
+ realtime: RealtimeCapability[];
34
+ telemetry: TelemetryCapability[];
35
+ apiClient: ApiClientCapability[];
36
+ docs: DocsCapability[];
37
+ contracts: ContractsCapability[];
38
+ }
39
+ export interface SoapProjectConfig {
40
+ schemaVersion: 1;
41
+ name: string;
42
+ framework: Framework;
43
+ architecture: Architecture;
44
+ language: Language;
45
+ packageManager: PackageManager;
46
+ capabilities: ProjectCapabilities;
47
+ zones: ApiZone[];
48
+ }
49
+ export interface SoapStructureConfig {
50
+ featuresRoot: string;
51
+ commonRoot: string;
52
+ configRoot: string;
53
+ paths: {
54
+ domain: string;
55
+ application: string;
56
+ ports: string;
57
+ useCases: string;
58
+ commands: string;
59
+ queries: string;
60
+ data: string;
61
+ api: string;
62
+ contracts: string;
63
+ sockets: string;
64
+ };
65
+ }
66
+ export interface SoapApiConfig {
67
+ baseUrl: string;
68
+ health: {
69
+ method: "GET";
70
+ path: string;
71
+ };
72
+ auth: {
73
+ default: "none" | AuthCapability;
74
+ loginRoute?: {
75
+ method: "POST";
76
+ path: string;
77
+ tokenVariable: string;
78
+ };
79
+ };
80
+ bruno: {
81
+ enabled: boolean;
82
+ collectionPath: string;
83
+ environment: string;
84
+ };
85
+ }
86
+ export type GeneratedFileType = "project" | "resource" | "entity" | "use-case" | "repository" | "route" | "bruno" | "docker" | "config";
87
+ export interface GeneratedFileEntry {
88
+ path: string;
89
+ type: GeneratedFileType;
90
+ owner?: string;
91
+ hash: string;
92
+ generatedAt: string;
93
+ }
94
+ export interface ResourceRegistryEntry {
95
+ name: string;
96
+ path: string;
97
+ crud: boolean;
98
+ db: "none" | DatabaseCapability;
99
+ auth: "none" | AuthCapability;
100
+ zone: ApiZone;
101
+ fields: ResourceFieldDefinition[];
102
+ policy?: AuthPolicy;
103
+ generatedAt: string;
104
+ }
105
+ export interface RouteRegistryEntry {
106
+ resource: string;
107
+ name: string;
108
+ method: string;
109
+ path: string;
110
+ auth: "none" | AuthCapability;
111
+ zone: ApiZone;
112
+ policy?: AuthPolicy;
113
+ bruno?: boolean;
114
+ generatedAt: string;
115
+ }
116
+ export interface SoapRegistryConfig {
117
+ resources: ResourceRegistryEntry[];
118
+ routes: RouteRegistryEntry[];
119
+ generatedFiles: GeneratedFileEntry[];
120
+ }
121
+ export interface SoapConfig {
122
+ root: string;
123
+ project: SoapProjectConfig;
124
+ structure: SoapStructureConfig;
125
+ api: SoapApiConfig;
126
+ registry: SoapRegistryConfig;
127
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import { SoapApiConfig, SoapProjectConfig, SoapRegistryConfig, SoapStructureConfig } from "./types";
2
+ export declare function validateProjectConfig(value: unknown): SoapProjectConfig;
3
+ export declare function validateStructureConfig(value: unknown): SoapStructureConfig;
4
+ export declare function validateApiConfig(value: unknown): SoapApiConfig;
5
+ export declare function validateRegistryConfig(value: unknown): SoapRegistryConfig;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateRegistryConfig = exports.validateApiConfig = exports.validateStructureConfig = exports.validateProjectConfig = void 0;
4
+ const errors_1 = require("../../core/errors");
5
+ const frameworks = ["express"];
6
+ const architectures = ["regular", "cqrs"];
7
+ const packageManagers = ["npm", "pnpm", "yarn", "bun"];
8
+ const databases = ["mongo", "postgres", "mysql", "sqlite", "redis"];
9
+ const auth = ["jwt", "api-key", "local"];
10
+ const messaging = ["in-memory", "kafka"];
11
+ const realtime = ["ws"];
12
+ const telemetry = ["logs", "otel-noop"];
13
+ const apiClients = ["bruno"];
14
+ const docs = ["openapi"];
15
+ const contracts = ["zod"];
16
+ const zones = ["public", "private", "admin"];
17
+ function assertObject(value, label) {
18
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
19
+ throw new errors_1.CliError(`${label} must be an object.`);
20
+ }
21
+ }
22
+ function assertString(value, label) {
23
+ if (typeof value !== "string" || value.trim() === "") {
24
+ throw new errors_1.CliError(`${label} must be a non-empty string.`);
25
+ }
26
+ }
27
+ function assertArrayOf(value, label, allowed) {
28
+ if (!Array.isArray(value)) {
29
+ throw new errors_1.CliError(`${label} must be an array.`);
30
+ }
31
+ const invalid = value.find((item) => typeof item !== "string" || !allowed.includes(item));
32
+ if (invalid) {
33
+ throw new errors_1.CliError(`${label} contains unsupported value "${String(invalid)}".`);
34
+ }
35
+ }
36
+ function assertOneOf(value, label, allowed) {
37
+ if (typeof value !== "string" || !allowed.includes(value)) {
38
+ throw new errors_1.CliError(`${label} must be one of: ${allowed.join(", ")}.`);
39
+ }
40
+ }
41
+ function validateProjectConfig(value) {
42
+ assertObject(value, ".soap/project.json");
43
+ if (value.schemaVersion !== 1) {
44
+ throw new errors_1.CliError(".soap/project.json schemaVersion must be 1.");
45
+ }
46
+ assertString(value.name, "project.name");
47
+ assertOneOf(value.framework, "project.framework", frameworks);
48
+ assertOneOf(value.architecture, "project.architecture", architectures);
49
+ if (value.language !== "typescript") {
50
+ throw new errors_1.CliError("project.language must be typescript.");
51
+ }
52
+ assertOneOf(value.packageManager, "project.packageManager", packageManagers);
53
+ assertObject(value.capabilities, "project.capabilities");
54
+ assertArrayOf(value.capabilities.databases, "project.capabilities.databases", databases);
55
+ assertArrayOf(value.capabilities.auth, "project.capabilities.auth", auth);
56
+ assertArrayOf(value.capabilities.messaging, "project.capabilities.messaging", messaging);
57
+ assertArrayOf(value.capabilities.realtime, "project.capabilities.realtime", realtime);
58
+ assertArrayOf(value.capabilities.telemetry, "project.capabilities.telemetry", telemetry);
59
+ assertArrayOf(value.capabilities.apiClient, "project.capabilities.apiClient", apiClients);
60
+ assertArrayOf(value.capabilities.docs, "project.capabilities.docs", docs);
61
+ if (!Array.isArray(value.capabilities.contracts)) {
62
+ value.capabilities.contracts = [];
63
+ }
64
+ assertArrayOf(value.capabilities.contracts, "project.capabilities.contracts", contracts);
65
+ assertArrayOf(value.zones, "project.zones", zones);
66
+ return value;
67
+ }
68
+ exports.validateProjectConfig = validateProjectConfig;
69
+ function validateStructureConfig(value) {
70
+ assertObject(value, ".soap/structure.json");
71
+ assertString(value.featuresRoot, "structure.featuresRoot");
72
+ assertString(value.commonRoot, "structure.commonRoot");
73
+ assertString(value.configRoot, "structure.configRoot");
74
+ assertObject(value.paths, "structure.paths");
75
+ return value;
76
+ }
77
+ exports.validateStructureConfig = validateStructureConfig;
78
+ function validateApiConfig(value) {
79
+ assertObject(value, ".soap/api.json");
80
+ assertString(value.baseUrl, "api.baseUrl");
81
+ assertObject(value.health, "api.health");
82
+ assertObject(value.auth, "api.auth");
83
+ assertObject(value.bruno, "api.bruno");
84
+ return value;
85
+ }
86
+ exports.validateApiConfig = validateApiConfig;
87
+ function validateRegistryConfig(value) {
88
+ assertObject(value, ".soap/registry.json");
89
+ if (!Array.isArray(value.resources) || !Array.isArray(value.routes) || !Array.isArray(value.generatedFiles)) {
90
+ throw new errors_1.CliError(".soap/registry.json must contain resources, routes, and generatedFiles arrays.");
91
+ }
92
+ for (const resource of value.resources) {
93
+ if (resource && typeof resource === "object" && !Array.isArray(resource) && !Array.isArray(resource.fields)) {
94
+ resource.fields = [];
95
+ }
96
+ if (resource && typeof resource === "object" && !Array.isArray(resource)) {
97
+ assertAuthPolicy(resource.policy, "resource.policy");
98
+ }
99
+ }
100
+ for (const route of value.routes) {
101
+ if (route && typeof route === "object" && !Array.isArray(route) && typeof route.bruno !== "boolean") {
102
+ route.bruno = true;
103
+ }
104
+ if (route && typeof route === "object" && !Array.isArray(route)) {
105
+ assertAuthPolicy(route.policy, "route.policy");
106
+ }
107
+ }
108
+ return value;
109
+ }
110
+ exports.validateRegistryConfig = validateRegistryConfig;
111
+ function assertAuthPolicy(value, label) {
112
+ if (value === undefined) {
113
+ return;
114
+ }
115
+ assertObject(value, label);
116
+ if (value.type === "admin") {
117
+ return;
118
+ }
119
+ if (value.type === "roles") {
120
+ if (!Array.isArray(value.roles) || value.roles.some((role) => typeof role !== "string" || role.trim() === "")) {
121
+ throw new errors_1.CliError(`${label}.roles must contain non-empty strings.`);
122
+ }
123
+ return;
124
+ }
125
+ if (value.type === "custom") {
126
+ assertString(value.name, `${label}.name`);
127
+ return;
128
+ }
129
+ throw new errors_1.CliError(`${label}.type must be admin, roles, or custom.`);
130
+ }
@@ -0,0 +1,4 @@
1
+ export { findSoapRoot } from "./find-soap-root";
2
+ export { loadSoapConfig } from "./load-soap-config";
3
+ export { writeSoapConfig } from "./write-soap-config";
4
+ export * from "./schemas/types";
@@ -0,0 +1,24 @@
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
+ exports.writeSoapConfig = exports.loadSoapConfig = exports.findSoapRoot = void 0;
18
+ var find_soap_root_1 = require("./find-soap-root");
19
+ Object.defineProperty(exports, "findSoapRoot", { enumerable: true, get: function () { return find_soap_root_1.findSoapRoot; } });
20
+ var load_soap_config_1 = require("./load-soap-config");
21
+ Object.defineProperty(exports, "loadSoapConfig", { enumerable: true, get: function () { return load_soap_config_1.loadSoapConfig; } });
22
+ var write_soap_config_1 = require("./write-soap-config");
23
+ Object.defineProperty(exports, "writeSoapConfig", { enumerable: true, get: function () { return write_soap_config_1.writeSoapConfig; } });
24
+ __exportStar(require("./schemas/types"), exports);
@@ -0,0 +1,8 @@
1
+ import { CommandContext } from "../core/command-context";
2
+ import { SoapApiConfig, SoapProjectConfig, SoapRegistryConfig, SoapStructureConfig } from "./schemas/types";
3
+ export declare function writeSoapConfig(root: string, config: {
4
+ project: SoapProjectConfig;
5
+ structure: SoapStructureConfig;
6
+ api: SoapApiConfig;
7
+ registry: SoapRegistryConfig;
8
+ }, context: CommandContext): Promise<void>;
@@ -0,0 +1,25 @@
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.writeSoapConfig = void 0;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ const path_1 = __importDefault(require("path"));
9
+ async function writeJson(filePath, value, context) {
10
+ const content = `${JSON.stringify(value, null, 2)}\n`;
11
+ if (context.dryRun) {
12
+ context.output.info(`[dry-run] write ${filePath}`);
13
+ return;
14
+ }
15
+ await promises_1.default.mkdir(path_1.default.dirname(filePath), { recursive: true });
16
+ await promises_1.default.writeFile(filePath, content, "utf8");
17
+ }
18
+ async function writeSoapConfig(root, config, context) {
19
+ const soapRoot = path_1.default.join(root, ".soap");
20
+ await writeJson(path_1.default.join(soapRoot, "project.json"), config.project, context);
21
+ await writeJson(path_1.default.join(soapRoot, "structure.json"), config.structure, context);
22
+ await writeJson(path_1.default.join(soapRoot, "api.json"), config.api, context);
23
+ await writeJson(path_1.default.join(soapRoot, "registry.json"), config.registry, context);
24
+ }
25
+ exports.writeSoapConfig = writeSoapConfig;
@@ -0,0 +1,20 @@
1
+ import { Output } from "./output";
2
+ export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
3
+ export interface GlobalOptions {
4
+ cwd?: string;
5
+ verbose?: boolean;
6
+ silent?: boolean;
7
+ dryRun?: boolean;
8
+ }
9
+ export interface CommandContext {
10
+ cwd: string;
11
+ verbose: boolean;
12
+ silent: boolean;
13
+ dryRun: boolean;
14
+ packageManager?: PackageManager;
15
+ output: Output;
16
+ }
17
+ export declare function createCommandContext(options?: GlobalOptions): CommandContext;
18
+ export declare function getCommandContext(command: {
19
+ getOptionValue(name: string): unknown;
20
+ }): CommandContext;
@@ -0,0 +1,30 @@
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.getCommandContext = exports.createCommandContext = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const output_1 = require("./output");
9
+ function createCommandContext(options = {}) {
10
+ const cwd = path_1.default.resolve(options.cwd ?? process.cwd());
11
+ const verbose = Boolean(options.verbose);
12
+ const silent = Boolean(options.silent);
13
+ const dryRun = Boolean(options.dryRun);
14
+ return {
15
+ cwd,
16
+ verbose,
17
+ silent,
18
+ dryRun,
19
+ output: (0, output_1.createOutput)({ verbose, silent }),
20
+ };
21
+ }
22
+ exports.createCommandContext = createCommandContext;
23
+ function getCommandContext(command) {
24
+ const context = command.getOptionValue("_context");
25
+ if (!context) {
26
+ return createCommandContext();
27
+ }
28
+ return context;
29
+ }
30
+ exports.getCommandContext = getCommandContext;
@@ -0,0 +1,6 @@
1
+ import { CommandContext } from "./command-context";
2
+ export declare class CliError extends Error {
3
+ readonly exitCode: number;
4
+ constructor(message: string, exitCode?: number);
5
+ }
6
+ export declare function handleCliError(error: unknown, context: CommandContext): void;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleCliError = exports.CliError = void 0;
4
+ class CliError extends Error {
5
+ exitCode;
6
+ constructor(message, exitCode = 1) {
7
+ super(message);
8
+ this.exitCode = exitCode;
9
+ this.name = "CliError";
10
+ }
11
+ }
12
+ exports.CliError = CliError;
13
+ function handleCliError(error, context) {
14
+ if (error instanceof Error) {
15
+ context.output.error(error.message);
16
+ if (context.verbose && error.stack) {
17
+ context.output.debug(error.stack);
18
+ }
19
+ return;
20
+ }
21
+ context.output.error(String(error));
22
+ }
23
+ exports.handleCliError = handleCliError;
@@ -0,0 +1,12 @@
1
+ export interface Output {
2
+ info(message: string): void;
3
+ success(message: string): void;
4
+ warn(message: string): void;
5
+ error(message: string): void;
6
+ debug(message: string): void;
7
+ }
8
+ export interface OutputOptions {
9
+ verbose: boolean;
10
+ silent: boolean;
11
+ }
12
+ export declare function createOutput(options: OutputOptions): Output;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOutput = void 0;
4
+ function createOutput(options) {
5
+ const write = (stream, message) => {
6
+ stream.write(`${message}\n`);
7
+ };
8
+ return {
9
+ info(message) {
10
+ if (!options.silent)
11
+ write(process.stdout, message);
12
+ },
13
+ success(message) {
14
+ if (!options.silent)
15
+ write(process.stdout, message);
16
+ },
17
+ warn(message) {
18
+ if (!options.silent)
19
+ write(process.stderr, `Warning: ${message}`);
20
+ },
21
+ error(message) {
22
+ write(process.stderr, `Error: ${message}`);
23
+ },
24
+ debug(message) {
25
+ if (options.verbose && !options.silent)
26
+ write(process.stderr, `Debug: ${message}`);
27
+ },
28
+ };
29
+ }
30
+ exports.createOutput = createOutput;
@@ -0,0 +1,9 @@
1
+ export type Result<T, E = Error> = {
2
+ ok: true;
3
+ value: T;
4
+ } | {
5
+ ok: false;
6
+ error: E;
7
+ };
8
+ export declare function ok<T>(value: T): Result<T>;
9
+ export declare function err<E = Error>(error: E): Result<never, E>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.err = exports.ok = void 0;
4
+ function ok(value) {
5
+ return { ok: true, value };
6
+ }
7
+ exports.ok = ok;
8
+ function err(error) {
9
+ return { ok: false, error };
10
+ }
11
+ exports.err = err;
@@ -0,0 +1,6 @@
1
+ import { ProjectCapabilities } from "../config/schemas/types";
2
+ export interface ResolvedDependencies {
3
+ dependencies: Record<string, string>;
4
+ devDependencies: Record<string, string>;
5
+ }
6
+ export declare function resolveDependencies(capabilities: ProjectCapabilities): ResolvedDependencies;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveDependencies = void 0;
4
+ function resolveDependencies(capabilities) {
5
+ const dependencies = {
6
+ "@soapjs/soap": "^0.12.1",
7
+ "@soapjs/soap-express": "^0.5.1",
8
+ dotenv: "^16.4.5",
9
+ express: "^4.18.2",
10
+ "reflect-metadata": "^0.2.2",
11
+ };
12
+ const devDependencies = {
13
+ "@types/express": "^4.17.21",
14
+ "@types/node": "^24.0.0",
15
+ tsx: "^4.7.1",
16
+ typescript: "^5.4.0",
17
+ };
18
+ if (capabilities.databases.includes("mongo")) {
19
+ dependencies["@soapjs/soap-node-mongo"] = "^0.7.1";
20
+ dependencies.mongodb = "^6.3.0";
21
+ }
22
+ if (capabilities.databases.includes("postgres") || capabilities.databases.includes("mysql") || capabilities.databases.includes("sqlite")) {
23
+ dependencies["@soapjs/soap-node-sql"] = "^0.2.1";
24
+ }
25
+ if (capabilities.databases.includes("postgres")) {
26
+ dependencies.pg = "^8.11.3";
27
+ devDependencies["@types/pg"] = "^8.11.6";
28
+ }
29
+ if (capabilities.databases.includes("mysql")) {
30
+ dependencies.mysql2 = "^3.11.0";
31
+ }
32
+ if (capabilities.databases.includes("sqlite")) {
33
+ dependencies["better-sqlite3"] = "^11.1.2";
34
+ devDependencies["@types/better-sqlite3"] = "^7.6.11";
35
+ }
36
+ if (capabilities.databases.includes("redis")) {
37
+ dependencies["@soapjs/soap-node-redis"] = "^0.1.0";
38
+ dependencies.redis = "^4.6.13";
39
+ }
40
+ if (capabilities.auth.length > 0) {
41
+ dependencies["@soapjs/soap-auth"] = "^0.4.4";
42
+ dependencies.jsonwebtoken = "^9.0.2";
43
+ devDependencies["@types/jsonwebtoken"] = "^9.0.6";
44
+ }
45
+ if (capabilities.messaging.includes("kafka")) {
46
+ dependencies["@soapjs/soap-node-kafka"] = "^0.1.3";
47
+ dependencies.kafkajs = "^2.2.4";
48
+ }
49
+ if (capabilities.realtime.includes("ws")) {
50
+ dependencies["@soapjs/soap-node-socket"] = "^0.0.3";
51
+ dependencies.ws = "^8.16.0";
52
+ devDependencies["@types/ws"] = "^8.5.10";
53
+ }
54
+ if (capabilities.telemetry.includes("otel-noop")) {
55
+ dependencies["@soapjs/soap-node-otel"] = "^0.1.3";
56
+ }
57
+ if (capabilities.docs.includes("openapi")) {
58
+ dependencies["@soapjs/soap-openapi"] = "^0.1.1";
59
+ }
60
+ if (capabilities.contracts.includes("zod")) {
61
+ dependencies.zod = "^3.23.8";
62
+ }
63
+ if (capabilities.apiClient.includes("bruno")) {
64
+ devDependencies["@usebruno/cli"] = "^3.4.2";
65
+ }
66
+ return { dependencies, devDependencies };
67
+ }
68
+ exports.resolveDependencies = resolveDependencies;
@@ -0,0 +1,7 @@
1
+ import { PackageManager } from "../core/command-context";
2
+ export declare function detectPackageManager(root: string, override?: PackageManager): PackageManager;
3
+ export declare function installCommand(packageManager: PackageManager): string;
4
+ export declare function installCommandParts(packageManager: PackageManager): {
5
+ command: string;
6
+ args: string[];
7
+ };
@@ -0,0 +1,54 @@
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.installCommandParts = exports.installCommand = exports.detectPackageManager = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ function detectPackageManager(root, override) {
10
+ if (override) {
11
+ return override;
12
+ }
13
+ const lockfiles = [
14
+ ["pnpm-lock.yaml", "pnpm"],
15
+ ["yarn.lock", "yarn"],
16
+ ["bun.lockb", "bun"],
17
+ ["package-lock.json", "npm"],
18
+ ];
19
+ for (const [lockfile, packageManager] of lockfiles) {
20
+ if (fs_1.default.existsSync(path_1.default.join(root, lockfile))) {
21
+ return packageManager;
22
+ }
23
+ }
24
+ return "npm";
25
+ }
26
+ exports.detectPackageManager = detectPackageManager;
27
+ function installCommand(packageManager) {
28
+ switch (packageManager) {
29
+ case "pnpm":
30
+ return "pnpm install";
31
+ case "yarn":
32
+ return "yarn install";
33
+ case "bun":
34
+ return "bun install";
35
+ case "npm":
36
+ default:
37
+ return "npm install";
38
+ }
39
+ }
40
+ exports.installCommand = installCommand;
41
+ function installCommandParts(packageManager) {
42
+ switch (packageManager) {
43
+ case "pnpm":
44
+ return { command: "pnpm", args: ["install"] };
45
+ case "yarn":
46
+ return { command: "yarn", args: ["install"] };
47
+ case "bun":
48
+ return { command: "bun", args: ["install"] };
49
+ case "npm":
50
+ default:
51
+ return { command: "npm", args: ["install"] };
52
+ }
53
+ }
54
+ exports.installCommandParts = installCommandParts;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const cli_1 = require("./cli");
5
+ (0, cli_1.runCli)(process.argv).catch((error) => {
6
+ const message = error instanceof Error ? error.message : String(error);
7
+ process.stderr.write(`${message}\n`);
8
+ process.exitCode = 1;
9
+ });
@@ -0,0 +1,10 @@
1
+ export type ConflictPolicy = "ask" | "skip" | "overwrite" | "new" | "abort";
2
+ export interface ConflictPolicyOptions {
3
+ force?: boolean;
4
+ writeNew?: boolean;
5
+ skipModified?: boolean;
6
+ onConflict?: string;
7
+ }
8
+ export declare function parseConflictPolicy(value: string): ConflictPolicy;
9
+ export declare function resolveConflictPolicy(options?: ConflictPolicyOptions): ConflictPolicy;
10
+ export declare function conflictPolicyHelp(): string;