@codenotch/codenotch.cli 1.0.33 → 1.0.35

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 (99) hide show
  1. package/dist/commands/index.js +2 -0
  2. package/dist/commands/index.js.map +1 -1
  3. package/dist/commands/project/new.js +227 -1
  4. package/dist/commands/project/new.js.map +1 -1
  5. package/dist/commands/validation/ValidationUtils.d.ts +28 -0
  6. package/dist/commands/validation/ValidationUtils.js +182 -0
  7. package/dist/commands/validation/ValidationUtils.js.map +1 -0
  8. package/dist/commands/validation/files/AppManifestValidator.d.ts +6 -0
  9. package/dist/commands/validation/files/AppManifestValidator.js +93 -0
  10. package/dist/commands/validation/files/AppManifestValidator.js.map +1 -0
  11. package/dist/commands/validation/files/BpmnValidator.d.ts +5 -0
  12. package/dist/commands/validation/files/BpmnValidator.js +32 -0
  13. package/dist/commands/validation/files/BpmnValidator.js.map +1 -0
  14. package/dist/commands/validation/files/DbSchemaValidator.d.ts +5 -0
  15. package/dist/commands/validation/files/DbSchemaValidator.js +16 -0
  16. package/dist/commands/validation/files/DbSchemaValidator.js.map +1 -0
  17. package/dist/commands/validation/files/DocumentValidator.d.ts +5 -0
  18. package/dist/commands/validation/files/DocumentValidator.js +12 -0
  19. package/dist/commands/validation/files/DocumentValidator.js.map +1 -0
  20. package/dist/commands/validation/files/I18nValidator.d.ts +5 -0
  21. package/dist/commands/validation/files/I18nValidator.js +13 -0
  22. package/dist/commands/validation/files/I18nValidator.js.map +1 -0
  23. package/dist/commands/validation/files/JsonValidator.d.ts +5 -0
  24. package/dist/commands/validation/files/JsonValidator.js +13 -0
  25. package/dist/commands/validation/files/JsonValidator.js.map +1 -0
  26. package/dist/commands/validation/files/ManifestCacheValidator.d.ts +5 -0
  27. package/dist/commands/validation/files/ManifestCacheValidator.js +121 -0
  28. package/dist/commands/validation/files/ManifestCacheValidator.js.map +1 -0
  29. package/dist/commands/validation/files/ManifestValidator.d.ts +5 -0
  30. package/dist/commands/validation/files/ManifestValidator.js +14 -0
  31. package/dist/commands/validation/files/ManifestValidator.js.map +1 -0
  32. package/dist/commands/validation/files/ScriptValidator.d.ts +12 -0
  33. package/dist/commands/validation/files/ScriptValidator.js +128 -0
  34. package/dist/commands/validation/files/ScriptValidator.js.map +1 -0
  35. package/dist/commands/validation/files/TableValidator.d.ts +5 -0
  36. package/dist/commands/validation/files/TableValidator.js +19 -0
  37. package/dist/commands/validation/files/TableValidator.js.map +1 -0
  38. package/dist/commands/validation/validate.d.ts +2 -0
  39. package/dist/commands/validation/validate.js +245 -0
  40. package/dist/commands/validation/validate.js.map +1 -0
  41. package/dist/utils/BuildUtils.d.ts +23 -4
  42. package/dist/utils/BuildUtils.js +46 -16
  43. package/dist/utils/BuildUtils.js.map +1 -1
  44. package/dist/utils/FileUtils.d.ts +13 -0
  45. package/dist/utils/FileUtils.js +30 -0
  46. package/dist/utils/FileUtils.js.map +1 -1
  47. package/dist/utils/I18nUtils.js +0 -2
  48. package/dist/utils/I18nUtils.js.map +1 -1
  49. package/package.json +14 -6
  50. package/.github/copilot-instructions.md +0 -3
  51. package/bin/cli.js +0 -3
  52. package/docs/ARCHITECTURE.md +0 -179
  53. package/docs/TODO.md +0 -18
  54. package/src/bin/cli.ts +0 -4
  55. package/src/commands/index.ts +0 -13
  56. package/src/commands/project/compile.ts +0 -20
  57. package/src/commands/project/deploy.ts +0 -11
  58. package/src/commands/project/index.ts +0 -28
  59. package/src/commands/project/inspect.ts +0 -12
  60. package/src/commands/project/new.ts +0 -11
  61. package/src/commands/project/open.ts +0 -21
  62. package/src/commands/project/package.ts +0 -20
  63. package/src/commands/project/refresh.ts +0 -13
  64. package/src/commands/project/remove.ts +0 -12
  65. package/src/commands/project/shared.ts +0 -9
  66. package/src/commands/project/start.ts +0 -24
  67. package/src/commands/project/test.ts +0 -15
  68. package/src/commands/react/build.ts +0 -12
  69. package/src/commands/react/index.ts +0 -12
  70. package/src/commands/react/serve.ts +0 -13
  71. package/src/commands/runtime/clear.ts +0 -11
  72. package/src/commands/runtime/index.ts +0 -24
  73. package/src/commands/runtime/info.ts +0 -47
  74. package/src/commands/runtime/latest.ts +0 -18
  75. package/src/commands/runtime/portal.ts +0 -20
  76. package/src/commands/runtime/start.ts +0 -16
  77. package/src/commands/runtime/stop.ts +0 -13
  78. package/src/commands/runtime/update.ts +0 -12
  79. package/src/commands/system/index.ts +0 -9
  80. package/src/commands/system/info.ts +0 -23
  81. package/src/commands/system/read.ts +0 -25
  82. package/src/index.ts +0 -22
  83. package/src/models/Codenotch.ts +0 -361
  84. package/src/models/DbModels.ts +0 -428
  85. package/src/models/OpenApiModels.ts +0 -145
  86. package/src/utils/BuildUtils.ts +0 -739
  87. package/src/utils/ConsoleUtils.ts +0 -22
  88. package/src/utils/FileUtils.ts +0 -266
  89. package/src/utils/GitHubAuthUtils.ts +0 -83
  90. package/src/utils/I18nUtils.ts +0 -58
  91. package/src/utils/OpenAPIUtils.ts +0 -285
  92. package/src/utils/OsUtils.ts +0 -32
  93. package/src/utils/ProjectCompilationUtils.ts +0 -1002
  94. package/src/utils/ProjectUtils.ts +0 -151
  95. package/src/utils/RuntimeUtils.ts +0 -743
  96. package/src/utils/ServeUtils.ts +0 -175
  97. package/src/utils/ShellUtils.ts +0 -26
  98. package/src/utils/StringUtils.ts +0 -80
  99. package/tsconfig.json +0 -35
