@digitaldefiance/express-suite-starter 2.1.44 → 2.1.45

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 (65) hide show
  1. package/README.md +5 -1
  2. package/dist/src/core/dry-run-executor.d.ts.map +1 -1
  3. package/dist/src/core/dry-run-executor.js +15 -13
  4. package/dist/src/core/dry-run-executor.js.map +1 -1
  5. package/dist/src/core/package-resolver.d.ts.map +1 -1
  6. package/dist/src/core/package-resolver.js +4 -2
  7. package/dist/src/core/package-resolver.js.map +1 -1
  8. package/dist/src/core/plugin-manager.d.ts.map +1 -1
  9. package/dist/src/core/plugin-manager.js +4 -2
  10. package/dist/src/core/plugin-manager.js.map +1 -1
  11. package/dist/src/core/step-executor.d.ts.map +1 -1
  12. package/dist/src/core/step-executor.js +10 -8
  13. package/dist/src/core/step-executor.js.map +1 -1
  14. package/dist/src/generate-monorepo.d.ts.map +1 -1
  15. package/dist/src/generate-monorepo.js +138 -90
  16. package/dist/src/generate-monorepo.js.map +1 -1
  17. package/dist/src/i18n/i18n-setup.d.ts +12 -0
  18. package/dist/src/i18n/i18n-setup.d.ts.map +1 -0
  19. package/dist/src/i18n/i18n-setup.js +69 -0
  20. package/dist/src/i18n/i18n-setup.js.map +1 -0
  21. package/dist/src/i18n/index.d.ts +4 -0
  22. package/dist/src/i18n/index.d.ts.map +1 -0
  23. package/dist/src/i18n/index.js +20 -0
  24. package/dist/src/i18n/index.js.map +1 -0
  25. package/dist/src/i18n/starter-string-key.d.ts +159 -0
  26. package/dist/src/i18n/starter-string-key.d.ts.map +1 -0
  27. package/dist/src/i18n/starter-string-key.js +183 -0
  28. package/dist/src/i18n/starter-string-key.js.map +1 -0
  29. package/dist/src/i18n/translations-all.d.ts +177 -0
  30. package/dist/src/i18n/translations-all.d.ts.map +1 -0
  31. package/dist/src/i18n/translations-all.js +30 -0
  32. package/dist/src/i18n/translations-all.js.map +1 -0
  33. package/dist/src/i18n/translations-de.d.ts +3 -0
  34. package/dist/src/i18n/translations-de.d.ts.map +1 -0
  35. package/dist/src/i18n/translations-de.js +163 -0
  36. package/dist/src/i18n/translations-de.js.map +1 -0
  37. package/dist/src/i18n/translations-en-gb.d.ts +159 -0
  38. package/dist/src/i18n/translations-en-gb.d.ts.map +1 -0
  39. package/dist/src/i18n/translations-en-gb.js +7 -0
  40. package/dist/src/i18n/translations-en-gb.js.map +1 -0
  41. package/dist/src/i18n/translations-en-us.d.ts +3 -0
  42. package/dist/src/i18n/translations-en-us.d.ts.map +1 -0
  43. package/dist/src/i18n/translations-en-us.js +183 -0
  44. package/dist/src/i18n/translations-en-us.js.map +1 -0
  45. package/dist/src/i18n/translations-es.d.ts +3 -0
  46. package/dist/src/i18n/translations-es.d.ts.map +1 -0
  47. package/dist/src/i18n/translations-es.js +163 -0
  48. package/dist/src/i18n/translations-es.js.map +1 -0
  49. package/dist/src/i18n/translations-fr.d.ts +3 -0
  50. package/dist/src/i18n/translations-fr.d.ts.map +1 -0
  51. package/dist/src/i18n/translations-fr.js +163 -0
  52. package/dist/src/i18n/translations-fr.js.map +1 -0
  53. package/dist/src/i18n/translations-ja.d.ts +3 -0
  54. package/dist/src/i18n/translations-ja.d.ts.map +1 -0
  55. package/dist/src/i18n/translations-ja.js +163 -0
  56. package/dist/src/i18n/translations-ja.js.map +1 -0
  57. package/dist/src/i18n/translations-uk.d.ts +3 -0
  58. package/dist/src/i18n/translations-uk.d.ts.map +1 -0
  59. package/dist/src/i18n/translations-uk.js +163 -0
  60. package/dist/src/i18n/translations-uk.js.map +1 -0
  61. package/dist/src/i18n/translations-zh-cn.d.ts +3 -0
  62. package/dist/src/i18n/translations-zh-cn.d.ts.map +1 -0
  63. package/dist/src/i18n/translations-zh-cn.js +163 -0
  64. package/dist/src/i18n/translations-zh-cn.js.map +1 -0
  65. package/package.json +1 -1
