@aiot-toolkit/aiotpack 2.1.0-prender.12 → 2.1.0-prender.13

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.
@@ -22,6 +22,16 @@ declare class UxAfterCompile {
22
22
  * @param params
23
23
  */
24
24
  static compressResource: FollowWork<IJavascriptCompileOption>;
25
+ /**
26
+ * Relocate manifest.icon into build root so debug and release rpks share the
27
+ * same asset layout. Rewrites `manifest.icon` + every string reference to the
28
+ * old icon path inside template.json / css.json / *.js. Files are text-scanned
29
+ * and quoted-substring matched only (no cross-string boundary rewriting).
30
+ *
31
+ * No-op when manifest.icon is already at root, the physical file is missing,
32
+ * or the destination basename already exists at root.
33
+ */
34
+ static relocateManifestIcon: FollowWork<IJavascriptCompileOption>;
25
35
  /**
26
36
  * 如果是更新触发,则对比临时项目build文件夹 和 项目build文件夹,生成diff.json
27
37
  * @param context
@@ -99,8 +99,12 @@ class UxAfterCompile {
99
99
  context,
100
100
  compilerOption
101
101
  } = params;
102
- if (compilerOption && compilerOption.enableJsc === true) {
103
- return new _Jsc.default(context.projectPath, _path.default.join(context.projectPath, context.output, compilerOption.outputPath)).jsc();
102
+ if (compilerOption) {
103
+ const buildPath = _path.default.join(context.projectPath, context.output, compilerOption.outputPath);
104
+ _Jsc.default.wrapAllJsWithIife(buildPath);
105
+ if (compilerOption.enableJsc === true) {
106
+ return new _Jsc.default(context.projectPath, buildPath).jsc();
107
+ }
104
108
  }
105
109
  };
106
110
  static toRpk = async params => {
@@ -334,6 +338,78 @@ class UxAfterCompile {
334
338
  }
335
339
  };
336
340
 
341
+ /**
342
+ * Relocate manifest.icon into build root so debug and release rpks share the
343
+ * same asset layout. Rewrites `manifest.icon` + every string reference to the
344
+ * old icon path inside template.json / css.json / *.js. Files are text-scanned
345
+ * and quoted-substring matched only (no cross-string boundary rewriting).
346
+ *
347
+ * No-op when manifest.icon is already at root, the physical file is missing,
348
+ * or the destination basename already exists at root.
349
+ */
350
+ static relocateManifestIcon = async params => {
351
+ const {
352
+ compilerOption,
353
+ onLog
354
+ } = params;
355
+ if (!compilerOption) return;
356
+ const {
357
+ projectPath,
358
+ outputPath
359
+ } = compilerOption;
360
+ const buildDir = _path.default.join(projectPath, outputPath);
361
+ const manifestPath = _path.default.join(buildDir, 'manifest.json');
362
+ if (!_fsExtra.default.existsSync(manifestPath)) return;
363
+ const manifest = _fsExtra.default.readJSONSync(manifestPath);
364
+ const oldIcon = manifest.icon;
365
+ if (!oldIcon || typeof oldIcon !== 'string') return;
366
+ const basename = _path.default.basename(oldIcon);
367
+ const newIcon = '/' + basename;
368
+ if (oldIcon === newIcon) return;
369
+ const oldFile = _path.default.join(buildDir, oldIcon.replace(/^\//, ''));
370
+ const newFile = _path.default.join(buildDir, basename);
371
+ if (!_fsExtra.default.existsSync(oldFile)) return;
372
+ if (_fsExtra.default.existsSync(newFile)) {
373
+ onLog?.([{
374
+ level: _sharedUtils.Loglevel.WARN,
375
+ message: [`relocateManifestIcon: skipped — build root already contains ${basename}`]
376
+ }]);
377
+ return;
378
+ }
379
+ _fsExtra.default.moveSync(oldFile, newFile);
380
+ manifest.icon = newIcon;
381
+ _fsExtra.default.writeJSONSync(manifestPath, manifest, {
382
+ spaces: 2
383
+ });
384
+ const variants = [oldIcon, oldIcon.replace(/^\//, '')];
385
+ const replacements = [];
386
+ for (const v of variants) {
387
+ const target = v === oldIcon ? newIcon : basename;
388
+ replacements.push([JSON.stringify(v), JSON.stringify(target)]);
389
+ replacements.push([`'${v}'`, `'${target}'`]);
390
+ }
391
+ const rewriteFile = fp => {
392
+ let text;
393
+ try {
394
+ text = _fsExtra.default.readFileSync(fp, 'utf-8');
395
+ } catch {
396
+ return;
397
+ }
398
+ let changed = false;
399
+ for (const [from, to] of replacements) {
400
+ if (text.includes(from)) {
401
+ text = text.split(from).join(to);
402
+ changed = true;
403
+ }
404
+ }
405
+ if (changed) _fsExtra.default.writeFileSync(fp, text, 'utf-8');
406
+ };
407
+ for (const fp of _sharedUtils.FileUtil.readAlldirSync(buildDir)) {
408
+ if (fp === manifestPath) continue;
409
+ if (/\.(template\.json|css\.json|js|jsx?)$/.test(fp)) rewriteFile(fp);
410
+ }
411
+ };
412
+
337
413
  /**
338
414
  * 如果是更新触发,则对比临时项目build文件夹 和 项目build文件夹,生成diff.json
339
415
  * @param context
@@ -1,4 +1,4 @@
1
- declare function uxToTemplateJson(templateNode: any, styleObjectId?: number, styleSheet?: any, importMap?: Record<string, string>, pageDir?: string): any;
1
+ declare function uxToTemplateJson(templateNode: any, styleObjectId?: number, styleSheet?: any, importMap?: Record<string, string>, pageDir?: string, componentsMap?: Record<string, string>): any;
2
2
  /**
3
3
  * Normalize a media query condition text from CSS Level 4 syntax to Level 3.
4
4
  *
@@ -231,11 +231,17 @@ function normalizeCssTransform(input) {
231
231
  }
232
232
  return matched ? JSON.stringify(out) : null;
233
233
  }
234
- function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pageDir) {
234
+ function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pageDir, componentsMap) {
235
235
  const children = templateNode.content?.childNodes || templateNode.childNodes || [];
236
236
  const rootEl = children.find(n => n.tagName && n.nodeName !== '#text');
237
237
  if (!rootEl) return {};
238
238
  const result = elementToJson(rootEl, styleSheet, importMap, undefined, pageDir);
239
+ const componentsForRoot = componentsMap && Object.keys(componentsMap).length ? componentsMap : importMap;
240
+ if (componentsForRoot && Object.keys(componentsForRoot).length) {
241
+ result.components = {
242
+ ...componentsForRoot
243
+ };
244
+ }
239
245
  // Insert styleObjectId before children (vivo format)
240
246
  if (styleObjectId !== undefined) {
241
247
  const ordered = {};
@@ -253,6 +259,16 @@ function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pa
253
259
  /** Add this. prefix to variable references in an expression */
254
260
  // blueos-pack's pathTestRE: matches simple paths like a.b.c, a['key'], a[0], a[$idx]
255
261
  const pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[\w$]+|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/;
262
+ function tryEvalStaticShowLiteral(expr) {
263
+ if (/^'[^']*'$/.test(expr) || /^"[^"]*"$/.test(expr)) {
264
+ const inner = expr.slice(1, -1);
265
+ return inner.length > 0;
266
+ }
267
+ if (expr === 'undefined' || expr === 'null' || expr === 'NaN') return false;
268
+ if (expr === 'Infinity') return true;
269
+ return undefined;
270
+ }
271
+
256
272
  /**
257
273
  * Normalize a media query condition text from CSS Level 4 syntax to Level 3.
258
274
  *
@@ -612,13 +628,20 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
612
628
  } else if (name === 'show') {
613
629
  const showVal = value.replace(/\{\{|\}\}/g, '').trim();
614
630
  if (showVal === 'true') attrObj['show'] = true;else if (showVal === 'false') attrObj['show'] = false;else {
615
- // Try to evaluate as literal
616
631
  try {
617
632
  const v = JSON.parse(showVal);
618
633
  attrObj["show"] = v;
619
634
  } catch {
620
- attrObj['$show'] = showVal;
621
- hasBind = true;
635
+ const staticVal = tryEvalStaticShowLiteral(showVal);
636
+ if (staticVal !== undefined) {
637
+ attrObj['show'] = staticVal;
638
+ } else if (pathTestRE.test(showVal)) {
639
+ attrObj['$show'] = showVal;
640
+ hasBind = true;
641
+ } else {
642
+ attrObj['$show'] = `function () { return ${addThisPrefix(showVal)}; }`;
643
+ hasBind = true;
644
+ }
622
645
  }
623
646
  }
624
647
  } else if (name === 'for') {
@@ -90,12 +90,43 @@ function rewriteSystemImports(code) {
90
90
  replacement: parts.join(' ')
91
91
  });
92
92
  }
93
+ // Rewrite CJS require() calls for system modules: require('@system.xxx') → $app_require$("@app-module/system.xxx")
94
+ collectRequireEdits(ast, edits);
93
95
  if (edits.length === 0) return code;
94
96
  edits.sort((a, b) => b.start - a.start);
95
97
  let out = code;
96
98
  for (const e of edits) out = out.slice(0, e.start) + e.replacement + out.slice(e.end);
97
99
  return out;
98
100
  }
101
+ function collectRequireEdits(node, edits) {
102
+ if (!node || typeof node !== 'object') return;
103
+ if (node.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'require' && node.arguments?.length === 1 && node.arguments[0].type === 'Literal' && typeof node.arguments[0].value === 'string') {
104
+ const src = node.arguments[0].value;
105
+ let moduleName = null;
106
+ if (NS_PREFIX.test(src)) {
107
+ moduleName = src.replace(NS_PREFIX, '$1.');
108
+ } else if (src.startsWith(APP_MODULE_PREFIX)) {
109
+ moduleName = src.slice(APP_MODULE_PREFIX.length);
110
+ }
111
+ if (moduleName !== null) {
112
+ edits.push({
113
+ start: node.start,
114
+ end: node.end,
115
+ replacement: `$app_require$("${APP_MODULE_PREFIX}${moduleName}")`
116
+ });
117
+ return;
118
+ }
119
+ }
120
+ for (const key of Object.keys(node)) {
121
+ if (key === 'start' || key === 'end' || key === 'type') continue;
122
+ const val = node[key];
123
+ if (Array.isArray(val)) {
124
+ for (const child of val) collectRequireEdits(child, edits);
125
+ } else if (val && typeof val === 'object' && val.type) {
126
+ collectRequireEdits(val, edits);
127
+ }
128
+ }
129
+ }
99
130
  function loadUserViteConfig(projectPath, mode) {
100
131
  const configPath = _path.default.join(projectPath, 'quickapp.config.js');
101
132
  if (!_fsExtra.default.existsSync(configPath)) return {};
@@ -397,6 +428,7 @@ class ViteCompiler {
397
428
  });
398
429
  let templateNode = null;
399
430
  const importMap = {}; // name -> path
431
+ const componentsMap = {}; // originalName -> path
400
432
  for (const node of doc.childNodes) {
401
433
  if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
402
434
  const nameAttr = node.attrs?.find(a => a.name === 'name');
@@ -405,6 +437,7 @@ class ViteCompiler {
405
437
  const compAbsPath = _path.default.resolve(_path.default.dirname(resolvedEntry), srcAttr.value).replace(/\.ux$/, '');
406
438
  const compPath = _path.default.relative(srcPath, compAbsPath).replace(/\\/g, '/');
407
439
  importMap[nameAttr.value.toLowerCase()] = compPath;
440
+ componentsMap[nameAttr.value] = compPath;
408
441
  }
409
442
  }
410
443
  }
@@ -444,7 +477,7 @@ class ViteCompiler {
444
477
  const tplPath = _path.default.join(buildPath, `${pageName}.template.json`);
445
478
  _fsExtra.default.ensureDirSync(_path.default.dirname(tplPath));
446
479
  const mergedSheet = mergeStyleSheets(appStyleSheet, styleSheet);
447
- _fsExtra.default.writeJSONSync(tplPath, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, mergedSheet, importMap, _path.default.dirname(pageName)), param.mode === 'production' ? undefined : {
480
+ _fsExtra.default.writeJSONSync(tplPath, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, mergedSheet, importMap, _path.default.dirname(pageName), componentsMap), param.mode === 'production' ? undefined : {
448
481
  spaces: 2
449
482
  });
450
483
  // Worklist BFS over nested <import> chain so transitively imported
@@ -474,6 +507,7 @@ class ViteCompiler {
474
507
  });
475
508
  let compTpl = null;
476
509
  const compImportMap = {};
510
+ const compComponentsMap = {};
477
511
  for (const node of compDoc.childNodes) {
478
512
  if (node.nodeName === 'template') compTpl = node;else if (node.nodeName === 'import') {
479
513
  const n = node.attrs?.find(a => a.name === 'name');
@@ -482,6 +516,7 @@ class ViteCompiler {
482
516
  const nestedAbsPath = _path.default.resolve(_path.default.dirname(compUxPath), s.value).replace(/\.ux$/, '');
483
517
  const nestedPath = _path.default.relative(srcPath, nestedAbsPath).replace(/\\/g, '/');
484
518
  compImportMap[n.value.toLowerCase()] = nestedPath;
519
+ compComponentsMap[n.value] = nestedPath;
485
520
  if (!visited.has(nestedPath)) {
486
521
  worklist.push({
487
522
  compName: n.value.toLowerCase(),
@@ -509,7 +544,7 @@ class ViteCompiler {
509
544
  compStyleSheet = (0, _TemplateCompiler.parseStyleArray)(csm);
510
545
  }
511
546
  const compSid = (0, _TemplateCompiler.getStyleObjectId)(compPath);
512
- _fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, mergeStyleSheets(appStyleSheet, compStyleSheet), compImportMap, _path.default.dirname(compPath)), param.mode === 'production' ? undefined : {
547
+ _fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, mergeStyleSheets(appStyleSheet, compStyleSheet), compImportMap, _path.default.dirname(compPath), compComponentsMap), param.mode === 'production' ? undefined : {
513
548
  spaces: 2
514
549
  });
515
550
  const compCssPath = _path.default.join(buildPath, `${compPath}.css.json`);
@@ -599,13 +634,16 @@ class ViteCompiler {
599
634
  });
600
635
  let templateNode = null;
601
636
  const importMap = {};
637
+ const componentsMap = {};
602
638
  for (const node of doc.childNodes) {
603
639
  if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
604
640
  const nameAttr = node.attrs?.find(a => a.name === 'name');
605
641
  const srcAttr = node.attrs?.find(a => a.name === 'src');
606
642
  if (nameAttr && srcAttr) {
607
643
  const compPath = _path.default.resolve(_path.default.dirname(uxFile), srcAttr.value).replace(/\.ux$/, '');
608
- importMap[nameAttr.value.toLowerCase()] = _path.default.relative(srcPath, compPath).replace(/\\/g, '/');
644
+ const rel = _path.default.relative(srcPath, compPath).replace(/\\/g, '/');
645
+ importMap[nameAttr.value.toLowerCase()] = rel;
646
+ componentsMap[nameAttr.value] = rel;
609
647
  }
610
648
  }
611
649
  }
@@ -635,7 +673,7 @@ class ViteCompiler {
635
673
  // Generate template.json
636
674
  if (templateNode) {
637
675
  _fsExtra.default.ensureDirSync(_path.default.dirname(outputTpl));
638
- _fsExtra.default.writeJSONSync(outputTpl, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, mergeStyleSheets(appStyleSheet, styleSheet), Object.keys(importMap).length ? importMap : undefined, _path.default.dirname(relPath)), param.mode === 'production' ? undefined : {
676
+ _fsExtra.default.writeJSONSync(outputTpl, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, mergeStyleSheets(appStyleSheet, styleSheet), Object.keys(importMap).length ? importMap : undefined, _path.default.dirname(relPath), Object.keys(componentsMap).length ? componentsMap : undefined), param.mode === 'production' ? undefined : {
639
677
  spaces: 2
640
678
  });
641
679
  }
@@ -713,6 +751,29 @@ function wrapOutput(code, entryName, isApp) {
713
751
  });
714
752
  // Remove Object.defineProperty for Symbol.toStringTag
715
753
  code = code.replace(/\s*Object\.defineProperty\(\w+,\s*Symbol\.toStringTag[^;]*;\s*/g, '');
754
+ // Rewrite __require("@system.*") → $app_require$("@app-module/system.*") in rolldown output.
755
+ // Rolldown emits __require when CJS require() survives bundling (aliased require, dynamic
756
+ // concat, or patterns the pre-transform couldn't catch). Also catch _require() which appears
757
+ // when the original code does `var _require = require; _require('@system.xxx')`.
758
+ const sysRequirePattern = /\b_?_?require\(\s*"(@(?:system|service|android|hap)\.[^"]+)"\s*\)/g;
759
+ code = code.replace(sysRequirePattern, (_, mod) => {
760
+ const moduleName = mod.replace(/^@(system|service|android|hap)\./, '$1.');
761
+ return `$app_require$("@app-module/${moduleName}")`;
762
+ });
763
+ // Same for @app-module/ prefix
764
+ code = code.replace(/\b_?_?require\(\s*"(@app-module\/[^"]+)"\s*\)/g, (_, mod) => {
765
+ const moduleName = mod.slice('@app-module/'.length);
766
+ return `$app_require$("@app-module/${moduleName}")`;
767
+ });
768
+ // Also handle single-quoted variants
769
+ code = code.replace(/\b_?_?require\(\s*'(@(?:system|service|android|hap)\.[^']+)'\s*\)/g, (_, mod) => {
770
+ const moduleName = mod.replace(/^@(system|service|android|hap)\./, '$1.');
771
+ return `$app_require$("@app-module/${moduleName}")`;
772
+ });
773
+ // Remove the __require polyfill definition if it's no longer referenced anywhere
774
+ if (!/\b__require\b/.test(code)) {
775
+ code = code.replace(/var __require\s*=\s*\/\*[^*]*\*\/\s*\(\(x\)\s*=>[\s\S]*?}\);\n?/g, '');
776
+ }
716
777
  // Extract the default export variable
