@magentrix-corp/magentrix-cli 1.3.16 → 1.3.17

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 (68) hide show
  1. package/LICENSE +25 -25
  2. package/README.md +1166 -1166
  3. package/actions/autopublish.old.js +293 -293
  4. package/actions/config.js +182 -182
  5. package/actions/create.js +466 -466
  6. package/actions/help.js +164 -164
  7. package/actions/iris/buildStage.js +874 -874
  8. package/actions/iris/delete.js +256 -256
  9. package/actions/iris/dev.js +391 -391
  10. package/actions/iris/index.js +6 -6
  11. package/actions/iris/link.js +375 -375
  12. package/actions/iris/recover.js +268 -268
  13. package/actions/main.js +80 -80
  14. package/actions/publish.js +1420 -1420
  15. package/actions/pull.js +684 -684
  16. package/actions/setup.js +148 -148
  17. package/actions/status.js +17 -17
  18. package/actions/update.js +248 -248
  19. package/bin/magentrix.js +393 -393
  20. package/package.json +55 -55
  21. package/utils/assetPaths.js +158 -158
  22. package/utils/autopublishLock.js +77 -77
  23. package/utils/cacher.js +206 -206
  24. package/utils/cli/checkInstanceUrl.js +76 -74
  25. package/utils/cli/helpers/compare.js +282 -282
  26. package/utils/cli/helpers/ensureApiKey.js +63 -63
  27. package/utils/cli/helpers/ensureCredentials.js +68 -68
  28. package/utils/cli/helpers/ensureInstanceUrl.js +75 -75
  29. package/utils/cli/writeRecords.js +262 -262
  30. package/utils/compare.js +135 -135
  31. package/utils/compress.js +17 -17
  32. package/utils/config.js +527 -527
  33. package/utils/debug.js +144 -144
  34. package/utils/diagnostics/testPublishLogic.js +96 -96
  35. package/utils/diff.js +49 -49
  36. package/utils/downloadAssets.js +291 -291
  37. package/utils/filetag.js +115 -115
  38. package/utils/hash.js +14 -14
  39. package/utils/iris/backup.js +411 -411
  40. package/utils/iris/builder.js +541 -541
  41. package/utils/iris/config-reader.js +664 -664
  42. package/utils/iris/deleteHelper.js +150 -150
  43. package/utils/iris/errors.js +537 -537
  44. package/utils/iris/linker.js +601 -601
  45. package/utils/iris/lock.js +360 -360
  46. package/utils/iris/validation.js +360 -360
  47. package/utils/iris/validator.js +281 -281
  48. package/utils/iris/zipper.js +248 -248
  49. package/utils/logger.js +291 -291
  50. package/utils/magentrix/api/assets.js +220 -220
  51. package/utils/magentrix/api/auth.js +107 -107
  52. package/utils/magentrix/api/createEntity.js +61 -61
  53. package/utils/magentrix/api/deleteEntity.js +55 -55
  54. package/utils/magentrix/api/iris.js +251 -251
  55. package/utils/magentrix/api/meqlQuery.js +36 -36
  56. package/utils/magentrix/api/retrieveEntity.js +86 -86
  57. package/utils/magentrix/api/updateEntity.js +66 -66
  58. package/utils/magentrix/fetch.js +168 -168
  59. package/utils/merge.js +22 -22
  60. package/utils/permissionError.js +70 -70
  61. package/utils/preferences.js +40 -40
  62. package/utils/progress.js +469 -469
  63. package/utils/spinner.js +43 -43
  64. package/utils/template.js +52 -52
  65. package/utils/updateFileBase.js +121 -121
  66. package/utils/workspaces.js +108 -108
  67. package/vars/config.js +11 -11
  68. package/vars/global.js +50 -50