@@ -57,22 +57,43 @@ const nodeSetup_1 = require("../scripts/nodeSetup");
57
57
  const licensePrompt_1 = require("../scripts/licensePrompt");
58
58
  const addScriptsToPackageJson_1 = require("../scripts/addScriptsToPackageJson");
59
59
  const templateUtils_1 = require("../scripts/templateUtils");
60
+ const i18n_1 = require("./i18n");
61
+ const i18n_lib_1 = require("@digitaldefiance/i18n-lib");
62
+ const i18n_lib_2 = require("@digitaldefiance/i18n-lib");
60
63
  async function main() {
61
64
  (0, albatross_1.printBanner)();
62
65
  (0, nodeSetup_1.checkAndUseNode)();
63
66
  // Disable Yarn build scripts globally to avoid native module issues
64
67
  process.env.YARN_ENABLE_SCRIPTS = 'false';
68
+ // Language selection
69
+ const selectedLanguage = await (0, select_1.default)({
70
+ message: 'Select language / Seleccionar idioma / Choisir la langue / Sprache wählen / 选择语言 / 言語を選択 / Виберіть мову:',
71
+ choices: [
72
+ { name: 'English (US)', value: i18n_lib_2.LanguageCodes.EN_US },
73
+ { name: 'English (UK)', value: i18n_lib_2.LanguageCodes.EN_GB },
74
+ { name: 'Español', value: i18n_lib_2.LanguageCodes.ES },
75
+ { name: 'Français', value: i18n_lib_2.LanguageCodes.FR },
76
+ { name: 'Deutsch', value: i18n_lib_2.LanguageCodes.DE },
77
+ { name: '中文', value: i18n_lib_2.LanguageCodes.ZH_CN },
78
+ { name: '日本語', value: i18n_lib_2.LanguageCodes.JA },
79
+ { name: 'Українська', value: i18n_lib_2.LanguageCodes.UK },
80
+ ],
81
+ default: i18n_lib_2.LanguageCodes.EN_US,
82
+ });
83
+ // Set the language for the i18n engine
84
+ const i18nEngine = (0, i18n_1.getStarterI18nEngine)();
85
+ i18nEngine.setLanguage(selectedLanguage);
65
86
  // System check
66
- logger_1.Logger.header('System Check');
87
+ logger_1.Logger.header((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SYSTEM_CHECK_HEADER));
67
88
  const systemCheck = system_check_1.SystemCheck.check();
68
89
  system_check_1.SystemCheck.printReport(systemCheck);
69
90
  if (!systemCheck.passed) {
70
91
  const proceed = await (0, confirm_1.default)({
71
- message: 'Continue anyway? (Installation may fail)',
92
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SYSTEM_CHECK_CONTINUE_ANYWAY),
72
93
  default: false,
73
94
  });
74
95
  if (!proceed) {
75
- logger_1.Logger.info('Cancelled. Please install required tools and try again.');
96
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.CLI_CANCELLED));
76
97
  process.exit(0);
77
98
  }
78
99
  }
@@ -80,49 +101,49 @@ async function main() {
80
101
  const presetPath = path.resolve(__dirname, '../../config/presets/standard.json');
81
102
  const preset = JSON.parse(fs.readFileSync(presetPath, 'utf-8'));
82
103
  // Prompt for workspace configuration
83
- logger_1.Logger.header('Workspace Configuration');
104
+ logger_1.Logger.header((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_WORKSPACE_CONFIG));
84
105
  const workspaceName = await (0, input_1.default)({
85
- message: 'Enter the workspace name:',
106
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_WORKSPACE_NAME),
86
107
  default: 'example-project',
87
- validate: (val) => config_schema_1.ConfigValidator.validateWorkspaceName(val) || 'Invalid workspace name (letters, numbers, dashes only)',
108
+ validate: (val) => config_schema_1.ConfigValidator.validateWorkspaceName(val) || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_INVALID_WORKSPACE_NAME),
88
109
  });
89
110
  const projectPrefix = await (0, input_1.default)({
90
- message: 'Enter the project prefix:',
111
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_PROJECT_PREFIX),
91
112
  default: workspaceName,
92
- validate: (val) => config_schema_1.ConfigValidator.validatePrefix(val) || 'Invalid prefix (lowercase letters, numbers, dashes only)',
113
+ validate: (val) => config_schema_1.ConfigValidator.validatePrefix(val) || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_INVALID_PREFIX),
93
114
  });
