@magentrix-corp/magentrix-cli 1.3.2 → 1.3.3
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 +1 -1
- package/actions/iris/dev.js +43 -41
- package/actions/iris/link.js +13 -15
- package/bin/magentrix.js +61 -10
- package/package.json +1 -1
package/README.md
CHANGED
package/actions/iris/dev.js
CHANGED
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
getInjectionTarget
|
|
14
14
|
} from '../../utils/iris/config-reader.js';
|
|
15
15
|
import { getIrisAssets } from '../../utils/magentrix/api/iris.js';
|
|
16
|
+
import { getAccessToken } from '../../utils/magentrix/api/auth.js';
|
|
16
17
|
import {
|
|
17
18
|
getLinkedProjectsWithStatus,
|
|
18
19
|
buildProjectChoices
|
|
19
20
|
} from '../../utils/iris/linker.js';
|
|
20
|
-
import { ensureValidCredentials } from '../../utils/cli/helpers/ensureCredentials.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* iris-dev command - Start Vue dev server with platform assets injected.
|
|
@@ -100,55 +100,57 @@ export const irisDev = async (options = {}) => {
|
|
|
100
100
|
|
|
101
101
|
// Inject assets if enabled
|
|
102
102
|
if (inject && siteUrl) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Use siteUrl from config if different from instanceUrl
|
|
110
|
-
const targetUrl = siteUrl || instanceUrl;
|
|
111
|
-
|
|
112
|
-
const assetsResult = await getIrisAssets(targetUrl, token.value);
|
|
113
|
-
|
|
114
|
-
if (assetsResult.success && assetsResult.assets?.length > 0) {
|
|
115
|
-
console.log(chalk.green(`\u2713 Found ${assetsResult.assets.length} platform assets`));
|
|
116
|
-
|
|
117
|
-
// Determine which file will be modified
|
|
118
|
-
const { targetFile, targetName } = getInjectionTarget(projectPath);
|
|
103
|
+
// Check if we have the refresh token for authentication
|
|
104
|
+
if (!vueConfig.refreshToken) {
|
|
105
|
+
console.log(chalk.yellow('Warning: VITE_REFRESH_TOKEN not set in .env.development'));
|
|
106
|
+
console.log(chalk.gray('Asset injection requires authentication. Continuing without assets.'));
|
|
107
|
+
} else {
|
|
108
|
+
console.log(chalk.blue('Fetching platform assets...'));
|
|
119
109
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
modifiedFilePath = targetFile;
|
|
125
|
-
modifiedFileName = targetName;
|
|
110
|
+
try {
|
|
111
|
+
// Get access token using the refresh token from .env.development
|
|
112
|
+
const tokenData = await getAccessToken(vueConfig.refreshToken, siteUrl);
|
|
113
|
+
const assetsResult = await getIrisAssets(siteUrl, tokenData.token);
|
|
126
114
|
|
|
127
|
-
|
|
128
|
-
console.log(chalk.
|
|
129
|
-
backupPath = backupFile(modifiedFilePath);
|
|
130
|
-
console.log(chalk.green(`\u2713 Backup created`));
|
|
115
|
+
if (assetsResult.success && assetsResult.assets?.length > 0) {
|
|
116
|
+
console.log(chalk.green(`\u2713 Found ${assetsResult.assets.length} platform assets`));
|
|
131
117
|
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
const injectResult = injectAssets(projectPath, assetsResult.assets);
|
|
118
|
+
// Determine which file will be modified
|
|
119
|
+
const { targetFile, targetName } = getInjectionTarget(projectPath);
|
|
135
120
|
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
console.log(chalk.
|
|
121
|
+
if (!targetFile) {
|
|
122
|
+
console.log(chalk.yellow('Warning: No .env.development file found. Cannot inject assets.'));
|
|
123
|
+
console.log(chalk.gray('Create a .env.development file to enable asset injection.'));
|
|
139
124
|
} else {
|
|
140
|
-
|
|
125
|
+
modifiedFilePath = targetFile;
|
|
126
|
+
modifiedFileName = targetName;
|
|
127
|
+
|
|
128
|
+
// Backup before modifying
|
|
129
|
+
console.log(chalk.blue(`Backing up ${modifiedFileName}...`));
|
|
130
|
+
backupPath = backupFile(modifiedFilePath);
|
|
131
|
+
console.log(chalk.green(`\u2713 Backup created`));
|
|
132
|
+
|
|
133
|
+
// Inject assets
|
|
134
|
+
console.log(chalk.blue('Injecting assets...'));
|
|
135
|
+
const injectResult = injectAssets(projectPath, assetsResult.assets);
|
|
136
|
+
|
|
137
|
+
if (injectResult.success) {
|
|
138
|
+
assetsInjected = true;
|
|
139
|
+
console.log(chalk.green(`\u2713 Assets injected into ${injectResult.targetName}`));
|
|
140
|
+
} else {
|
|
141
|
+
console.log(chalk.yellow('Warning: Could not inject assets. Continuing without injection.'));
|
|
142
|
+
}
|
|
141
143
|
}
|
|
144
|
+
} else if (assetsResult.error) {
|
|
145
|
+
console.log(chalk.yellow(`Warning: Could not fetch assets: ${assetsResult.error}`));
|
|
146
|
+
console.log(chalk.gray('Continuing without asset injection.'));
|
|
147
|
+
} else {
|
|
148
|
+
console.log(chalk.yellow('No platform assets found.'));
|
|
142
149
|
}
|
|
143
|
-
}
|
|
144
|
-
console.log(chalk.yellow(`Warning:
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.log(chalk.yellow(`Warning: Error fetching assets: ${err.message}`));
|
|
145
152
|
console.log(chalk.gray('Continuing without asset injection.'));
|
|
146
|
-
} else {
|
|
147
|
-
console.log(chalk.yellow('No platform assets found.'));
|
|
148
153
|
}
|
|
149
|
-
} catch (err) {
|
|
150
|
-
console.log(chalk.yellow(`Warning: Error fetching assets: ${err.message}`));
|
|
151
|
-
console.log(chalk.gray('Continuing without asset injection.'));
|
|
152
154
|
}
|
|
153
155
|
} else if (!inject) {
|
|
154
156
|
console.log(chalk.gray('Skipping asset injection (--no-inject)'));
|
package/actions/iris/link.js
CHANGED
|
@@ -77,9 +77,9 @@ async function showMainMenu() {
|
|
|
77
77
|
|
|
78
78
|
const choices = [
|
|
79
79
|
{
|
|
80
|
-
name: 'Link a
|
|
80
|
+
name: 'Link a Vue project',
|
|
81
81
|
value: 'link',
|
|
82
|
-
description: 'Add a Vue project to the CLI'
|
|
82
|
+
description: chalk.dim('→ Add a Vue project to the CLI')
|
|
83
83
|
}
|
|
84
84
|
];
|
|
85
85
|
|
|
@@ -87,12 +87,12 @@ async function showMainMenu() {
|
|
|
87
87
|
choices.push({
|
|
88
88
|
name: 'View linked projects',
|
|
89
89
|
value: 'list',
|
|
90
|
-
description: 'Show all linked Vue projects with status'
|
|
90
|
+
description: chalk.dim('→ Show all linked Vue projects with status')
|
|
91
91
|
});
|
|
92
92
|
choices.push({
|
|
93
93
|
name: 'Unlink a project',
|
|
94
94
|
value: 'unlink',
|
|
95
|
-
description: 'Remove a Vue project from the CLI'
|
|
95
|
+
description: chalk.dim('→ Remove a Vue project from the CLI')
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -100,7 +100,7 @@ async function showMainMenu() {
|
|
|
100
100
|
choices.push({
|
|
101
101
|
name: `Clean up invalid projects (${invalidCount})`,
|
|
102
102
|
value: 'cleanup',
|
|
103
|
-
description: 'Remove projects with missing paths'
|
|
103
|
+
description: chalk.dim('→ Remove projects with missing paths')
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -152,33 +152,31 @@ async function handleLink(pathOption) {
|
|
|
152
152
|
if (cwdConfig.found && cwdConfig.errors.length === 0) {
|
|
153
153
|
// Valid Vue project
|
|
154
154
|
choices.push({
|
|
155
|
-
name: `Current directory
|
|
155
|
+
name: `Current directory (${cwdPath})`,
|
|
156
156
|
value: cwdPath,
|
|
157
|
-
description:
|
|
157
|
+
description: chalk.dim(`→ App: "${cwdConfig.appName}" (${cwdConfig.slug})`)
|
|
158
158
|
});
|
|
159
159
|
} else if (cwdConfig.found && cwdConfig.errors.length > 0) {
|
|
160
160
|
// Has config.ts but with errors
|
|
161
161
|
const errorMsg = cwdConfig.errors[0] || 'Invalid config';
|
|
162
162
|
choices.push({
|
|
163
|
-
name: `Current directory`,
|
|
163
|
+
name: `Current directory (${cwdPath})`,
|
|
164
164
|
value: '__disabled__',
|
|
165
|
-
disabled: `Config error: ${errorMsg}
|
|
166
|
-
description: cwdPath
|
|
165
|
+
disabled: `Config error: ${errorMsg}`
|
|
167
166
|
});
|
|
168
167
|
} else {
|
|
169
168
|
// No config.ts found
|
|
170
169
|
choices.push({
|
|
171
|
-
name: `Current directory`,
|
|
170
|
+
name: `Current directory (${cwdPath})`,
|
|
172
171
|
value: '__disabled__',
|
|
173
|
-
disabled: 'No config.ts found'
|
|
174
|
-
description: cwdPath
|
|
172
|
+
disabled: 'No config.ts found'
|
|
175
173
|
});
|
|
176
174
|
}
|
|
177
175
|
|
|
178
176
|
choices.push({
|
|
179
177
|
name: 'Enter path manually',
|
|
180
178
|
value: '__manual__',
|
|
181
|
-
description: 'Specify the full path to a Vue project'
|
|
179
|
+
description: chalk.dim('→ Specify the full path to a Vue project')
|
|
182
180
|
});
|
|
183
181
|
|
|
184
182
|
choices.push({
|
|
@@ -303,7 +301,7 @@ async function handleUnlink(pathOption) {
|
|
|
303
301
|
return {
|
|
304
302
|
name: `${prefix}${displayName} (${displaySlug})`,
|
|
305
303
|
value: p.slug,
|
|
306
|
-
description: p.path
|
|
304
|
+
description: chalk.dim(`→ Path: ${p.path}`)
|
|
307
305
|
};
|
|
308
306
|
});
|
|
309
307
|
|
package/bin/magentrix.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// Imports
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
6
8
|
import { VERSION } from '../vars/config.js';
|
|
7
9
|
import { setup } from '../actions/setup.js';
|
|
8
10
|
import { main } from '../actions/main.js';
|
|
@@ -17,6 +19,40 @@ import { update } from '../actions/update.js';
|
|
|
17
19
|
import { configWizard } from '../actions/config.js';
|
|
18
20
|
import { irisLink, irisDev, irisDelete, irisRecover, vueBuildStage } from '../actions/iris/index.js';
|
|
19
21
|
|
|
22
|
+
// ── Vue Project Detection ────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Check if current directory is a Vue project (has config.ts)
|
|
25
|
+
*/
|
|
26
|
+
function isInVueProject() {
|
|
27
|
+
const configLocations = [
|
|
28
|
+
'src/config.ts',
|
|
29
|
+
'config.ts',
|
|
30
|
+
'src/iris-config.ts',
|
|
31
|
+
'iris-config.ts'
|
|
32
|
+
];
|
|
33
|
+
return configLocations.some(loc => existsSync(join(process.cwd(), loc)));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Block non-iris commands when in a Vue project
|
|
38
|
+
*/
|
|
39
|
+
function requireMagentrixWorkspace(fn) {
|
|
40
|
+
return async (...args) => {
|
|
41
|
+
if (isInVueProject()) {
|
|
42
|
+
console.error(`\n${chalk.bgRed.white.bold(' ERROR ')} ${chalk.redBright('This command must be run in a Magentrix workspace')}\n`);
|
|
43
|
+
console.error(chalk.yellow('It looks like you\'re in a Vue project directory.'));
|
|
44
|
+
console.error(chalk.gray('This command requires a Magentrix workspace with global API key and instance URL.\n'));
|
|
45
|
+
console.error(chalk.cyan('Available commands in Vue projects:'));
|
|
46
|
+
console.error(chalk.gray(' • magentrix iris-link'));
|
|
47
|
+
console.error(chalk.gray(' • magentrix iris-dev'));
|
|
48
|
+
console.error(chalk.gray(' • magentrix vue-build-stage\n'));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
// Execute the command
|
|
52
|
+
await fn(...args);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
20
56
|
// ── Middleware ────────────────────────────────
|
|
21
57
|
async function preMiddleware() {
|
|
22
58
|
await recacheFileIdIndex(EXPORT_ROOT);
|
|
@@ -32,6 +68,11 @@ const withMiddleware = ({ pre, post }) => (fn) => async (...args) => {
|
|
|
32
68
|
if (post) await post(...args);
|
|
33
69
|
};
|
|
34
70
|
|
|
71
|
+
const withDefault = withMiddleware({ pre: preMiddleware, post: postMiddleware });
|
|
72
|
+
|
|
73
|
+
// Combined wrapper: check for Vue project + run middleware
|
|
74
|
+
const withWorkspaceCheck = (fn) => requireMagentrixWorkspace(withDefault(fn));
|
|
75
|
+
|
|
35
76
|
// ── CLI Setup ────────────────────────────────
|
|
36
77
|
const program = new Command();
|
|
37
78
|
program
|
|
@@ -93,8 +134,6 @@ program
|
|
|
93
134
|
}
|
|
94
135
|
});
|
|
95
136
|
|
|
96
|
-
const withDefault = withMiddleware({ pre: preMiddleware, post: postMiddleware });
|
|
97
|
-
|
|
98
137
|
// ── Error Handlers ───────────────────────────
|
|
99
138
|
program.showHelpAfterError(false);
|
|
100
139
|
program.configureOutput({
|
|
@@ -128,8 +167,8 @@ program
|
|
|
128
167
|
.description('Configure your Magentrix API key')
|
|
129
168
|
.option('--api-key <apiKey>', 'Magentrix API key')
|
|
130
169
|
.option('--instance-url <instanceUrl>', 'Magentrix instance URL (e.g., https://example.magentrixcloud.com)')
|
|
131
|
-
.action(
|
|
132
|
-
program.command('pull').description('Pull files from the remote server').action(
|
|
170
|
+
.action(withWorkspaceCheck(setup));
|
|
171
|
+
program.command('pull').description('Pull files from the remote server').action(withWorkspaceCheck(pull));
|
|
133
172
|
const createCommand = program
|
|
134
173
|
.command('create')
|
|
135
174
|
.description('Create files locally')
|
|
@@ -138,7 +177,7 @@ const createCommand = program
|
|
|
138
177
|
.option('--name <name>', 'Name of the file to create')
|
|
139
178
|
.option('--description <description>', 'Optional description')
|
|
140
179
|
.option('--entity-id <entityId>', 'Entity ID (required for triggers)')
|
|
141
|
-
.action(
|
|
180
|
+
.action(withWorkspaceCheck(create));
|
|
142
181
|
|
|
143
182
|
// Override help for create command to show options
|
|
144
183
|
createCommand.configureHelp({
|
|
@@ -185,17 +224,17 @@ createCommand.configureHelp({
|
|
|
185
224
|
return help;
|
|
186
225
|
}
|
|
187
226
|
});
|
|
188
|
-
program.command('status').description('Show file conflicts').action(
|
|
189
|
-
program.command('autopublish').description('Watch & sync changes in real time').action(
|
|
227
|
+
program.command('status').description('Show file conflicts').action(withWorkspaceCheck(status));
|
|
228
|
+
program.command('autopublish').description('Watch & sync changes in real time').action(withWorkspaceCheck(autoPublish));
|
|
190
229
|
// Publish does its own comprehensive file scanning, so skip the pre-cache middleware
|
|
191
|
-
program.command('publish').description('Publish pending changes to the remote server').action(
|
|
192
|
-
program.command('update').description('Update MagentrixCLI to the latest version').action(update);
|
|
230
|
+
program.command('publish').description('Publish pending changes to the remote server').action(withWorkspaceCheck(publish));
|
|
231
|
+
program.command('update').description('Update MagentrixCLI to the latest version').action(requireMagentrixWorkspace(update));
|
|
193
232
|
|
|
194
233
|
// Config command - interactive wizard
|
|
195
234
|
program
|
|
196
235
|
.command('config')
|
|
197
236
|
.description('Configure CLI settings')
|
|
198
|
-
.action(configWizard);
|
|
237
|
+
.action(requireMagentrixWorkspace(configWizard));
|
|
199
238
|
|
|
200
239
|
// Iris commands for Vue.js app management
|
|
201
240
|
program
|
|
@@ -236,6 +275,18 @@ program
|
|
|
236
275
|
// ── Unknown Command Handler ──────────────────
|
|
237
276
|
program.argument('[command]', 'command to run').action((cmd) => {
|
|
238
277
|
const runMain = async () => {
|
|
278
|
+
// Check if in Vue project
|
|
279
|
+
if (isInVueProject()) {
|
|
280
|
+
console.error(`\n${chalk.bgRed.white.bold(' ERROR ')} ${chalk.redBright('This command must be run in a Magentrix workspace')}\n`);
|
|
281
|
+
console.error(chalk.yellow('It looks like you\'re in a Vue project directory.'));
|
|
282
|
+
console.error(chalk.gray('This command requires a Magentrix workspace with global API key and instance URL.\n'));
|
|
283
|
+
console.error(chalk.cyan('Available commands in Vue projects:'));
|
|
284
|
+
console.error(chalk.gray(' • magentrix iris-link'));
|
|
285
|
+
console.error(chalk.gray(' • magentrix iris-dev'));
|
|
286
|
+
console.error(chalk.gray(' • magentrix vue-build-stage\n'));
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
|
|
239
290
|
await preMiddleware();
|
|
240
291
|
await main();
|
|
241
292
|
await postMiddleware();
|