@crazx/dsh-client-modules 0.1.2-alpha.3.zw.1 → 0.1.2-alpha.3.zw.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/modules/README.md
5
- README.md: 414d34af202ee4ab24e1b7570697ad63bd8cdbc8
6
- README.zh.md: e6adc7b7d0265e52d5108e241a8f8a551976536d
5
+ README.md: 9e7dee9fd3162d7bbcec0b06294d36ffc60d0794
6
+ README.zh.md: 88fa3b7780c638bf3c41766844442a01759f861b
package/README.md CHANGED
@@ -63,7 +63,7 @@ Executing a plugin bundle only registers its factory; every module-body side eff
63
63
 
64
64
  ### Incremental composition
65
65
 
66
- The node half scans incrementally per package — no full-rescan path. Every `internal/plugin` emission marks the fiber's entry name dirty; a microtask flush reconciles each dirty name against the live loader entries, and the activation pass seeds the same dirty set and flushes synchronously, so first scan and steady state share one implementation. Package metadata is cached per Loader specifier and owning-tree base URL until restart, while the resolved manifest package name identifies the browser module. Distinct active Loader sources resolving to one package name are rejected; removing the conflict promotes the remaining source without requiring its fiber to restart. Bundle content changes reach the graph only through `rebuilt()` (the HMR hook).
66
+ The node half scans incrementally per package — no full-rescan path. Every `internal/plugin` emission marks the fiber's entry name dirty; a microtask flush reconciles each dirty name against the live loader entries, and the activation pass seeds the same dirty set and flushes synchronously, so first scan and steady state share one implementation. Package metadata is cached per Loader specifier and owning-tree base URL until restart. The Loader specifier is the browser module id; a scoped republish whose unscoped name matches still owns that row. Distinct active Loader sources resolving to one package name are rejected; removing the conflict promotes the remaining source without requiring its fiber to restart. Bundle content changes reach the graph only through `rebuilt()` (the HMR hook).
67
67
 
68
68
  The node half snapshots each client bundle and available source map before publication. It groups resources into `/plugins/??...&rev=...` combo URLs, with one bootstrap combo for the modules row and one or more application combos for the other rows; each phase is partitioned before a URL exceeds 3 KiB. Every combo map is Indexed Source Map v3 and uses an authored section when available or an identity section for the packaged bundle. Initial per-plugin revisions use process nonces, so startup does not hash every plugin; HMR hashes only an artifact reported as changed. Advertised responses are immutable, and an unknown combination or revision returns 404.
69
69
 
package/README.zh.md CHANGED
@@ -63,7 +63,7 @@ application combo 脚本在启动时注册插件 factory;模块主体仍保持
63
63
 
64
64
  ### 增量组合
65
65
 
66
- node 半侧逐包增量扫描——没有全量重扫路径。每次 `internal/plugin` 发出都会把该 fiber 的 entry 名标脏;一个微任务 flush 会把每个脏名与当前 loader 条目对账,激活 pass 播种同一脏集合并同步 flush,因此首次扫描与稳态共用同一实现。包元数据按 Loader specifier 与所属 tree base URL 缓存至重启,解析出的 manifest 包名作为浏览器模块身份。若不同的 active Loader source 解析到同一包名,组合会失败;移除冲突来源后,剩余来源无需重启 fiber 即可接替。bundle 内容变更只能通过 `rebuilt()`(HMR 钩子)进入图。
66
+ node 半侧逐包增量扫描——没有全量重扫路径。每次 `internal/plugin` 发出都会把该 fiber 的 entry 名标脏;一个微任务 flush 会把每个脏名与当前 loader 条目对账,激活 pass 播种同一脏集合并同步 flush,因此首次扫描与稳态共用同一实现。包元数据按 Loader specifier 与所属 tree base URL 缓存至重启。浏览器模块 id Loader specifier;换 scope 再发布且去掉 scope 后的包名仍相同的清单,仍拥有该行。若不同的 active Loader source 解析到同一包名,组合会失败;移除冲突来源后,剩余来源无需重启 fiber 即可接替。bundle 内容变更只能通过 `rebuilt()`(HMR 钩子)进入图。
67
67
 
68
68
  node 半侧会在发布前快照每个客户端 bundle 及其现有 source map。它把资源分组到 `/plugins/??...&rev=...` combo URL:modules row 使用一个 bootstrap combo,其余 row 使用一个或多个 application combo;每个阶段都会在 URL 超过 3 KiB 之前分区。每个 combo map 都是 Indexed Source Map v3,并在可用时使用作者提供的 section,否则为已打包 bundle 生成 identity section。初始逐插件 revision 使用进程 nonce,所以启动时不哈希每个插件;HMR 只哈希被报告为已变化的产物。已公告响应不可变;未知组合或 revision 返回 404。