94
115
  const namespaceRoot = await (0, input_1.default)({
95
- message: 'Enter the npm namespace:',
116
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_NPM_NAMESPACE),
96
117
  default: `@${projectPrefix}`,
97
- validate: (val) => config_schema_1.ConfigValidator.validateNamespace(val) || 'Invalid namespace (must start with @)',
118
+ validate: (val) => config_schema_1.ConfigValidator.validateNamespace(val) || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_INVALID_NAMESPACE),
98
119
  });
99
120
  const parentDir = path.resolve(await (0, input_1.default)({
100
- message: 'Enter the parent directory:',
121
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_PARENT_DIRECTORY),
101
122
  default: process.cwd(),
102
123
  }));
103
124
  const gitRepo = await (0, input_1.default)({
104
- message: 'Enter the git repository URL (optional):',
105
- validate: (val) => config_schema_1.ConfigValidator.validateGitRepo(val) || 'Invalid git repository URL',
125
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_GIT_REPO),
126
+ validate: (val) => config_schema_1.ConfigValidator.validateGitRepo(val) || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_INVALID_GIT_REPO),
106
127
  });
107
128
  const hostname = await (0, input_1.default)({
108
- message: 'Enter the hostname for development (e.g., example-project.local):',
129
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_HOSTNAME),
109
130
  default: `${workspaceName}.local`,
110
- validate: (val) => /^[a-z0-9-]+(\.[a-z0-9-]+)*$/.test(val) || 'Invalid hostname format',
131
+ validate: (val) => /^[a-z0-9-]+(\.[a-z0-9-]+)*$/.test(val) || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_INVALID_HOSTNAME),
111
132
  });
112
133
  const dryRun = await (0, confirm_1.default)({
113
- message: 'Run in dry-run mode (preview without creating files)?',
134
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_DRY_RUN),
114
135
  default: false,
115
136
  });
116
- logger_1.Logger.section('Optional Projects');
137
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_OPTIONAL_PROJECTS));
117
138
  const includeE2e = await (0, confirm_1.default)({
118
- message: 'Include E2E tests?',
139
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_INCLUDE_E2E),
119
140
  default: true,
120
141
  });
121
- logger_1.Logger.section('Package Groups');
142
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_PACKAGE_GROUPS));
122
143
  const packageGroupsPath = path.resolve(__dirname, '../../config/package-groups.json');
123
144
  const packageGroups = JSON.parse(fs.readFileSync(packageGroupsPath, 'utf-8')).groups;
124
145
  const selectedGroups = await (0, checkbox_1.default)({
125
- message: 'Select optional package groups:',
146
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_SELECT_PACKAGE_GROUPS),
126
147
  choices: packageGroups
127
148
  .filter((g) => !g.enabled)
128
149
  .map((g) => ({
@@ -132,70 +153,70 @@ async function main() {
132
153
  })),
133
154
  });
134
155
  const enableDocGeneration = await (0, confirm_1.default)({
135
- message: 'Generate documentation (README, ARCHITECTURE, API docs)?',
156
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_ENABLE_DOC_GENERATION),
136
157
  default: true,
137
158
  });
138
- logger_1.Logger.section('DevContainer Configuration');
159
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_DEVCONTAINER_CONFIG));
139
160
  const setupDevcontainer = await (0, confirm_1.default)({
140
- message: 'Set up DevContainer configuration?',
161
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_SETUP_DEVCONTAINER),
141
162
  default: true,
142
163
  });
143
164
  let devcontainerChoice = 'none';
144
165
  let mongoPassword = '';
145
166
  if (setupDevcontainer) {
146
167
  devcontainerChoice = await (0, select_1.default)({
147
- message: 'DevContainer configuration:',
168
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_DEVCONTAINER_CONFIG),
148
169
  choices: [
149
- { name: 'Simple (Node.js only)', value: 'simple' },
150
- { name: 'With MongoDB', value: 'mongodb' },
151
- { name: 'With MongoDB Replica Set', value: 'mongodb-replicaset' },
170
+ { name: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.DEVCONTAINER_SIMPLE), value: 'simple' },
171
+ { name: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.DEVCONTAINER_MONGODB), value: 'mongodb' },
172
+ { name: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.DEVCONTAINER_MONGODB_REPLICASET), value: 'mongodb-replicaset' },
152
173
  ],
153
174
  default: 'mongodb-replicaset',
154
175
  });
