@trinacria/cli 0.1.1-alpha.1

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.

Potentially problematic release.


This version of @trinacria/cli might be problematic. Click here for more details.

Files changed (129) hide show
  1. package/README.md +109 -0
  2. package/README.npm.md +109 -0
  3. package/dist/cli.d.ts +19 -0
  4. package/dist/cli.js +88 -0
  5. package/dist/commands/build.d.ts +2 -0
  6. package/dist/commands/build.js +102 -0
  7. package/dist/commands/dev.d.ts +28 -0
  8. package/dist/commands/dev.js +186 -0
  9. package/dist/commands/new.d.ts +41 -0
  10. package/dist/commands/new.js +280 -0
  11. package/dist/commands/start.d.ts +13 -0
  12. package/dist/commands/start.js +110 -0
  13. package/dist/config/config.contract.d.ts +9 -0
  14. package/dist/config/config.contract.js +2 -0
  15. package/dist/config/default-config.d.ts +2 -0
  16. package/dist/config/default-config.js +11 -0
  17. package/dist/config/load-config.d.ts +2 -0
  18. package/dist/config/load-config.js +113 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +5 -0
  21. package/dist/templates/api-events-rabbitmq/.env.example +23 -0
  22. package/dist/templates/api-events-rabbitmq/Dockerfile +18 -0
  23. package/dist/templates/api-events-rabbitmq/README.md +97 -0
  24. package/dist/templates/api-events-rabbitmq/docker-compose.yml +30 -0
  25. package/dist/templates/api-events-rabbitmq/package.json +21 -0
  26. package/dist/templates/api-events-rabbitmq/src/global/config.service.ts +95 -0
  27. package/dist/templates/api-events-rabbitmq/src/global/controllers/swagger/docs.html +28 -0
  28. package/dist/templates/api-events-rabbitmq/src/global/controllers/swagger/swagger-docs.controller.ts +79 -0
  29. package/dist/templates/api-events-rabbitmq/src/global/rabbitmq.service.ts +86 -0
  30. package/dist/templates/api-events-rabbitmq/src/global/register-global-controllers.ts +20 -0
  31. package/dist/templates/api-events-rabbitmq/src/main.ts +89 -0
  32. package/dist/templates/api-events-rabbitmq/src/modules/events/dto/event.dto.ts +24 -0
  33. package/dist/templates/api-events-rabbitmq/src/modules/events/dto/index.ts +2 -0
  34. package/dist/templates/api-events-rabbitmq/src/modules/events/dto/publish-event.dto.ts +12 -0
  35. package/dist/templates/api-events-rabbitmq/src/modules/events/events.controller.ts +76 -0
  36. package/dist/templates/api-events-rabbitmq/src/modules/events/events.module.ts +27 -0
  37. package/dist/templates/api-events-rabbitmq/src/modules/events/events.provider.ts +28 -0
  38. package/dist/templates/api-events-rabbitmq/src/modules/events/events.service.ts +19 -0
  39. package/dist/templates/api-events-rabbitmq/src/modules/events/events.store.ts +42 -0
  40. package/dist/templates/api-events-rabbitmq/src/modules/events/events.tokens.ts +11 -0
  41. package/dist/templates/api-events-rabbitmq/trinacria.config.mjs +12 -0
  42. package/dist/templates/api-events-rabbitmq/tsconfig.json +14 -0
  43. package/dist/templates/api-events-redis/.env.example +18 -0
  44. package/dist/templates/api-events-redis/Dockerfile +18 -0
  45. package/dist/templates/api-events-redis/README.md +97 -0
  46. package/dist/templates/api-events-redis/docker-compose.yml +33 -0
  47. package/dist/templates/api-events-redis/package.json +18 -0
  48. package/dist/templates/api-events-redis/src/global/config.service.ts +93 -0
  49. package/dist/templates/api-events-redis/src/global/controllers/swagger/docs.html +28 -0
  50. package/dist/templates/api-events-redis/src/global/controllers/swagger/swagger-docs.controller.ts +79 -0
  51. package/dist/templates/api-events-redis/src/global/redis.service.ts +50 -0
  52. package/dist/templates/api-events-redis/src/global/register-global-controllers.ts +20 -0
  53. package/dist/templates/api-events-redis/src/main.ts +88 -0
  54. package/dist/templates/api-events-redis/src/modules/events/dto/event.dto.ts +24 -0
  55. package/dist/templates/api-events-redis/src/modules/events/dto/index.ts +2 -0
  56. package/dist/templates/api-events-redis/src/modules/events/dto/publish-event.dto.ts +12 -0
  57. package/dist/templates/api-events-redis/src/modules/events/events.controller.ts +76 -0
  58. package/dist/templates/api-events-redis/src/modules/events/events.module.ts +27 -0
  59. package/dist/templates/api-events-redis/src/modules/events/events.provider.ts +28 -0
  60. package/dist/templates/api-events-redis/src/modules/events/events.service.ts +19 -0
  61. package/dist/templates/api-events-redis/src/modules/events/events.store.ts +42 -0
  62. package/dist/templates/api-events-redis/src/modules/events/events.tokens.ts +11 -0
  63. package/dist/templates/api-events-redis/trinacria.config.mjs +12 -0
  64. package/dist/templates/api-events-redis/tsconfig.json +14 -0
  65. package/dist/templates/api-mongoose-mongodb/.env.example +17 -0
  66. package/dist/templates/api-mongoose-mongodb/Dockerfile +18 -0
  67. package/dist/templates/api-mongoose-mongodb/README.md +98 -0
  68. package/dist/templates/api-mongoose-mongodb/docker-compose.yml +34 -0
  69. package/dist/templates/api-mongoose-mongodb/package.json +17 -0
  70. package/dist/templates/api-mongoose-mongodb/src/global/config.service.ts +92 -0
  71. package/dist/templates/api-mongoose-mongodb/src/global/controllers/swagger/docs.html +28 -0
  72. package/dist/templates/api-mongoose-mongodb/src/global/controllers/swagger/swagger-docs.controller.ts +79 -0
  73. package/dist/templates/api-mongoose-mongodb/src/global/mongoose-schema.provider.ts +18 -0
  74. package/dist/templates/api-mongoose-mongodb/src/global/mongoose.service.ts +36 -0
  75. package/dist/templates/api-mongoose-mongodb/src/global/register-global-controllers.ts +20 -0
  76. package/dist/templates/api-mongoose-mongodb/src/main.ts +70 -0
  77. package/dist/templates/api-mongoose-mongodb/src/modules/users/dto/create-user.dto.ts +14 -0
  78. package/dist/templates/api-mongoose-mongodb/src/modules/users/dto/index.ts +2 -0
  79. package/dist/templates/api-mongoose-mongodb/src/modules/users/dto/public-user.dto.ts +22 -0
  80. package/dist/templates/api-mongoose-mongodb/src/modules/users/users.controller.ts +89 -0
  81. package/dist/templates/api-mongoose-mongodb/src/modules/users/users.module.ts +17 -0
  82. package/dist/templates/api-mongoose-mongodb/src/modules/users/users.schema.ts +35 -0
  83. package/dist/templates/api-mongoose-mongodb/src/modules/users/users.service.ts +35 -0
  84. package/dist/templates/api-mongoose-mongodb/src/modules/users/users.tokens.ts +9 -0
  85. package/dist/templates/api-mongoose-mongodb/trinacria.config.mjs +12 -0
  86. package/dist/templates/api-mongoose-mongodb/tsconfig.json +14 -0
  87. package/dist/templates/api-prisma-postgresql/.env.example +19 -0
  88. package/dist/templates/api-prisma-postgresql/Dockerfile +24 -0
  89. package/dist/templates/api-prisma-postgresql/README.md +107 -0
  90. package/dist/templates/api-prisma-postgresql/docker-compose.yml +38 -0
  91. package/dist/templates/api-prisma-postgresql/package.json +26 -0
  92. package/dist/templates/api-prisma-postgresql/prisma/schema.prisma +15 -0
  93. package/dist/templates/api-prisma-postgresql/prisma.config.ts +9 -0
  94. package/dist/templates/api-prisma-postgresql/src/global/config.service.ts +92 -0
  95. package/dist/templates/api-prisma-postgresql/src/global/controllers/swagger/docs.html +28 -0
  96. package/dist/templates/api-prisma-postgresql/src/global/controllers/swagger/swagger-docs.controller.ts +79 -0
  97. package/dist/templates/api-prisma-postgresql/src/global/prisma.service.ts +20 -0
  98. package/dist/templates/api-prisma-postgresql/src/global/register-global-controllers.ts +20 -0
  99. package/dist/templates/api-prisma-postgresql/src/main.ts +70 -0
  100. package/dist/templates/api-prisma-postgresql/src/modules/users/dto/create-user.dto.ts +14 -0
  101. package/dist/templates/api-prisma-postgresql/src/modules/users/dto/index.ts +2 -0
  102. package/dist/templates/api-prisma-postgresql/src/modules/users/dto/public-user.dto.ts +22 -0
  103. package/dist/templates/api-prisma-postgresql/src/modules/users/users.controller.ts +89 -0
  104. package/dist/templates/api-prisma-postgresql/src/modules/users/users.module.ts +15 -0
  105. package/dist/templates/api-prisma-postgresql/src/modules/users/users.service.ts +36 -0
  106. package/dist/templates/api-prisma-postgresql/src/modules/users/users.tokens.ts +7 -0
  107. package/dist/templates/api-prisma-postgresql/trinacria.config.mjs +12 -0
  108. package/dist/templates/api-prisma-postgresql/tsconfig.json +14 -0
  109. package/dist/templates/app-starter/.env.example +1 -0
  110. package/dist/templates/app-starter/Dockerfile +13 -0
  111. package/dist/templates/app-starter/README.md +32 -0
  112. package/dist/templates/app-starter/docker-compose.yml +8 -0
  113. package/dist/templates/app-starter/package.json +14 -0
  114. package/dist/templates/app-starter/src/main.ts +14 -0
  115. package/dist/templates/app-starter/trinacria.config.mjs +12 -0
  116. package/dist/templates/app-starter/tsconfig.json +14 -0
  117. package/dist/templates/cron-example/.env.example +11 -0
  118. package/dist/templates/cron-example/Dockerfile +13 -0
  119. package/dist/templates/cron-example/README.md +68 -0
  120. package/dist/templates/cron-example/docker-compose.yml +11 -0
  121. package/dist/templates/cron-example/package.json +15 -0
  122. package/dist/templates/cron-example/src/config.service.ts +46 -0
  123. package/dist/templates/cron-example/src/main.ts +41 -0
  124. package/dist/templates/cron-example/src/modules/cron/cron.module.ts +15 -0
  125. package/dist/templates/cron-example/src/modules/cron/cron.tokens.ts +6 -0
  126. package/dist/templates/cron-example/src/modules/cron/example-cron-jobs.provider.ts +48 -0
  127. package/dist/templates/cron-example/trinacria.config.mjs +12 -0
  128. package/dist/templates/cron-example/tsconfig.json +14 -0
  129. package/package.json +32 -0