@@ -1,281 +1,281 @@
1
- import { existsSync, readdirSync, statSync } from 'node:fs';
2
- import path from 'node:path';
3
-
4
- /**
5
- * Required file patterns for a valid Iris build.
6
- */
7
- const REQUIRED_FILES = {
8
- remoteEntry: {
9
- pattern: /^remoteEntry\.js$/,
10
- location: 'root',
11
- description: 'remoteEntry.js (required at dist root)'
12
- },
13
- hostInit: {
14
- pattern: /^hostInit.*\.js$/,
15
- location: 'assets',
16
- description: 'assets/hostInit*.js (required in assets folder)'
17
- },
18
- main: {
19
- pattern: /^main.*\.js$/,
20
- location: 'assets',
21
- description: 'assets/main*.js (required in assets folder)'
22
- },
23
- index: {
24
- pattern: /^index.*\.js$/,
25
- location: 'assets',
26
- description: 'assets/index*.js (required in assets folder)'
27
- }
28
- };
29
-
30
- /**
31
- * Validate that a build output directory contains all required Iris files.
32
- *
33
- * @param {string} distPath - Path to the build output directory (e.g., ./dist)
34
- * @returns {{
35
- * valid: boolean,
36
- * errors: string[],
37
- * warnings: string[],
38
- * files: {
39
- * remoteEntry: string | null,
40
- * hostInit: string | null,
41
- * main: string | null,
42
- * index: string | null
43
- * },
44
- * assetsPath: string | null
45
- * }}
46
- */
47
- export function validateIrisBuild(distPath) {
48
- const result = {
49
- valid: true,
50
- errors: [],
51
- warnings: [],
52
- files: {
53
- remoteEntry: null,
54
- hostInit: null,
55
- main: null,
56
- index: null
57
- },
58
- assetsPath: null
59
- };
60
-
61
- // Check if dist path exists
62
- if (!existsSync(distPath)) {
63
- result.valid = false;
64
- result.errors.push(`Build output directory not found: ${distPath}`);
65
- return result;
66
- }
67
-
68
- // Check if it's a directory
69
- const distStat = statSync(distPath);
70
- if (!distStat.isDirectory()) {
71
- result.valid = false;
72
- result.errors.push(`Build output path is not a directory: ${distPath}`);
73
- return result;
74
- }
75
-
76
- // Get root files
77
- let rootFiles;
78
- try {
79
- rootFiles = readdirSync(distPath);
80
- } catch (err) {
81
- result.valid = false;
82
- result.errors.push(`Failed to read build directory: ${err.message}`);
83
- return result;
84
- }
85
-
86
- // Check for remoteEntry.js in root
87
- const remoteEntryFile = rootFiles.find(f => REQUIRED_FILES.remoteEntry.pattern.test(f));
88
- if (remoteEntryFile) {
89
- result.files.remoteEntry = path.join(distPath, remoteEntryFile);
90
- } else {
91
- result.valid = false;
92
- result.errors.push(REQUIRED_FILES.remoteEntry.description);
93
- }
94
-
95
- // Check for assets directory
96
- const assetsDir = rootFiles.find(f => f.toLowerCase() === 'assets');
97
- if (!assetsDir) {
98
- result.valid = false;
99
- result.errors.push('assets/ directory not found in build output');
100
- return result;
101
- }
102
-
103
- const assetsPath = path.join(distPath, assetsDir);
104
- result.assetsPath = assetsPath;
105
-
106
- // Check if assets is a directory
107
- const assetsStat = statSync(assetsPath);
108
- if (!assetsStat.isDirectory()) {
109
- result.valid = false;
110
- result.errors.push('assets is not a directory');
111
- return result;
112
- }
113
-
114
- // Get assets files
115
- let assetsFiles;
116
- try {
117
- assetsFiles = readdirSync(assetsPath);
118
- } catch (err) {
119
- result.valid = false;
120
- result.errors.push(`Failed to read assets directory: ${err.message}`);
121
- return result;
122
- }
123
-
124
- // Check for required files in assets
125
- const hostInitFile = assetsFiles.find(f => REQUIRED_FILES.hostInit.pattern.test(f));
126
- if (hostInitFile) {
127
- result.files.hostInit = path.join(assetsPath, hostInitFile);
128
- } else {
129
- result.valid = false;
130
- result.errors.push(REQUIRED_FILES.hostInit.description);
131
- }
132
-
133
- const mainFile = assetsFiles.find(f => REQUIRED_FILES.main.pattern.test(f));
134
- if (mainFile) {
135
- result.files.main = path.join(assetsPath, mainFile);
136
- } else {
137
- result.valid = false;
138
- result.errors.push(REQUIRED_FILES.main.description);
139
- }
140
-
141
- const indexFile = assetsFiles.find(f => REQUIRED_FILES.index.pattern.test(f));
142
- if (indexFile) {
143
- result.files.index = path.join(assetsPath, indexFile);
144
- } else {
145
- result.valid = false;
146
- result.errors.push(REQUIRED_FILES.index.description);
147
- }
148
-
149
- // Warnings for potential issues
150
- if (rootFiles.includes('index.html')) {
151
- result.warnings.push('Found index.html in root - this file is typically not needed for Iris apps');
152
- }
153
-
154
- return result;
155
- }
156
-
157
- /**
158
- * Format validation errors for display to the user.
159
- *
160
- * @param {ReturnType<typeof validateIrisBuild>} validation - Validation result
161
- * @returns {string} - Formatted error message
162
- */
163
- export function formatValidationErrors(validation) {
164
- const lines = [
165
- 'Invalid Build Output',
166
- '────────────────────────────────────────────────────',
167
- '',
168
- 'The build output is missing required Iris files.',
169
- '',
170
- 'Status:'
171
- ];
172
-
173
- // Show status of each required file
174
- const fileStatus = [
175
- {
176
- name: 'remoteEntry.js',
177
- found: validation.files.remoteEntry !== null,
178
- foundName: validation.files.remoteEntry ? path.basename(validation.files.remoteEntry) : null
179
- },
180
- {
181
- name: 'assets/hostInit*.js',
182
- found: validation.files.hostInit !== null,
183
- foundName: validation.files.hostInit ? path.basename(validation.files.hostInit) : null
184
- },
185
- {
186
- name: 'assets/main*.js',
187
- found: validation.files.main !== null,
188
- foundName: validation.files.main ? path.basename(validation.files.main) : null
189
- },
190
- {
191
- name: 'assets/index*.js',
192
- found: validation.files.index !== null,
193
- foundName: validation.files.index ? path.basename(validation.files.index) : null
194
- }
195
- ];
196
-
197
- for (const file of fileStatus) {
198
- if (file.found) {
199
- lines.push(` ✓ ${file.name} (found: ${file.foundName})`);
200
- } else {
201
- lines.push(` ✗ ${file.name}`);
202
- }
203
- }
204
-
205
- lines.push('');
206
- lines.push('Expected structure:');
207
- lines.push(' dist/');
208
- lines.push(' ├── remoteEntry.js');
209
- lines.push(' └── assets/');
210
- lines.push(' ├── hostInit-[hash].js');
211
- lines.push(' ├── main-[hash].js');
212
- lines.push(' └── index-[hash].js');
213
- lines.push('');
214
- lines.push('Make sure your Vue.js project is configured for Module Federation.');
215
-
216
- if (validation.warnings.length > 0) {
217
- lines.push('');
218
- lines.push('Warnings:');
219
- for (const warning of validation.warnings) {
220
- lines.push(` ⚠ ${warning}`);
221
- }
222
- }
223
-
224
- return lines.join('\n');
225
- }
226
-
227
- /**
228
- * Get a summary of found files for successful validation.
229
- *
230
- * @param {ReturnType<typeof validateIrisBuild>} validation - Validation result
231
- * @returns {string} - Summary of found files
232
- */
233
- export function getValidationSummary(validation) {
234
- const files = [];
235
-
236
- if (validation.files.remoteEntry) {
237
- files.push(` • ${path.basename(validation.files.remoteEntry)}`);
238
- }
239
- if (validation.files.hostInit) {
240
- files.push(` • assets/${path.basename(validation.files.hostInit)}`);
241
- }
242
- if (validation.files.main) {
243
- files.push(` • assets/${path.basename(validation.files.main)}`);
244
- }
245
- if (validation.files.index) {
246
- files.push(` • assets/${path.basename(validation.files.index)}`);
247
- }
248
-
249
- return `Found ${files.length} required files:\n${files.join('\n')}`;
250
- }
251
-
252
- /**
253
- * Validate an Iris app folder (already staged, not a dist folder).
254
- * This is used to validate apps in src/iris-apps/<slug>/.
255
- *
256
- * @param {string} appPath - Path to the app folder
257
- * @returns {{valid: boolean, errors: string[], slug: string | null}}
258
- */
259
- export function validateIrisAppFolder(appPath) {
260
- const result = {
261
- valid: true,
262
- errors: [],
263
- slug: null
264
- };
265
-
266
- if (!existsSync(appPath)) {
267
- result.valid = false;
268
- result.errors.push(`App folder not found: ${appPath}`);
269
- return result;
270
- }
271
-
272
- result.slug = path.basename(appPath);
273
-
274
- // Use the same validation as build output
275
- const validation = validateIrisBuild(appPath);
276
-
277
- result.valid = validation.valid;
278
- result.errors = validation.errors;
279
-
280
- return result;
281
- }
1
+ import { existsSync, readdirSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ /**
5
+ * Required file patterns for a valid Iris build.
6
+ */
7
+ const REQUIRED_FILES = {
8
+ remoteEntry: {
9
+ pattern: /^remoteEntry\.js$/,
10
+ location: 'root',
11
+ description: 'remoteEntry.js (required at dist root)'
12
+ },
13
+ hostInit: {
14
+ pattern: /^hostInit.*\.js$/,
15
+ location: 'assets',
16
+ description: 'assets/hostInit*.js (required in assets folder)'
17
+ },
18
+ main: {
19
+ pattern: /^main.*\.js$/,
20
+ location: 'assets',
21
+ description: 'assets/main*.js (required in assets folder)'
22
+ },
23
+ index: {
24
+ pattern: /^index.*\.js$/,
25
+ location: 'assets',
26
+ description: 'assets/index*.js (required in assets folder)'
27
+ }
28
+ };
29
+
30
+ /**
31
+ * Validate that a build output directory contains all required Iris files.
32
+ *
33
+ * @param {string} distPath - Path to the build output directory (e.g., ./dist)
34
+ * @returns {{
35
+ * valid: boolean,
36
+ * errors: string[],
37
+ * warnings: string[],
38
+ * files: {
39
+ * remoteEntry: string | null,
40
+ * hostInit: string | null,
41
+ * main: string | null,
42
+ * index: string | null
43
+ * },
44
+ * assetsPath: string | null
45
+ * }}
46
+ */
47
+ export function validateIrisBuild(distPath) {
48
+ const result = {
49
+ valid: true,
50
+ errors: [],
51
+ warnings: [],
52
+ files: {
53
+ remoteEntry: null,
54
+ hostInit: null,
55
+ main: null,
56
+ index: null
57
+ },
58
+ assetsPath: null
59
+ };
60
+
61
+ // Check if dist path exists
62
+ if (!existsSync(distPath)) {
63
+ result.valid = false;
64
+ result.errors.push(`Build output directory not found: ${distPath}`);
65
+ return result;
66
+ }
67
+
68
+ // Check if it's a directory
69
+ const distStat = statSync(distPath);
70
+ if (!distStat.isDirectory()) {
71
+ result.valid = false;
72
+ result.errors.push(`Build output path is not a directory: ${distPath}`);
73
+ return result;
74
+ }
75
+
76
+ // Get root files
77
+ let rootFiles;
78
+ try {
79
+ rootFiles = readdirSync(distPath);
80
+ } catch (err) {
81
+ result.valid = false;
82
+ result.errors.push(`Failed to read build directory: ${err.message}`);
83
+ return result;
84
+ }
85
+
86
+ // Check for remoteEntry.js in root
87
+ const remoteEntryFile = rootFiles.find(f => REQUIRED_FILES.remoteEntry.pattern.test(f));
88
+ if (remoteEntryFile) {
89
+ result.files.remoteEntry = path.join(distPath, remoteEntryFile);
90
+ } else {
91
+ result.valid = false;
92
+ result.errors.push(REQUIRED_FILES.remoteEntry.description);
93
+ }
94
+
95
+ // Check for assets directory
96
+ const assetsDir = rootFiles.find(f => f.toLowerCase() === 'assets');
97
+ if (!assetsDir) {
98
+ result.valid = false;
99
+ result.errors.push('assets/ directory not found in build output');
100
+ return result;
101
+ }
102
+
103
+ const assetsPath = path.join(distPath, assetsDir);
104
+ result.assetsPath = assetsPath;
105
+
106
+ // Check if assets is a directory
107
+ const assetsStat = statSync(assetsPath);
108
+ if (!assetsStat.isDirectory()) {
109
+ result.valid = false;
110
+ result.errors.push('assets is not a directory');
111
+ return result;
112
+ }
113
+
114
+ // Get assets files
115
+ let assetsFiles;
116
+ try {
117
+ assetsFiles = readdirSync(assetsPath);
118
+ } catch (err) {
119
+ result.valid = false;
120
+ result.errors.push(`Failed to read assets directory: ${err.message}`);
121
+ return result;
122
+ }
123
+
124
+ // Check for required files in assets
125
+ const hostInitFile = assetsFiles.find(f => REQUIRED_FILES.hostInit.pattern.test(f));
126
+ if (hostInitFile) {
127
+ result.files.hostInit = path.join(assetsPath, hostInitFile);
128
+ } else {
129
+ result.valid = false;
130
+ result.errors.push(REQUIRED_FILES.hostInit.description);
131
+ }
132
+
133
+ const mainFile = assetsFiles.find(f => REQUIRED_FILES.main.pattern.test(f));
134
+ if (mainFile) {
135
+ result.files.main = path.join(assetsPath, mainFile);
136
+ } else {
137
+ result.valid = false;
138
+ result.errors.push(REQUIRED_FILES.main.description);
139
+ }
140
+
141
+ const indexFile = assetsFiles.find(f => REQUIRED_FILES.index.pattern.test(f));
142
+ if (indexFile) {
143
+ result.files.index = path.join(assetsPath, indexFile);
144
+ } else {
145
+ result.valid = false;
146
+ result.errors.push(REQUIRED_FILES.index.description);
147
+ }
148
+
149
+ // Warnings for potential issues
150
+ if (rootFiles.includes('index.html')) {
151
+ result.warnings.push('Found index.html in root - this file is typically not needed for Iris apps');
152
+ }
153
+
154
+ return result;
155
+ }
156
+
157
+ /**
158
+ * Format validation errors for display to the user.
159
+ *
160
+ * @param {ReturnType<typeof validateIrisBuild>} validation - Validation result
161
+ * @returns {string} - Formatted error message
162
+ */
163
+ export function formatValidationErrors(validation) {
164
+ const lines = [
165
+ 'Invalid Build Output',
166
+ '────────────────────────────────────────────────────',
167
+ '',
168
+ 'The build output is missing required Iris files.',
169
+ '',
170
+ 'Status:'
171
+ ];
172
+
173
+ // Show status of each required file
174
+ const fileStatus = [
175
+ {
176
+ name: 'remoteEntry.js',
177
+ found: validation.files.remoteEntry !== null,
178
+ foundName: validation.files.remoteEntry ? path.basename(validation.files.remoteEntry) : null
179
+ },
180
+ {
181
+ name: 'assets/hostInit*.js',
182
+ found: validation.files.hostInit !== null,
183
+ foundName: validation.files.hostInit ? path.basename(validation.files.hostInit) : null
184
+ },
185
+ {
186
+ name: 'assets/main*.js',
187
+ found: validation.files.main !== null,
188
+ foundName: validation.files.main ? path.basename(validation.files.main) : null
189
+ },
190
+ {
191
+ name: 'assets/index*.js',
192
+ found: validation.files.index !== null,
193
+ foundName: validation.files.index ? path.basename(validation.files.index) : null
194
+ }
195
+ ];
196
+
197
+ for (const file of fileStatus) {
198
+ if (file.found) {
199
+ lines.push(` ✓ ${file.name} (found: ${file.foundName})`);
200
+ } else {
201
+ lines.push(` ✗ ${file.name}`);
202
+ }
203
+ }
204
+
205
+ lines.push('');
206
+ lines.push('Expected structure:');
207
+ lines.push(' dist/');
208
+ lines.push(' ├── remoteEntry.js');
209
+ lines.push(' └── assets/');
210
+ lines.push(' ├── hostInit-[hash].js');
211
+ lines.push(' ├── main-[hash].js');
212
+ lines.push(' └── index-[hash].js');
213
+ lines.push('');
214
+ lines.push('Make sure your Vue.js project is configured for Module Federation.');
215
+
216
+ if (validation.warnings.length > 0) {
217
+ lines.push('');
218
+ lines.push('Warnings:');
219
+ for (const warning of validation.warnings) {
220
+ lines.push(` ⚠ ${warning}`);
221
+ }
222
+ }
223
+
224
+ return lines.join('\n');
225
+ }
226
+
227
+ /**
228
+ * Get a summary of found files for successful validation.
229
+ *
230
+ * @param {ReturnType<typeof validateIrisBuild>} validation - Validation result
231
+ * @returns {string} - Summary of found files
232
+ */
233
+ export function getValidationSummary(validation) {
234
+ const files = [];
235
+
236
+ if (validation.files.remoteEntry) {
237
+ files.push(` • ${path.basename(validation.files.remoteEntry)}`);
238
+ }
239
+ if (validation.files.hostInit) {
240
+ files.push(` • assets/${path.basename(validation.files.hostInit)}`);
241
+ }
242
+ if (validation.files.main) {
243
+ files.push(` • assets/${path.basename(validation.files.main)}`);
244
+ }
245
+ if (validation.files.index) {
246
+ files.push(` • assets/${path.basename(validation.files.index)}`);
247
+ }
248
+
249
+ return `Found ${files.length} required files:\n${files.join('\n')}`;
250
+ }
251
+
252
+ /**
253
+ * Validate an Iris app folder (already staged, not a dist folder).
254
+ * This is used to validate apps in src/iris-apps/<slug>/.
255
+ *
256
+ * @param {string} appPath - Path to the app folder
257
+ * @returns {{valid: boolean, errors: string[], slug: string | null}}
258
+ */
259
+ export function validateIrisAppFolder(appPath) {
260
+ const result = {
261
+ valid: true,
262
+ errors: [],
263
+ slug: null
264
+ };
265
+
266
+ if (!existsSync(appPath)) {
267
+ result.valid = false;
268
+ result.errors.push(`App folder not found: ${appPath}`);
269
+ return result;
270
+ }
271
+
272
+ result.slug = path.basename(appPath);
273
+
274
+ // Use the same validation as build output
275
+ const validation = validateIrisBuild(appPath);
276
+
277
+ result.valid = validation.valid;
278
+ result.errors = validation.errors;
279
+
280
+ return result;
281
+ }