155
176
  if (devcontainerChoice === 'mongodb' || devcontainerChoice === 'mongodb-replicaset') {
156
177
  mongoPassword = await (0, input_1.default)({
157
- message: 'Enter MongoDB root password:',
158
- validate: (val) => val.length > 0 || 'Password required',
178
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_MONGO_PASSWORD),
179
+ validate: (val) => val.length > 0 || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_PASSWORD_REQUIRED),
159
180
  });
160
181
  }
161
182
  }
162
- logger_1.Logger.section('Database Configuration');
183
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_DATABASE_CONFIG));
163
184
  const useInMemoryDb = await (0, confirm_1.default)({
164
- message: 'Use in-memory database for development?',
185
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_USE_IN_MEMORY_DB),
165
186
  default: false,
166
187
  });
167
188
  let devDatabaseName = '';
168
189
  if (useInMemoryDb) {
169
190
  devDatabaseName = await (0, input_1.default)({
170
- message: 'Enter the in-memory database name:',
191
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_DEV_DATABASE_NAME),
171
192
  default: 'test',
172
- validate: (val) => val.length > 0 || 'Database name cannot be empty',
193
+ validate: (val) => val.length > 0 || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_DATABASE_NAME_REQUIRED),
173
194
  });
174
195
  }
175
- logger_1.Logger.section('Security Configuration');
196
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_SECURITY_CONFIG));
176
197
  const crypto = await Promise.resolve().then(() => __importStar(require('crypto')));
177
198
  const HEX_64_REGEX = /^[0-9a-f]{64}$/i;
178
199
  const promptOrGenerateSecret = async (name) => {
179
200
  const generate = await (0, confirm_1.default)({
180
- message: `Generate ${name}?`,
201
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_GENERATE_SECRET, { name }),
181
202
  default: true,
182
203
  });
183
204
  if (generate) {
184
205
  const secret = crypto.randomBytes(32).toString('hex');
185
- logger_1.Logger.info(`Generated ${name}`);
206
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.ENV_GENERATED_SECRET, { name }));
186
207
  return secret;
187
208
  }
188
209
  else {
189
210
  return await (0, input_1.default)({
190
- message: `Enter ${name} (64-character hex string):`,
191
- validate: (val) => HEX_64_REGEX.test(val) || 'Must be 64-character hex string',
211
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_ENTER_SECRET, { name }),
212
+ validate: (val) => HEX_64_REGEX.test(val) || (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.VALIDATION_MUST_BE_HEX_64),
192
213
  });
193
214
  }
194
215
  };
195
216
  const jwtSecret = await promptOrGenerateSecret('JWT_SECRET');
196
217
  const mnemonicEncryptionKey = await promptOrGenerateSecret('MNEMONIC_ENCRYPTION_KEY');
197
218
  const mnemonicHmacSecret = await promptOrGenerateSecret('MNEMONIC_HMAC_SECRET');
198
- logger_1.Logger.section('Express Suite Packages');
219
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_EXPRESS_SUITE_PACKAGES));
199
220
  const monorepoPath = path.join(parentDir, workspaceName);
200
221
  // Build project configurations
