@zhin.js/pagemanager 2.0.3 → 2.0.4

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.
Files changed (46) hide show
  1. package/README.md +20 -0
  2. package/lib/client-build/index.d.ts +6 -0
  3. package/lib/client-build/index.d.ts.map +1 -0
  4. package/lib/client-build/index.js +6 -0
  5. package/lib/client-build/index.js.map +1 -0
  6. package/lib/client-build/manifest-loader.d.ts +9 -0
  7. package/lib/client-build/manifest-loader.d.ts.map +1 -0
  8. package/lib/client-build/manifest-loader.js +47 -0
  9. package/lib/client-build/manifest-loader.js.map +1 -0
  10. package/lib/client-build/module-runtime.d.ts +17 -0
  11. package/lib/client-build/module-runtime.d.ts.map +1 -0
  12. package/lib/client-build/module-runtime.js +28 -0
  13. package/lib/client-build/module-runtime.js.map +1 -0
  14. package/lib/client-build/static-metadata.d.ts +9 -0
  15. package/lib/client-build/static-metadata.d.ts.map +1 -0
  16. package/lib/client-build/static-metadata.js +126 -0
  17. package/lib/client-build/static-metadata.js.map +1 -0
  18. package/lib/client-build/types.d.ts +21 -0
  19. package/lib/client-build/types.d.ts.map +1 -0
  20. package/lib/client-build/types.js +2 -0
  21. package/lib/client-build/types.js.map +1 -0
  22. package/lib/client-build/typescript-builder.d.ts +9 -0
  23. package/lib/client-build/typescript-builder.d.ts.map +1 -0
  24. package/lib/client-build/typescript-builder.js +129 -0
  25. package/lib/client-build/typescript-builder.js.map +1 -0
  26. package/lib/plugin-runtime/access.d.ts +8 -0
  27. package/lib/plugin-runtime/access.d.ts.map +1 -0
  28. package/lib/plugin-runtime/access.js +11 -0
  29. package/lib/plugin-runtime/access.js.map +1 -0
  30. package/lib/plugin-runtime/console-catalog.d.ts +22 -0
  31. package/lib/plugin-runtime/console-catalog.d.ts.map +1 -0
  32. package/lib/plugin-runtime/console-catalog.js +69 -0
  33. package/lib/plugin-runtime/console-catalog.js.map +1 -0
  34. package/lib/plugin-runtime/console-runtime.d.ts +10 -0
  35. package/lib/plugin-runtime/console-runtime.d.ts.map +1 -0
  36. package/lib/plugin-runtime/console-runtime.js +26 -0
  37. package/lib/plugin-runtime/console-runtime.js.map +1 -0
  38. package/lib/plugin-runtime/index.d.ts +5 -0
  39. package/lib/plugin-runtime/index.d.ts.map +1 -0
  40. package/lib/plugin-runtime/index.js +5 -0
  41. package/lib/plugin-runtime/index.js.map +1 -0
  42. package/lib/plugin-runtime/navigation.d.ts +4 -0
  43. package/lib/plugin-runtime/navigation.d.ts.map +1 -0
  44. package/lib/plugin-runtime/navigation.js +57 -0
  45. package/lib/plugin-runtime/navigation.js.map +1 -0
  46. package/package.json +27 -3
package/README.md CHANGED
@@ -35,6 +35,26 @@ pnpm add @zhin.js/pagemanager
35
35
 
36
36
  类型(`ConsoleServerOptions`、`PluginServerRegisterHostApi` 等)自 `./consoleServerOptions.js` 导出。
37
37
 
38
+ ## Plugin Runtime
39
+
40
+ `@zhin.js/pagemanager/plugin-runtime` 提供 snapshot-coherent 的 `ConsoleRuntime`。一次
41
+ `runView()` 在完整回调期间持有同一 generation lease,route guard、权限过滤、Navigation
42
+ 树和 Layout fallback chain 都从同一个 Page/Layout projection 读取;回调结束后 catalog
43
+ 失效,避免浏览器模块 URL 跨 generation 逃逸。
44
+
45
+ 该子路径不引入 React、Router 或客户端编译器。Page 与 Layout 的约定式发现分别由
46
+ `@zhin.js/page`、`@zhin.js/layout` 提供,wire types 来自零依赖
47
+ `@zhin.js/console-contract`。
48
+
49
+ ## Client Build
50
+
51
+ `@zhin.js/pagemanager/client-build` 是可选的 TypeScript AST/build adapter。它静态提取
52
+ `definePage()` 的 JSON-like metadata,生成 content-hash ESM 与
53
+ `pages.manifest.json`,生产 loader 不记录构建机绝对路径。
54
+
55
+ TypeScript 是 optional peer,不进入默认 PageManager 或 Plugin Runtime 的生产闭包。
56
+ 选择该子路径的构建 workspace 需要显式安装兼容版本的 `typescript`。
57
+
38
58
  ## 插件注册 Entry
39
59
 
40
60
  在插件 Node 侧通过 `web` 上下文获取 **PageManager 实例**(非静态全局):