@@ -0,0 +1,280 @@
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.__newTestUtils = void 0;
7
+ exports.createNewApp = createNewApp;
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_child_process_1 = require("node:child_process");
11
+ const core_1 = require("@trinacria/core");
12
+ const context = "TrinacriaCLI";
13
+ const log = new core_1.ConsoleLogger(context);
14
+ const DEFAULT_GITIGNORE = "node_modules\ndist\n.env\n";
15
+ const TEMPLATE_APP_NAMES = [
16
+ "app-starter",
17
+ "cron-example",
18
+ "api-prisma-postgresql",
19
+ "api-mongoose-mongodb",
20
+ "api-events-redis",
21
+ "api-events-rabbitmq",
22
+ ];
23
+ const defaultDeps = {
24
+ cwd: () => process.cwd(),
25
+ templatesRoot: () => resolveTemplatesRoot(),
26
+ pathExists: (target) => node_fs_1.default.existsSync(target),
27
+ mkdir: (target) => node_fs_1.default.mkdirSync(target, { recursive: true }),
28
+ readdir: (target) => node_fs_1.default.readdirSync(target, { withFileTypes: true }),
29
+ stat: (target) => node_fs_1.default.statSync(target),
30
+ readFile: (target) => node_fs_1.default.readFileSync(target, "utf8"),
31
+ writeFile: (target, content) => node_fs_1.default.writeFileSync(target, content, "utf8"),
32
+ copyFile: (from, to) => node_fs_1.default.copyFileSync(from, to),
33
+ runCommand: (command, args, cwd) => new Promise((resolve, reject) => {
34
+ const child = (0, node_child_process_1.spawn)(command, args, {
35
+ cwd,
36
+ stdio: "inherit",
37
+ });
38
+ child.on("error", reject);
39
+ child.on("exit", (code) => {
40
+ if (code === 0) {
41
+ resolve();
42
+ return;
43
+ }
44
+ reject(new Error(`Command failed: ${command} ${args.join(" ")}`));
45
+ });
46
+ }),
47
+ info: (message) => log.info(message, context),
48
+ };
49
+ function resolveTemplatesRoot() {
50
+ const distributedTemplatesRoot = node_path_1.default.resolve(__dirname, "../templates");
51
+ if (node_fs_1.default.existsSync(distributedTemplatesRoot)) {
52
+ return distributedTemplatesRoot;
53
+ }
54
+ return node_path_1.default.resolve(__dirname, "../../../../apps");
55
+ }
56
+ async function createNewApp(args, deps = defaultDeps) {
57
+ const options = parseNewArgs(args);
58
+ const sourceDir = resolveTemplatePath(options.template, deps.templatesRoot());
59
+ const targetDir = node_path_1.default.resolve(deps.cwd(), options.projectName);
60
+ const publishedTrinacriaVersion = resolvePublishedTrinacriaVersion();
61
+ ensureTargetDirectory(targetDir, options.force, deps);
62
+ copyDirectory(sourceDir, targetDir, deps);
63
+ ensureGeneratedProjectFiles(targetDir, deps);
64
+ adaptGeneratedPackageJson(targetDir, options.projectName, publishedTrinacriaVersion, deps);
65
+ deps.info(`Project "${options.projectName}" generated from template "${options.template}".`);
66
+ if (options.git) {
67
+ deps.info("Initializing git repository...");
68
+ await deps.runCommand("git", ["init"], targetDir);
69
+ }
70
+ if (options.install) {
71
+ const packageManager = detectPackageManager();
72
+ const command = packageManager === "npm" ? "npm" : packageManager;
73
+ const commandArgs = packageManager === "npm" ? ["install"] : ["install"];
74
+ deps.info(`Installing dependencies with ${packageManager}...`);
75
+ await deps.runCommand(command, commandArgs, targetDir);
76
+ }
77
+ }
78
+ function parseNewArgs(args) {
79
+ const positionals = [];
80
+ let templateInput = "app-starter";
81
+ let install = true;
82
+ let git = true;
83
+ let force = false;
84
+ for (let index = 0; index < args.length; index++) {
85
+ const arg = args[index];
86
+ if (!arg.startsWith("-")) {
87
+ positionals.push(arg);
88
+ continue;
89
+ }
90
+ if (arg === "--template" || arg === "-t") {
91
+ const next = args[index + 1];
92
+ if (!next || next.startsWith("-")) {
93
+ throw new Error("Missing value for --template <name>.");
94
+ }
95
+ templateInput = next;
96
+ index += 1;
97
+ continue;
98
+ }
99
+ if (arg === "--install") {
100
+ install = true;
101
+ continue;
102
+ }
103
+ if (arg === "--no-install") {
104
+ install = false;
105
+ continue;
106
+ }
107
+ if (arg === "--git") {
108
+ git = true;
109
+ continue;
110
+ }
111
+ if (arg === "--no-git") {
112
+ git = false;
113
+ continue;
114
+ }
115
+ if (arg === "--force" || arg === "-f") {
116
+ force = true;
117
+ continue;
118
+ }
119
+ throw new Error(`Unknown option for "new": ${arg}`);
120
+ }
121
+ const projectName = positionals[0];
122
+ if (!projectName) {
123
+ throw new Error(`Missing project name. Usage: trinacria new <project-name> [--template <name>] [--no-install] [--no-git] [--force]. Available templates: ${TEMPLATE_APP_NAMES.join(", ")}.`);
124
+ }
125
+ const template = normalizeTemplateName(templateInput);
126
+ return {
127
+ projectName,
128
+ template,
129
+ install,
130
+ git,
131
+ force,
132
+ };
133
+ }
134
+ function normalizeTemplateName(templateInput) {
135
+ const normalized = templateInput.trim().toLowerCase();
136
+ if (normalized === "minimal" ||
137
+ normalized === "starter" ||
138
+ normalized === "base" ||
139
+ normalized === "default") {
140
+ return "app-starter";
141
+ }
142
+ if (isTemplateAppName(normalized)) {
143
+ return normalized;
144
+ }
145
+ throw new Error(`Unknown template "${templateInput}". Available templates: ${TEMPLATE_APP_NAMES.join(", ")}, minimal.`);
146
+ }
147
+ function isTemplateAppName(value) {
148
+ return TEMPLATE_APP_NAMES.includes(value);
149
+ }
150
+ function resolveTemplatePath(template, templatesRoot) {
151
+ const templatePath = node_path_1.default.resolve(templatesRoot, template);
152
+ if (!node_fs_1.default.existsSync(templatePath)) {
153
+ throw new Error(`Template source not found: ${templatePath}`);
154
+ }
155
+ return templatePath;
156
+ }
157
+ function ensureTargetDirectory(targetDir, force, deps) {
158
+ if (!deps.pathExists(targetDir)) {
159
+ deps.mkdir(targetDir);
160
+ return;
161
+ }
162
+ const stat = deps.stat(targetDir);
163
+ if (!stat.isDirectory()) {
164
+ throw new Error(`Target path exists and is not a directory: ${targetDir}`);
165
+ }
166
+ const entries = deps.readdir(targetDir);
167
+ if (entries.length > 0 && !force) {
168
+ throw new Error(`Target directory is not empty: ${targetDir}. Use --force to continue.`);
169
+ }
170
+ }
171
+ function copyDirectory(fromDir, toDir, deps) {
172
+ for (const entry of deps.readdir(fromDir)) {
173
+ if (shouldSkipEntry(entry.name)) {
174
+ continue;
175
+ }
176
+ const sourcePath = node_path_1.default.resolve(fromDir, entry.name);
177
+ const targetPath = node_path_1.default.resolve(toDir, entry.name);
178
+ if (entry.isDirectory()) {
179
+ deps.mkdir(targetPath);
180
+ copyDirectory(sourcePath, targetPath, deps);
181
+ continue;
182
+ }
183
+ deps.copyFile(sourcePath, targetPath);
184
+ }
185
+ }
186
+ function shouldSkipEntry(entryName) {
187
+ return (entryName === "dist" || entryName === "node_modules" || entryName === ".git");
188
+ }
189
+ function resolvePublishedTrinacriaVersion() {
190
+ const packageJsonPath = node_path_1.default.resolve(__dirname, "../../package.json");
191
+ const packageJson = JSON.parse(node_fs_1.default.readFileSync(packageJsonPath, "utf8"));
192
+ if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
193
+ return packageJson.version;
194
+ }
195
+ return "latest";
196
+ }
197
+ function ensureGeneratedProjectFiles(targetDir, deps) {
198
+ const envExamplePath = node_path_1.default.resolve(targetDir, ".env.example");
199
+ const envPath = node_path_1.default.resolve(targetDir, ".env");
200
+ if (deps.pathExists(envExamplePath) && !deps.pathExists(envPath)) {
201
+ deps.writeFile(envPath, deps.readFile(envExamplePath));
202
+ }
203
+ const gitignorePath = node_path_1.default.resolve(targetDir, ".gitignore");
204
+ if (!deps.pathExists(gitignorePath)) {
205
+ deps.writeFile(gitignorePath, DEFAULT_GITIGNORE);
206
+ }
207
+ }
208
+ function adaptGeneratedPackageJson(targetDir, projectName, trinacriaVersion, deps) {
209
+ const packageJsonPath = node_path_1.default.resolve(targetDir, "package.json");
210
+ if (!deps.pathExists(packageJsonPath)) {
211
+ return;
212
+ }
213
+ const packageJson = JSON.parse(deps.readFile(packageJsonPath));
214
+ const projectBaseName = node_path_1.default.basename(targetDir);
215
+ packageJson.name = projectBaseName || projectName;
216
+ const scripts = normalizeScripts(packageJson.scripts);
217
+ packageJson.scripts = scripts;
218
+ const dependencies = normalizeDependencyMap(packageJson.dependencies, trinacriaVersion);
219
+ const devDependencies = normalizeDependencyMap(packageJson.devDependencies, trinacriaVersion);
220
+ const cliVersion = dependencies["@trinacria/cli"] ?? devDependencies["@trinacria/cli"];
221
+ if (cliVersion) {
222
+ delete dependencies["@trinacria/cli"];
223
+ devDependencies["@trinacria/cli"] = cliVersion;
224
+ }
225
+ else {
226
+ devDependencies["@trinacria/cli"] = trinacriaVersion;
227
+ }
228
+ if (!devDependencies.typescript) {
229
+ devDependencies.typescript = "latest";
230
+ }
231
+ if (!devDependencies["@types/node"]) {
232
+ devDependencies["@types/node"] = "latest";
233
+ }
234
+ packageJson.dependencies = dependencies;
235
+ packageJson.devDependencies = devDependencies;
236
+ deps.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
237
+ }
238
+ function normalizeScripts(scriptsInput) {
239
+ const scripts = {};
240
+ for (const [key, value] of Object.entries(scriptsInput ?? {})) {
241
+ if (typeof value === "string") {
242
+ scripts[key] = value;
243
+ }
244
+ }
245
+ scripts.dev = "trinacria dev";
246
+ scripts.build = "trinacria build";
247
+ scripts.start = "trinacria start";
248
+ return scripts;
249
+ }
250
+ function normalizeDependencyMap(input, trinacriaVersion) {
251
+ const output = {};
252
+ for (const [pkgName, version] of Object.entries(input ?? {})) {
253
+ if (typeof version !== "string") {
254
+ continue;
255
+ }
256
+ output[pkgName] = pkgName.startsWith("@trinacria/")
257
+ ? trinacriaVersion
258
+ : version;
259
+ }
260
+ return output;
261
+ }
262
+ function detectPackageManager() {
263
+ const userAgent = process.env.npm_config_user_agent ?? "";
264
+ if (userAgent.startsWith("pnpm/"))
265
+ return "pnpm";
266
+ if (userAgent.startsWith("yarn/"))
267
+ return "yarn";
268
+ if (userAgent.startsWith("bun/"))
269
+ return "bun";
270
+ return "npm";
271
+ }
272
+ exports.__newTestUtils = {
273
+ parseNewArgs,
274
+ normalizeTemplateName,
275
+ normalizeDependencyMap,
276
+ normalizeScripts,
277
+ adaptGeneratedPackageJson,
278
+ ensureGeneratedProjectFiles,
279
+ ensureTargetDirectory,
280
+ };
@@ -0,0 +1,13 @@
1
+ import { ResolvedConfig } from "../config/config.contract";
2
+ export declare function start(config: ResolvedConfig): Promise<void>;
3
+ declare function resolveBuiltEntryPath(entry: string, outDir: string): string;
4
+ declare function resolveCommonRootDir(fileNames: readonly string[]): string;
5
+ declare function commonDirectory(a: string, b: string): string;
6
+ declare function replaceSourceExtension(filePath: string): string;
7
+ export declare const __startTestUtils: {
8
+ resolveBuiltEntryPath: typeof resolveBuiltEntryPath;
9
+ resolveCommonRootDir: typeof resolveCommonRootDir;
10
+ commonDirectory: typeof commonDirectory;
11
+ replaceSourceExtension: typeof replaceSourceExtension;
12
+ };
13
+ export {};
@@ -0,0 +1,110 @@
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.__startTestUtils = void 0;
7
+ exports.start = start;
8
+ const node_child_process_1 = require("node:child_process");
9
+ const node_fs_1 = __importDefault(require("node:fs"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const typescript_1 = __importDefault(require("typescript"));
12
+ const core_1 = require("@trinacria/core");
13
+ const context = "TrinacriaCLI";
14
+ const log = new core_1.ConsoleLogger(context);
15
+ async function start(config) {
16
+ const entry = resolveBuiltEntryPath(config.entry, config.outDir);
17
+ log.info(`Starting application in production mode (${entry})`, context);
18
+ if (!node_fs_1.default.existsSync(entry)) {
19
+ throw new Error(`Built entry file not found: ${entry}. Run "trinacria build" first or verify tsconfig rootDir/outDir.`);
20
+ }
21
+ await new Promise((resolve, reject) => {
22
+ const child = (0, node_child_process_1.spawn)(process.execPath, [entry], {
23
+ stdio: "inherit",
24
+ });
25
+ child.on("exit", (code) => {
26
+ if (code !== 0) {
27
+ reject(new Error(`Exited with code ${code}`));
28
+ }
29
+ else {
30
+ resolve();
31
+ }
32
+ });
33
+ child.on("error", reject);
34
+ });
35
+ }
36
+ function resolveBuiltEntryPath(entry, outDir) {
37
+ const entryAbs = node_path_1.default.resolve(entry);
38
+ const outDirAbs = node_path_1.default.resolve(outDir);
39
+ const configPath = typescript_1.default.findConfigFile(process.cwd(), typescript_1.default.sys.fileExists, "tsconfig.json");
40
+ let rootDirAbs = process.cwd();
41
+ if (configPath) {
42
+ const configFile = typescript_1.default.readConfigFile(configPath, typescript_1.default.sys.readFile);
43
+ if (configFile.error) {
44
+ throw new Error(`Failed to read tsconfig.json: ${typescript_1.default.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`);
45
+ }
46
+ const parsed = typescript_1.default.parseJsonConfigFileContent(configFile.config, typescript_1.default.sys, node_path_1.default.dirname(configPath), { outDir: outDirAbs });
47
+ if (parsed.errors.length > 0) {
48
+ const message = parsed.errors
49
+ .map((diagnostic) => typescript_1.default.flattenDiagnosticMessageText(diagnostic.messageText, "\n"))
50
+ .join("; ");
51
+ throw new Error(`Failed to parse tsconfig.json: ${message}`);
52
+ }
53
+ if (parsed.options.rootDir) {
54
+ rootDirAbs = node_path_1.default.resolve(parsed.options.rootDir);
55
+ }
56
+ else {
57
+ rootDirAbs = resolveCommonRootDir(parsed.fileNames);
58
+ }
59
+ }
60
+ const relativeFromRoot = node_path_1.default.relative(rootDirAbs, entryAbs);
61
+ if (relativeFromRoot.startsWith("..") ||
62
+ node_path_1.default.isAbsolute(relativeFromRoot) ||
63
+ relativeFromRoot === "") {
64
+ throw new Error(`Entry "${entryAbs}" is outside resolved TypeScript rootDir "${rootDirAbs}".`);
65
+ }
66
+ return node_path_1.default.resolve(outDirAbs, replaceSourceExtension(relativeFromRoot));
67
+ }
68
+ function resolveCommonRootDir(fileNames) {
69
+ if (fileNames.length === 0) {
70
+ return process.cwd();
71
+ }
72
+ const directories = fileNames.map((file) => node_path_1.default.dirname(node_path_1.default.resolve(file)));
73
+ let common = directories[0];
74
+ for (let i = 1; i < directories.length; i++) {
75
+ common = commonDirectory(common, directories[i]);
76
+ }
77
+ return common;
78
+ }
79
+ function commonDirectory(a, b) {
80
+ const aParts = node_path_1.default.resolve(a).split(node_path_1.default.sep);
81
+ const bParts = node_path_1.default.resolve(b).split(node_path_1.default.sep);
82
+ const length = Math.min(aParts.length, bParts.length);
83
+ const shared = [];
84
+ for (let i = 0; i < length; i++) {
85
+ if (aParts[i] !== bParts[i])
86
+ break;
87
+ shared.push(aParts[i]);
88
+ }
89
+ if (shared.length === 0) {
90
+ return process.cwd();
91
+ }
92
+ return shared.join(node_path_1.default.sep) || node_path_1.default.sep;
93
+ }
94
+ function replaceSourceExtension(filePath) {
95
+ if (filePath.endsWith(".mts"))
96
+ return filePath.slice(0, -4) + ".mjs";
97
+ if (filePath.endsWith(".cts"))
98
+ return filePath.slice(0, -4) + ".cjs";
99
+ if (filePath.endsWith(".tsx"))
100
+ return filePath.slice(0, -4) + ".js";
101
+ if (filePath.endsWith(".ts"))
102
+ return filePath.slice(0, -3) + ".js";
103
+ return filePath;
104
+ }
105
+ exports.__startTestUtils = {
106
+ resolveBuiltEntryPath,
107
+ resolveCommonRootDir,
108
+ commonDirectory,
109
+ replaceSourceExtension,
110
+ };
@@ -0,0 +1,9 @@
1
+ export interface ResolvedConfig {
2
+ entry: string;
3
+ outDir: string;
4
+ watchDir: string;
5
+ env: "development" | "production" | string;
6
+ crashLoopWindowMs: number;
7
+ maxConsecutiveCrashRestarts: number;
8
+ }
9
+ export type TrinacriaConfig = Partial<ResolvedConfig>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import { ResolvedConfig } from "./config.contract.js";
2
+ export declare const defaultConfig: ResolvedConfig;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultConfig = void 0;
4
+ exports.defaultConfig = {
5
+ entry: "src/main.ts",
6
+ outDir: "dist",
7
+ watchDir: "src",
8
+ env: "development",
9
+ crashLoopWindowMs: 15_000,
10
+ maxConsecutiveCrashRestarts: 3,
11
+ };
@@ -0,0 +1,2 @@
1
+ import type { ResolvedConfig } from "./config.contract";
2
+ export declare function loadConfig(args: string[]): Promise<ResolvedConfig>;
@@ -0,0 +1,113 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.loadConfig = loadConfig;
40
+ const node_path_1 = __importDefault(require("node:path"));
41
+ const node_fs_1 = __importDefault(require("node:fs"));
42
+ const node_url_1 = require("node:url");
43
+ const default_config_1 = require("./default-config");
44
+ async function loadConfig(args) {
45
+ const configFlagIndex = args.indexOf("--config");
46
+ const hasExplicitConfig = configFlagIndex !== -1;
47
+ let configPath;
48
+ if (hasExplicitConfig && args[configFlagIndex + 1]) {
49
+ configPath = node_path_1.default.resolve(args[configFlagIndex + 1]);
50
+ }
51
+ else if (hasExplicitConfig) {
52
+ throw new Error("Missing value for --config <path>.");
53
+ }
54
+ else {
55
+ configPath = resolveDefaultConfigPath();
56
+ }
57
+ if (hasExplicitConfig && configPath && !node_fs_1.default.existsSync(configPath)) {
58
+ throw new Error(`Config file not found: ${configPath}`);
59
+ }
60
+ if (!configPath || !node_fs_1.default.existsSync(configPath)) {
61
+ return normalizeConfig(default_config_1.defaultConfig);
62
+ }
63
+ try {
64
+ // 🟢 Prima prova CommonJS
65
+ const required = require(configPath);
66
+ const userConfig = required.default ?? required;
67
+ return normalizeConfig({
68
+ ...default_config_1.defaultConfig,
69
+ ...userConfig,
70
+ });
71
+ }
72
+ catch (err) {
73
+ // 🔵 Se è errore ESM → fallback a dynamic import
74
+ if (err.code === "ERR_REQUIRE_ESM") {
75
+ const module = await Promise.resolve(`${(0, node_url_1.pathToFileURL)(configPath).href}`).then(s => __importStar(require(s)));
76
+ const userConfig = module.default ?? module;
77
+ return normalizeConfig({
78
+ ...default_config_1.defaultConfig,
79
+ ...userConfig,
80
+ });
81
+ }
82
+ throw new Error(`Failed to load config file "${configPath}": ${err instanceof Error ? err.message : String(err)}`);
83
+ }
84
+ }
85
+ function normalizeConfig(config) {
86
+ const crashLoopWindowMs = Number(config.crashLoopWindowMs);
87
+ const maxConsecutiveCrashRestarts = Number(config.maxConsecutiveCrashRestarts);
88
+ return {
89
+ ...config,
90
+ crashLoopWindowMs: Number.isFinite(crashLoopWindowMs) && crashLoopWindowMs > 0
91
+ ? Math.floor(crashLoopWindowMs)
92
+ : default_config_1.defaultConfig.crashLoopWindowMs,
93
+ maxConsecutiveCrashRestarts: Number.isFinite(maxConsecutiveCrashRestarts) &&
94
+ maxConsecutiveCrashRestarts >= 1
95
+ ? Math.floor(maxConsecutiveCrashRestarts)
96
+ : default_config_1.defaultConfig.maxConsecutiveCrashRestarts,
97
+ };
98
+ }
99
+ function resolveDefaultConfigPath() {
100
+ const cwd = process.cwd();
101
+ const possibleFiles = [
102
+ "trinacria.config.js",
103
+ "trinacria.config.cjs",
104
+ "trinacria.config.mjs",
105
+ ];
106
+ for (const file of possibleFiles) {
107
+ const fullPath = node_path_1.default.resolve(cwd, file);
108
+ if (node_fs_1.default.existsSync(fullPath)) {
109
+ return fullPath;
110
+ }
111
+ }
112
+ return null;
113
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export type { TrinacriaConfig } from "./config/config.contract";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
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.main)();
@@ -0,0 +1,23 @@
1
+ # ------------------------------------------------------------
2
+ # Local app runtime (used by `npm run dev -w api-events-rabbitmq`)
3
+ # ------------------------------------------------------------
4
+ ENV=development
5
+ HOST=127.0.0.1
6
+ PORT=4004
7
+ OPENAPI_ENABLED=true
8
+ CORS_ALLOWED_ORIGINS=
9
+ RABBITMQ_URL=amqp://127.0.0.1:5672
10
+ RABBITMQ_EXCHANGE=trinacria.events
11
+ RABBITMQ_QUEUE_NAME=api-events-rabbitmq.events
12
+ RABBITMQ_ROUTING_PATTERN=#
13
+
14
+ # ------------------------------------------------------------
15
+ # Docker runtime (used by `docker compose ... --env-file .../.env`)
16
+ # ------------------------------------------------------------
17
+ DOCKER_RABBITMQ_PORT=5672
18
+ DOCKER_RABBITMQ_MANAGEMENT_PORT=15672
19
+ DOCKER_API_PORT=4004
20
+ DOCKER_RABBITMQ_URL=amqp://rabbitmq:5672
21
+ DOCKER_RABBITMQ_EXCHANGE=trinacria.events
22
+ DOCKER_RABBITMQ_QUEUE_NAME=api-events-rabbitmq.events
23
+ DOCKER_RABBITMQ_ROUTING_PATTERN=#
@@ -0,0 +1,18 @@
1
+ FROM node:24-bookworm-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY package.json package-lock.json tsconfig.base.json ./
6
+ COPY packages ./packages
7
+ COPY apps/api-events-rabbitmq ./apps/api-events-rabbitmq
8
+
9
+ RUN npm ci
10
+ RUN npm run build:packages
11
+ RUN npm run build -w api-events-rabbitmq
12
+
13
+ ENV HOST=0.0.0.0
14
+ ENV PORT=4004
15
+
16
+ EXPOSE 4004
17
+
18
+ CMD ["npm", "run", "start", "-w", "api-events-rabbitmq"]