201
222
  const projects = project_config_builder_1.ProjectConfigBuilder.build(projectPrefix, namespaceRoot, {
@@ -260,27 +281,27 @@ async function main() {
260
281
  ? new (await Promise.resolve().then(() => __importStar(require('./core/dry-run-executor')))).DryRunExecutor()
261
282
  : new step_executor_1.StepExecutor();
262
283
  if (dryRun) {
263
- logger_1.Logger.warning('DRY RUN MODE - No files will be created');
284
+ logger_1.Logger.warning((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.GENERATION_DRY_RUN_MODE));
264
285
  }
265
286
  executor.addStep({
266
287
  name: 'checkTargetDir',
267
- description: 'Checking target directory',
288
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_CHECK_TARGET_DIR),
268
289
  execute: () => {
269
290
  if (fs.existsSync(monorepoPath) && fs.readdirSync(monorepoPath).length > 0) {
270
- throw new Error(`Directory ${logger_1.Logger.path(monorepoPath)} already exists and is not empty`);
291
+ throw new i18n_lib_1.TranslatableGenericError(i18n_1.StarterComponentId, i18n_1.StarterStringKey.ERROR_DIRECTORY_NOT_EMPTY, { path: monorepoPath });
271
292
  }
272
293
  },
273
294
  });
274
295
  executor.addStep({
275
296
  name: 'createMonorepo',
276
- description: 'Creating Nx monorepo',
297
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_CREATE_MONOREPO),
277
298
  execute: () => {
278
299
  (0, shell_utils_1.runCommand)(`npx create-nx-workspace@latest "${workspaceName}" --package-manager=yarn --preset=apps --ci=${config.nx?.ciProvider}`, { cwd: parentDir });
279
300
  },
280
301
  });
281
302
  executor.addStep({
282
303
  name: 'setupGitOrigin',
283
- description: 'Setting up git remote',
304
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_SETUP_GIT_ORIGIN),
284
305
  skip: () => !gitRepo,
285
306
  execute: () => {
286
307
  (0, shell_utils_1.runCommand)(`git remote add origin ${gitRepo}`, { cwd: monorepoPath });
@@ -288,7 +309,7 @@ async function main() {
288
309
  });
289
310
  executor.addStep({
290
311
  name: 'yarnBerrySetup',
291
- description: 'Configuring Yarn Berry',
312
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_YARN_BERRY_SETUP),
292
313
  execute: () => {
293
314
  (0, shell_utils_1.runCommand)('yarn set version berry', { cwd: monorepoPath });
294
315
  (0, shell_utils_1.runCommand)('yarn config set nodeLinker node-modules', { cwd: monorepoPath });
@@ -297,19 +318,19 @@ async function main() {
297
318
  });
298
319
  executor.addStep({
299
320
  name: 'addNxPlugins',
300
- description: 'Installing Nx plugins',
321
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_ADD_NX_PLUGINS),
301
322
  execute: () => {
302
323
  try {
303
324
  (0, shell_utils_1.runCommand)('yarn add -D @nx/react @nx/node', { cwd: monorepoPath });
304
325
  }
305
326
  catch (error) {
306
327
  if (error.status === 1) {
307
- logger_1.Logger.error('\nPackage installation failed.');
308
- logger_1.Logger.section('If you see "exit code 127" above, install build tools:');
309
- logger_1.Logger.dim(' Ubuntu/Debian: sudo apt-get install build-essential python3');
310
- logger_1.Logger.dim(' Fedora/RHEL: sudo dnf install gcc-c++ make python3');
311
- logger_1.Logger.dim(' macOS: xcode-select --install');
312
- logger_1.Logger.section('\nThen retry or skip: yarn start --start-at=addYarnPackages');
328
+ logger_1.Logger.error('\n' + (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PACKAGE_INSTALLATION_FAILED));
329
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PACKAGE_INSTALL_BUILD_TOOLS));
330
+ logger_1.Logger.dim(' ' + (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SYSTEM_CHECK_UBUNTU_DEBIAN));
331
+ logger_1.Logger.dim(' ' + (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SYSTEM_CHECK_FEDORA_RHEL));
332
+ logger_1.Logger.dim(' ' + (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SYSTEM_CHECK_MACOS));
333
+ logger_1.Logger.section('\n' + (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PACKAGE_RETRY_OR_SKIP));
313
334
  }
314
335
  throw error;
315
336
  }
@@ -317,7 +338,7 @@ async function main() {
317
338
  });
318
339
  executor.addStep({
319
340
  name: 'addYarnPackages',
320
- description: 'Installing dependencies',
341
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_ADD_YARN_PACKAGES),
321
342
  execute: () => {
322
343
  const devPkgs = config.packages?.dev || [];
323
344
  const prodPkgs = config.packages?.prod || [];
@@ -331,12 +352,12 @@ async function main() {
331
352
  });
332
353
  executor.addStep({
333
354
  name: 'generateProjects',
334
- description: 'Generating project structure',
355
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_GENERATE_PROJECTS),
335
356
  execute: () => {
336
357
  projects.forEach(project => {
337
358
  if (!project.enabled)
338
359
  return;
339
- logger_1.Logger.info(`Generating ${project.type}: ${project.name}`);
360
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROJECT_GENERATING, { type: project.type, name: project.name }));
340
361
  switch (project.type) {
341
362
  case 'react':
342
363
  project_generator_1.ProjectGenerator.generateReact(project, monorepoPath, config.nx);
@@ -389,7 +410,7 @@ async function main() {
389
410
  }
390
411
  }
391
412
  fs.writeFileSync(projectJsonPath, JSON.stringify(projectJson, null, 2) + '\n');
392
- logger_1.Logger.info(`Added copy-env and post-build targets to ${apiProject.name}/project.json`);
413
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROJECT_ADDED_TARGETS, { name: apiProject.name }));
393
414
  }
394
415
  }
395
416
  if (initUserDbProject) {
@@ -424,18 +445,18 @@ async function main() {
424
445
  }
425
446
  }
426
447
  fs.writeFileSync(projectJsonPath, JSON.stringify(projectJson, null, 2) + '\n');
427
- logger_1.Logger.info(`Added copy-env and post-build targets to ${initUserDbProject.name}/project.json`);
448
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROJECT_ADDED_TARGETS, { name: initUserDbProject.name }));
428
449
  }
