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

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,19 @@ 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
+ assertNoRelativeAssetPaths(result, pageDir);
240
+ assertNoDelimitersInEvents(result, pageDir);
241
+ const componentsForRoot = componentsMap && Object.keys(componentsMap).length ? componentsMap : importMap;
242
+ if (componentsForRoot && Object.keys(componentsForRoot).length) {
243
+ result.components = {
244
+ ...componentsForRoot
245
+ };
246
+ }
239
247
  // Insert styleObjectId before children (vivo format)
240
248
  if (styleObjectId !== undefined) {
241
249
  const ordered = {};
@@ -253,6 +261,185 @@ function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pa
253
261
  /** Add this. prefix to variable references in an expression */
254
262
  // blueos-pack's pathTestRE: matches simple paths like a.b.c, a['key'], a[0], a[$idx]
255
263
  const pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[\w$]+|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/;
264
+
265
+ // Attributes whose value is a resource path and therefore must be rewritten from
266
+ // `./x` / `../x` (relative to the owning .ux file) to an rpk-root absolute path.
267
+ // Runtime resolves <image src> against the rpk root, so a relative path emitted
268
+ // from a nested component directory never resolves and falls back to a placeholder.
269
+ const PATH_ATTRS = new Set(['src', 'href', 'alt']);
270
+ const ARROW_RE = /=>/;
271
+
272
+ /**
273
+ * Canonical event key for an `@x` / `onx` attribute.
274
+ *
275
+ * Every event name the platform defines is a lowercase single word
276
+ * (`click`, `longpress`, `touchstart`, `animationiteration`, ... — 72 of them
277
+ * across vela and android, none camelCase or hyphenated), and the parser's own
278
+ * `translateEventName` just drops the prefix. Camel-casing the remainder turned
279
+ * `on-long-press` into `LongPress`, which matches no event and silently never
280
+ * fires, so separators are removed and the name lowercased instead.
281
+ */
282
+ function normalizeEventName(name) {
283
+ const stripped = name.startsWith('@') ? name.slice(1) : name.replace(/^on/, '');
284
+ return stripped.replace(/[-_]/g, '').toLowerCase();
285
+ }
286
+
287
+ /**
288
+ * Strip one wrapping `{{ ... }}` from an attribute value.
289
+ *
290
+ * Only the outer pair is removed, and only when it actually wraps the whole
291
+ * value — `{{()=>{ x() }}}` must yield `()=>{ x() }`, so a global
292
+ * `replace(/\{\{|\}\}/g, '')` is wrong: it would also eat the arrow body's
293
+ * braces. A value that merely contains an interpolation (`a {{b}} c`) is left
294
+ * alone; callers that need that do their own splitting.
295
+ */
296
+ function stripTemplateDelimiters(value) {
297
+ let v = (value ?? '').trim();
298
+ if (!v.startsWith('{{') || !v.endsWith('}}')) return v;
299
+ const inner = v.slice(2, -2);
300
+ // Reject `{{a}} + {{b}}`, where the opening pair closes before the end.
301
+ let depth = 0;
302
+ for (let i = 0; i < inner.length; i++) {
303
+ if (inner[i] === '{') depth++;else if (inner[i] === '}') {
304
+ depth--;
305
+ if (depth < 0) return v;
306
+ }
307
+ }
308
+ return depth === 0 ? inner.trim() : v;
309
+ }
310
+ function isRelAssetPath(v) {
311
+ return v.startsWith('./') || v.startsWith('../');
312
+ }
313
+ function resolveRelFromPageDir(rel, pageDir) {
314
+ // A trailing slash is significant when the path is a prefix fragment of a
315
+ // concatenated expression ('./assets/full/' + lang + '.png') — dropping it
316
+ // would yield '/.../fullcn.png'.
317
+ const trailing = rel.endsWith('/') ? '/' : '';
318
+ const segments = pageDir.split('/').filter(Boolean).concat(rel.split('/'));
319
+ const stack = [];
320
+ for (const seg of segments) {
321
+ if (seg === '..') stack.pop();else if (seg && seg !== '.') stack.push(seg);
322
+ }
323
+ return '/' + stack.join('/') + trailing;
324
+ }
325
+
326
+ /**
327
+ * Rewrite relative resource-path string literals inside a generated expression.
328
+ * Dynamic `src="{{'./assets/' + lang + '.png'}}"` compiles to a `$src` function
329
+ * body, so the path lives in a literal rather than a plain attribute value — the
330
+ * static-attribute rewrite never sees it. Only literals starting with ./ or ../
331
+ * are touched, so suffix fragments like '.png' pass through untouched.
332
+ */
333
+ function rewriteRelPathLiterals(exprSrc, pageDir) {
334
+ let out = '';
335
+ let i = 0;
336
+ while (i < exprSrc.length) {
337
+ const ch = exprSrc[i];
338
+ if (ch !== "'" && ch !== '"') {
339
+ out += ch;
340
+ i++;
341
+ continue;
342
+ }
343
+ const quote = ch;
344
+ let j = i + 1;
345
+ let raw = '';
346
+ let closed = false;
347
+ while (j < exprSrc.length) {
348
+ const c = exprSrc[j];
349
+ if (c === '\\') {
350
+ raw += c + (exprSrc[j + 1] ?? '');
351
+ j += 2;
352
+ continue;
353
+ }
354
+ if (c === quote) {
355
+ closed = true;
356
+ break;
357
+ }
358
+ raw += c;
359
+ j++;
360
+ }
361
+ if (!closed) {
362
+ out += exprSrc.slice(i);
363
+ break;
364
+ }
365
+ const unescaped = raw.replace(/\\(['"\\])/g, '$1');
366
+ if (isRelAssetPath(unescaped)) {
367
+ const abs = resolveRelFromPageDir(unescaped, pageDir);
368
+ out += quote + abs.replace(/\\/g, '\\\\').replace(new RegExp(quote, 'g'), '\\' + quote) + quote;
369
+ } else {
370
+ out += quote + raw + quote;
371
+ }
372
+ i = j + 1;
373
+ }
374
+ return out;
375
+ }
376
+ const REL_LITERAL_IN_EXPR_RE = /(['"])\.\.?\//;
377
+
378
+ /**
379
+ * Fail the build when a template still carries a relative resource path, in a
380
+ * static attr or inside a `$`-bound expression's literals. Runtime resolves
381
+ * these against the rpk root, silently falling back to a placeholder image —
382
+ * far harder to diagnose on-device than a pack-time error.
383
+ */
384
+ function assertNoRelativeAssetPaths(root, pageDir) {
385
+ const offenders = [];
386
+ const walk = node => {
387
+ if (!node || typeof node !== 'object') return;
388
+ const attr = node.attr;
389
+ if (attr && typeof attr === 'object') {
390
+ for (const [key, val] of Object.entries(attr)) {
391
+ if (typeof val !== 'string') continue;
392
+ const bare = key.startsWith('$') ? key.slice(1) : key;
393
+ if (!PATH_ATTRS.has(bare)) continue;
394
+ const bad = key.startsWith('$') ? REL_LITERAL_IN_EXPR_RE.test(val) : isRelAssetPath(val);
395
+ if (bad) offenders.push(`<${node.type ?? '?'} ${key}="${val}">`);
396
+ }
397
+ }
398
+ if (Array.isArray(node.children)) node.children.forEach(walk);
399
+ };
400
+ walk(root);
401
+ if (offenders.length) {
402
+ throw new Error(`[template] ${offenders.length} relative resource path(s) survived rewriting` + `${pageDir ? ` in ${pageDir}` : ' (no pageDir supplied)'}. Runtime resolves src/href ` + `against the rpk root, so these render a placeholder instead of the asset:\n` + offenders.map(o => ` ${o}`).join('\n'));
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Fail the build when an event value still carries template delimiters. Runtime
408
+ * cannot recover: the `$`-prefixed form fails to compile (logged, event skipped)
409
+ * and the bare form is looked up as a method literally named `{{fn}}` (silent).
410
+ * Either way the handler is dead, so catching it at pack time is the only way
411
+ * the breakage is visible before the device.
412
+ */
413
+ function assertNoDelimitersInEvents(root, pageDir) {
414
+ const offenders = [];
415
+ const walk = node => {
416
+ if (!node || typeof node !== 'object') return;
417
+ const events = node.events;
418
+ if (events && typeof events === 'object') {
419
+ for (const [key, val] of Object.entries(events)) {
420
+ if (typeof val !== 'string') continue;
421
+ if (val.includes('{{') || val.includes('}}')) {
422
+ offenders.push(`<${node.type ?? '?'} ${key}="${val}">`);
423
+ }
424
+ }
425
+ }
426
+ if (Array.isArray(node.children)) node.children.forEach(walk);
427
+ };
428
+ walk(root);
429
+ if (offenders.length) {
430
+ throw new Error(`[template] ${offenders.length} event handler(s) still contain template delimiters` + `${pageDir ? ` in ${pageDir}` : ''}. Runtime cannot compile or resolve these, so the ` + `events are silently dead:\n` + offenders.map(o => ` ${o}`).join('\n'));
431
+ }
432
+ }
433
+ function tryEvalStaticShowLiteral(expr) {
434
+ if (/^'[^']*'$/.test(expr) || /^"[^"]*"$/.test(expr)) {
435
+ const inner = expr.slice(1, -1);
436
+ return inner.length > 0;
437
+ }
438
+ if (expr === 'undefined' || expr === 'null' || expr === 'NaN') return false;
439
+ if (expr === 'Infinity') return true;
440
+ return undefined;
441
+ }
442
+
256
443
  /**
257
444
  * Normalize a media query condition text from CSS Level 4 syntax to Level 3.
258
445
  *
@@ -572,11 +759,18 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
572
759
  if (name === 'class') {
573
760
  className = value.replace(/\s+/g, ' ').trim();
574
761
  } else if (name.startsWith('@') || name.startsWith('on') && name.length > 2) {
575
- const rawEvtName = name.startsWith('@') ? name.slice(1) : name.replace(/^on/, '');
576
- const evtName = rawEvtName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
577
- // Events with parameters use $event format with function wrapper
578
- const evtVal = value.trim();
579
- if (evtVal.includes('(')) {
762
+ const evtName = normalizeEventName(name);
763
+ // Event values may be written bare (@click="fn") or wrapped in template
764
+ // delimiters (@click="{{fn}}"); both mean the same thing, so strip the
765
+ // delimiters before classifying. Leaving them in emits `{{fn}}`, which
766
+ // runtime either fails to compile ($-form) or looks up as a method name
767
+ // literally called "{{fn}}" (bare form) — a silent dead event either way.
768
+ const evtVal = stripTemplateDelimiters(value);
769
+ // An arrow function is already a handler; wrapping it in `function (evt)`
770
+ // and appending evt to its call would both mis-bind and drop the event arg.
771
+ if (ARROW_RE.test(evtVal)) {
772
+ events[`$${evtName}`] = `function (evt) { return (${addThisPrefix(evtVal)})(evt); }`;
773
+ } else if (evtVal.includes('(')) {
580
774
  // Add evt as last parameter
581
775
  const withEvt = evtVal.replace(/\)$/, evtVal.includes('()') ? 'evt)' : ', evt)');
582
776
  events[`$${evtName}`] = `function (evt) { return ${addThisPrefix(withEvt)}; }`;
@@ -612,13 +806,20 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
612
806
  } else if (name === 'show') {
613
807
  const showVal = value.replace(/\{\{|\}\}/g, '').trim();
614
808
  if (showVal === 'true') attrObj['show'] = true;else if (showVal === 'false') attrObj['show'] = false;else {
615
- // Try to evaluate as literal
616
809
  try {
617
810
  const v = JSON.parse(showVal);
618
811
  attrObj["show"] = v;
619
812
  } catch {
620
- attrObj['$show'] = showVal;
621
- hasBind = true;
813
+ const staticVal = tryEvalStaticShowLiteral(showVal);
814
+ if (staticVal !== undefined) {
815
+ attrObj['show'] = staticVal;
816
+ } else if (pathTestRE.test(showVal)) {
817
+ attrObj['$show'] = showVal;
818
+ hasBind = true;
819
+ } else {
820
+ attrObj['$show'] = `function () { return ${addThisPrefix(showVal)}; }`;
821
+ hasBind = true;
822
+ }
622
823
  }
623
824
  }
624
825
  } else if (name === 'for') {
@@ -727,11 +928,16 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
727
928
  } else if (/\{\{.*\}\}/.test(value)) {
728
929
  // Dynamic binding - build expression from mixed static/dynamic parts
729
930
  const parts = value.split(/(\{\{[\s\S]*?\}\})/);
730
- const exprs = parts.filter(Boolean).map(p => {
931
+ let exprs = parts.filter(Boolean).map(p => {
731
932
  const m = p.match(/^\{\{([\s\S]*?)\}\}$/);
732
933
  if (m) return addThisPrefix(m[1].trim());
733
934
  return `'${p.replace(/'/g, "\\'")}'`;
734
935
  });
936
+ // Resource-path attrs carry their path inside the expression's string
937
+ // literals; rewrite those too so dynamic src matches static src form.
938
+ if (PATH_ATTRS.has(name) && pageDir) {
939
+ exprs = exprs.map(e => rewriteRelPathLiterals(e, pageDir));
940
+ }
735
941
  const camelName = '$' + name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
736
942
  const plainName = name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
737
943
  // Handle literal values (null, true, false, numbers)
@@ -770,15 +976,8 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
770
976
  // Normalize relative path attrs (src, href, alt) to absolute paths from src root.
771
977
  // alt can also carry prose (e.g. "blank") — only rewrite when the value starts with
772
978
  // ./ or ../ so image alt-text prose passes through untouched.
773
- const isRelPath = staticVal.startsWith('./') || staticVal.startsWith('../');
774
- if (staticVal && isRelPath && (name === 'src' || name === 'href' || name === 'alt') && pageDir) {
775
- // Resolve relative to pageDir, then make absolute from src root
776
- const segments = pageDir.split('/').filter(Boolean).concat(staticVal.split('/'));
777
- const stack = [];
778
- for (const seg of segments) {
779
- if (seg === '..') stack.pop();else if (seg && seg !== '.') stack.push(seg);
780
- }
781
- staticVal = '/' + stack.join('/');
979
+ if (staticVal && isRelAssetPath(staticVal) && PATH_ATTRS.has(name) && pageDir) {
980
+ staticVal = resolveRelFromPageDir(staticVal, pageDir);
782
981
  }
783
982
  attrObj[name.replace(/-([a-z])/g, (_, c) => c.toUpperCase())] = staticVal;
784
983
  if (name === 'id') hasBind = true;
@@ -11,9 +11,22 @@ declare class ViteCompiler implements ICompiler {
11
11
  clean(param: ICompileParam & IJavascriptCompileOption): Promise<void>;
12
12
  }
13
13
  declare function stripDeadDefProp(code: string): string;
14
+ /**
15
+ * Build a sub-component's standalone `.js`.
16
+ *
17
+ * A component is registered as its own `$app_define$` module and loaded
18
+ * independently at runtime — the host page bundle does not carry its code. So
19
+ * everything the component's `<script>` declares at module level has to survive:
20
+ * feature imports (`import vibrator from "@system.vibrator"`), consts, helpers.
21
+ * Keeping only the `export default` object literal strips the feature binding and
22
+ * leaves `vibrator` as a free identifier, which is why the 咪咕/百度地图 keyboard
23
+ * could no longer vibrate.
24
+ */
25
+ declare function buildComponentJs(compCode: string, compName: string, compSid: number, relPath: string): string;
14
26
  declare function mergeStyleSheets(app: any, page: any): any;
15
27
  export declare const __test: {
16
28
  stripDeadDefProp: typeof stripDeadDefProp;
17
29
  mergeStyleSheets: typeof mergeStyleSheets;
30
+ buildComponentJs: typeof buildComponentJs;
18
31
  };
19
32
  export default ViteCompiler;
@@ -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`);
@@ -519,11 +554,7 @@ class ViteCompiler {
519
554
  spaces: 2
520
555
  });
521
556
  const compJsPath = _path.default.join(buildPath, `${compPath}.js`);
522
- const exportMatch = compCode.match(/export\s+default\s+([\s\S]*?);?\s*$/);
523
- const compObj = exportMatch ? exportMatch[1].trim() : '{}';
524
- const compVarName = compName.replace(/-/g, '_') + '_default';
525
- const compJsContent = `let $style$${compSid} = {"@info":{"styleObjectId":${compSid}}};\nconst $app_style$${compSid} = $style$${compSid};\nvar ${compVarName} = ${compObj};\n$app_define$("@app-component/${compName}", [], function($app_require$, $app_exports$, $app_module$) {\n $app_module$.exports = ${compVarName}.default || ${compVarName};\n $app_module$.exports.style = $app_style$${compSid};\n});\n`;
526
- _fsExtra.default.writeFileSync(compJsPath, compJsContent);
557
+ _fsExtra.default.writeFileSync(compJsPath, buildComponentJs(compCode, compName, compSid, compPath));
527
558
  }
528
559
  }
529
560
  }
@@ -599,13 +630,16 @@ class ViteCompiler {
599
630
  });
600
631
  let templateNode = null;
601
632
  const importMap = {};
633
+ const componentsMap = {};
602
634
  for (const node of doc.childNodes) {
603
635
  if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
604
636
  const nameAttr = node.attrs?.find(a => a.name === 'name');
605
637
  const srcAttr = node.attrs?.find(a => a.name === 'src');
606
638
  if (nameAttr && srcAttr) {
607
639
  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, '/');
640
+ const rel = _path.default.relative(srcPath, compPath).replace(/\\/g, '/');
641
+ importMap[nameAttr.value.toLowerCase()] = rel;
642
+ componentsMap[nameAttr.value] = rel;
609
643
  }
610
644
  }
611
645
  }
@@ -635,7 +669,7 @@ class ViteCompiler {
635
669
  // Generate template.json
636
670
  if (templateNode) {
637
671
  _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 : {
672
+ _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
673
  spaces: 2
640
674
  });
641
675
  }
@@ -647,13 +681,15 @@ class ViteCompiler {
647
681
  spaces: 2
648
682
  });
649
683
  // Generate js
650
- const exportMatch = compCode.match(/export\s+default\s+([\s\S]*?);?\s*$/);
651
- const compObj = exportMatch ? exportMatch[1].trim() : '{}';
652
684
  const compName = _path.default.basename(relPath).toLowerCase();
653
- const varName = compName.replace(/-/g, '_') + '_default';
654
685
  _fsExtra.default.ensureDirSync(_path.default.dirname(outputJs));
655
- _fsExtra.default.writeFileSync(outputJs, `let $style$${sid} = {"@info":{"styleObjectId":${sid}}};\nconst $app_style$${sid} = $style$${sid};\nvar ${varName} = ${compObj};\n$app_define$("@app-component/${compName}", [], function($app_require$, $app_exports$, $app_module$) {\n $app_module$.exports = ${varName}.default || ${varName};\n $app_module$.exports.style = $app_style$${sid};\n});\n`);
656
- } catch {}
686
+ _fsExtra.default.writeFileSync(outputJs, buildComponentJs(compCode, compName, sid, relPath));
687
+ } catch (e) {
688
+ // A component that fails to emit renders but has no behaviour, so don't
689
+ // swallow the guard errors that report exactly why.
690
+ if (e?.message?.startsWith('[component]')) throw e;
691
+ console.warn(`vite: failed to emit component ${relPath}:`, e?.message ?? e);
692
+ }
657
693
  }
658
694
  }
659
695
  async clean(param) {
@@ -669,6 +705,51 @@ function stripDeadDefProp(code) {
669
705
  const withoutDefine = code.replace(/var __defProp = Object\.defineProperty;\n?/g, '');
670
706
  return /\b__defProp\s*\(/.test(withoutDefine) ? code : withoutDefine;
671
707
  }
708
+
709
+ /**
710
+ * Build a sub-component's standalone `.js`.
711
+ *
712
+ * A component is registered as its own `$app_define$` module and loaded
713
+ * independently at runtime — the host page bundle does not carry its code. So
714
+ * everything the component's `<script>` declares at module level has to survive:
715
+ * feature imports (`import vibrator from "@system.vibrator"`), consts, helpers.
716
+ * Keeping only the `export default` object literal strips the feature binding and
717
+ * leaves `vibrator` as a free identifier, which is why the 咪咕/百度地图 keyboard
718
+ * could no longer vibrate.
719
+ */
720
+ function buildComponentJs(compCode, compName, compSid, relPath) {
721
+ let code = compCode;
722
+ // The raw `var $app_style$ = [...]` array is superseded by the $app_style$<sid>
723
+ // @info reference emitted below; css.json already carries the real style data.
724
+ const styleLit = extractAppStyleLiteral(code);
725
+ if (styleLit) {
726
+ const decl = code.match(/var\s+\$app_style\$\s*=\s*/);
727
+ if (decl) {
728
+ const start = decl.index;
729
+ let end = code.indexOf(styleLit, start) + styleLit.length;
730
+ if (code[end] === ';') end++;
731
+ code = code.slice(0, start) + code.slice(end);
732
+ }
733
+ }
734
+ // Turn @system.*/@app-module imports into $app_require$ calls, same as entries.
735
+ code = rewriteSystemImports(code);
736
+ let defaultExpr = '{}';
737
+ const edIdx = code.search(/export\s+default\s+/);
738
+ if (edIdx !== -1) {
739
+ const kw = code.slice(edIdx).match(/^export\s+default\s+/);
740
+ defaultExpr = code.slice(edIdx + kw[0].length).trim().replace(/;\s*$/, '') || '{}';
741
+ code = code.slice(0, edIdx);
742
+ }
743
+ // Named exports have no consumer in a $app_define$ module; keep the declaration.
744
+ code = code.replace(/\bexport\s+(?=(?:const|let|var|function|class|async)\b)/g, '');
745
+ const leftoverImport = code.match(/^\s*import\s[^\n]*/m);
746
+ if (leftoverImport) {
747
+ throw new Error(`[component] ${relPath} has an unresolved ESM import that cannot be emitted into a ` + `standalone $app_define$ module: ${leftoverImport[0].trim()}\n` + `Only @system.*/@service.*/@android.*/@hap.*/@app-module imports are rewritten to ` + `$app_require$. Inline the dependency into the component or move it behind a feature module.`);
748
+ }
749
+ const varName = compName.replace(/-/g, '_') + '_default';
750
+ const moduleCode = code.trim();
751
+ return [`let $style$${compSid} = {"@info":{"styleObjectId":${compSid}}};`, `const $app_style$${compSid} = $style$${compSid};`, ...(moduleCode ? [moduleCode] : []), `var ${varName} = ${defaultExpr};`, `$app_define$("@app-component/${compName}", [], function($app_require$, $app_exports$, $app_module$) {`, ` $app_module$.exports = ${varName}.default || ${varName};`, ` $app_module$.exports.style = $app_style$${compSid};`, `});`, ''].join('\n');
752
+ }
672
753
  function wrapOutput(code, entryName, isApp) {
673
754
  const componentName = _path.default.parse(entryName).name;
674
755
  const defineId = isApp ? '@app-component/app' : `@app-component/${componentName}`;
@@ -713,6 +794,29 @@ function wrapOutput(code, entryName, isApp) {
713
794
  });
714
795
  // Remove Object.defineProperty for Symbol.toStringTag
715
796
  code = code.replace(/\s*Object\.defineProperty\(\w+,\s*Symbol\.toStringTag[^;]*;\s*/g, '');
797
+ // Rewrite __require("@system.*") → $app_require$("@app-module/system.*") in rolldown output.
798
+ // Rolldown emits __require when CJS require() survives bundling (aliased require, dynamic
799
+ // concat, or patterns the pre-transform couldn't catch). Also catch _require() which appears
800
+ // when the original code does `var _require = require; _require('@system.xxx')`.
801
+ const sysRequirePattern = /\b_?_?require\(\s*"(@(?:system|service|android|hap)\.[^"]+)"\s*\)/g;
802
+ code = code.replace(sysRequirePattern, (_, mod) => {
803
+ const moduleName = mod.replace(/^@(system|service|android|hap)\./, '$1.');
804
+ return `$app_require$("@app-module/${moduleName}")`;
805
+ });
806
+ // Same for @app-module/ prefix
807
+ code = code.replace(/\b_?_?require\(\s*"(@app-module\/[^"]+)"\s*\)/g, (_, mod) => {
808
+ const moduleName = mod.slice('@app-module/'.length);
809
+ return `$app_require$("@app-module/${moduleName}")`;
810
+ });
811
+ // Also handle single-quoted variants
812
+ code = code.replace(/\b_?_?require\(\s*'(@(?:system|service|android|hap)\.[^']+)'\s*\)/g, (_, mod) => {
813
+ const moduleName = mod.replace(/^@(system|service|android|hap)\./, '$1.');
814
+ return `$app_require$("@app-module/${moduleName}")`;
815
+ });
816
+ // Remove the __require polyfill definition if it's no longer referenced anywhere
817
+ if (!/\b__require\b/.test(code)) {
818
+ code = code.replace(/var __require\s*=\s*\/\*[^*]*\*\/\s*\(\(x\)\s*=>[\s\S]*?}\);\n?/g, '');
819
+ }
716
820
  // Extract the default export variable
717
821
  let exportVar = '_default';
718
822
  const m1 = code.match(/export\s*\{\s*(\w+)\s+as\s+default\s*\}/);
@@ -770,6 +874,7 @@ function mergeStyleSheets(app, page) {
770
874
  }
771
875
  const __test = exports.__test = {
772
876
  stripDeadDefProp,
773
- mergeStyleSheets
877
+ mergeStyleSheets,
878
+ buildComponentJs
774
879
  };
775
880
  var _default = exports.default = ViteCompiler;
@@ -6,5 +6,9 @@ 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 assertLegacyGlobalBinding;
12
+ private static compareSemver;
9
13
  }
10
14
  export default Jsc;
@@ -9,6 +9,17 @@ 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
+
14
+ // `__ctx` is the page scope whose prototype is `ferryGlobal` (where the runtime
15
+ // registers `runGC` and friends). A bare `global` in legacy page source resolves
16
+ // to QuickJS's real global object, which does NOT carry those APIs — hence
17
+ // `global.runGC()` throws `TypeError: not a function`. Bind `global`/`window`/`self`
18
+ // to `__ctx` so `global.xxx` walks `__ctx → ferryGlobal`. `globalThis` is left
19
+ // untouched (still the real global), so `console` must default from `globalThis`,
20
+ // not `global` — after the rebind `global.console` would look up ferryGlobal.
21
+ const IIFE_WRAP_PREFIX = 'export default (function (__ctx) {\n' + ' const global = __ctx, window = __ctx, self = __ctx;\n' + ' let { requireModule, unRequireModule, $app_define$, $app_bootstrap$, $app_require$,\n' + ' console = globalThis.console } = __ctx;\n' + ' let { setTimeout, clearTimeout, setInterval, clearInterval } = __ctx;\n\n';
22
+ const IIFE_WRAP_SUFFIX = '\n});\n';
12
23
  class Jsc {
13
24
  constructor(projectPath, buildPath) {
14
25
  this.projectPath = projectPath;
@@ -23,8 +34,10 @@ class Jsc {
23
34
  const beforeJsCount = Jsc.listFiles(buildPath, '.js').length;
24
35
  return _sharedUtils.CommonUtil.requireNodeModule(projectPath, `@aiot-toolkit/jsc`).then(async module => {
25
36
  this.logBeforeInvoke();
37
+ this.assertJscVersion();
38
+ Jsc.wrapAllJsWithIife(buildPath);
26
39
  const start = Date.now();
27
- const msg = await module.default(buildPath);
40
+ const msg = await module.default(buildPath, []);
28
41
  const elapsed = Date.now() - start;
29
42
  if (msg) {
30
43
  _sharedUtils.ColorConsole.success({
@@ -119,5 +132,60 @@ class Jsc {
119
132
  walk(dir);
120
133
  return out;
121
134
  }
135
+ assertJscVersion() {
136
+ const {
137
+ projectPath
138
+ } = this;
139
+ const jscName = '@aiot-toolkit/jsc';
140
+ try {
141
+ const pkgJsonPath = require.resolve(`${jscName}/package.json`, {
142
+ paths: [projectPath]
143
+ });
144
+ const pkg = require(pkgJsonPath);
145
+ const version = pkg.version || '0.0.0';
146
+ if (Jsc.compareSemver(version, REQUIRED_JSC_VERSION) < 0) {
147
+ _sharedUtils.ColorConsole.throw(`[jsc] ${jscName}@${version} is too old — need >= ${REQUIRED_JSC_VERSION}. ` + `Run: npm i ${jscName}@^${REQUIRED_JSC_VERSION}`);
148
+ throw new Error(`[jsc] ${jscName} must be >= ${REQUIRED_JSC_VERSION}, got ${version}`);
149
+ }
150
+ } catch (e) {
151
+ if (e?.message?.includes(`must be >= ${REQUIRED_JSC_VERSION}`)) throw e;
152
+ }
153
+ }
154
+ static wrapAllJsWithIife(buildPath) {
155
+ for (const {
156
+ rel
157
+ } of Jsc.listFiles(buildPath, '.js')) {
158
+ const abs = path.join(buildPath, rel);
159
+ const body = fs.readFileSync(abs, 'utf-8');
160
+ if (body.startsWith('export default (function (__ctx)')) continue;
161
+ const wrapped = IIFE_WRAP_PREFIX + body + IIFE_WRAP_SUFFIX;
162
+ Jsc.assertLegacyGlobalBinding(rel, wrapped);
163
+ fs.writeFileSync(abs, wrapped, 'utf-8');
164
+ }
165
+ }
166
+
167
+ // Fail the build if a Component-JS page keeps a bare `global`/`window`/`self`
168
+ // member access but the wrapper lost its compat alias — otherwise the page
169
+ // ships and only blows up at runtime (`global.runGC is not a function` →
170
+ // unhandled promise rejection stuck on the loading page). The alias is emitted
171
+ // unconditionally by IIFE_WRAP_PREFIX, so this trips only if that prefix
172
+ // regresses, surfacing the break at pack time instead of on-device.
173
+ static assertLegacyGlobalBinding(rel, wrapped) {
174
+ const usesLegacyGlobal = /\b(global|window|self)\s*\./.test(wrapped);
175
+ if (!usesLegacyGlobal) return;
176
+ const hasAlias = /\bconst global = __ctx, window = __ctx, self = __ctx;/.test(wrapped);
177
+ if (!hasAlias) {
178
+ _sharedUtils.ColorConsole.throw(`[jsc] ${rel} references bare global/window/self but the IIFE wrapper is ` + `missing the \`const global = __ctx, window = __ctx, self = __ctx\` compat ` + `alias. Such a page would throw at runtime (e.g. global.runGC is not a ` + `function) and hang on the loading page.`);
179
+ throw new Error(`[jsc] ${rel}: missing legacy global compat alias in wrapper`);
180
+ }
181
+ }
182
+ static compareSemver(a, b) {
183
+ const parse = v => v.replace(/^[\^~=v]/, '').split(/[.-]/).slice(0, 3).map(p => parseInt(p, 10) || 0);
184
+ const [a1, a2, a3] = parse(a);
185
+ const [b1, b2, b3] = parse(b);
186
+ if (a1 !== b1) return a1 - b1;
187
+ if (a2 !== b2) return a2 - b2;
188
+ return a3 - b3;
189
+ }
122
190
  }
123
191
  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.14",
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.14",
23
+ "@aiot-toolkit/parser": "2.1.0-prender.14",
24
+ "@aiot-toolkit/shared-utils": "2.1.0-prender.14",
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.14",
32
32
  "file-loader": "^6.2.0",
33
33
  "fs-extra": "^11.2.0",
34
34
  "jsrsasign": "^11.1.0",