@magentrix-corp/magentrix-cli 1.3.15 → 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.
- package/LICENSE +25 -25
- package/README.md +1166 -1166
- package/actions/autopublish.old.js +293 -293
- package/actions/config.js +182 -182
- package/actions/create.js +466 -466
- package/actions/help.js +164 -164
- package/actions/iris/buildStage.js +874 -874
- package/actions/iris/delete.js +256 -256
- package/actions/iris/dev.js +391 -391
- package/actions/iris/index.js +6 -6
- package/actions/iris/link.js +375 -375
- package/actions/iris/recover.js +268 -268
- package/actions/main.js +80 -80
- package/actions/publish.js +1420 -1420
- package/actions/pull.js +684 -684
- package/actions/setup.js +148 -148
- package/actions/status.js +17 -17
- package/actions/update.js +248 -248
- package/bin/magentrix.js +393 -393
- package/package.json +55 -55
- package/utils/assetPaths.js +158 -158
- package/utils/autopublishLock.js +77 -77
- package/utils/cacher.js +206 -206
- package/utils/cli/checkInstanceUrl.js +76 -45
- package/utils/cli/helpers/compare.js +282 -282
- package/utils/cli/helpers/ensureApiKey.js +63 -63
- package/utils/cli/helpers/ensureCredentials.js +68 -68
- package/utils/cli/helpers/ensureInstanceUrl.js +75 -75
- package/utils/cli/writeRecords.js +262 -262
- package/utils/compare.js +135 -135
- package/utils/compress.js +17 -17
- package/utils/config.js +527 -527
- package/utils/debug.js +144 -144
- package/utils/diagnostics/testPublishLogic.js +96 -96
- package/utils/diff.js +49 -49
- package/utils/downloadAssets.js +291 -291
- package/utils/filetag.js +115 -115
- package/utils/hash.js +14 -14
- package/utils/iris/backup.js +411 -411
- package/utils/iris/builder.js +541 -541
- package/utils/iris/config-reader.js +664 -664
- package/utils/iris/deleteHelper.js +150 -150
- package/utils/iris/errors.js +537 -537
- package/utils/iris/linker.js +601 -601
- package/utils/iris/lock.js +360 -360
- package/utils/iris/validation.js +360 -360
- package/utils/iris/validator.js +281 -281
- package/utils/iris/zipper.js +248 -248
- package/utils/logger.js +291 -291
- package/utils/magentrix/api/assets.js +220 -220
- package/utils/magentrix/api/auth.js +107 -107
- package/utils/magentrix/api/createEntity.js +61 -61
- package/utils/magentrix/api/deleteEntity.js +55 -55
- package/utils/magentrix/api/iris.js +251 -251
- package/utils/magentrix/api/meqlQuery.js +36 -36
- package/utils/magentrix/api/retrieveEntity.js +86 -86
- package/utils/magentrix/api/updateEntity.js +66 -66
- package/utils/magentrix/fetch.js +168 -168
- package/utils/merge.js +22 -22
- package/utils/permissionError.js +70 -70
- package/utils/preferences.js +40 -40
- package/utils/progress.js +469 -469
- package/utils/spinner.js +43 -43
- package/utils/template.js +52 -52
- package/utils/updateFileBase.js +121 -121
- package/utils/workspaces.js +108 -108
- package/vars/config.js +11 -11
- package/vars/global.js +50 -50
package/utils/debug.js
CHANGED
|
@@ -1,144 +1,144 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import { VERSION } from '../vars/config.js';
|
|
5
|
-
import { CWD, HASHED_CWD } from '../vars/global.js';
|
|
6
|
-
import Config from './config.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Masks a sensitive string, showing only the first 4 and last 4 characters.
|
|
10
|
-
* @param {string} value
|
|
11
|
-
* @returns {string}
|
|
12
|
-
*/
|
|
13
|
-
function mask(value) {
|
|
14
|
-
if (!value || typeof value !== 'string') return '(empty)';
|
|
15
|
-
if (value.length <= 12) return '****';
|
|
16
|
-
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Centralized debug logger singleton.
|
|
21
|
-
* When enabled, writes timestamped lines to .magentrix/logs/debug-<timestamp>.log.
|
|
22
|
-
* All methods are no-ops when debug.enabled === false.
|
|
23
|
-
*/
|
|
24
|
-
const debug = {
|
|
25
|
-
enabled: false,
|
|
26
|
-
_logFile: null,
|
|
27
|
-
_startTime: null,
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Enable debug mode and open the log file.
|
|
31
|
-
*/
|
|
32
|
-
enable() {
|
|
33
|
-
this.enabled = true;
|
|
34
|
-
this._startTime = Date.now();
|
|
35
|
-
|
|
36
|
-
const logsDir = path.join(CWD, '.magentrix', 'logs');
|
|
37
|
-
fs.mkdirSync(logsDir, { recursive: true, mode: 0o700 });
|
|
38
|
-
|
|
39
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
40
|
-
this._logFile = path.join(logsDir, `debug-${timestamp}.log`);
|
|
41
|
-
|
|
42
|
-
// Write header
|
|
43
|
-
fs.writeFileSync(this._logFile, `# MagentrixCLI Debug Log\n# Started: ${new Date().toISOString()}\n\n`, { mode: 0o600 });
|
|
44
|
-
console.log(`Debug log: ${path.relative(CWD, this._logFile)}`);
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Write a timestamped line to the debug log.
|
|
49
|
-
* @param {string} label
|
|
50
|
-
* @param {...any} args
|
|
51
|
-
*/
|
|
52
|
-
log(label, ...args) {
|
|
53
|
-
if (!this.enabled || !this._logFile) return;
|
|
54
|
-
const elapsed = Date.now() - this._startTime;
|
|
55
|
-
const ts = `[+${String(elapsed).padStart(6)}ms]`;
|
|
56
|
-
const detail = args.length
|
|
57
|
-
? ' ' + args.map(a => (typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a))).join(' ')
|
|
58
|
-
: '';
|
|
59
|
-
fs.appendFileSync(this._logFile, `${ts} [${label}]${detail}\n`);
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Log an outgoing HTTP request (sanitizes auth tokens/API keys).
|
|
64
|
-
*/
|
|
65
|
-
request(method, url, headers, body) {
|
|
66
|
-
if (!this.enabled) return;
|
|
67
|
-
const safeHeaders = { ...headers };
|
|
68
|
-
if (safeHeaders.Authorization) {
|
|
69
|
-
safeHeaders.Authorization = `Bearer ${mask(safeHeaders.Authorization.replace('Bearer ', ''))}`;
|
|
70
|
-
}
|
|
71
|
-
this.log('HTTP-REQ', `${method} ${url}`);
|
|
72
|
-
this.log('HTTP-REQ', 'Headers:', JSON.stringify(safeHeaders, null, 2));
|
|
73
|
-
if (body !== undefined && body !== null) {
|
|
74
|
-
let bodyStr = typeof body === 'string' ? body : JSON.stringify(body, null, 2);
|
|
75
|
-
// Mask sensitive fields in body
|
|
76
|
-
bodyStr = bodyStr.replace(/"refresh_token"\s*:\s*"([^"]+)"/g, (_, val) => `"refresh_token": "${mask(val)}"`);
|
|
77
|
-
bodyStr = bodyStr.replace(/"apiKey"\s*:\s*"([^"]+)"/g, (_, val) => `"apiKey": "${mask(val)}"`);
|
|
78
|
-
this.log('HTTP-REQ', 'Body:', bodyStr);
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Log an HTTP response including status, headers, and body.
|
|
84
|
-
*/
|
|
85
|
-
response(status, statusText, headers, body) {
|
|
86
|
-
if (!this.enabled) return;
|
|
87
|
-
this.log('HTTP-RES', `${status} ${statusText}`);
|
|
88
|
-
if (headers) {
|
|
89
|
-
const headerObj = {};
|
|
90
|
-
if (typeof headers.forEach === 'function') {
|
|
91
|
-
headers.forEach((value, key) => { headerObj[key] = value; });
|
|
92
|
-
} else if (typeof headers === 'object') {
|
|
93
|
-
Object.assign(headerObj, headers);
|
|
94
|
-
}
|
|
95
|
-
this.log('HTTP-RES', 'Headers:', JSON.stringify(headerObj, null, 2));
|
|
96
|
-
}
|
|
97
|
-
if (body !== undefined && body !== null) {
|
|
98
|
-
let bodyStr = typeof body === 'string' ? body : JSON.stringify(body, null, 2);
|
|
99
|
-
// Mask tokens in response
|
|
100
|
-
bodyStr = bodyStr.replace(/"token"\s*:\s*"([^"]+)"/g, (_, val) => `"token": "${mask(val)}"`);
|
|
101
|
-
this.log('HTTP-RES', 'Body:', bodyStr);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Log environment information.
|
|
107
|
-
*/
|
|
108
|
-
env() {
|
|
109
|
-
if (!this.enabled) return;
|
|
110
|
-
const config = new Config();
|
|
111
|
-
const instanceUrl = config.read('instanceUrl', { global: true, pathHash: HASHED_CWD }) || '(not set)';
|
|
112
|
-
|
|
113
|
-
this.log('ENV', 'Node version:', process.version);
|
|
114
|
-
this.log('ENV', 'OS:', `${os.type()} ${os.release()} (${os.arch()})`);
|
|
115
|
-
this.log('ENV', 'CLI version:', VERSION);
|
|
116
|
-
this.log('ENV', 'CWD:', CWD);
|
|
117
|
-
this.log('ENV', 'Hashed CWD:', HASHED_CWD);
|
|
118
|
-
this.log('ENV', 'Instance URL:', instanceUrl);
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Auth-specific debug logging.
|
|
123
|
-
*/
|
|
124
|
-
auth(message, details) {
|
|
125
|
-
if (!this.enabled) return;
|
|
126
|
-
if (details) {
|
|
127
|
-
this.log('AUTH', message, details);
|
|
128
|
-
} else {
|
|
129
|
-
this.log('AUTH', message);
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Finalize the debug log and print its path.
|
|
135
|
-
*/
|
|
136
|
-
close() {
|
|
137
|
-
if (!this.enabled || !this._logFile) return;
|
|
138
|
-
const elapsed = Date.now() - this._startTime;
|
|
139
|
-
this.log('END', `Debug session ended. Total time: ${elapsed}ms`);
|
|
140
|
-
console.log(`\nDebug log saved: ${path.relative(CWD, this._logFile)}`);
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
export default debug;
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { VERSION } from '../vars/config.js';
|
|
5
|
+
import { CWD, HASHED_CWD } from '../vars/global.js';
|
|
6
|
+
import Config from './config.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Masks a sensitive string, showing only the first 4 and last 4 characters.
|
|
10
|
+
* @param {string} value
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function mask(value) {
|
|
14
|
+
if (!value || typeof value !== 'string') return '(empty)';
|
|
15
|
+
if (value.length <= 12) return '****';
|
|
16
|
+
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Centralized debug logger singleton.
|
|
21
|
+
* When enabled, writes timestamped lines to .magentrix/logs/debug-<timestamp>.log.
|
|
22
|
+
* All methods are no-ops when debug.enabled === false.
|
|
23
|
+
*/
|
|
24
|
+
const debug = {
|
|
25
|
+
enabled: false,
|
|
26
|
+
_logFile: null,
|
|
27
|
+
_startTime: null,
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Enable debug mode and open the log file.
|
|
31
|
+
*/
|
|
32
|
+
enable() {
|
|
33
|
+
this.enabled = true;
|
|
34
|
+
this._startTime = Date.now();
|
|
35
|
+
|
|
36
|
+
const logsDir = path.join(CWD, '.magentrix', 'logs');
|
|
37
|
+
fs.mkdirSync(logsDir, { recursive: true, mode: 0o700 });
|
|
38
|
+
|
|
39
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
40
|
+
this._logFile = path.join(logsDir, `debug-${timestamp}.log`);
|
|
41
|
+
|
|
42
|
+
// Write header
|
|
43
|
+
fs.writeFileSync(this._logFile, `# MagentrixCLI Debug Log\n# Started: ${new Date().toISOString()}\n\n`, { mode: 0o600 });
|
|
44
|
+
console.log(`Debug log: ${path.relative(CWD, this._logFile)}`);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Write a timestamped line to the debug log.
|
|
49
|
+
* @param {string} label
|
|
50
|
+
* @param {...any} args
|
|
51
|
+
*/
|
|
52
|
+
log(label, ...args) {
|
|
53
|
+
if (!this.enabled || !this._logFile) return;
|
|
54
|
+
const elapsed = Date.now() - this._startTime;
|
|
55
|
+
const ts = `[+${String(elapsed).padStart(6)}ms]`;
|
|
56
|
+
const detail = args.length
|
|
57
|
+
? ' ' + args.map(a => (typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a))).join(' ')
|
|
58
|
+
: '';
|
|
59
|
+
fs.appendFileSync(this._logFile, `${ts} [${label}]${detail}\n`);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Log an outgoing HTTP request (sanitizes auth tokens/API keys).
|
|
64
|
+
*/
|
|
65
|
+
request(method, url, headers, body) {
|
|
66
|
+
if (!this.enabled) return;
|
|
67
|
+
const safeHeaders = { ...headers };
|
|
68
|
+
if (safeHeaders.Authorization) {
|
|
69
|
+
safeHeaders.Authorization = `Bearer ${mask(safeHeaders.Authorization.replace('Bearer ', ''))}`;
|
|
70
|
+
}
|
|
71
|
+
this.log('HTTP-REQ', `${method} ${url}`);
|
|
72
|
+
this.log('HTTP-REQ', 'Headers:', JSON.stringify(safeHeaders, null, 2));
|
|
73
|
+
if (body !== undefined && body !== null) {
|
|
74
|
+
let bodyStr = typeof body === 'string' ? body : JSON.stringify(body, null, 2);
|
|
75
|
+
// Mask sensitive fields in body
|
|
76
|
+
bodyStr = bodyStr.replace(/"refresh_token"\s*:\s*"([^"]+)"/g, (_, val) => `"refresh_token": "${mask(val)}"`);
|
|
77
|
+
bodyStr = bodyStr.replace(/"apiKey"\s*:\s*"([^"]+)"/g, (_, val) => `"apiKey": "${mask(val)}"`);
|
|
78
|
+
this.log('HTTP-REQ', 'Body:', bodyStr);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Log an HTTP response including status, headers, and body.
|
|
84
|
+
*/
|
|
85
|
+
response(status, statusText, headers, body) {
|
|
86
|
+
if (!this.enabled) return;
|
|
87
|
+
this.log('HTTP-RES', `${status} ${statusText}`);
|
|
88
|
+
if (headers) {
|
|
89
|
+
const headerObj = {};
|
|
90
|
+
if (typeof headers.forEach === 'function') {
|
|
91
|
+
headers.forEach((value, key) => { headerObj[key] = value; });
|
|
92
|
+
} else if (typeof headers === 'object') {
|
|
93
|
+
Object.assign(headerObj, headers);
|
|
94
|
+
}
|
|
95
|
+
this.log('HTTP-RES', 'Headers:', JSON.stringify(headerObj, null, 2));
|
|
96
|
+
}
|
|
97
|
+
if (body !== undefined && body !== null) {
|
|
98
|
+
let bodyStr = typeof body === 'string' ? body : JSON.stringify(body, null, 2);
|
|
99
|
+
// Mask tokens in response
|
|
100
|
+
bodyStr = bodyStr.replace(/"token"\s*:\s*"([^"]+)"/g, (_, val) => `"token": "${mask(val)}"`);
|
|
101
|
+
this.log('HTTP-RES', 'Body:', bodyStr);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Log environment information.
|
|
107
|
+
*/
|
|
108
|
+
env() {
|
|
109
|
+
if (!this.enabled) return;
|
|
110
|
+
const config = new Config();
|
|
111
|
+
const instanceUrl = config.read('instanceUrl', { global: true, pathHash: HASHED_CWD }) || '(not set)';
|
|
112
|
+
|
|
113
|
+
this.log('ENV', 'Node version:', process.version);
|
|
114
|
+
this.log('ENV', 'OS:', `${os.type()} ${os.release()} (${os.arch()})`);
|
|
115
|
+
this.log('ENV', 'CLI version:', VERSION);
|
|
116
|
+
this.log('ENV', 'CWD:', CWD);
|
|
117
|
+
this.log('ENV', 'Hashed CWD:', HASHED_CWD);
|
|
118
|
+
this.log('ENV', 'Instance URL:', instanceUrl);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Auth-specific debug logging.
|
|
123
|
+
*/
|
|
124
|
+
auth(message, details) {
|
|
125
|
+
if (!this.enabled) return;
|
|
126
|
+
if (details) {
|
|
127
|
+
this.log('AUTH', message, details);
|
|
128
|
+
} else {
|
|
129
|
+
this.log('AUTH', message);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Finalize the debug log and print its path.
|
|
135
|
+
*/
|
|
136
|
+
close() {
|
|
137
|
+
if (!this.enabled || !this._logFile) return;
|
|
138
|
+
const elapsed = Date.now() - this._startTime;
|
|
139
|
+
this.log('END', `Debug session ended. Total time: ${elapsed}ms`);
|
|
140
|
+
console.log(`\nDebug log saved: ${path.relative(CWD, this._logFile)}`);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export default debug;
|
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
import { walkFiles } from '../cacher.js';
|
|
2
|
-
import Config from '../config.js';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
const config = new Config();
|
|
6
|
-
const EXPORT_ROOT = 'src';
|
|
7
|
-
|
|
8
|
-
// Load cache
|
|
9
|
-
const hits = await config.searchObject({}, { filename: "base.json", global: false });
|
|
10
|
-
const cachedResults = hits?.[0]?.value || {};
|
|
11
|
-
|
|
12
|
-
const cachedFiles = Object.values(cachedResults).map((c) => ({
|
|
13
|
-
...c,
|
|
14
|
-
tag: c.recordId,
|
|
15
|
-
filePath: c.filePath || c.lastKnownPath,
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
console.log('Total cached files:', cachedFiles.length);
|
|
19
|
-
console.log('Cached assets (type=File):', cachedFiles.filter(cf => cf.type === 'File').length);
|
|
20
|
-
console.log('Cached folders (type=Folder):', cachedFiles.filter(cf => cf.type === 'Folder').length);
|
|
21
|
-
console.log('');
|
|
22
|
-
|
|
23
|
-
// Build Set like in publish
|
|
24
|
-
const cachedAssetPaths = new Set();
|
|
25
|
-
cachedFiles
|
|
26
|
-
.filter(cf => cf.type === 'File' || cf.type === 'Folder')
|
|
27
|
-
.forEach(cf => {
|
|
28
|
-
if (cf.lastKnownActualPath) {
|
|
29
|
-
cachedAssetPaths.add(path.normalize(path.resolve(cf.lastKnownActualPath)).toLowerCase());
|
|
30
|
-
}
|
|
31
|
-
if (cf.filePath) {
|
|
32
|
-
cachedAssetPaths.add(path.normalize(path.resolve(cf.filePath)).toLowerCase());
|
|
33
|
-
}
|
|
34
|
-
if (cf.lastKnownPath) {
|
|
35
|
-
cachedAssetPaths.add(path.normalize(path.resolve(cf.lastKnownPath)).toLowerCase());
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
console.log('Cached asset paths in Set:', cachedAssetPaths.size);
|
|
40
|
-
console.log('');
|
|
41
|
-
|
|
42
|
-
// Get local assets
|
|
43
|
-
const assetPaths = await walkFiles(path.join(EXPORT_ROOT, 'Assets'));
|
|
44
|
-
console.log('Local asset files found:', assetPaths.length);
|
|
45
|
-
console.log('');
|
|
46
|
-
|
|
47
|
-
// Check first few
|
|
48
|
-
let matched = 0;
|
|
49
|
-
let notMatched = 0;
|
|
50
|
-
|
|
51
|
-
for (let i = 0; i < Math.min(10, assetPaths.length); i++) {
|
|
52
|
-
const assetPath = assetPaths[i];
|
|
53
|
-
const normalizedAssetPath = path.normalize(path.resolve(assetPath)).toLowerCase();
|
|
54
|
-
const inCache = cachedAssetPaths.has(normalizedAssetPath);
|
|
55
|
-
|
|
56
|
-
if (inCache) {
|
|
57
|
-
matched++;
|
|
58
|
-
} else {
|
|
59
|
-
notMatched++;
|
|
60
|
-
console.log('NOT IN CACHE:', assetPath);
|
|
61
|
-
console.log(' Normalized:', normalizedAssetPath);
|
|
62
|
-
console.log('');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
console.log(`First 10 files: ${matched} matched, ${notMatched} not matched`);
|
|
67
|
-
console.log('');
|
|
68
|
-
|
|
69
|
-
// Check if the Set actually contains the sample path
|
|
70
|
-
const samplePath = assetPaths[0];
|
|
71
|
-
const sampleNormalized = path.normalize(path.resolve(samplePath)).toLowerCase();
|
|
72
|
-
console.log('Sample path:', samplePath);
|
|
73
|
-
console.log('Normalized:', sampleNormalized);
|
|
74
|
-
console.log('In Set:', cachedAssetPaths.has(sampleNormalized));
|
|
75
|
-
console.log('');
|
|
76
|
-
|
|
77
|
-
// Check what's actually in the Set for this file
|
|
78
|
-
const sampleInBase = Object.values(cachedResults).find(b =>
|
|
79
|
-
b.filePath === 'Assets/Acronis/Banners/1.png' ||
|
|
80
|
-
b.lastKnownActualPath === 'src/Assets/Acronis/Banners/1.png'
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
if (sampleInBase) {
|
|
84
|
-
console.log('Found in base.json:');
|
|
85
|
-
console.log(' type:', sampleInBase.type);
|
|
86
|
-
console.log(' filePath:', sampleInBase.filePath);
|
|
87
|
-
console.log(' lastKnownActualPath:', sampleInBase.lastKnownActualPath);
|
|
88
|
-
console.log(' lastKnownPath:', sampleInBase.lastKnownPath);
|
|
89
|
-
|
|
90
|
-
// Check what gets added to the Set
|
|
91
|
-
if (sampleInBase.lastKnownActualPath) {
|
|
92
|
-
const normalized = path.normalize(path.resolve(sampleInBase.lastKnownActualPath)).toLowerCase();
|
|
93
|
-
console.log(' Normalized lastKnownActualPath:', normalized);
|
|
94
|
-
console.log(' Match:', normalized === sampleNormalized);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
1
|
+
import { walkFiles } from '../cacher.js';
|
|
2
|
+
import Config from '../config.js';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
const config = new Config();
|
|
6
|
+
const EXPORT_ROOT = 'src';
|
|
7
|
+
|
|
8
|
+
// Load cache
|
|
9
|
+
const hits = await config.searchObject({}, { filename: "base.json", global: false });
|
|
10
|
+
const cachedResults = hits?.[0]?.value || {};
|
|
11
|
+
|
|
12
|
+
const cachedFiles = Object.values(cachedResults).map((c) => ({
|
|
13
|
+
...c,
|
|
14
|
+
tag: c.recordId,
|
|
15
|
+
filePath: c.filePath || c.lastKnownPath,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
console.log('Total cached files:', cachedFiles.length);
|
|
19
|
+
console.log('Cached assets (type=File):', cachedFiles.filter(cf => cf.type === 'File').length);
|
|
20
|
+
console.log('Cached folders (type=Folder):', cachedFiles.filter(cf => cf.type === 'Folder').length);
|
|
21
|
+
console.log('');
|
|
22
|
+
|
|
23
|
+
// Build Set like in publish
|
|
24
|
+
const cachedAssetPaths = new Set();
|
|
25
|
+
cachedFiles
|
|
26
|
+
.filter(cf => cf.type === 'File' || cf.type === 'Folder')
|
|
27
|
+
.forEach(cf => {
|
|
28
|
+
if (cf.lastKnownActualPath) {
|
|
29
|
+
cachedAssetPaths.add(path.normalize(path.resolve(cf.lastKnownActualPath)).toLowerCase());
|
|
30
|
+
}
|
|
31
|
+
if (cf.filePath) {
|
|
32
|
+
cachedAssetPaths.add(path.normalize(path.resolve(cf.filePath)).toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
if (cf.lastKnownPath) {
|
|
35
|
+
cachedAssetPaths.add(path.normalize(path.resolve(cf.lastKnownPath)).toLowerCase());
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log('Cached asset paths in Set:', cachedAssetPaths.size);
|
|
40
|
+
console.log('');
|
|
41
|
+
|
|
42
|
+
// Get local assets
|
|
43
|
+
const assetPaths = await walkFiles(path.join(EXPORT_ROOT, 'Assets'));
|
|
44
|
+
console.log('Local asset files found:', assetPaths.length);
|
|
45
|
+
console.log('');
|
|
46
|
+
|
|
47
|
+
// Check first few
|
|
48
|
+
let matched = 0;
|
|
49
|
+
let notMatched = 0;
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < Math.min(10, assetPaths.length); i++) {
|
|
52
|
+
const assetPath = assetPaths[i];
|
|
53
|
+
const normalizedAssetPath = path.normalize(path.resolve(assetPath)).toLowerCase();
|
|
54
|
+
const inCache = cachedAssetPaths.has(normalizedAssetPath);
|
|
55
|
+
|
|
56
|
+
if (inCache) {
|
|
57
|
+
matched++;
|
|
58
|
+
} else {
|
|
59
|
+
notMatched++;
|
|
60
|
+
console.log('NOT IN CACHE:', assetPath);
|
|
61
|
+
console.log(' Normalized:', normalizedAssetPath);
|
|
62
|
+
console.log('');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(`First 10 files: ${matched} matched, ${notMatched} not matched`);
|
|
67
|
+
console.log('');
|
|
68
|
+
|
|
69
|
+
// Check if the Set actually contains the sample path
|
|
70
|
+
const samplePath = assetPaths[0];
|
|
71
|
+
const sampleNormalized = path.normalize(path.resolve(samplePath)).toLowerCase();
|
|
72
|
+
console.log('Sample path:', samplePath);
|
|
73
|
+
console.log('Normalized:', sampleNormalized);
|
|
74
|
+
console.log('In Set:', cachedAssetPaths.has(sampleNormalized));
|
|
75
|
+
console.log('');
|
|
76
|
+
|
|
77
|
+
// Check what's actually in the Set for this file
|
|
78
|
+
const sampleInBase = Object.values(cachedResults).find(b =>
|
|
79
|
+
b.filePath === 'Assets/Acronis/Banners/1.png' ||
|
|
80
|
+
b.lastKnownActualPath === 'src/Assets/Acronis/Banners/1.png'
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (sampleInBase) {
|
|
84
|
+
console.log('Found in base.json:');
|
|
85
|
+
console.log(' type:', sampleInBase.type);
|
|
86
|
+
console.log(' filePath:', sampleInBase.filePath);
|
|
87
|
+
console.log(' lastKnownActualPath:', sampleInBase.lastKnownActualPath);
|
|
88
|
+
console.log(' lastKnownPath:', sampleInBase.lastKnownPath);
|
|
89
|
+
|
|
90
|
+
// Check what gets added to the Set
|
|
91
|
+
if (sampleInBase.lastKnownActualPath) {
|
|
92
|
+
const normalized = path.normalize(path.resolve(sampleInBase.lastKnownActualPath)).toLowerCase();
|
|
93
|
+
console.log(' Normalized lastKnownActualPath:', normalized);
|
|
94
|
+
console.log(' Match:', normalized === sampleNormalized);
|
|
95
|
+
}
|
|
96
|
+
}
|
package/utils/diff.js
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { execSync, spawn } from 'child_process';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Checks if VS Code is installed and accessible via the CLI (`code` command).
|
|
6
|
-
* @returns {boolean} True if VS Code is available in PATH, false otherwise.
|
|
7
|
-
*/
|
|
8
|
-
export const canOpenDiffInVSCode = () => {
|
|
9
|
-
try {
|
|
10
|
-
execSync('code --version', { stdio: 'ignore' });
|
|
11
|
-
return true;
|
|
12
|
-
} catch (err) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Opens a side-by-side diff of two files in VS Code, if available.
|
|
19
|
-
* Falls back to terminal diff if VS Code is unavailable.
|
|
20
|
-
* @param {string} file1 - Path to the first file.
|
|
21
|
-
* @param {string} file2 - Path to the second file.
|
|
22
|
-
* @returns {boolean} True if VS Code diff was opened, false if fallback used.
|
|
23
|
-
*/
|
|
24
|
-
export const openDiffInVSCode = (file1, file2) => {
|
|
25
|
-
if (!canOpenDiffInVSCode()) {
|
|
26
|
-
console.log(
|
|
27
|
-
chalk.yellow(
|
|
28
|
-
'Warning: VS Code is not installed or the `code` command is not in your PATH.\n' +
|
|
29
|
-
'Falling back to terminal diff.\nSee: https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line'
|
|
30
|
-
)
|
|
31
|
-
);
|
|
32
|
-
// Fallback: Use built-in diff (Unix) or fc (Windows)
|
|
33
|
-
try {
|
|
34
|
-
if (process.platform === 'win32') {
|
|
35
|
-
execSync(`fc "${file1}" "${file2}"`, { stdio: 'inherit' });
|
|
36
|
-
} else {
|
|
37
|
-
execSync(`diff -u "${file1}" "${file2}"`, { stdio: 'inherit' });
|
|
38
|
-
}
|
|
39
|
-
} catch (e) {
|
|
40
|
-
// Optionally handle diff exit code (e.g., files differ)
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const child = spawn('code', ['--diff', file1, file2], { stdio: 'inherit', shell: true });
|
|
46
|
-
console.log(chalk.green('Opening diff in VS Code...'));
|
|
47
|
-
|
|
48
|
-
return true;
|
|
49
|
-
};
|
|
1
|
+
import { execSync, spawn } from 'child_process';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Checks if VS Code is installed and accessible via the CLI (`code` command).
|
|
6
|
+
* @returns {boolean} True if VS Code is available in PATH, false otherwise.
|
|
7
|
+
*/
|
|
8
|
+
export const canOpenDiffInVSCode = () => {
|
|
9
|
+
try {
|
|
10
|
+
execSync('code --version', { stdio: 'ignore' });
|
|
11
|
+
return true;
|
|
12
|
+
} catch (err) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Opens a side-by-side diff of two files in VS Code, if available.
|
|
19
|
+
* Falls back to terminal diff if VS Code is unavailable.
|
|
20
|
+
* @param {string} file1 - Path to the first file.
|
|
21
|
+
* @param {string} file2 - Path to the second file.
|
|
22
|
+
* @returns {boolean} True if VS Code diff was opened, false if fallback used.
|
|
23
|
+
*/
|
|
24
|
+
export const openDiffInVSCode = (file1, file2) => {
|
|
25
|
+
if (!canOpenDiffInVSCode()) {
|
|
26
|
+
console.log(
|
|
27
|
+
chalk.yellow(
|
|
28
|
+
'Warning: VS Code is not installed or the `code` command is not in your PATH.\n' +
|
|
29
|
+
'Falling back to terminal diff.\nSee: https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line'
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
// Fallback: Use built-in diff (Unix) or fc (Windows)
|
|
33
|
+
try {
|
|
34
|
+
if (process.platform === 'win32') {
|
|
35
|
+
execSync(`fc "${file1}" "${file2}"`, { stdio: 'inherit' });
|
|
36
|
+
} else {
|
|
37
|
+
execSync(`diff -u "${file1}" "${file2}"`, { stdio: 'inherit' });
|
|
38
|
+
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// Optionally handle diff exit code (e.g., files differ)
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const child = spawn('code', ['--diff', file1, file2], { stdio: 'inherit', shell: true });
|
|
46
|
+
console.log(chalk.green('Opening diff in VS Code...'));
|
|
47
|
+
|
|
48
|
+
return true;
|
|
49
|
+
};
|