429
450
  }
430
451
  },
431
452
  });
432
453
  executor.addStep({
433
454
  name: 'installReactComponents',
434
- description: 'Installing React components package',
455
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_INSTALL_REACT_COMPONENTS),
435
456
  execute: () => {
436
457
  const reactLibProject = projects.find(p => p.type === 'react-lib' && p.enabled);
437
458
  if (reactLibProject) {
438
- logger_1.Logger.info(`Installing @digitaldefiance/express-suite-react-components in ${reactLibProject.name}`);
459
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROJECT_INSTALLING_PACKAGE, { package: '@digitaldefiance/express-suite-react-components', project: reactLibProject.name }));
439
460
  const projectPackageJsonPath = path.join(monorepoPath, reactLibProject.name, 'package.json');
440
461
  const projectPackageJson = JSON.parse(fs.readFileSync(projectPackageJsonPath, 'utf-8'));
441
462
  projectPackageJson.dependencies = projectPackageJson.dependencies || {};
@@ -447,7 +468,7 @@ async function main() {
447
468
  });
448
469
  executor.addStep({
449
470
  name: 'renderTemplates',
450
- description: 'Rendering configuration templates',
471
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_RENDER_TEMPLATES),
451
472
  execute: () => {
452
473
  const variables = {
453
474
  WORKSPACE_NAME: workspaceName,
@@ -469,7 +490,7 @@ async function main() {
469
490
  });
470
491
  executor.addStep({
471
492
  name: 'copyScaffolding',
472
- description: 'Copying scaffolding files',
493
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_COPY_SCAFFOLDING),
473
494
  execute: () => {
474
495
  const scaffoldingDir = context.state.get('scaffoldingDir');
475
496
  // Template variables for scaffolding
@@ -504,14 +525,14 @@ async function main() {
504
525
  });
505
526
  executor.addStep({
506
527
  name: 'generateLicense',
507
- description: 'Generating LICENSE file',
528
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_GENERATE_LICENSE),
508
529
  execute: async () => {
509
530
  await (0, licensePrompt_1.promptAndGenerateLicense)(monorepoPath);
510
531
  },
511
532
  });
512
533
  executor.addStep({
513
534
  name: 'addScripts',
514
- description: 'Adding package.json scripts',
535
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_ADD_SCRIPTS),
515
536
  execute: () => {
516
537
  const packageJsonPath = path.join(monorepoPath, 'package.json');
517
538
  const scriptContext = {
@@ -553,7 +574,7 @@ async function main() {
553
574
  });
554
575
  executor.addStep({
555
576
  name: 'generateDocumentation',
556
- description: 'Generating documentation',
577
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_GENERATE_DOCUMENTATION),
557
578
  skip: () => !enableDocGeneration || dryRun,
558
579
  execute: async () => {
559
580
  const { DocGenerator } = await Promise.resolve().then(() => __importStar(require('./utils/doc-generator')));
@@ -562,7 +583,7 @@ async function main() {
562
583
  });
563
584
  executor.addStep({
564
585
  name: 'setupEnvironment',
565
- description: 'Setting up environment files',
586
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_SETUP_ENVIRONMENT),
566
587
  execute: () => {
567
588
  const apiProject = projects.find(p => p.type === 'api');
568
589
  const initUserDbProject = projects.find(p => p.type === 'inituserdb');
@@ -611,46 +632,73 @@ async function main() {
611
632
  }
612
633
  // Setup devcontainer .env if devcontainer with MongoDB
613
634
  if (devcontainerChoice === 'mongodb' || devcontainerChoice === 'mongodb-replicaset') {
635
+ const devcontainerEnvExamplePath = path.join(monorepoPath, '.devcontainer', '.env.example');
614
636
  const devcontainerEnvPath = path.join(monorepoPath, '.devcontainer', '.env');
615
- const mongoUri = buildMongoUri(workspaceName);
616
- const envContent = `MONGO_PASSWORD=${mongoPassword}\nMONGO_URI=${mongoUri}\n`;
617
- fs.writeFileSync(devcontainerEnvPath, envContent);
618
- logger_1.Logger.info('Created .devcontainer/.env with MongoDB configuration');
637
+ if (fs.existsSync(devcontainerEnvExamplePath)) {
638
+ let envContent = fs.readFileSync(devcontainerEnvExamplePath, 'utf-8');
639
+ const mongoUri = buildMongoUri(workspaceName);
640
+ // Replace MongoDB configuration
641
+ envContent = envContent.replace(/MONGO_INITDB_ROOT_PASSWORD=.*/g, `MONGO_INITDB_ROOT_PASSWORD=${mongoPassword}`);
642
+ envContent = envContent.replace(/MONGO_INITDB_DATABASE=.*/g, `MONGO_INITDB_DATABASE=${workspaceName}`);
643
+ envContent = envContent.replace(/COMPOSE_PROJECT_NAME=.*/g, `COMPOSE_PROJECT_NAME=${workspaceName}_devcontainer`);
644
+ // Add MONGO_PASSWORD and MONGO_URI if not present
645
+ if (!envContent.includes('MONGO_PASSWORD=')) {
646
+ envContent += `\nMONGO_PASSWORD=${mongoPassword}\n`;
647
+ }
648
+ else {
649
+ envContent = envContent.replace(/MONGO_PASSWORD=.*/g, `MONGO_PASSWORD=${mongoPassword}`);
650
+ }
651
+ if (!envContent.includes('MONGO_URI=')) {
652
+ envContent += `MONGO_URI=${mongoUri}\n`;
653
+ }
654
+ else {
655
+ envContent = envContent.replace(/MONGO_URI=.*/g, `MONGO_URI=${mongoUri}`);
656
+ }
657
+ fs.writeFileSync(devcontainerEnvPath, envContent);
658
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.ENV_CREATED_DEVCONTAINER_FROM_EXAMPLE));
659
+ }
660
+ else {
661
+ // Fallback to minimal .env if .env.example doesn't exist
662
+ const mongoUri = buildMongoUri(workspaceName);
663
+ const envContent = `MONGO_PASSWORD=${mongoPassword}\nMONGO_URI=${mongoUri}\n`;
664
+ fs.writeFileSync(devcontainerEnvPath, envContent);
665
+ logger_1.Logger.warning((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.ENV_CREATED_DEVCONTAINER_MINIMAL));
666
+ }
619
667
  }
620
668
  },
621
669
  });
622
670
  executor.addStep({
623
671
  name: 'rebuildNativeModules',
624
- description: 'Building native modules',
672
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_REBUILD_NATIVE_MODULES),
625
673
  execute: () => {
626
- logger_1.Logger.info('Re-enabling build scripts and building native modules...');
674
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.COMMAND_REBUILDING_NATIVE));
627
675
  (0, shell_utils_1.runCommand)('yarn config set enableScripts true', { cwd: monorepoPath });
628
676
  (0, shell_utils_1.runCommand)('yarn rebuild', { cwd: monorepoPath });
629
677
  },
630
678
  });
