@magentrix-corp/magentrix-cli 1.3.5 → 1.3.7
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.
- package/README.md +18 -3
- package/actions/iris/buildStage.js +108 -6
- package/package.json +1 -1
- package/utils/iris/builder.js +17 -3
package/README.md
CHANGED
|
@@ -505,7 +505,9 @@ magentrix vue-build-stage
|
|
|
505
505
|
1. Select from linked projects or enter path manually
|
|
506
506
|
2. Run `npm run build` in the Vue project
|
|
507
507
|
3. Validate the build output
|
|
508
|
-
4. Copy to workspace `src/iris-apps/<app-slug>/`
|
|
508
|
+
4. Copy to workspace `src/iris-apps/<app-slug>/` (excludes index.html, favicon.ico)
|
|
509
|
+
5. Check sync status and prompt to pull if needed (required before publishing)
|
|
510
|
+
6. Prompt to publish to Magentrix
|
|
509
511
|
|
|
510
512
|
#### Vue Development Server
|
|
511
513
|
```bash
|
|
@@ -621,7 +623,7 @@ magentrix run-dev # Start dev server with platform assets
|
|
|
621
623
|
# Deployment - Option A (from Vue project folder)
|
|
622
624
|
cd ~/my-vue-app # Work from your Vue project
|
|
623
625
|
magentrix vue-build-stage # Build and select workspace to stage into
|
|
624
|
-
#
|
|
626
|
+
# Prompted: "Do you want to publish to Magentrix now?" → Yes/No
|
|
625
627
|
|
|
626
628
|
# Deployment - Option B (from Magentrix workspace)
|
|
627
629
|
cd ~/magentrix-workspace # Navigate to Magentrix workspace
|
|
@@ -678,6 +680,19 @@ When running from a Vue project, the command looks for registered workspaces in
|
|
|
678
680
|
|
|
679
681
|
**Note**: Existing workspaces are auto-registered when you run any command from them.
|
|
680
682
|
|
|
683
|
+
#### "Publishing Iris apps from an out-of-sync workspace is not allowed"
|
|
684
|
+
When running `vue-build-stage` from a Vue project, the CLI checks if the target workspace is in sync with the server. If there are pending remote changes, you must pull first.
|
|
685
|
+
|
|
686
|
+
**Why this is required:**
|
|
687
|
+
- Prevents deployment conflicts
|
|
688
|
+
- Ensures your app is deployed alongside the latest server state
|
|
689
|
+
- Avoids overwriting changes made by other team members
|
|
690
|
+
|
|
691
|
+
**To resolve:**
|
|
692
|
+
1. Navigate to the workspace: `cd /path/to/workspace`
|
|
693
|
+
2. Pull latest changes: `magentrix pull`
|
|
694
|
+
3. Re-run `vue-build-stage` from your Vue project
|
|
695
|
+
|
|
681
696
|
#### "Missing required field in config.ts: slug (appPath)"
|
|
682
697
|
Your Vue project's `config.ts` is missing the app identifier. Add an `appPath` or `slug` field.
|
|
683
698
|
|
|
@@ -785,7 +800,7 @@ magentrix status # Verify everything is in sync
|
|
|
785
800
|
cd ~/my-vue-app # Navigate to your Vue project
|
|
786
801
|
magentrix iris-link # Link project (first time only)
|
|
787
802
|
magentrix vue-build-stage # Build and select workspace to stage into
|
|
788
|
-
#
|
|
803
|
+
# Prompted: "Do you want to publish to Magentrix now?" → Yes/No
|
|
789
804
|
```
|
|
790
805
|
|
|
791
806
|
**Option B: From Magentrix workspace**
|
|
@@ -419,6 +419,61 @@ async function buildFromVueProject(options) {
|
|
|
419
419
|
console.log(chalk.gray(`Staged to: ${stageResult.stagedPath}`));
|
|
420
420
|
console.log();
|
|
421
421
|
|
|
422
|
+
// Check if workspace might be out of sync and offer to pull first
|
|
423
|
+
console.log(chalk.gray('Checking workspace sync status...'));
|
|
424
|
+
const syncStatus = await checkWorkspaceSyncStatus(workspacePath);
|
|
425
|
+
|
|
426
|
+
if (syncStatus.needsPull) {
|
|
427
|
+
console.log();
|
|
428
|
+
console.log(chalk.yellow('⚠ Your workspace may be out of sync with the server.'));
|
|
429
|
+
|
|
430
|
+
const shouldPull = await confirm({
|
|
431
|
+
message: 'Would you like to pull latest changes first?',
|
|
432
|
+
default: true
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
if (shouldPull) {
|
|
436
|
+
console.log();
|
|
437
|
+
console.log(chalk.blue('Running pull from workspace...'));
|
|
438
|
+
console.log();
|
|
439
|
+
|
|
440
|
+
const pullSuccess = await runCommandFromWorkspace(workspacePath, 'pull');
|
|
441
|
+
|
|
442
|
+
if (!pullSuccess) {
|
|
443
|
+
console.log();
|
|
444
|
+
console.log(chalk.yellow('Pull encountered issues. You may want to resolve them manually.'));
|
|
445
|
+
|
|
446
|
+
const continueAnyway = await confirm({
|
|
447
|
+
message: 'Do you still want to continue with publishing?',
|
|
448
|
+
default: false
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
if (!continueAnyway) {
|
|
452
|
+
console.log();
|
|
453
|
+
console.log(chalk.cyan('To continue manually:'));
|
|
454
|
+
console.log(chalk.white(` 1. Navigate to workspace: ${chalk.yellow(`cd "${workspacePath}"`)}`));
|
|
455
|
+
console.log(chalk.white(` 2. Run ${chalk.yellow('magentrix pull')} to resolve conflicts`));
|
|
456
|
+
console.log(chalk.white(` 3. Run ${chalk.yellow('magentrix publish')} to deploy`));
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
console.log();
|
|
461
|
+
} else {
|
|
462
|
+
// User declined to pull - block publishing from out-of-sync workspace
|
|
463
|
+
console.log();
|
|
464
|
+
console.log(chalk.red('Publishing Iris apps from an out-of-sync workspace is not allowed.'));
|
|
465
|
+
console.log(chalk.gray('This prevents conflicts and ensures your deployment is based on the latest server state.'));
|
|
466
|
+
console.log();
|
|
467
|
+
console.log(chalk.cyan('To continue:'));
|
|
468
|
+
console.log(chalk.white(` 1. Navigate to workspace: ${chalk.yellow(`cd "${workspacePath}"`)}`));
|
|
469
|
+
console.log(chalk.white(` 2. Run ${chalk.yellow('magentrix pull')} to sync with server`));
|
|
470
|
+
console.log(chalk.white(` 3. Run ${chalk.yellow('magentrix publish')} to deploy`));
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
} else if (syncStatus.checked) {
|
|
474
|
+
console.log(chalk.green('✓ Workspace is in sync'));
|
|
475
|
+
}
|
|
476
|
+
|
|
422
477
|
// Ask if they want to publish now
|
|
423
478
|
const shouldPublish = await confirm({
|
|
424
479
|
message: 'Do you want to publish to Magentrix now?',
|
|
@@ -430,7 +485,7 @@ async function buildFromVueProject(options) {
|
|
|
430
485
|
console.log(chalk.blue('Running publish from workspace...'));
|
|
431
486
|
console.log();
|
|
432
487
|
|
|
433
|
-
const publishSuccess = await
|
|
488
|
+
const publishSuccess = await runCommandFromWorkspace(workspacePath, 'publish');
|
|
434
489
|
|
|
435
490
|
if (!publishSuccess) {
|
|
436
491
|
console.log();
|
|
@@ -448,17 +503,64 @@ async function buildFromVueProject(options) {
|
|
|
448
503
|
}
|
|
449
504
|
|
|
450
505
|
/**
|
|
451
|
-
*
|
|
506
|
+
* Check if a workspace needs to pull (has remote changes or conflicts).
|
|
507
|
+
*
|
|
508
|
+
* @param {string} workspacePath - Path to the Magentrix workspace
|
|
509
|
+
* @returns {Promise<{checked: boolean, needsPull: boolean}>}
|
|
510
|
+
*/
|
|
511
|
+
async function checkWorkspaceSyncStatus(workspacePath) {
|
|
512
|
+
return new Promise((resolvePromise) => {
|
|
513
|
+
const isWindows = process.platform === 'win32';
|
|
514
|
+
const npmCmd = isWindows ? 'npx.cmd' : 'npx';
|
|
515
|
+
|
|
516
|
+
let output = '';
|
|
517
|
+
|
|
518
|
+
const child = spawn(npmCmd, ['magentrix', 'status'], {
|
|
519
|
+
cwd: workspacePath,
|
|
520
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
521
|
+
shell: isWindows
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
child.stdout.on('data', (data) => {
|
|
525
|
+
output += data.toString();
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
child.stderr.on('data', (data) => {
|
|
529
|
+
output += data.toString();
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
child.on('close', (code) => {
|
|
533
|
+
// Check output for signs of remote changes or conflicts
|
|
534
|
+
const lowerOutput = output.toLowerCase();
|
|
535
|
+
const needsPull = lowerOutput.includes('conflict') ||
|
|
536
|
+
lowerOutput.includes('remote') ||
|
|
537
|
+
lowerOutput.includes('server has changes') ||
|
|
538
|
+
lowerOutput.includes('out of sync') ||
|
|
539
|
+
lowerOutput.includes('modified on server');
|
|
540
|
+
|
|
541
|
+
resolvePromise({ checked: code === 0, needsPull });
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
child.on('error', () => {
|
|
545
|
+
// If we can't check, assume it's fine and let them proceed
|
|
546
|
+
resolvePromise({ checked: false, needsPull: false });
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Run a magentrix command from a specific workspace directory.
|
|
452
553
|
*
|
|
453
554
|
* @param {string} workspacePath - Path to the Magentrix workspace
|
|
454
|
-
* @
|
|
555
|
+
* @param {string} command - The magentrix command to run (e.g., 'pull', 'publish')
|
|
556
|
+
* @returns {Promise<boolean>} - True if command succeeded
|
|
455
557
|
*/
|
|
456
|
-
async function
|
|
558
|
+
async function runCommandFromWorkspace(workspacePath, command) {
|
|
457
559
|
return new Promise((resolvePromise) => {
|
|
458
560
|
const isWindows = process.platform === 'win32';
|
|
459
561
|
const npmCmd = isWindows ? 'npx.cmd' : 'npx';
|
|
460
562
|
|
|
461
|
-
const child = spawn(npmCmd, ['magentrix',
|
|
563
|
+
const child = spawn(npmCmd, ['magentrix', command], {
|
|
462
564
|
cwd: workspacePath,
|
|
463
565
|
stdio: 'inherit',
|
|
464
566
|
shell: isWindows
|
|
@@ -469,7 +571,7 @@ async function runPublishFromWorkspace(workspacePath) {
|
|
|
469
571
|
});
|
|
470
572
|
|
|
471
573
|
child.on('error', (err) => {
|
|
472
|
-
console.log(chalk.yellow(`Warning: Could not run
|
|
574
|
+
console.log(chalk.yellow(`Warning: Could not run ${command}: ${err.message}`));
|
|
473
575
|
resolvePromise(false);
|
|
474
576
|
});
|
|
475
577
|
});
|
package/package.json
CHANGED
package/utils/iris/builder.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { existsSync, mkdirSync, cpSync, rmSync, readdirSync } from 'node:fs';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
3
|
+
import { join, resolve, basename } from 'node:path';
|
|
4
4
|
import { validateIrisBuild } from './validator.js';
|
|
5
5
|
import { updateLastBuild } from './linker.js';
|
|
6
6
|
import { EXPORT_ROOT, IRIS_APPS_DIR } from '../../vars/global.js';
|
|
7
7
|
|
|
8
|
+
// Files to exclude when staging Iris apps (not needed on server)
|
|
9
|
+
const EXCLUDED_FILES = new Set(['index.html', 'favicon.ico']);
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Build a Vue project using npm run build.
|
|
10
13
|
*
|
|
@@ -176,9 +179,20 @@ export function stageToWorkspace(distPath, slug, workspacePath = process.cwd())
|
|
|
176
179
|
rmSync(targetDir, { recursive: true, force: true });
|
|
177
180
|
}
|
|
178
181
|
|
|
179
|
-
// Copy dist contents to target
|
|
182
|
+
// Copy dist contents to target, excluding unnecessary files
|
|
180
183
|
try {
|
|
181
|
-
cpSync(resolvedDistPath, targetDir, {
|
|
184
|
+
cpSync(resolvedDistPath, targetDir, {
|
|
185
|
+
recursive: true,
|
|
186
|
+
filter: (src) => {
|
|
187
|
+
// Use basename for reliable cross-platform filename extraction
|
|
188
|
+
const filename = basename(src);
|
|
189
|
+
// Only exclude specific files, not directories
|
|
190
|
+
if (EXCLUDED_FILES.has(filename)) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
182
196
|
} catch (err) {
|
|
183
197
|
return {
|
|
184
198
|
success: false,
|