717
778
  let exportVar = '_default';
718
779
  const m1 = code.match(/export\s*\{\s*(\w+)\s+as\s+default\s*\}/);
@@ -6,5 +6,8 @@ declare class Jsc {
6
6
  private logBeforeInvoke;
7
7
  private logAfterInvoke;
8
8
  private static listFiles;
9
+ private assertJscVersion;
10
+ static wrapAllJsWithIife(buildPath: string): void;
11
+ private static compareSemver;
9
12
  }
10
13
  export default Jsc;
@@ -9,6 +9,9 @@ var path = _interopRequireWildcard(require("path"));
9
9
  var _sharedUtils = require("@aiot-toolkit/shared-utils");
10
10
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
11
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
12
+ const REQUIRED_JSC_VERSION = '1.0.9';
13
+ const IIFE_WRAP_PREFIX = 'export default (function (__ctx) {\n' + ' let { requireModule, unRequireModule, $app_define$, $app_bootstrap$, $app_require$,\n' + ' console = global.console } = __ctx;\n' + ' let { setTimeout, clearTimeout, setInterval, clearInterval } = __ctx;\n\n';
14
+ const IIFE_WRAP_SUFFIX = '\n});\n';
12
15
  class Jsc {
13
16
  constructor(projectPath, buildPath) {
14
17
  this.projectPath = projectPath;
@@ -23,8 +26,10 @@ class Jsc {
23
26
  const beforeJsCount = Jsc.listFiles(buildPath, '.js').length;
24
27
  return _sharedUtils.CommonUtil.requireNodeModule(projectPath, `@aiot-toolkit/jsc`).then(async module => {
25
28
  this.logBeforeInvoke();
29
+ this.assertJscVersion();
30
+ Jsc.wrapAllJsWithIife(buildPath);
26
31
  const start = Date.now();
27
- const msg = await module.default(buildPath);
32
+ const msg = await module.default(buildPath, []);
28
33
  const elapsed = Date.now() - start;
29
34
  if (msg) {
30
35
  _sharedUtils.ColorConsole.success({
@@ -119,5 +124,42 @@ class Jsc {
119
124
  walk(dir);
120
125
  return out;
121
126
  }
127
+ assertJscVersion() {
128
+ const {
129
+ projectPath
130
+ } = this;
131
+ const jscName = '@aiot-toolkit/jsc';
132
+ try {
133
+ const pkgJsonPath = require.resolve(`${jscName}/package.json`, {
134
+ paths: [projectPath]
135
+ });
136
+ const pkg = require(pkgJsonPath);
137
+ const version = pkg.version || '0.0.0';
138
+ if (Jsc.compareSemver(version, REQUIRED_JSC_VERSION) < 0) {
139
+ _sharedUtils.ColorConsole.throw(`[jsc] ${jscName}@${version} is too old — need >= ${REQUIRED_JSC_VERSION}. ` + `Run: npm i ${jscName}@^${REQUIRED_JSC_VERSION}`);
140
+ throw new Error(`[jsc] ${jscName} must be >= ${REQUIRED_JSC_VERSION}, got ${version}`);
141
+ }
142
+ } catch (e) {
143
+ if (e?.message?.includes(`must be >= ${REQUIRED_JSC_VERSION}`)) throw e;
144
+ }
145
+ }
146
+ static wrapAllJsWithIife(buildPath) {
147
+ for (const {
148
+ rel
149
+ } of Jsc.listFiles(buildPath, '.js')) {
150
+ const abs = path.join(buildPath, rel);
151
+ const body = fs.readFileSync(abs, 'utf-8');
152
+ if (body.startsWith('export default (function (__ctx)')) continue;
153
+ fs.writeFileSync(abs, IIFE_WRAP_PREFIX + body + IIFE_WRAP_SUFFIX, 'utf-8');
154
+ }
155
+ }
156
+ static compareSemver(a, b) {
157
+ const parse = v => v.replace(/^[\^~=v]/, '').split(/[.-]/).slice(0, 3).map(p => parseInt(p, 10) || 0);
158
+ const [a1, a2, a3] = parse(a);
159
+ const [b1, b2, b3] = parse(b);
160
+ if (a1 !== b1) return a1 - b1;
161
+ if (a2 !== b2) return a2 - b2;
162
+ return a3 - b3;
163
+ }
122
164
  }
123
165
  var _default = exports.default = Jsc;
@@ -153,8 +153,17 @@ class ZipUtil {
153
153
  // basename from manifest.icon (e.g. `/resources/base/media/icon_small.png`
154
154
  // → `icon_small.vug` at rpk root) so runtime + IDE previews can look it up
155
155
  // by the manifest-declared name.
156
- if (config.icon) {
157
- const iconPath = _path.default.join(buildDir, config.icon.replace(/^\//, ''));
156
+ const runtimeIconPath = (() => {
157
+ const buildManifest = _path.default.join(buildDir, 'manifest.json');
158
+ if (_fsExtra.default.existsSync(buildManifest)) {
159
+ try {
160
+ return _fsExtra.default.readJSONSync(buildManifest).icon;
161
+ } catch {/* fall through */}
162
+ }
163
+ return config.icon;
164
+ })();
165
+ if (runtimeIconPath) {
166
+ const iconPath = _path.default.join(buildDir, runtimeIconPath.replace(/^\//, ''));
158
167
  if (_fsExtra.default.existsSync(iconPath)) {
159
168
  const iconBuf = _fsExtra.default.readFileSync(iconPath);
160
169
  outerPackage.addResource({
@@ -86,6 +86,9 @@ class UxConfig {
86
86
  }, {
87
87
  worker: _UxAfterCompile.default.copyResource,
88
88
  workerDescribe: 'Copy resource files'
89
+ }, {
90
+ worker: _UxAfterCompile.default.relocateManifestIcon,
91
+ workerDescribe: 'Move manifest.icon to build root + rewrite refs'
89
92
  }, {
90
93
  worker: _UxAfterCompile.default.compressResource,
91
94
  workerDescribe: 'Compress resource files'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/aiotpack",
3
- "version": "2.1.0-prender.12",
3
+ "version": "2.1.0-prender.13",
4
4
  "description": "The process tool for packaging aiot projects.",
5
5
  "keywords": [
6
6
  "aiotpack"
@@ -19,16 +19,16 @@
19
19
  "test": "node ./__tests__/aiotpack.test.js"
20
20
  },
21
21
  "dependencies": {
22
- "@aiot-toolkit/generator": "2.1.0-prender.12",
23
- "@aiot-toolkit/parser": "2.1.0-prender.12",
24
- "@aiot-toolkit/shared-utils": "2.1.0-prender.12",
22
+ "@aiot-toolkit/generator": "2.1.0-prender.13",
23
+ "@aiot-toolkit/parser": "2.1.0-prender.13",
24
+ "@aiot-toolkit/shared-utils": "2.1.0-prender.13",
25
25
  "@hap-toolkit/aaptjs": "^2.0.0",
26
26
  "@rspack/core": "^1.3.9",
27
27
  "acorn": "^8.16.0",
28
28
  "aiot-parse5": "^1.0.2",
29
29
  "astring": "^1.9.0",
30
30
  "babel-loader": "^9.1.3",
31
- "file-lane": "2.1.0-prender.12",
31
+ "file-lane": "2.1.0-prender.13",
32
32
  "file-loader": "^6.2.0",
33
33
  "fs-extra": "^11.2.0",
34
34
  "jsrsasign": "^11.1.0",