@ubox-tools/deploy-xperience 1.1.19 → 1.1.21
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/deploy.js +52 -48
- package/package.json +1 -1
package/deploy.js
CHANGED
|
@@ -241,10 +241,7 @@ function generateProxy(appName) {
|
|
|
241
241
|
// 1. Parameter token substitution (JS only — parameters live in JS files)
|
|
242
242
|
if (isJS) {
|
|
243
243
|
for (const key of Object.keys(params)) {
|
|
244
|
-
const re = new RegExp(
|
|
245
|
-
`((?:const|let|var)\\s+${key}\\s*=\\s*)(?:"[^"]*"|'[^']*'|\`[^\`]*\`|-?\\d+\\.?\\d*(?:[eE][+-]?\\d+)?|true|false|null|undefined)`,
|
|
246
|
-
'g'
|
|
247
|
-
);
|
|
244
|
+
const re = new RegExp(`((?:const|let|var)\\s+${key}\\s*=\\s*)(?:"[^"]*"|'[^']*')`, 'g');
|
|
248
245
|
content = content.replace(re, `$1"{parameter:${key}}"`);
|
|
249
246
|
}
|
|
250
247
|
}
|
|
@@ -419,17 +416,33 @@ async function uploadFile(page, absPath) {
|
|
|
419
416
|
await client.detach();
|
|
420
417
|
}
|
|
421
418
|
|
|
422
|
-
/** Inject text content into the active Monaco/CodeMirror/Ace editor.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
419
|
+
/** Inject text content into the active Monaco/CodeMirror/Ace editor.
|
|
420
|
+
* @param {string} filename Source filename (e.g. "index.html") — used to pick
|
|
421
|
+
* the right Monaco model by URI when multiple models are
|
|
422
|
+
* pre-loaded (e.g. after visiting the Parameters tab). */
|
|
423
|
+
async function injectToEditor(page, content, filename) {
|
|
424
|
+
// Try Monaco API
|
|
425
|
+
const monacoResult = await page.evaluate((text, fn) => {
|
|
426
|
+
if (!window.monaco?.editor) return null;
|
|
427
|
+
const models = window.monaco.editor.getModels();
|
|
428
|
+
if (!models?.length) return null;
|
|
429
|
+
|
|
430
|
+
// Best: match model by filename in its URI — avoids the models[0] trap when
|
|
431
|
+
// multiple models are pre-loaded (happens after visiting the Parameters tab).
|
|
432
|
+
if (fn) {
|
|
433
|
+
const m = models.find(m => m.uri?.toString().includes(fn));
|
|
434
|
+
if (m) { m.setValue(text); return 'uri'; }
|
|
429
435
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
436
|
+
|
|
437
|
+
// Safe fallback: single model is always the active one (lazy-load case).
|
|
438
|
+
if (models.length === 1) { models[0].setValue(text); return 'single'; }
|
|
439
|
+
|
|
440
|
+
// Multiple models, no URI match — fall through to keyboard injection.
|
|
441
|
+
return `multi:${models.length}:${models.map(m => m.uri?.toString()).join('|')}`;
|
|
442
|
+
}, content, filename ?? null);
|
|
443
|
+
|
|
444
|
+
if (monacoResult === 'uri' || monacoResult === 'single') return;
|
|
445
|
+
if (monacoResult) console.log(` [editor] Monaco ${monacoResult} → keyboard fallback`);
|
|
433
446
|
|
|
434
447
|
// Try CodeMirror API
|
|
435
448
|
const cmOk = await page.evaluate(text => {
|
|
@@ -437,19 +450,25 @@ async function injectToEditor(page, content) {
|
|
|
437
450
|
if (cm?.CodeMirror) { cm.CodeMirror.setValue(text); return true; }
|
|
438
451
|
return false;
|
|
439
452
|
}, content);
|
|
440
|
-
if (cmOk)
|
|
453
|
+
if (cmOk) return;
|
|
441
454
|
|
|
442
|
-
//
|
|
443
|
-
|
|
455
|
+
// Keyboard injection: click the visible editor, Ctrl+A, Ctrl+V.
|
|
456
|
+
// Targets whatever editor is currently focused (active tab) — model-agnostic.
|
|
444
457
|
writeClipboard(content);
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
458
|
+
const edPos = await page.evaluate(() => {
|
|
459
|
+
for (const sel of ['.monaco-editor', '.ace_editor', '.cm-editor', 'textarea']) {
|
|
460
|
+
const el = Array.from(document.querySelectorAll(sel))
|
|
461
|
+
.find(e => { const r = e.getBoundingClientRect(); return r.width > 10 && r.height > 10; });
|
|
462
|
+
if (el) {
|
|
463
|
+
el.scrollIntoView({ block: 'nearest' });
|
|
464
|
+
const r = el.getBoundingClientRect();
|
|
465
|
+
return { x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2) };
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return null;
|
|
469
|
+
});
|
|
470
|
+
if (!edPos) throw new Error('No code editor found on page');
|
|
471
|
+
await page.mouse.click(edPos.x, edPos.y);
|
|
453
472
|
await sleep(200);
|
|
454
473
|
await page.keyboard.down('Control');
|
|
455
474
|
await page.keyboard.press('a');
|
|
@@ -609,6 +628,9 @@ async function configureParameters(page, params) {
|
|
|
609
628
|
|
|
610
629
|
console.log(` [params] Creating ${toCreate.length} new parameter(s) (${existingKeys.length} already exist)...`);
|
|
611
630
|
|
|
631
|
+
// Accept any confirm() dialogs that Save triggers
|
|
632
|
+
page.on('dialog', async d => { await d.accept(); });
|
|
633
|
+
|
|
612
634
|
await clickByText(page, 'Edit', 'button');
|
|
613
635
|
await sleep(1000);
|
|
614
636
|
|
|
@@ -662,20 +684,11 @@ async function configureParameters(page, params) {
|
|
|
662
684
|
|
|
663
685
|
async function injectSource(page, proxy) {
|
|
664
686
|
console.log(' [source] Injecting source files...');
|
|
665
|
-
console.log(` [source] URL: ${page.url()}`);
|
|
666
687
|
await clickByText(page, 'Source');
|
|
667
688
|
await sleep(1500);
|
|
668
689
|
|
|
669
690
|
await clickByText(page, 'Edit source');
|
|
670
691
|
await sleep(3000);
|
|
671
|
-
// Wait for the editor (Monaco or CodeMirror) to fully initialize.
|
|
672
|
-
// On first-ever source editor visit in a session, Monaco may still be loading
|
|
673
|
-
// after 3 s — this ensures injection happens only once it's ready.
|
|
674
|
-
await page.waitForFunction(() => {
|
|
675
|
-
return !!(window.monaco?.editor?.getModels) ||
|
|
676
|
-
!!(document.querySelector('.CodeMirror')?.CodeMirror);
|
|
677
|
-
}, { timeout: 15000 }).catch(() => null);
|
|
678
|
-
console.log(` [source] URL after Edit source: ${page.url()}`);
|
|
679
692
|
|
|
680
693
|
// Tab label → filename
|
|
681
694
|
const tabs = [
|
|
@@ -692,15 +705,12 @@ async function injectSource(page, proxy) {
|
|
|
692
705
|
console.log(` ${filename} → ${tabLabel}`);
|
|
693
706
|
await clickByText(page, tabLabel);
|
|
694
707
|
await sleep(1000);
|
|
695
|
-
await injectToEditor(page, proxy[filename]);
|
|
708
|
+
await injectToEditor(page, proxy[filename], filename);
|
|
696
709
|
await sleep(500);
|
|
697
710
|
}
|
|
698
711
|
|
|
699
|
-
const navPromise = page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 }).catch(() => null);
|
|
700
712
|
await clickByText(page, 'Save and back to app');
|
|
701
|
-
|
|
702
|
-
await sleep(1000);
|
|
703
|
-
console.log(` [source] URL after save: ${page.url()} (navigated: ${navResult ? 'yes' : 'no'})`);
|
|
713
|
+
await sleep(3000);
|
|
704
714
|
}
|
|
705
715
|
|
|
706
716
|
async function deployApp(page, appName, projectName, { noAssets = false, noSource = false } = {}) {
|
|
@@ -729,7 +739,7 @@ async function deployApp(page, appName, projectName, { noAssets = false, noSourc
|
|
|
729
739
|
// Extract app ID from current URL
|
|
730
740
|
const appId = page.url().match(/#\/application(?:-source)?\/(\d+)/)?.[1] || '?';
|
|
731
741
|
console.log(` [app] Done — ID: ${appId}`);
|
|
732
|
-
return
|
|
742
|
+
return appId;
|
|
733
743
|
}
|
|
734
744
|
|
|
735
745
|
// ─── Phase 3: Ubox Deployment ─────────────────────────────────────────────────
|
|
@@ -1143,12 +1153,6 @@ async function main() {
|
|
|
1143
1153
|
const state = {};
|
|
1144
1154
|
|
|
1145
1155
|
try {
|
|
1146
|
-
// Always accept any confirm() dialogs the studio may show during deployment
|
|
1147
|
-
page.on('dialog', async d => {
|
|
1148
|
-
console.log(` [dialog] type=${d.type()} msg="${d.message()}" → accepted`);
|
|
1149
|
-
await d.accept();
|
|
1150
|
-
});
|
|
1151
|
-
|
|
1152
1156
|
// Phase 1 — Login
|
|
1153
1157
|
await login(page, email, password);
|
|
1154
1158
|
|
|
@@ -1156,9 +1160,9 @@ async function main() {
|
|
|
1156
1160
|
const appParamsMap = {};
|
|
1157
1161
|
for (const appName of apps) {
|
|
1158
1162
|
state[appName] = {};
|
|
1159
|
-
const {
|
|
1160
|
-
state[appName].appId = appId;
|
|
1163
|
+
const { params } = generateProxy(appName);
|
|
1161
1164
|
appParamsMap[appName] = params;
|
|
1165
|
+
state[appName].appId = await deployApp(page, appName, projectName, { noAssets, noSource });
|
|
1162
1166
|
}
|
|
1163
1167
|
|
|
1164
1168
|
// Phase 3 — Deploy Uboxes
|
package/package.json
CHANGED