631
679
  executor.addStep({
632
680
  name: 'validateGeneration',
633
- description: 'Validating generated project',
681
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_VALIDATE_GENERATION),
634
682
  skip: () => dryRun,
635
683
  execute: async () => {
636
684
  const { PostGenerationValidator } = await Promise.resolve().then(() => __importStar(require('./core/validators/post-generation-validator')));
637
685
  const report = await PostGenerationValidator.validate(context);
638
686
  PostGenerationValidator.printReport(report);
639
687
  if (!report.passed) {
640
- logger_1.Logger.warning('Validation found errors, but continuing...');
688
+ logger_1.Logger.warning((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.WARNING_VALIDATION_ERRORS));
641
689
  }
642
690
  },
643
691
  });
644
692
  executor.addStep({
645
693
  name: 'initialCommit',
646
- description: 'Creating initial commit',
694
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_INITIAL_COMMIT),
647
695
  execute: async () => {
648
696
  // Ensure git is initialized
649
697
  if (!fs.existsSync(path.join(monorepoPath, '.git'))) {
650
698
  (0, shell_utils_1.runCommand)('git init', { cwd: monorepoPath });
651
699
  }
652
700
  const doCommit = await (0, confirm_1.default)({
653
- message: 'Create initial git commit?',
701
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_CREATE_INITIAL_COMMIT),
654
702
  default: true,
655
703
  });
656
704
  if (doCommit) {
@@ -658,7 +706,7 @@ async function main() {
658
706
  (0, shell_utils_1.runCommand)('git commit -m "Initial commit"', { cwd: monorepoPath });
659
707
  if (gitRepo) {
660
708
  const doPush = await (0, confirm_1.default)({
661
- message: 'Push to remote repository?',
709
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_PUSH_TO_REMOTE),
662
710
  default: true,
663
711
  });
664
712
  if (doPush) {
@@ -670,19 +718,19 @@ async function main() {
670
718
  });
671
719
  executor.addStep({
672
720
  name: 'installPlaywright',
673
- description: 'Installing Playwright browsers',
721
+ description: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.STEP_INSTALL_PLAYWRIGHT),
674
722
  skip: () => !includeE2e,
675
723
  execute: async () => {
676
724
  const installPlaywright = await (0, confirm_1.default)({
677
- message: 'Install Playwright browsers? (Required for E2E tests)',
725
+ message: (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.PROMPT_INSTALL_PLAYWRIGHT),
678
726
  default: true,
679
727
  });
680
728
  if (installPlaywright) {
681
- logger_1.Logger.info('Installing Playwright browsers (this may take a few minutes)...');
729
+ logger_1.Logger.info((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.COMMAND_INSTALLING_PLAYWRIGHT_BROWSERS));
682
730
  (0, shell_utils_1.runCommand)('yarn playwright install --with-deps', { cwd: monorepoPath });
683
731
  }
684
732
  else {
685
- logger_1.Logger.warning('Skipped. Run manually later: yarn playwright install --with-deps');
733
+ logger_1.Logger.warning((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.COMMAND_SKIPPED_PLAYWRIGHT));
686
734
  }
687
735
  },
688
736
  });
@@ -690,26 +738,26 @@ async function main() {
690
738
  try {
691
739
  await executor.execute(context);
692
740
  if (dryRun) {
693
- logger_1.Logger.warning('Dry-run complete. Re-run without dry-run to generate.');
741
+ logger_1.Logger.warning((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.WARNING_DRY_RUN_RERUN));
694
742
  process.exit(0);
695
743
  }
696
- logger_1.Logger.header('Generation Complete!');
697
- logger_1.Logger.success(`Monorepo created at: ${logger_1.Logger.path(monorepoPath)}`);
744
+ logger_1.Logger.header((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SUCCESS_GENERATION_COMPLETE));
745
+ logger_1.Logger.success((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SUCCESS_MONOREPO_CREATED, { path: logger_1.Logger.path(monorepoPath) }));
698
746
  const apiProject = projects.find(p => p.type === 'api');
699
747
  if (apiProject) {
700
- logger_1.Logger.warning(`\nIMPORTANT: Update ${apiProject.name}/.env with your configuration`);
748
+ logger_1.Logger.warning(`\n` + (0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.WARNING_UPDATE_ENV_FILE, { name: apiProject.name }));
701
749
  }
702
750
  if (devcontainerChoice === 'mongodb' || devcontainerChoice === 'mongodb-replicaset') {
703
- logger_1.Logger.warning(`IMPORTANT: Update .devcontainer/.env with your MongoDB configuration`);
751
+ logger_1.Logger.warning((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.WARNING_UPDATE_DEVCONTAINER_ENV));
704
752
  }
705
- logger_1.Logger.section('Next steps:');
753
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_NEXT_STEPS));
706
754
  logger_1.Logger.dim(` cd ${workspaceName}`);
707
755
  if (apiProject) {
708
- logger_1.Logger.dim(` # Update ${apiProject.name}/.env with your settings`);
756
+ logger_1.Logger.dim(` ${(0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_NEXT_STEPS_UPDATE_ENV, { name: apiProject.name })}`);
709
757
  }
710
758
  logger_1.Logger.dim(` yarn build:dev`);
711
759
  logger_1.Logger.dim(` yarn serve:dev`);
712
- logger_1.Logger.section('Generated projects:');
760
+ logger_1.Logger.section((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.SECTION_GENERATED_PROJECTS));
713
761
  projects.forEach(p => {
714
762
  if (p.enabled) {
715
763
  logger_1.Logger.dim(` ${p.type.padEnd(12)} ${p.name}`);
@@ -717,14 +765,14 @@ async function main() {
717
765
  });
718
766
  }
719
767
  catch (error) {
720
- logger_1.Logger.error('Generation failed');
768
+ logger_1.Logger.error((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.GENERATION_FAILED));
721
769
  console.error(error);
722
770
  process.exit(1);
723
771
  }
724
772
  }
725
773
  if (require.main === module) {
726
774
  main().catch((err) => {
727
- logger_1.Logger.error('Fatal error');
775
+ logger_1.Logger.error((0, i18n_1.getStarterTranslation)(i18n_1.StarterStringKey.ERROR_FATAL));
728
776
  console.error(err);
729
777
  process.exit(1);
730
778
  });