@@ -1,739 +0,0 @@
1
- import { existsSync, readFileSync, readSync } from "fs";
2
- import StringUtils from "./StringUtils";
3
- import { ApplicationManifest, IScenarioProjectManifest, IWorkspaceCache, ProjectManifest } from "../models/Codenotch";
4
- import FileUtils from "./FileUtils";
5
- import chalk from "chalk";
6
- import fs from 'fs';
7
- import fse from 'fs-extra';
8
- import I18nUtils from "./I18nUtils";
9
- import fetch from "node-fetch";
10
- import ShellUtils from "./ShellUtils";
11
- import { platform } from "os";
12
- import ConsoleUtils from "./ConsoleUtils";
13
-
14
- interface IWorkspace {
15
- manifest: ProjectManifest;
16
- path: string;
17
- }
18
-
19
- export interface IBuildOptions {
20
- cluster?: string;
21
- }
22
-
23
- export default abstract class BuildUtils {
24
-
25
- static findWorkspaceFromFile(childPath: string) {
26
- let parts = childPath.split(FileUtils.slash());
27
- parts = parts.slice(0, parts.length - 1); // Remove file name
28
- let workspacePath: string | undefined = undefined;
29
- while (parts.length > 0) {
30
- let checkPath = parts.join(FileUtils.slash());
31
- parts.pop();
32
- let checkManifestPath = StringUtils.normalizePath(`${checkPath}\\manifest.json`);
33
- if (existsSync(checkManifestPath)) {
34
- workspacePath = checkPath;
35
- }
36
- }
37
- return workspacePath;
38
- }
39
-
40
- /**
41
- * cn react build <target_file>
42
- */
43
-
44
- static async buildApp(appFilePath: string, clusterUrl?: string) {
45
- //appFilePath = '/home/fabian/Documents/Scenario/test-with-jsx/apps/AppWithFC.tsx';
46
- //clusterUrl = 'https://fabric.echino.com:19081/lemollqa/scenario';
47
-
48
- if(`${appFilePath??''}`.trim() === ''){
49
- console.log(chalk.red(`Error: No target file provided for build command.`));
50
- process.exit(1);
51
- }
52
-
53
- let isRelative = !appFilePath.startsWith('/') && !appFilePath.match(/^[a-zA-Z]:\\/);
54
- if (isRelative) {
55
- let currentPath = process.cwd();
56
- appFilePath = StringUtils.normalizePath(`${currentPath}/${appFilePath}`);
57
- }
58
-
59
-
60
- // Check arguments
61
- if (existsSync(appFilePath ?? '') === false) {
62
- console.log(chalk.red(`Error: File "${appFilePath}" not found`));
63
- process.exit(1);
64
- }
65
-
66
- let workspacePath = this.findWorkspaceFromFile(appFilePath) ?? '';
67
- if (workspacePath === '' || existsSync(workspacePath ?? '') === false) {
68
- console.log(chalk.red(`Error: Could not find workspace manifest for file "${appFilePath}".`));
69
- process.exit(1);
70
- }
71
-
72
-
73
-
74
- // Tenant name
75
- let tenantName = await this.fetchTenantName(clusterUrl);
76
-
77
-
78
-
79
- // Load workspace
80
- console.log("Loading workspace manifest...");
81
- let workspace: IWorkspace = {
82
- manifest: this.getFullManifestAt(workspacePath),
83
- path: workspacePath
84
- };
85
- ConsoleUtils.check(`Workspace manifest loaded successfully\n`);
86
-
87
-
88
-
89
- // Get app manifest
90
- console.log(`Reading app manifest... (${appFilePath})`);
91
- let appFilename = StringUtils.getFilenameFromUri(appFilePath);
92
- let appFileParentPath = StringUtils.getFolder(appFilePath);
93
- let appManifestPath = StringUtils.normalizePath(`${appFileParentPath}/${appFilename.replace(/\.[^/.]+$/, '.manifest.json')}`);
94
- let appManifestContent = fs.readFileSync(appManifestPath, 'utf-8');
95
- if (appManifestContent === undefined) {
96
- console.log(chalk.red(`Error: App manifest file not found at "${appManifestPath}"\n`));
97
- process.exit(1);
98
- }
99
- let appManifest: ApplicationManifest = JSON.parse(appManifestContent);
100
- let appName = `${appManifest.auml?.name ?? ''}`.trim();
101
- if (appName === '') {
102
- console.log(chalk.red(`Error: App name not found in manifest at "${appManifestPath}"\n`));
103
- process.exit(1);
104
- }
105
- ConsoleUtils.check(`App manifest loaded successfully (App name: "${appName}").\n`);
106
-
107
-
108
- // Define paths
109
- let outDir = StringUtils.normalizePath(`${workspacePath}/.codenotch/${appName}-source`);
110
- let distDir = StringUtils.normalizePath(`${workspacePath}/.codenotch/${appName}-dist`);
111
- let fileName = StringUtils.firstUpper(StringUtils.getNameWithoutExtention(appFilename));
112
- let outFilePath = StringUtils.normalizePath(`${appFilePath.replace(workspacePath, outDir + '/src')}`);
113
- let relativeOutFilePath = StringUtils.toRelativePath(outFilePath, outDir).replaceAll('\\', '/');
114
-
115
-
116
- // Clean previous builds
117
- if (existsSync(outDir) || existsSync(distDir)) {
118
- console.log("Cleaning previous builds...");
119
- FileUtils.delete(outDir);
120
- FileUtils.delete(distDir);
121
- ConsoleUtils.check(`Output directory cleaned (${outDir})\n`);
122
- }
123
-
124
-
125
- console.log("Creating build files...");
126
- // package.json
127
- let pgkJson = this.createPkgJson(workspacePath, appName);
128
- FileUtils.writeFileSync(outDir + '/package.json', JSON.stringify(pgkJson, null, 4));
129
- ConsoleUtils.check(`package.json created successfully`);
130
-
131
- // index.html
132
- let indexHtml = this.createIndexHtml(appManifest, appName);
133
- FileUtils.writeFileSync(outDir + '/index.html', indexHtml);
134
- ConsoleUtils.check(`index.html created successfully`);
135
-
136
- // index.jsx
137
- let indexJsx = this.createIndexJsx(relativeOutFilePath, fileName);
138
- FileUtils.writeFileSync(outDir + '/index.jsx', indexJsx);
139
- ConsoleUtils.check(`index.jsx created successfully`);
140
-
141
- // vite.config.js
142
- let viteConfig = this.createViteConfig(appName);
143
- FileUtils.writeFileSync(outDir + '/vite.config.js', viteConfig);
144
- ConsoleUtils.check(`vite.config.js created successfully`);
145
-
146
- // empty-module.js
147
- let emptyModule = this.createEmptyModule();
148
- FileUtils.writeFileSync(outDir + '/empty-module.js', emptyModule);
149
- ConsoleUtils.check(`empty-module.js created successfully`);
150
-
151
- // tsconfig.json
152
- let tsconfig = this.createTsConfig();
153
- FileUtils.writeFileSync(outDir + '/tsconfig.json', tsconfig);
154
- ConsoleUtils.check(`tsconfig.json created successfully`);
155
-
156
- let npmRcContent = fs.existsSync(StringUtils.normalizePath(`${workspacePath}/.npmrc`)) ?
157
- fs.readFileSync(StringUtils.normalizePath(`${workspacePath}/.npmrc`), 'utf-8') :
158
- '';
159
- if(npmRcContent.trim() !== ''){
160
- FileUtils.writeFileSync(outDir + '/.npmrc', npmRcContent);
161
- ConsoleUtils.check(`.npmrc copied successfully`);
162
- }
163
-
164
-
165
- // Find files to copy
166
- console.log("\n");
167
- console.log("Reading files...");
168
- let includedExts = ['.css', '.scss', '.tsx', '.jsx', '.ts', '.js'];
169
- let includedFiles: string[] = [];
170
- for (let file of FileUtils.getAllFilesFromPath(workspacePath)) {
171
- if (includedExts.some(ext => file.toLowerCase().endsWith(ext))) {
172
- includedFiles.push(file);
173
- }
174
- }
175
- if (includedFiles.length === 0) {
176
- console.log(chalk.red(`Error: No files found in "${workspacePath}" to include in the build`));
177
- return;
178
- }
179
- for (let includedFile of includedFiles) {
180
- let targetPath = StringUtils.normalizePath(`${includedFile.replace(workspacePath, outDir + '/src')}`);
181
- fse.copySync(includedFile, targetPath);
182
- }
183
- ConsoleUtils.check(`${includedFiles.length} files copied successfully\n`);
184
-
185
-
186
-
187
- // execute npm i in the outDir
188
- await ShellUtils.exec(outDir, 'npm install', 'Installing dependencies', true);
189
-
190
- // Install and use Node.js 20 with nvm (platform-specific)
191
- if (platform() === 'win32') {
192
- await ShellUtils.exec(outDir, 'nvm install 20 && nvm use 20 && npm run build', 'Setting up Node.js 20 and building project', true);
193
- } else {
194
- await ShellUtils.exec(outDir, 'bash -c ". ~/.nvm/nvm.sh && nvm install 20 && nvm use 20 && npm run build"', 'Setting up Node.js 20 and building project', true);
195
- }
196
- ConsoleUtils.check(`Nvm and build executed successfully\n`);
197
-
198
-
199
- // create .env file
200
- console.log("Creating .env file...");
201
- let envVariables: any = await this.getCodenotchEnvVariables(workspace, {
202
- appName: appName,
203
- app: appManifest,
204
- tenantName: tenantName,
205
- clusterUrl: clusterUrl
206
- });
207
- let envContent = Object.keys(envVariables).map(c => `${c}=${envVariables[c]}`).join('\n');
208
- FileUtils.writeFileSync(distDir + '/.env', envContent);
209
- ConsoleUtils.check(`.env file created successfully\n`);
210
-
211
- // create auml.json file
212
- console.log("Creating auml.json file...");
213
- let aumlJson = JSON.stringify(this.getAumlVariables(workspace, tenantName, clusterUrl), null, 4);
214
- FileUtils.writeFileSync(distDir + '/auml.json', aumlJson);
215
- ConsoleUtils.check(`auml.json file created successfully\n`);
216
-
217
- let bundlePath = StringUtils.normalizePath(`${distDir}`);
218
- console.log('');
219
- console.log(chalk.green(`Build completed!\n`));
220
- console.log(`Bundle available at "${bundlePath}"\n`);
221
-
222
- let serveCommand = `cn react serve '${bundlePath}'`;
223
- console.log(`You can serve the build using the following command:\n`);
224
- console.log(chalk.green(`${serveCommand}`) + ConsoleUtils.proposeCommand('Do you want to serve the build?', serveCommand));
225
- }
226
-
227
- static async buildApp2(appFilePath: string): Promise<string> {
228
-
229
- // Joé:
230
- // Temporary minimal method to build React app to package and deploy the project, not sure if should replaced the current build or not
231
- // Should work in CI/CD
232
- // Doesn't create .env or auml.json, assume we are using the correct Node version
233
- // Create/delete files, assume it's working in copy of the project
234
- // In this method, caller is responsible for having Node 20 installed and ready
235
-
236
- if(`${appFilePath??''}`.trim() === ''){
237
- throw new Error(`No target file provided for build command.`);
238
- }
239
-
240
- let isRelative = !appFilePath.startsWith('/') && !appFilePath.match(/^[a-zA-Z]:\\/);
241
- if (isRelative) {
242
- let currentPath = process.cwd();
243
- appFilePath = StringUtils.normalizePath(`${currentPath}/${appFilePath}`);
244
- }
245
-
246
- // Check arguments
247
- if (existsSync(appFilePath ?? '') === false) {
248
- throw new Error(`File "${appFilePath}" not found`);
249
- }
250
-
251
- let workspacePath = this.findWorkspaceFromFile(appFilePath) ?? '';
252
- if (workspacePath === '' || existsSync(workspacePath ?? '') === false) {
253
- throw new Error(`Could not find workspace manifest for file "${appFilePath}".`);
254
- }
255
-
256
- // Get app manifest
257
- let appFilename = StringUtils.getFilenameFromUri(appFilePath);
258
- let appFileParentPath = StringUtils.getFolder(appFilePath);
259
- let appManifestPath = StringUtils.normalizePath(`${appFileParentPath}/${appFilename.replace(/\.[^/.]+$/, '.manifest.json')}`);
260
- let appManifestContent = fs.readFileSync(appManifestPath, 'utf-8');
261
- if (appManifestContent === undefined) {
262
- throw new Error(`App manifest file not found at "${appManifestPath}"`);
263
- }
264
- let appManifest: ApplicationManifest = JSON.parse(appManifestContent);
265
- let appName = `${appManifest.auml?.name ?? ''}`.trim();
266
- if (appName === '') {
267
- throw new Error(`App name not found in manifest at "${appManifestPath}"`);
268
- }
269
-
270
- // Define paths
271
- // We mirror the user's workspace layout directly under outDir (no extra "src/" wrapper),
272
- // so any tool config that uses project-root-relative paths (e.g. tailwind's `content`,
273
- // postcss, eslint, ...) resolves exactly as it does in the user's project.
274
- let outDir = StringUtils.normalizePath(`${workspacePath}/.codenotch/${appName}-build`);
275
- let distDir = StringUtils.normalizePath(`${workspacePath}/.codenotch/${appName}-dist`);
276
- let fileName = StringUtils.firstUpper(StringUtils.getNameWithoutExtention(appFilename));
277
- let outFilePath = StringUtils.normalizePath(`${appFilePath.replace(workspacePath, outDir)}`);
278
- let relativeOutFilePath = StringUtils.toRelativePath(outFilePath, outDir).replaceAll('\\', '/');
279
-
280
- // package.json
281
- let pgkJson = this.createPkgJson(workspacePath, appName);
282
- FileUtils.writeFileSync(outDir + '/package.json', JSON.stringify(pgkJson, null, 4));
283
-
284
- // index.html
285
- let indexHtml = this.createIndexHtml(appManifest, appName);
286
- FileUtils.writeFileSync(outDir + '/index.html', indexHtml);
287
-
288
- // index.jsx
289
- let indexJsx = this.createIndexJsxDeployment(relativeOutFilePath, fileName);
290
- FileUtils.writeFileSync(outDir + '/index.jsx', indexJsx);
291
-
292
- // vite.config.mjs (.mjs so it always loads as ESM, regardless of package.json "type")
293
- let viteConfig = this.createViteConfig(appName);
294
- FileUtils.writeFileSync(outDir + '/vite.config.mjs', viteConfig);
295
-
296
- // empty-module.js , needed to mock some modules crypto-browserify -> can we avoid this ?
297
- let emptyModule = this.createEmptyModule();
298
- FileUtils.writeFileSync(outDir + '/empty-module.js', emptyModule);
299
-
300
- // tsconfig.json — layout is flat (mirrors the workspace), so typecheck the source trees
301
- let tsconfig = this.createTsConfig(["**/*.ts", "**/*.tsx"]);
302
- FileUtils.writeFileSync(outDir + '/tsconfig.json', tsconfig);
303
-
304
- let npmRcContent = fs.existsSync(StringUtils.normalizePath(`${workspacePath}/.npmrc`)) ?
305
- fs.readFileSync(StringUtils.normalizePath(`${workspacePath}/.npmrc`), 'utf-8') :
306
- '';
307
- if(npmRcContent.trim() !== ''){
308
- FileUtils.writeFileSync(outDir + '/.npmrc', npmRcContent);
309
- }
310
-
311
- // Find files to copy
312
- //TODO what if we have 2 apps in the /apps folder ? if we build one it will copy the file from the other as they are not separated in different folders
313
- let includedExts = ['.css', '.scss', '.tsx', '.jsx', '.ts', '.js', '.cjs', '.mjs'];
314
- let includedFiles: string[] = [];
315
- for (let file of FileUtils.getAllFilesFromPath(workspacePath)) {
316
- // Skip generated/dependency trees so we don't copy the build output back into itself.
317
- let normalized = file.replaceAll('\\', '/');
318
- if (normalized.includes('/.codenotch/') || normalized.includes('/node_modules/')) {
319
- continue;
320
- }
321
- if (includedExts.some(ext => file.toLowerCase().endsWith(ext))) {
322
- includedFiles.push(file);
323
- }
324
- }
325
- if (includedFiles.length === 0) {
326
- throw new Error(`No files found in "${workspacePath}" to include in the build`);
327
- }
328
- for (let includedFile of includedFiles) {
329
- // Mirror the workspace layout under outDir (no "src/" wrapper) so root config files
330
- // land at the build root and config-relative paths keep working.
331
- let targetPath = StringUtils.normalizePath(`${includedFile.replace(workspacePath, outDir)}`);
332
- fse.copySync(includedFile, targetPath);
333
- }
334
-
335
- try
336
- {
337
- await ShellUtils.exec(outDir, 'npm install', undefined, true);
338
- await ShellUtils.exec(outDir, 'npm run build', undefined, true);
339
-
340
- // Copy the app manifest to the dist folder
341
- const newAppManifestPath = StringUtils.normalizePath(`${distDir}/app.manifest.json`);
342
- fse.copyFileSync(appManifestPath, newAppManifestPath);
343
-
344
- let bundlePath = StringUtils.normalizePath(`${distDir}`);
345
- return bundlePath;
346
- }
347
- finally
348
- {
349
- // Delete the build folder
350
- fse.removeSync(outDir);
351
- }
352
- }
353
-
354
- private static createIndexJsx(relativeOutFilePath: string, fileName: string): string {
355
- return `
356
- import React from 'react';
357
- import ReactDOM from 'react-dom';
358
- import ${fileName} from './${relativeOutFilePath}';
359
- import { init } from 'codenotch-react';
360
-
361
- fetch('/api/env')
362
- .then(response => response.json())
363
- .then(data => {
364
- init(data);
365
- ReactDOM.render(<${fileName} />, document.getElementById('root'));
366
- })
367
- .catch(error => {
368
- console.error('Error fetching environment variables:', error);
369
- init(null);
370
- ReactDOM.render(<${fileName} />, document.getElementById('root'));
371
- });
372
- `.trim();
373
- }
374
-
375
- /**
376
- * When served from the runtime env variables are not available, the variables are injected into the html file instead
377
- */
378
- private static createIndexJsxDeployment(relativeOutFilePath: string, fileName: string): string {
379
- return `
380
- import React from 'react';
381
- import ReactDOM from 'react-dom';
382
- import ${fileName} from './${relativeOutFilePath}';
383
- import { init } from 'codenotch-react';
384
-
385
- // variables are injected into the html by the runtime, we can access them on the window object
386
- const data = {
387
- clusterUrl: tenant.clusterUrl,
388
- serviceName: serviceName,
389
- theme: 'dark',
390
- language: languages[0] ?? 'en',
391
- appManifest: appManifest,
392
- tenantName: tenant.name,
393
- appName: appName
394
- };
395
- init(data);
396
- ReactDOM.render(<${fileName} />, document.getElementById('root'));
397
-
398
- `.trim();
399
- }
400
-
401
-
402
- private static async fetchTenantName(clusterUrl?: string): Promise<string | undefined> {
403
- let tenantName: string | undefined = undefined;
404
- if (clusterUrl !== undefined) {
405
- console.log('Fetching tenant name from cluster URL...');
406
- tenantName = await this.getTenantName(clusterUrl);
407
- if (tenantName) {
408
- ConsoleUtils.check(`Tenant name "${tenantName}" fetched successfully\n`);
409
- }
410
- else {
411
- console.log(chalk.yellow(`Warning: Unable to fetch tenant name from cluster URL "${clusterUrl}".\n`));
412
- }
413
- }
414
- else {
415
- console.log(chalk.yellow(`Warning: No cluster URL provided.\n`));
416
- }
417
- return tenantName;
418
- }
419
-
420
- static async getCodenotchEnvVariables(workpace: IWorkspace, options: {
421
- baseUrl?: string,
422
- accessToken?: string,
423
- appName?: string,
424
- app?: ApplicationManifest,
425
- tenantName?: string,
426
- clusterUrl?: string
427
- }) {
428
-
429
- let result: any = {
430
- clusterUrl: options.clusterUrl,
431
- serviceName: workpace.manifest.serviceName,
432
- theme: 'dark',
433
- language: workpace.manifest?.languages?.[0] ?? 'en'
434
- };
435
-
436
- result.projectManifest = JSON.stringify(workpace.manifest);
437
-
438
- if (options.app) {
439
- result.appManifest = JSON.stringify(options.app);
440
- }
441
-
442
- if (options.tenantName) {
443
- result.tenantName = options.tenantName;
444
- }
445
-
446
-
447
- let tenantName = options.tenantName;
448
-
449
- if (tenantName) result.tenantName = tenantName;
450
- if (options.appName) result.appName = options.appName;
451
- if (options.accessToken) result.accessToken = options.accessToken;
452
- if (options.baseUrl) result.baseUrl = options.baseUrl;
453
-
454
- if (workpace) {
455
-
456
- let allI18nValues = await I18nUtils.getAllI18nFiles(workpace.path);
457
- for(let allI18nValue of allI18nValues){
458
- for(let langValue of allI18nValue.values){
459
- result[`i18n.${allI18nValue.key}.${langValue.lang}`] = JSON.stringify(langValue.value);
460
- }
461
- }
462
- }
463
-
464
- return result;
465
- }
466
-
467
-
468
-
469
- static async getTenantName(cluster: string): Promise<string | undefined> {
470
- try {
471
-
472
- let obj: any = await (await fetch(`${cluster}/portal/tenant`)).json();
473
-
474
- if (obj && obj.name && typeof obj.name === 'string') {
475
- return obj.name;
476
- }
477
-
478
- return undefined;
479
- }
480
- catch (e) {
481
- console.error("Error while fetching tenant name:", e);
482
- return undefined;
483
- }
484
- }
485
-
486
- private static createTsConfig(include: string[] = ["src"]) {
487
- let tsconfig = JSON.stringify({
488
- "compilerOptions": {
489
- "target": "ESNext",
490
- "lib": ["DOM", "DOM.Iterable", "ESNext"],
491
- "allowJs": true,
492
- "skipLibCheck": true,
493
- "esModuleInterop": true,
494
- "allowSyntheticDefaultImports": true,
495
- "strict": true,
496
- "forceConsistentCasingInFileNames": true,
497
- "module": "ESNext",
498
- "moduleResolution": "Node",
499
- "resolveJsonModule": true,
500
- "isolatedModules": true,
501
- "noEmit": true, // On demande à tsc de ne PAS générer de fichiers
502
- "jsx": "react" // "react" correspond au mode classic pour React 16
503
- },
504
- "include": include
505
- }, null, 4);
506
-
507
- return tsconfig;
508
- }
509
-
510
- private static createEmptyModule() {
511
- let emptyModule = `
512
- const deepMock = new Proxy(() => null, {
513
- get: (target, prop) => {
514
- console.warn('Empty module proxy accessed property: ', prop);
515
- if (prop === '__esModule') return true;
516
- return deepMock;
517
- }
518
- });
519
- export default deepMock;
520
- export class ComponentDescription {
521
- constructor() {
522
- this.tag = '';
523
- this.props = {};
524
- this.parentInheritedProps = {};
525
- this.children = [];
526
- this.storedData = {};
527
- }
528
- };
529
- export const DeclarationState = {
530
- IDLE : "idle",
531
- LOADING : "loading",
532
- SUCCESS : "success",
533
- ERROR : "error"
534
- };
535
- export const DspVarType = {
536
- STRING : "string",
537
- BOOLEAN : "boolean",
538
- NUMBER : "number",
539
- INTEGER : "integer",
540
- COLOR : "color",
541
- THICKNESS : "thickness",
542
- SIZE : "size",
543
- BORDER : "border",
544
- OBJECT : "object",
545
- ARRAY : "array",
546
- FUNCTION : "function",
547
- ACTION : "action",
548
- REACT_NODE : "reactNode",
549
- RENDERER : "renderer"
550
- };`.trim();
551
- return emptyModule;
552
- }
553
-
554
- private static createViteConfig(appName: string) {
555
- let debugOptions = `
556
- sourcemap: true,
557
- terserOptions: {
558
- mangle: false,
559
- keep_fnames: true,
560
- keep_classnames: true,
561
- }`;
562
- let viteConfig = `
563
- import { defineConfig } from 'vite'
564
- import react from '@vitejs/plugin-react'
565
- import path from 'path';
566
- export default defineConfig({
567
- plugins: [
568
- react({ jsxRuntime: 'classic' }),
569
- ],
570
- base: './',
571
- build: {
572
- outDir: '../${appName}-dist',
573
- emptyOutDir: true,
574
- ${debugOptions}
575
- },
576
- resolve: {
577
- alias: [
578
- { find: 'crypto-browserify', replacement: './empty-module.js' },
579
- { find: /^@echino\\/codenotch\\.ui\\.monaco(\\/.*)?$/, replacement: path.resolve(__dirname, './empty-module.js') },
580
- { find: /^@echino\\/echino\\.ui\\.sdk(\\/.*)?$/, replacement: path.resolve(__dirname, './empty-module.js') },
581
- ],
582
- },
583
- })`.trim();
584
-
585
- return viteConfig;
586
- }
587
-
588
- private static createIndexHtml(appManifest: ApplicationManifest, appName: string): string {
589
- let indexHtml = `<!DOCTYPE html>
590
- <html lang="fr">
591
- <head>
592
- <meta charset="${appManifest.html?.charset ?? 'UTF-8'}" />
593
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
594
- <title>${appManifest.html?.title ?? appName}</title>
595
- <meta name="description" content="${appManifest.html?.description ?? ''}" />
596
- <meta name="author" content="${appManifest.html?.author ?? ''}" />
597
- <meta name="keywords" content="${appManifest.html?.keywords ?? ''}" />
598
- <script src="https://kit.fontawesome.com/cd9ce0b05e.js" crossorigin="anonymous" data-auto-replace-svg="nest"></script>
599
- </head>
600
- <body>
601
- <div id="root"></div>
602
- <script type="module" src="/index.jsx"></script>
603
- </body>
604
- </html>`;
605
- return indexHtml;
606
- }
607
-
608
- private static createPkgJson(workspacePath: string, appName: string) {
609
- let currentPkg = JSON.parse((fs.readFileSync(StringUtils.normalizePath(`${workspacePath}/package.json`), 'utf-8'))!);
610
- ConsoleUtils.check(`package.json read successfully`);
611
-
612
-
613
- let pgkJson: any = {
614
- "name": appName,
615
- "private": true,
616
- "version": "1.0.0",
617
- // Inherit the module system from the user's package.json (default: CommonJS).
618
- // This lets user-provided tool configs (postcss.config.js, tailwind.config.js, ...)
619
- // use whichever style they wrote. Our own build config is emitted as vite.config.mjs
620
- // so it always loads as ESM regardless of this field.
621
- "type": currentPkg.type ?? "commonjs",
622
- "scripts": {
623
- "dev": "vite",
624
- "build": "tsc && vite build",
625
- "preview": "vite preview"
626
- },
627
- "dependencies": currentPkg.dependencies ?? {},
628
- "devDependencies": currentPkg.devDependencies ?? {}
629
- };
630
- let requiredDeps = ['react', 'react-dom'];
631
- for (let requiredDep of requiredDeps) {
632
- if (pgkJson.dependencies[requiredDep] === undefined) {
633
- throw new Error(`Dependency ${requiredDep} is required to run the React preview. Please add it to your package.json dependencies and try again.`);
634
- }
635
- }
636
- if (pgkJson.devDependencies['vite'] === undefined) {
637
- pgkJson.devDependencies['vite'] = "^7.3.1";
638
- }
639
- else {
640
- ConsoleUtils.checkWarning(`Warning: Using custom Vite version: ${pgkJson.devDependencies['vite']}`);
641
- }
642
-
643
- if (pgkJson.devDependencies['sass-embedded'] === undefined) {
644
- pgkJson.devDependencies['sass-embedded'] = "^1.97.3";
645
- }
646
- else {
647
- ConsoleUtils.checkWarning(`Warning: Using custom sass-embedded version: ${pgkJson.devDependencies['sass-embedded']}`);
648
- }
649
-
650
- return pgkJson;
651
- }
652
-
653
-
654
- private static getFullManifestAt(folderPath: string): ProjectManifest {
655
- let manifest = this.getManifestAt(folderPath);
656
- let manifestCache = this.getManifestCacheAt(folderPath);
657
- let result: ProjectManifest = {
658
- projectName: manifest.projectName,
659
- serviceName: manifest.serviceName,
660
- version: manifest.version,
661
- index: manifest.index,
662
- dependencies: manifest.dependencies,
663
- reactApplications: manifestCache.reactApplications,
664
- packages: manifest.packages,
665
- languages: manifest.languages,
666
- roles: manifest.roles,
667
- postInstallationProcesses: manifest.postInstallationProcesses,
668
- apis: manifestCache.apis,
669
- applications: manifestCache.applications,
670
- emails: manifestCache.emails,
671
- documentDataSources: manifestCache.documentDataSources,
672
- expressComponents: manifestCache.expressComponents,
673
- htmls: manifestCache.htmls,
674
- pdfs: manifestCache.pdfs,
675
- processes: manifestCache.processes,
676
- scripts: manifestCache.scripts,
677
- tableDataSources: manifestCache.tableDataSources,
678
- };
679
- return result;
680
- }
681
-
682
- private static getManifestAt(folderPath: string) {
683
- let filePath = StringUtils.normalizePath(`${folderPath}/manifest.json`);
684
- if (existsSync(filePath) === false) {
685
- throw new Error(`Manifest file not found at path "${filePath}"`);
686
- }
687
- let json = readFileSync(filePath, 'utf-8');
688
- return JSON.parse(json) as IScenarioProjectManifest;
689
- }
690
-
691
- private static getManifestCacheAt(folderPath: string) {
692
- let filePath = StringUtils.normalizePath(`${folderPath}/manifest.cache.json`);
693
- if (existsSync(filePath) === false) {
694
- throw new Error(`Manifest cache file not found at path "${filePath}"`);
695
- }
696
- let json = readFileSync(filePath, 'utf-8');
697
- return JSON.parse(json) as IWorkspaceCache;
698
- }
699
-
700
-
701
- static getAumlVariables(workpace: IWorkspace, tenantName: string | undefined, clusterUrl: string | undefined) {
702
- let workspaceManifest = workpace?.manifest;
703
-
704
- let result = {
705
- serviceName: workspaceManifest?.serviceName ?? 'DEV',
706
- tenant: {
707
- displayName: tenantName,
708
- name: tenantName,
709
- clusterUrl: clusterUrl
710
- },
711
- languages: workspaceManifest?.languages ?? ['en'],
712
- appManifest: workpace.manifest,
713
- packageVersions: workspaceManifest?.packages ?? {}
714
- };
715
- return result;
716
- }
717
-
718
- static async getGlobalAumlVariableDefinitions(workpace: IWorkspace, tenantName: string | undefined, clusterUrl: string | undefined): Promise<string> {
719
- let workspaceManifest = workpace?.manifest;
720
-
721
- return `window.serviceName = "${workspaceManifest?.serviceName ?? 'DEV'}";
722
- window.tenant = ${JSON.stringify({
723
- displayName: tenantName,
724
- name: tenantName,
725
- clusterUrl: clusterUrl
726
- }, null, 4)};
727
- window.languages = ${JSON.stringify(workspaceManifest?.languages ?? ['en'], null, 4)};
728
- window.user = ${JSON.stringify({
729
- id: '',
730
- roles: [],
731
- groups: [],
732
- email: '',
733
- firstName: '',
734
- lastName: ''
735
- }, null, 4)};
736
- window.appManifest = ${JSON.stringify(workpace.manifest, null, 4)};
737
- window.packageVersions = ${JSON.stringify(workpace.manifest.packages ?? {}, null, 4)}`;
738
- }
739
- }