69
69
 
package/lib/index.js CHANGED
@@ -136,6 +136,22 @@ function exactPackageSpecifier(specifier) {
136
136
  }
137
137
  return specifier.length > 0 && !specifier.includes("/") ? specifier : void 0;
138
138
  }
139
+ /**
140
+ * A scoped republish keeps the unscoped name and changes only the scope
141
+ * (`@deepseek-ai/dsh-client-modules` vs `@crazx/dsh-client-modules`). The
142
+ * graph row id stays the Loader specifier; this match only locates the
143
+ * owning manifest.
144
+ */
145
+ function manifestOwnsLoaderPackage(manifestName, expectedPackageName) {
146
+ if (manifestName === expectedPackageName) return true;
147
+ if (!manifestName.startsWith("@") || !expectedPackageName.startsWith("@")) return false;
148
+ const manifestSlash = manifestName.indexOf("/");
149
+ const expectedSlash = expectedPackageName.indexOf("/");
150
+ if (manifestSlash === -1 || expectedSlash === -1) return false;
151
+ const manifestSuffix = manifestName.slice(manifestSlash + 1);
152
+ const expectedSuffix = expectedPackageName.slice(expectedSlash + 1);
153
+ return expectedSuffix.length > 0 && manifestSuffix === expectedSuffix;
154
+ }
139
155
  /** Narrow an unknown parsed JSON value to the `dsh.client` declaration, throwing on malformed fields. */
140
156
  function parseDshClient(pkgName, value) {
141
157
  if (value === void 0) return void 0;
@@ -650,9 +666,11 @@ var ClientModuleRegistry = class extends Service {
650
666
  * Locate the manifest of the package the Loader mounts for a row. The row's
651
667
  * module location is authoritative: the specifier resolves through the same
652
668
  * Loader resolution that imported the row's host half — including any
653
- * active ESM hooks — and the nearest ancestor manifest declaring the name
654
- * owns the module. Tree-anchored `require` resolution remains only for
655
- * runtimes without Node internals.
669
+ * active ESM hooks — and the nearest ancestor manifest declaring the name,
670
+ * or a scoped republish of the same unscoped name, owns the module. The
671
+ * returned `packageName` is the Loader specifier so the graph row id stays
672
+ * the name the composition and HTML preload list already use. Tree-anchored
673
+ * `require` resolution remains only for runtimes without Node internals.
656
674
  * @param loaderName - module specifier of the loader row.
657
675
  * @param baseUrl - resolution base of the tree that owns the row.
658
676
  * @returns the manifest path, or `undefined` when the name resolves to no package root.
@@ -695,9 +713,9 @@ var ClientModuleRegistry = class extends Service {
695
713
  const candidate = join(dir, "package.json");
696
714
  if (existsSync(candidate)) try {
697
715
  const name = JSON.parse(readFileSync(candidate, "utf8")).name;
698
- if (typeof name === "string" && (expectedPackageName === void 0 || name === expectedPackageName)) return {
716
+ if (typeof name === "string" && (expectedPackageName === void 0 || manifestOwnsLoaderPackage(name, expectedPackageName))) return {
699
717
  path: candidate,
700
- packageName: name
718
+ packageName: expectedPackageName ?? name
701
719
  };
702
720
  } catch {}
703
721
  const parent = dirname(dir);
@@ -141,9 +141,11 @@ export declare class ClientModuleRegistry extends Service {
141
141
  * Locate the manifest of the package the Loader mounts for a row. The row's
142
142
  * module location is authoritative: the specifier resolves through the same
143
143
  * Loader resolution that imported the row's host half — including any
144
- * active ESM hooks — and the nearest ancestor manifest declaring the name
145
- * owns the module. Tree-anchored `require` resolution remains only for
146
- * runtimes without Node internals.
144
+ * active ESM hooks — and the nearest ancestor manifest declaring the name,
145
+ * or a scoped republish of the same unscoped name, owns the module. The
146
+ * returned `packageName` is the Loader specifier so the graph row id stays
147
+ * the name the composition and HTML preload list already use. Tree-anchored
148
+ * `require` resolution remains only for runtimes without Node internals.
147
149
  * @param loaderName - module specifier of the loader row.
148
150
  * @param baseUrl - resolution base of the tree that owns the row.
149
151
  * @returns the manifest path, or `undefined` when the name resolves to no package root.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@crazx/dsh-client-modules",
3
3
  "description": "Client module system, dual-face: node half composes the __DSH_BOOT__ entry graph (incremental dsh.client scan, bundle route, index tap, webPlugins service); browser half is the lazy-CJS module table the vendored cordis Loader consumes as its internal seam",
4
- "version": "0.1.2-alpha.3.zw.1",
4
+ "version": "0.1.2-alpha.3.zw.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },