@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,252 @@
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.createRepositoryFiles = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const naming_1 = require("../../templates/naming");
9
+ function createRepositoryFiles(plan) {
10
+ const repositoryNames = (0, naming_1.createNameVariants)(plan.name);
11
+ const featureNames = (0, naming_1.createNameVariants)(plan.feature);
12
+ const root = path_1.default.posix.join(plan.featuresRoot, featureNames.kebabName);
13
+ const commonFiles = [
14
+ {
15
+ path: `${root}/application/ports/${repositoryNames.kebabName}-repository.port.ts`,
16
+ type: "repository",
17
+ owner: featureNames.kebabName,
18
+ content: createRepositoryPortTs(repositoryNames.pascalName),
19
+ },
20
+ {
21
+ path: `${root}/data/${repositoryNames.kebabName}.mapper.ts`,
22
+ type: "repository",
23
+ owner: featureNames.kebabName,
24
+ content: createMapperTs(repositoryNames, plan.db),
25
+ },
26
+ ];
27
+ if (plan.db === "mongo") {
28
+ return [
29
+ ...commonFiles,
30
+ {
31
+ path: `${root}/data/${repositoryNames.kebabName}.model.ts`,
32
+ type: "repository",
33
+ owner: featureNames.kebabName,
34
+ content: createMongoModelTs(repositoryNames.pascalName),
35
+ },
36
+ {
37
+ path: `${root}/data/${repositoryNames.kebabName}.repository.mongo.ts`,
38
+ type: "repository",
39
+ owner: featureNames.kebabName,
40
+ content: createMongoRepositoryTs(repositoryNames),
41
+ },
42
+ ];
43
+ }
44
+ return [
45
+ ...commonFiles,
46
+ {
47
+ path: `${root}/data/${repositoryNames.kebabName}.row.ts`,
48
+ type: "repository",
49
+ owner: featureNames.kebabName,
50
+ content: createSqlRowTs(repositoryNames.pascalName),
51
+ },
52
+ {
53
+ path: `${root}/data/${repositoryNames.pluralName}.schema.ts`,
54
+ type: "repository",
55
+ owner: featureNames.kebabName,
56
+ content: createSqlSchemaTs(repositoryNames, plan.db),
57
+ },
58
+ {
59
+ path: `${root}/data/${repositoryNames.kebabName}.repository.sql.ts`,
60
+ type: "repository",
61
+ owner: featureNames.kebabName,
62
+ content: createSqlRepositoryTs(repositoryNames),
63
+ },
64
+ ];
65
+ }
66
+ exports.createRepositoryFiles = createRepositoryFiles;
67
+ function createRepositoryPortTs(className) {
68
+ return `import { ReadWriteRepository } from '@soapjs/soap';
69
+
70
+ export interface ${className}Record {
71
+ id: string;
72
+ createdAt: string;
73
+ updatedAt: string;
74
+ [key: string]: unknown;
75
+ }
76
+
77
+ export type ${className}Repository = ReadWriteRepository<${className}Record, unknown>;
78
+ `;
79
+ }
80
+ function createMongoModelTs(className) {
81
+ return `import { Document } from 'mongodb';
82
+
83
+ export interface ${className}Model extends Document {
84
+ id: string;
85
+ createdAt: string;
86
+ updatedAt: string;
87
+ [key: string]: unknown;
88
+ }
89
+ `;
90
+ }
91
+ function createSqlRowTs(className) {
92
+ return `export interface ${className}Row {
93
+ id: string;
94
+ createdAt: string;
95
+ updatedAt: string;
96
+ [key: string]: unknown;
97
+ }
98
+ `;
99
+ }
100
+ function createMapperTs(names, db) {
101
+ const persistenceName = db === "mongo" ? `${names.pascalName}Model` : `${names.pascalName}Row`;
102
+ const persistenceImport = db === "mongo"
103
+ ? `import { ${names.pascalName}Model } from './${names.kebabName}.model';`
104
+ : `import { ${names.pascalName}Row } from './${names.kebabName}.row';`;
105
+ return `import { Mapper } from '@soapjs/soap';
106
+ import { ${names.pascalName}Record } from '../application/ports/${names.kebabName}-repository.port';
107
+ ${persistenceImport}
108
+
109
+ export const ${names.camelName}Mapper: Mapper<${names.pascalName}Record, ${persistenceName}> = {
110
+ toEntity(model) {
111
+ const { _id, ...record } = model as ${persistenceName} & { _id?: unknown };
112
+
113
+ return {
114
+ ...record,
115
+ id: record.id || (_id ? String(_id) : ''),
116
+ };
117
+ },
118
+
119
+ toModel(entity) {
120
+ return {
121
+ ...entity,
122
+ } as ${persistenceName};
123
+ },
124
+ };
125
+ `;
126
+ }
127
+ function createMongoRepositoryTs(names) {
128
+ return `import { randomUUID } from 'crypto';
129
+ import {
130
+ DatabaseContext,
131
+ DatabaseSession,
132
+ DatabaseSessionRegistry,
133
+ ReadWriteRepository,
134
+ TransactionScope,
135
+ } from '@soapjs/soap';
136
+ import { MongoSource } from '@soapjs/soap-node-mongo';
137
+ import { ${names.pascalName}Record } from '../application/ports/${names.kebabName}-repository.port';
138
+ import { ${names.camelName}Mapper } from './${names.kebabName}.mapper';
139
+ import { ${names.pascalName}Model } from './${names.kebabName}.model';
140
+
141
+ export class Mongo${names.pascalName}Repository extends ReadWriteRepository<${names.pascalName}Record, ${names.pascalName}Model> {
142
+ constructor(source: MongoSource<${names.pascalName}Model>) {
143
+ super(new DatabaseContext(source, ${names.camelName}Mapper, createRepositorySessions()));
144
+ }
145
+ }
146
+
147
+ function createRepositorySessions(): DatabaseSessionRegistry {
148
+ const sessions = new Map<string, DatabaseSession>();
149
+
150
+ return {
151
+ transactionScope: TransactionScope.getInstance(),
152
+ createSession() {
153
+ const session = createNoopSession();
154
+ sessions.set(session.id, session);
155
+ return session;
156
+ },
157
+ deleteSession(id: string) {
158
+ sessions.delete(id);
159
+ },
160
+ getSession(id: string) {
161
+ return sessions.get(id);
162
+ },
163
+ hasSession(id: string) {
164
+ return sessions.has(id);
165
+ },
166
+ };
167
+ }
168
+
169
+ function createNoopSession(): DatabaseSession {
170
+ return {
171
+ id: randomUUID(),
172
+ async end() {},
173
+ async startTransaction() {},
174
+ async commitTransaction() {},
175
+ async rollbackTransaction() {},
176
+ };
177
+ }
178
+ `;
179
+ }
180
+ function createSqlSchemaTs(names, db) {
181
+ const tableName = names.pluralName.replace(/-/g, "_");
182
+ const createdAtColumn = db === "mysql" ? "`createdAt`" : "\"createdAt\"";
183
+ const updatedAtColumn = db === "mysql" ? "`updatedAt`" : "\"updatedAt\"";
184
+ return `import { SqlDataSource } from '@soapjs/soap-node-sql';
185
+ import { ${names.pascalName}Row } from './${names.kebabName}.row';
186
+
187
+ export const ${names.constantName}_TABLE = '${tableName}';
188
+
189
+ export async function ensure${names.pascalName}Schema(source: SqlDataSource<${names.pascalName}Row>): Promise<void> {
190
+ await source.query(\`
191
+ CREATE TABLE IF NOT EXISTS ${tableName} (
192
+ id TEXT PRIMARY KEY,
193
+ ${createdAtColumn} TEXT NOT NULL,
194
+ ${updatedAtColumn} TEXT NOT NULL
195
+ )
196
+ \`);
197
+ }
198
+ `;
199
+ }
200
+ function createSqlRepositoryTs(names) {
201
+ return `import { randomUUID } from 'crypto';
202
+ import {
203
+ DatabaseContext,
204
+ DatabaseSession,
205
+ DatabaseSessionRegistry,
206
+ ReadWriteRepository,
207
+ TransactionScope,
208
+ } from '@soapjs/soap';
209
+ import { SqlDataSource } from '@soapjs/soap-node-sql';
210
+ import { ${names.pascalName}Record } from '../application/ports/${names.kebabName}-repository.port';
211
+ import { ${names.camelName}Mapper } from './${names.kebabName}.mapper';
212
+ import { ${names.pascalName}Row } from './${names.kebabName}.row';
213
+
214
+ export class Sql${names.pascalName}Repository extends ReadWriteRepository<${names.pascalName}Record, ${names.pascalName}Row> {
215
+ constructor(source: SqlDataSource<${names.pascalName}Row>) {
216
+ super(new DatabaseContext(source, ${names.camelName}Mapper, createRepositorySessions()));
217
+ }
218
+ }
219
+
220
+ function createRepositorySessions(): DatabaseSessionRegistry {
221
+ const sessions = new Map<string, DatabaseSession>();
222
+
223
+ return {
224
+ transactionScope: TransactionScope.getInstance(),
225
+ createSession() {
226
+ const session = createNoopSession();
227
+ sessions.set(session.id, session);
228
+ return session;
229
+ },
230
+ deleteSession(id: string) {
231
+ sessions.delete(id);
232
+ },
233
+ getSession(id: string) {
234
+ return sessions.get(id);
235
+ },
236
+ hasSession(id: string) {
237
+ return sessions.has(id);
238
+ },
239
+ };
240
+ }
241
+
242
+ function createNoopSession(): DatabaseSession {
243
+ return {
244
+ id: randomUUID(),
245
+ async end() {},
246
+ async startTransaction() {},
247
+ async commitTransaction() {},
248
+ async rollbackTransaction() {},
249
+ };
250
+ }
251
+ `;
252
+ }
@@ -0,0 +1,52 @@
1
+ import { ApiZone, AuthPolicy, AuthCapability, DatabaseCapability, ResourceFieldDefinition, ResourceRegistryEntry } from "../../config/schemas/types";
2
+ import { PlannedFile } from "../../io/file-writer";
3
+ export interface AddResourcePlan {
4
+ name: string;
5
+ crud: boolean;
6
+ db: "none" | DatabaseCapability;
7
+ auth: "none" | AuthCapability;
8
+ zone: ApiZone;
9
+ featuresRoot: string;
10
+ architecture?: "regular" | "cqrs";
11
+ contracts?: "plain" | "zod";
12
+ fields?: ResourceFieldDefinition[];
13
+ crudRoutes?: CrudRouteMatrix;
14
+ policy?: AuthPolicy;
15
+ }
16
+ export type CrudOperation = "list" | "get" | "create" | "update" | "delete";
17
+ export interface CrudRouteConfig {
18
+ method?: "get" | "post" | "put" | "patch" | "delete";
19
+ path?: string;
20
+ auth?: "none" | AuthCapability;
21
+ zone?: ApiZone;
22
+ bruno?: boolean;
23
+ policy?: AuthPolicy;
24
+ }
25
+ export type CrudRouteMatrix = Partial<Record<CrudOperation, CrudRouteConfig>>;
26
+ export interface ResourceAddPlanningOptions extends AddResourcePlan {
27
+ architecture: "regular" | "cqrs";
28
+ }
29
+ export interface ResourceAddPlanningStep {
30
+ type: "entity" | "repository" | "use-case" | "command" | "query" | "route" | "contract" | "bruno";
31
+ name: string;
32
+ }
33
+ export interface ResourceAddPlanningSummary {
34
+ resource: string;
35
+ architecture: "regular" | "cqrs";
36
+ steps: ResourceAddPlanningStep[];
37
+ }
38
+ export declare function createResourceEntry(plan: AddResourcePlan): ResourceRegistryEntry;
39
+ export declare function createResourceAddPlanningSummary(plan: ResourceAddPlanningOptions): ResourceAddPlanningSummary;
40
+ export declare function formatResourceAddPlanningSummary(summary: ResourceAddPlanningSummary): string;
41
+ export declare function createResourceFiles(plan: AddResourcePlan): PlannedFile[];
42
+ export declare function createResourcesFile(resources: ResourceRegistryEntry[], featuresRoot: string): PlannedFile;
43
+ export declare function createFeaturesIndexFile(resources: ResourceRegistryEntry[], authCapabilities?: AuthCapability[]): PlannedFile;
44
+ export declare function createControllersFile(resources: ResourceRegistryEntry[], featuresRoot: string, authCapabilities?: AuthCapability[], routeControllerIndexes?: string[], mainControllerResources?: string[]): PlannedFile;
45
+ export declare function parseCrudRouteMatrix(values: string[] | undefined): CrudRouteMatrix;
46
+ export declare function parseResourceFieldDefinitions(values: string[] | undefined): ResourceFieldDefinition[];
47
+ export declare function createAuthDecorator(auth: "none" | AuthCapability, zone: ApiZone, policy?: AuthPolicy): string | undefined;
48
+ export declare function createRouteApiDocOptions(input: {
49
+ summary: string;
50
+ operationId: string;
51
+ auth: "none" | AuthCapability;
52
+ }): string;