@@ -0,0 +1,6 @@
1
+ export * from './manifest-loader.js';
2
+ export * from './module-runtime.js';
3
+ export * from './static-metadata.js';
4
+ export * from './typescript-builder.js';
5
+ export * from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client-build/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './manifest-loader.js';
2
+ export * from './module-runtime.js';
3
+ export * from './static-metadata.js';
4
+ export * from './typescript-builder.js';
5
+ export * from './types.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client-build/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ClientModuleRequest } from '@zhin.js/feature-kit';
2
+ import type { ClientArtifactManifest, ClientModuleLoader } from './types.js';
3
+ export declare class ManifestClientModuleLoader implements ClientModuleLoader {
4
+ #private;
5
+ constructor(manifest: ClientArtifactManifest);
6
+ static fromFile(path: string): Promise<ManifestClientModuleLoader>;
7
+ load<T = unknown>(_source: string, request: ClientModuleRequest): Promise<T>;
8
+ }
9
+ //# sourceMappingURL=manifest-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../../src/client-build/manifest-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EACV,sBAAsB,EAEtB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,qBAAa,0BAA2B,YAAW,kBAAkB;;gBAGvD,QAAQ,EAAE,sBAAsB;WAc/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAKlE,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;CASnF"}
@@ -0,0 +1,47 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ export class ManifestClientModuleLoader {
3
+ #entries;
4
+ constructor(manifest) {
5
+ if (manifest.protocol !== 1 || !Array.isArray(manifest.entries)) {
6
+ throw new TypeError('Unsupported client artifact manifest');
7
+ }
8
+ const entries = new Map();
9
+ for (const candidate of manifest.entries) {
10
+ const entry = validateEntry(candidate);
11
+ const key = artifactKey(entry);
12
+ if (entries.has(key))
13
+ throw new Error(`Duplicate client artifact: ${key}`);
14
+ entries.set(key, Object.freeze({ ...entry }));
15
+ }
16
+ this.#entries = entries;
17
+ }
18
+ static async fromFile(path) {
19
+ const parsed = JSON.parse(await readFile(path, 'utf8'));
20
+ return new ManifestClientModuleLoader(parsed);
21
+ }
22
+ async load(_source, request) {
23
+ const entry = this.#entries.get(artifactKey(request));
24
+ if (!entry)
25
+ throw new Error(`Missing client artifact for ${request.feature}:${request.localName}`);
26
+ return Object.freeze({
27
+ module: entry.module,
28
+ hash: entry.hash,
29
+ metadata: entry.metadata,
30
+ });
31
+ }
32
+ }
33
+ function artifactKey(request) {
34
+ return `${request.owner}\0${request.feature}\0${request.localName}`;
35
+ }
36
+ function validateEntry(value) {
37
+ if (!value || typeof value !== 'object')
38
+ throw new TypeError('Invalid client artifact entry');
39
+ const entry = value;
40
+ for (const field of ['source', 'owner', 'feature', 'localName', 'module', 'hash']) {
41
+ if (typeof entry[field] !== 'string' || !entry[field]) {
42
+ throw new TypeError(`Invalid client artifact ${field}`);
43
+ }
44
+ }
45
+ return entry;
46
+ }
47
+ //# sourceMappingURL=manifest-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-loader.js","sourceRoot":"","sources":["../../src/client-build/manifest-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAQ5C,MAAM,OAAO,0BAA0B;IAC5B,QAAQ,CAAsD;IAEvE,YAAY,QAAgC;QAC1C,IAAI,QAAQ,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0C,CAAC;QAClE,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAY;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAA2B,CAAC;QAClF,OAAO,IAAI,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,IAAI,CAAc,OAAe,EAAE,OAA4B;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACnG,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAM,CAAC;IACV,CAAC;CACF;AAED,SAAS,WAAW,CAAC,OAA4B;IAC/C,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;AACtE,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,+BAA+B,CAAC,CAAC;IAC9F,MAAM,KAAK,GAAG,KAAsC,CAAC;IACrD,KAAK,MAAM,KAAK,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAU,EAAE,CAAC;QAC3F,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,SAAS,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,OAAO,KAA6B,CAAC;AACvC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Dispose } from '@zhin.js/plugin-runtime';
2
+ import type { ClientModuleRequest } from '@zhin.js/feature-kit';
3
+ import type { ModuleRuntime } from '@zhin.js/runtime';
4
+ import type { ClientModuleLoader } from './types.js';
5
+ /** Adds client artifact loading while preserving the server ModuleRuntime authority. */
6
+ export declare class ClientBuildModuleRuntime implements ModuleRuntime {
7
+ private readonly server;
8
+ private readonly client;
9
+ constructor(server: ModuleRuntime, client: ClientModuleLoader);
10
+ load<T = unknown>(source: string): Promise<T>;
11
+ loadClientModule<T = unknown>(source: string, request: ClientModuleRequest): Promise<T>;
12
+ invalidate(source: string): Promise<void> | void;
13
+ affectedSources(source: string): readonly string[];
14
+ watch(listener: (source: string) => void): Dispose;
15
+ close(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=module-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-runtime.d.ts","sourceRoot":"","sources":["../../src/client-build/module-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,wFAAwF;AACxF,qBAAa,wBAAyB,YAAW,aAAa;IAE1D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,kBAAkB;IAG7C,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAI7C,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAIvF,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIhD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE;IAIlD,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO;IAIlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvB"}
@@ -0,0 +1,28 @@
1
+ /** Adds client artifact loading while preserving the server ModuleRuntime authority. */
2
+ export class ClientBuildModuleRuntime {
3
+ server;
4
+ client;
5
+ constructor(server, client) {
6
+ this.server = server;
7
+ this.client = client;
8
+ }
9
+ load(source) {
10
+ return this.server.load(source);
11
+ }
12
+ loadClientModule(source, request) {
13
+ return this.client.load(source, request);
14
+ }
15
+ invalidate(source) {
16
+ return this.server.invalidate?.(source);
17
+ }
18
+ affectedSources(source) {
19
+ return this.server.affectedSources?.(source) ?? [source];
20
+ }
21
+ watch(listener) {
22
+ return this.server.watch?.(listener) ?? (() => undefined);
23
+ }
24
+ close() {
25
+ return this.server.close();
26
+ }
27
+ }
28
+ //# sourceMappingURL=module-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-runtime.js","sourceRoot":"","sources":["../../src/client-build/module-runtime.ts"],"names":[],"mappings":"AAKA,wFAAwF;AACxF,MAAM,OAAO,wBAAwB;IAEhB;IACA;IAFnB,YACmB,MAAqB,EACrB,MAA0B;QAD1B,WAAM,GAAN,MAAM,CAAe;QACrB,WAAM,GAAN,MAAM,CAAoB;IAC1C,CAAC;IAEJ,IAAI,CAAc,MAAc;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAI,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,gBAAgB,CAAc,MAAc,EAAE,OAA4B;QACxE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAI,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,eAAe,CAAC,MAAc;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,QAAkC;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ export declare function extractPageMetadata(source: string, fileName: string): unknown;
2
+ export declare function assertLayoutModule(source: string, fileName: string): void;
3
+ export declare class ClientSourceError extends Error {
4
+ readonly source: string;
5
+ readonly line: number;
6
+ readonly column: number;
7
+ constructor(source: string, line: number, column: number, message: string);
8
+ }
9
+ //# sourceMappingURL=static-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-metadata.d.ts","sourceRoot":"","sources":["../../src/client-build/static-metadata.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgB7E;AAmBD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAGzE;AAyED,qBAAa,iBAAkB,SAAQ,KAAK;IAExC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAFd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM;CAKlB"}
@@ -0,0 +1,126 @@
1
+ import ts from 'typescript';
2
+ export function extractPageMetadata(source, fileName) {
3
+ const file = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, scriptKind(fileName));
4
+ assertDefaultExport(file);
5
+ let metadata;
6
+ let found = false;
7
+ for (const statement of file.statements) {
8
+ if (!ts.isVariableStatement(statement) || !hasModifier(statement, ts.SyntaxKind.ExportKeyword))
9
+ continue;
10
+ for (const declaration of statement.declarationList.declarations) {
11
+ if (!ts.isIdentifier(declaration.name) || declaration.name.text !== 'meta')
12
+ continue;
13
+ if (found)
14
+ fail(file, declaration, 'Page module exports meta more than once');
15
+ found = true;
16
+ assertDefinePageImport(file, declaration);
17
+ metadata = parseDefinePage(file, declaration.initializer);
18
+ }
19
+ }
20
+ return metadata;
21
+ }
22
+ function assertDefinePageImport(file, node) {
23
+ const found = file.statements.some((statement) => {
24
+ if (!ts.isImportDeclaration(statement)
25
+ || !ts.isStringLiteral(statement.moduleSpecifier)
26
+ || statement.moduleSpecifier.text !== '@zhin.js/console-contract')
27
+ return false;
28
+ const bindings = statement.importClause?.namedBindings;
29
+ return bindings && ts.isNamedImports(bindings)
30
+ && bindings.elements.some((element) => element.name.text === 'definePage'
31
+ && (element.propertyName?.text ?? element.name.text) === 'definePage');
32
+ });
33
+ if (!found)
34
+ fail(file, node, 'Page meta requires a named definePage import from @zhin.js/console-contract');
35
+ }
36
+ export function assertLayoutModule(source, fileName) {
37
+ const file = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, scriptKind(fileName));
38
+ assertDefaultExport(file);
39
+ }
40
+ function parseDefinePage(file, expression) {
41
+ if (!expression || !ts.isCallExpression(expression)
42
+ || !ts.isIdentifier(expression.expression) || expression.expression.text !== 'definePage') {
43
+ fail(file, expression ?? file, 'Page meta must be definePage({...})');
44
+ }
45
+ if (expression.arguments.length > 1)
46
+ fail(file, expression, 'definePage() accepts at most one argument');
47
+ const argument = expression.arguments[0];
48
+ return argument ? literal(file, argument) : {};
49
+ }
50
+ function literal(file, node) {
51
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
52
+ return node.text;
53
+ if (ts.isNumericLiteral(node))
54
+ return Number(node.text);
55
+ if (node.kind === ts.SyntaxKind.TrueKeyword)
56
+ return true;
57
+ if (node.kind === ts.SyntaxKind.FalseKeyword)
58
+ return false;
59
+ if (node.kind === ts.SyntaxKind.NullKeyword)
60
+ return null;
61
+ if (ts.isPrefixUnaryExpression(node)
62
+ && node.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(node.operand)) {
63
+ return -Number(node.operand.text);
64
+ }
65
+ if (ts.isArrayLiteralExpression(node)) {
66
+ return node.elements.map((element) => {
67
+ if (ts.isSpreadElement(element) || ts.isOmittedExpression(element)) {
68
+ fail(file, element, 'Page metadata arrays cannot contain spreads or holes');
69
+ }
70
+ return literal(file, element);
71
+ });
72
+ }
73
+ if (ts.isObjectLiteralExpression(node)) {
74
+ const result = {};
75
+ for (const property of node.properties) {
76
+ if (!ts.isPropertyAssignment(property)) {
77
+ fail(file, property, 'Page metadata only supports static property assignments');
78
+ }
79
+ const name = propertyName(file, property.name);
80
+ if (Object.hasOwn(result, name))
81
+ fail(file, property.name, `Duplicate Page metadata key: ${name}`);
82
+ result[name] = literal(file, property.initializer);
83
+ }
84
+ return result;
85
+ }
86
+ fail(file, node, 'Page metadata must contain JSON-like literals only');
87
+ }
88
+ function propertyName(file, name) {
89
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name))
90
+ return name.text;
91
+ fail(file, name, 'Page metadata does not support computed property names');
92
+ }
93
+ function assertDefaultExport(file) {
94
+ const found = file.statements.some((statement) => {
95
+ if (ts.isExportAssignment(statement))
96
+ return !statement.isExportEquals;
97
+ return (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement))
98
+ && hasModifier(statement, ts.SyntaxKind.ExportKeyword)
99
+ && hasModifier(statement, ts.SyntaxKind.DefaultKeyword);
100
+ });
101
+ if (!found)
102
+ fail(file, file, 'Client module must have a default export');
103
+ }
104
+ function hasModifier(node, kind) {
105
+ return ts.canHaveModifiers(node) && ts.getModifiers(node)?.some((modifier) => modifier.kind === kind) === true;
106
+ }
107
+ function scriptKind(fileName) {
108
+ return fileName.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
109
+ }
110
+ function fail(file, node, message) {
111
+ const position = file.getLineAndCharacterOfPosition(node.getStart(file, false));
112
+ throw new ClientSourceError(file.fileName, position.line + 1, position.character + 1, message);
113
+ }
114
+ export class ClientSourceError extends Error {
115
+ source;
116
+ line;
117
+ column;
118
+ constructor(source, line, column, message) {
119
+ super(`${source}:${line}:${column} ${message}`);
120
+ this.source = source;
121
+ this.line = line;
122
+ this.column = column;
123
+ this.name = 'ClientSourceError';
124
+ }
125
+ }
126
+ //# sourceMappingURL=static-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-metadata.js","sourceRoot":"","sources":["../../src/client-build/static-metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ClientModuleArtifact } from '@zhin.js/console-contract';
2
+ import type { ClientModuleRequest } from '@zhin.js/feature-kit';
3
+ export interface ClientBuildEntry extends ClientModuleRequest {
4
+ readonly source: string;
5
+ }
6
+ export interface ClientArtifactRecord extends ClientBuildEntry, ClientModuleArtifact {
7
+ }
8
+ export interface ClientArtifactManifest {
9
+ readonly protocol: 1;
10
+ readonly entries: readonly ClientArtifactRecord[];
11
+ }
12
+ export interface ClientModuleLoader {
13
+ load<T = unknown>(source: string, request: ClientModuleRequest): Promise<T>;
14
+ }
15
+ export interface TypeScriptClientBuilderOptions {
16
+ readonly outDir: string;
17
+ readonly projectRoot?: string;
18
+ readonly publicBase?: string;
19
+ readonly manifestFile?: string;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client-build/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB,EAAE,oBAAoB;CAAG;AAEvF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/client-build/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { ClientModuleRequest } from '@zhin.js/feature-kit';
2
+ import type { ClientArtifactManifest, ClientBuildEntry, ClientModuleLoader, TypeScriptClientBuilderOptions } from './types.js';
3
+ export declare class TypeScriptClientBuilder implements ClientModuleLoader {
4
+ #private;
5
+ constructor(options: TypeScriptClientBuilderOptions);
6
+ load<T = unknown>(source: string, request: ClientModuleRequest): Promise<T>;
7
+ build(entries: readonly ClientBuildEntry[]): Promise<Readonly<ClientArtifactManifest>>;
8
+ }
9
+ //# sourceMappingURL=typescript-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-builder.d.ts","sourceRoot":"","sources":["../../src/client-build/typescript-builder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAMhE,OAAO,KAAK,EACV,sBAAsB,EAEtB,gBAAgB,EAChB,kBAAkB,EAClB,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAKpB,qBAAa,uBAAwB,YAAW,kBAAkB;;gBAMpD,OAAO,EAAE,8BAA8B;IAO7C,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAe3E,KAAK,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;CAiB7F"}
@@ -0,0 +1,129 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
3
+ import { basename, dirname, join, relative, resolve, sep } from 'node:path';
4
+ import ts from 'typescript';
5
+ import { assertLayoutModule, extractPageMetadata, } from './static-metadata.js';
6
+ const pageFeature = 'zhin.page';
7
+ const layoutFeature = 'zhin.layout';
8
+ export class TypeScriptClientBuilder {
9
+ #outDir;
10
+ #projectRoot;
11
+ #publicBase;
12
+ #manifestFile;
13
+ constructor(options) {
14
+ this.#outDir = resolve(options.outDir);
15
+ this.#projectRoot = resolve(options.projectRoot ?? process.cwd());
16
+ this.#publicBase = `/${trimSlashes(options.publicBase ?? '@zhin/client')}`;
17
+ this.#manifestFile = resolve(options.manifestFile ?? join(this.#outDir, 'pages.manifest.json'));
18
+ }
19
+ async load(source, request) {
20
+ const text = await readFile(source, 'utf8');
21
+ const metadata = metadataFor(text, source, request);
22
+ const hash = contentHash(text);
23
+ const fileName = `${safe(request.owner)}-${safe(request.localName)}-${hash}.js`;
24
+ const output = join(this.#outDir, fileName);
25
+ const code = transpile(text, source);
26
+ await atomicWrite(output, code);
27
+ return Object.freeze({
28
+ module: `${this.#publicBase}/${fileName}`,
29
+ hash,
30
+ metadata,
31
+ });
32
+ }
33
+ async build(entries) {
34
+ const records = [];
35
+ for (const entry of [...entries].sort(compareEntry)) {
36
+ const artifact = await this.load(entry.source, entry);
37
+ records.push(Object.freeze({
38
+ ...entry,
39
+ source: manifestSource(this.#projectRoot, entry.source),
40
+ ...artifact,
41
+ }));
42
+ }
43
+ const manifest = Object.freeze({
44
+ protocol: 1,
45
+ entries: Object.freeze(records),
46
+ });
47
+ await atomicWrite(this.#manifestFile, `${JSON.stringify(manifest, null, 2)}\n`);
48
+ return manifest;
49
+ }
50
+ }
51
+ function manifestSource(root, source) {
52
+ const result = relative(root, resolve(source));
53
+ if (!result || result === '..' || result.startsWith(`..${sep}`)) {
54
+ throw new Error(`Client source is outside project Root: ${source}`);
55
+ }
56
+ return result.split(sep).join('/');
57
+ }
58
+ function metadataFor(source, fileName, request) {
59
+ if (request.feature === pageFeature)
60
+ return extractPageMetadata(source, fileName);
61
+ if (request.feature === layoutFeature) {
62
+ assertLayoutModule(source, fileName);
63
+ return undefined;
64
+ }
65
+ throw new Error(`Unsupported client Feature: ${request.feature}`);
66
+ }
67
+ function transpile(source, fileName) {
68
+ const result = ts.transpileModule(source, {
69
+ fileName,
70
+ reportDiagnostics: true,
71
+ compilerOptions: {
72
+ target: ts.ScriptTarget.ES2022,
73
+ module: ts.ModuleKind.ESNext,
74
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
75
+ jsx: ts.JsxEmit.ReactJSX,
76
+ isolatedModules: true,
77
+ sourceMap: false,
78
+ },
79
+ });
80
+ const errors = (result.diagnostics ?? []).filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
81
+ if (errors.length > 0) {
82
+ throw new Error(ts.formatDiagnostics(errors, {
83
+ getCanonicalFileName: (name) => name,
84
+ getCurrentDirectory: () => process.cwd(),
85
+ getNewLine: () => '\n',
86
+ }));
87
+ }
88
+ return result.outputText;
89
+ }
90
+ function contentHash(source) {
91
+ return createHash('sha256').update(source).digest('hex').slice(0, 16);
92
+ }
93
+ function safe(value) {
94
+ const result = trimDashes(value.replace(/[^a-z0-9-]+/giu, '-')).toLowerCase();
95
+ return result || 'root';
96
+ }
97
+ /** 线性裁剪首尾 `/`(等价于 /^\/+|\/+$/gu,无回溯 — js/polynomial-redos)。 */
98
+ function trimSlashes(value) {
99
+ let start = 0;
100
+ let end = value.length;
101
+ while (start < end && value[start] === '/')
102
+ start += 1;
103
+ while (end > start && value[end - 1] === '/')
104
+ end -= 1;
105
+ return value.slice(start, end);
106
+ }
107
+ /** 线性裁剪首尾 `-`(等价于 /^-+|-+$/gu,无回溯 — js/polynomial-redos)。 */
108
+ function trimDashes(value) {
109
+ let start = 0;
110
+ let end = value.length;
111
+ while (start < end && value[start] === '-')
112
+ start += 1;
113
+ while (end > start && value[end - 1] === '-')
114
+ end -= 1;
115
+ return value.slice(start, end);
116
+ }
117
+ function compareEntry(left, right) {
118
+ return left.owner.localeCompare(right.owner)
119
+ || String(left.feature).localeCompare(String(right.feature))
120
+ || left.localName.localeCompare(right.localName)
121
+ || left.source.localeCompare(right.source);
122
+ }
123
+ async function atomicWrite(path, content) {
124
+ await mkdir(dirname(path), { recursive: true });
125
+ const temporary = join(dirname(path), `.${basename(path)}.${process.pid}.tmp`);
126
+ await writeFile(temporary, content);
127
+ await rename(temporary, path);
128
+ }
129
+ //# sourceMappingURL=typescript-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-builder.js","sourceRoot":"","sources":["../../src/client-build/typescript-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AccessSnapshot, PageManifest } from '@zhin.js/console-contract';
2
+ export interface AccessIndex {
3
+ readonly permissions: ReadonlySet<string>;
4
+ readonly roles: ReadonlySet<string>;
5
+ }
6
+ export declare function createAccessIndex(access: AccessSnapshot): AccessIndex;
7
+ export declare function allowsPage(page: PageManifest, access: AccessIndex): boolean;
8
+ //# sourceMappingURL=access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/plugin-runtime/access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACrC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAKrE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAG3E"}
@@ -0,0 +1,11 @@
1
+ export function createAccessIndex(access) {
2
+ return Object.freeze({
3
+ permissions: new Set(access.permissions),
4
+ roles: new Set(access.roles),
5
+ });
6
+ }
7
+ export function allowsPage(page, access) {
8
+ return page.requiredPermissions.every((permission) => access.permissions.has(permission))
9
+ && page.requiredRoles.every((role) => access.roles.has(role));
10
+ }
11
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/plugin-runtime/access.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;QACxC,KAAK,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;KAC7B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAkB,EAAE,MAAmB;IAChE,OAAO,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;WACpF,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { AccessSnapshot, LayoutManifest, LayoutSlot, NavNode, PageManifest } from '@zhin.js/console-contract';
2
+ import type { PluginId, RuntimeSnapshot } from '@zhin.js/plugin-runtime';
3
+ export type RouteMatch = {
4
+ readonly status: 'found';
5
+ readonly page: Readonly<PageManifest>;
6
+ } | {
7
+ readonly status: 'forbidden';
8
+ readonly page: Readonly<PageManifest>;
9
+ } | {
10
+ readonly status: 'missing';
11
+ };
12
+ export declare class ConsoleCatalog {
13
+ #private;
14
+ readonly generation: number;
15
+ constructor(snapshot: RuntimeSnapshot, access: AccessSnapshot, active?: () => boolean);
16
+ pages(): readonly Readonly<PageManifest>[];
17
+ match(path: string): RouteMatch;
18
+ navigation(): readonly Readonly<NavNode>[];
19
+ layouts(owner: PluginId, slot: LayoutSlot): readonly Readonly<LayoutManifest>[];
20
+ fallback(owner: PluginId): string | undefined;
21
+ }
22
+ //# sourceMappingURL=console-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-catalog.d.ts","sourceRoot":"","sources":["../../src/plugin-runtime/console-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,OAAO,EACP,YAAY,EACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAa,QAAQ,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAMpF,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC;AAEnC,qBAAa,cAAc;;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAQ1B,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,MAAM,OAAoB;IAUpC,KAAK,IAAI,SAAS,QAAQ,CAAC,YAAY,CAAC,EAAE;IAK1C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAS/B,UAAU,IAAI,SAAS,QAAQ,CAAC,OAAO,CAAC,EAAE;IAK1C,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS,QAAQ,CAAC,cAAc,CAAC,EAAE;IAM/E,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS;CAe9C"}
@@ -0,0 +1,69 @@
1
+ import { LayoutIndex, layoutFeatureId } from '@zhin.js/layout';
2
+ import { PageIndex, pageFeatureId } from '@zhin.js/page';
3
+ import { allowsPage, createAccessIndex } from './access.js';
4
+ import { buildNavigation } from './navigation.js';
5
+ export class ConsoleCatalog {
6
+ generation;
7
+ #snapshot;
8
+ #pages;
9
+ #layouts;
10
+ #access;
11
+ #active;
12
+ constructor(snapshot, access, active = () => true) {
13
+ this.generation = snapshot.generation;
14
+ this.#snapshot = snapshot;
15
+ this.#pages = projection(snapshot, pageFeatureId, PageIndex);
16
+ this.#layouts = projection(snapshot, layoutFeatureId, LayoutIndex);
17
+ this.#access = createAccessIndex(access);
18
+ this.#active = active;
19
+ }
20
+ pages() {
21
+ this.#assertActive();
22
+ return Object.freeze((this.#pages?.list() ?? []).filter((page) => allowsPage(page, this.#access)));
23
+ }
24
+ match(path) {
25
+ this.#assertActive();
26
+ const page = this.#pages?.route(path);
27
+ if (!page)
28
+ return Object.freeze({ status: 'missing' });
29
+ return allowsPage(page, this.#access)
30
+ ? Object.freeze({ status: 'found', page })
31
+ : Object.freeze({ status: 'forbidden', page });
32
+ }
33
+ navigation() {
34
+ this.#assertActive();
35
+ return buildNavigation(this.#snapshot, this.pages());
36
+ }
37
+ layouts(owner, slot) {
38
+ this.#assertActive();
39
+ if (!this.#snapshot.tree.has(owner))
40
+ throw new Error(`Unknown Layout owner: ${owner}`);
41
+ return this.#layouts?.chain(owner, slot) ?? Object.freeze([]);
42
+ }
43
+ fallback(owner) {
44
+ this.#assertActive();
45
+ if (!this.#snapshot.tree.has(owner))
46
+ throw new Error(`Unknown Page fallback owner: ${owner}`);
47
+ let current = owner;
48
+ while (current) {
49
+ const page = this.#pages?.ownedBy(current).find((candidate) => allowsPage(candidate, this.#access));
50
+ if (page)
51
+ return page.route;
52
+ current = this.#snapshot.tree.get(current)?.parent;
53
+ }
54
+ return undefined;
55
+ }
56
+ #assertActive() {
57
+ if (!this.#active())
58
+ throw new Error('Console catalog view scope has ended');
59
+ }
60
+ }
61
+ function projection(snapshot, id, constructor) {
62
+ const value = snapshot.projections.get(id);
63
+ return value
64
+ && typeof value === 'object'
65
+ && Object.prototype.isPrototypeOf.call(constructor.prototype, value)
66
+ ? value
67
+ : undefined;
68
+ }
69
+ //# sourceMappingURL=console-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-catalog.js","sourceRoot":"","sources":["../../src/plugin-runtime/console-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type SnapshotStore } from '@zhin.js/plugin-runtime';
2
+ import type { AccessSnapshot } from '@zhin.js/console-contract';
3
+ import { ConsoleCatalog } from './console-catalog.js';
4
+ export declare const consoleRuntimeToken: import("@zhin.js/plugin-runtime").Token<ConsoleRuntime>;
5
+ export declare class ConsoleRuntime {
6
+ #private;
7
+ attach(snapshots: SnapshotStore): void;
8
+ runView<TResult>(access: AccessSnapshot, operation: (catalog: ConsoleCatalog) => TResult | Promise<TResult>): Promise<TResult>;
9
+ }
10
+ //# sourceMappingURL=console-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-runtime.d.ts","sourceRoot":"","sources":["../../src/plugin-runtime/console-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,eAAO,MAAM,mBAAmB,yDAAsD,CAAC;AAEvF,qBAAa,cAAc;;IAGzB,MAAM,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI;IAOhC,OAAO,CAAC,OAAO,EACnB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GACjE,OAAO,CAAC,OAAO,CAAC;CAWpB"}
@@ -0,0 +1,26 @@
1
+ import { createToken } from '@zhin.js/plugin-runtime';
2
+ import { ConsoleCatalog } from './console-catalog.js';
3
+ export const consoleRuntimeToken = createToken('zhin.console.runtime');
4
+ export class ConsoleRuntime {
5
+ #snapshots;
6
+ attach(snapshots) {
7
+ if (this.#snapshots && this.#snapshots !== snapshots) {
8
+ throw new Error('ConsoleRuntime is already attached to another Root');
9
+ }
10
+ this.#snapshots = snapshots;
11
+ }
12
+ async runView(access, operation) {
13
+ if (!this.#snapshots)
14
+ throw new Error('ConsoleRuntime is not attached to a Root');
15
+ const lease = this.#snapshots.acquire();
16
+ let active = true;
17
+ try {
18
+ return await operation(new ConsoleCatalog(lease.value, access, () => active));
19
+ }
20
+ finally {
21
+ active = false;
22
+ lease.release();
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=console-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-runtime.js","sourceRoot":"","sources":["../../src/plugin-runtime/console-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAiB,sBAAsB,CAAC,CAAC;AAEvF,MAAM,OAAO,cAAc;IACzB,UAAU,CAAiB;IAE3B,MAAM,CAAC,SAAwB;QAC7B,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,OAAO,CACX,MAAsB,EACtB,SAAkE;QAElE,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxC,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,CAAC;gBAAS,CAAC;YACT,MAAM,GAAG,KAAK,CAAC;YACf,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export * from './access.js';
2
+ export * from './console-catalog.js';
3
+ export * from './console-runtime.js';
4
+ export * from './navigation.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin-runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './access.js';
2
+ export * from './console-catalog.js';
3
+ export * from './console-runtime.js';
4
+ export * from './navigation.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin-runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { NavNode, PageManifest } from '@zhin.js/console-contract';
2
+ import type { RuntimeSnapshot } from '@zhin.js/plugin-runtime';
3
+ export declare function buildNavigation(snapshot: RuntimeSnapshot, pages: readonly Readonly<PageManifest>[]): readonly Readonly<NavNode>[];
4
+ //# sourceMappingURL=navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/plugin-runtime/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EAAgC,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE7F,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,SAAS,QAAQ,CAAC,YAAY,CAAC,EAAE,GACvC,SAAS,QAAQ,CAAC,OAAO,CAAC,EAAE,CAiC9B"}
@@ -0,0 +1,57 @@
1
+ export function buildNavigation(snapshot, pages) {
2
+ const byOwner = new Map();
3
+ for (const page of pages) {
4
+ if (page.hideInNav)
5
+ continue;
6
+ const owned = byOwner.get(page.owner) ?? [];
7
+ owned.push(page);
8
+ byOwner.set(page.owner, owned);
9
+ }
10
+ const visit = (id) => {
11
+ const plugin = requiredPlugin(snapshot, id);
12
+ const leaves = (byOwner.get(id) ?? []).map(pageNode);
13
+ const groups = plugin.children
14
+ .map(visit)
15
+ .filter((node) => node !== undefined);
16
+ const children = Object.freeze([...leaves, ...groups].sort(compareNode));
17
+ if (children.length === 0)
18
+ return undefined;
19
+ return Object.freeze({
20
+ id: plugin.id,
21
+ type: 'plugin',
22
+ label: plugin.metadata?.displayName ?? plugin.instanceKey,
23
+ icon: plugin.metadata?.icon,
24
+ order: plugin.metadata?.order ?? 100,
25
+ children,
26
+ });
27
+ };
28
+ const root = requiredPlugin(snapshot, snapshot.root);
29
+ const rootPages = (byOwner.get(snapshot.root) ?? []).map(pageNode);
30
+ const groups = root.children
31
+ .map(visit)
32
+ .filter((node) => node !== undefined);
33
+ return Object.freeze([...rootPages, ...groups].sort(compareNode));
34
+ }
35
+ function pageNode(page) {
36
+ return Object.freeze({
37
+ id: page.id,
38
+ type: 'page',
39
+ label: page.title,
40
+ icon: page.icon,
41
+ path: page.route,
42
+ order: page.order,
43
+ children: Object.freeze([]),
44
+ });
45
+ }
46
+ function compareNode(left, right) {
47
+ return left.order - right.order
48
+ || left.type.localeCompare(right.type)
49
+ || left.id.localeCompare(right.id);
50
+ }
51
+ function requiredPlugin(snapshot, id) {
52
+ const node = snapshot.tree.get(id);
53
+ if (!node)
54
+ throw new Error(`Unknown Plugin in Console tree: ${id}`);
55
+ return node;
56
+ }
57
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/plugin-runtime/navigation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/pagemanager",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "Zhin PageManager Host runtime: entries, esbuild pipeline (no UI; contract in @zhin.js/contract)",
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,6 +13,16 @@
13
13
  "types": "./lib/node/index.d.ts",
14
14
  "import": "./lib/node/index.js",
15
15
  "default": "./lib/node/index.js"
16
+ },
17
+ "./plugin-runtime": {
18
+ "types": "./lib/plugin-runtime/index.d.ts",
19
+ "development": "./src/plugin-runtime/index.ts",
20
+ "import": "./lib/plugin-runtime/index.js"
21
+ },
22
+ "./client-build": {
23
+ "types": "./lib/client-build/index.d.ts",
24
+ "development": "./src/client-build/index.ts",
25
+ "import": "./lib/client-build/index.js"
16
26
  }
17
27
  },
18
28
  "dependencies": {
@@ -21,7 +31,11 @@
21
31
  "koa": "^3.2.1",
22
32
  "koa-compose": "^4.1.0",
23
33
  "koa-static": "^5.0.0",
24
- "@zhin.js/contract": "1.0.3"
34
+ "@zhin.js/contract": "1.0.4",
35
+ "@zhin.js/console-contract": "1.0.0",
36
+ "@zhin.js/layout": "1.0.1",
37
+ "@zhin.js/page": "1.0.1",
38
+ "@zhin.js/plugin-runtime": "1.0.1"
25
39
  },
26
40
  "devDependencies": {
27
41
  "@types/koa": "^3.0.3",
@@ -30,7 +44,17 @@
30
44
  "@types/koa__router": "^12.0.4",
31
45
  "@types/node": "^26.1.0",
32
46
  "rimraf": "^6.0.1",
33
- "typescript": "^6.0.2"
47
+ "typescript": "^6.0.2",
48
+ "@zhin.js/feature-kit": "1.0.1",
49
+ "@zhin.js/runtime": "1.0.1"
50
+ },
51
+ "peerDependencies": {
52
+ "typescript": ">=5.8.0 <7.0.0"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "typescript": {
56
+ "optional": true
57
+ }
34
58
  },
35
59
  "files": [
36
60
  "lib"