@powerhousedao/reactor-api 6.2.2-dev.8 → 6.2.2-dev.80

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.
@@ -1,8 +1,8 @@
1
1
 
2
2
  !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c7cff29c-399f-5fdb-84b9-d0be2e6093bb")}catch(e){}}();
3
+ import { pathToFileURL } from "node:url";
3
4
  import { get } from "node:http";
4
5
  import { get as get$1 } from "node:https";
5
- import { pathToFileURL } from "node:url";
6
6
  //#region src/packages/https-hooks.mts
7
7
  /**
8
8
  * Resolve hook: resolves relative specifiers against HTTP/HTTPS parent URLs.
@@ -1,6 +1,6 @@
1
- import { a as ISubscribablePackageLoader, o as ISubscriptionOptions } from "../../types-DnHgkahK.mjs";
1
+ import { a as ISubscribablePackageLoader, o as ISubscriptionOptions } from "../../types-D2ZrjmCk.mjs";
2
2
  import { ILogger } from "document-model";
3
- import { DocumentModelModule } from "@powerhousedao/shared/document-model";
3
+ import { DocumentModelModule, UpgradeManifest } from "@powerhousedao/shared/document-model";
4
4
  import { Logger, ViteDevServer } from "vite";
5
5
  import { ProcessorFactoryBuilder, SubgraphClass } from "@powerhousedao/reactor-api";
6
6
 
@@ -17,6 +17,7 @@ declare class VitePackageLoader implements ISubscribablePackageLoader {
17
17
  private getSubgraphsPath;
18
18
  private getProcessorsPath;
19
19
  loadDocumentModels(identifier: string, immediate?: boolean): Promise<DocumentModelModule[]>;
20
+ loadUpgradeManifests(identifier: string): Promise<UpgradeManifest<readonly number[]>[]>;
20
21
  loadSubgraphs(identifier: string): Promise<SubgraphClass[]>;
21
22
  loadProcessors(identifier: string): Promise<ProcessorFactoryBuilder | null>;
22
23
  onDocumentModelsChange(identifier: string, handler: (documentModels: DocumentModelModule[]) => void, options?: ISubscriptionOptions): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"vite-loader.d.mts","names":[],"sources":["../../../src/packages/vite-loader.mts"],"mappings":";;;;;;;iBAkBgB,gBAAA,CAAiB,MAAA,EAAQ,OAAA,EAAS,MAAA,YAAW,MAAA;AAAA,cAUhD,iBAAA,YAA6B,0BAAA;EAAA;mBACvB,MAAA;EAAA,iBAEA,IAAA;EAAA,SAER,IAAA;EAAA,OAEF,KAAA,CAAM,IAAA,EAAM,aAAA,GAAa,iBAAA;cAIpB,IAAA,EAAM,aAAA;EAAA,QAIV,qBAAA;EAAA,QAIA,gBAAA;EAAA,QAIA,iBAAA;EAID,kBAAA,CAAmB,UAAA,UAAoB,SAAA,aAAiB,OAAA,CAAA,mBAAA;EA2CzD,aAAA,CAAc,UAAA,WAAqB,OAAA,CAAQ,aAAA;EA4B3C,cAAA,CACJ,UAAA,WACC,OAAA,CAAQ,uBAAA;EA+BX,sBAAA,CACE,UAAA,UACA,OAAA,GAAU,cAAA,EAAgB,mBAAA,aAC1B,OAAA,GAAU,oBAAA;EAiBZ,iBAAA,CACE,UAAA,UACA,OAAA,GAAU,SAAA,EAAW,aAAA,aACrB,OAAA,GAAU,oBAAA;EAgBZ,kBAAA,CACE,UAAA,UACA,OAAA,GAAU,UAAA,EAAY,uBAAA,kBACtB,OAAA,GAAU,oBAAA;AAAA;AAAA,iBAiBQ,eAAA,CAAgB,IAAA,UAAc,MAAA,GAAS,MAAA,GAAM,OAAA,CAAA,aAAA"}
1
+ {"version":3,"file":"vite-loader.d.mts","names":[],"sources":["../../../src/packages/vite-loader.mts"],"mappings":";;;;;;;iBAqBgB,gBAAA,CAAiB,MAAA,EAAQ,OAAA,EAAS,MAAA,YAAW,MAAA;AAAA,cAUhD,iBAAA,YAA6B,0BAAA;EAAA;mBACvB,MAAA;EAAA,iBAEA,IAAA;EAAA,SAER,IAAA;EAAA,OAEF,KAAA,CAAM,IAAA,EAAM,aAAA,GAAa,iBAAA;cAIpB,IAAA,EAAM,aAAA;EAAA,QAIV,qBAAA;EAAA,QAIA,gBAAA;EAAA,QAIA,iBAAA;EAID,kBAAA,CAAmB,UAAA,UAAoB,SAAA,aAAiB,OAAA,CAAA,mBAAA;EA2CzD,oBAAA,CACJ,UAAA,WACC,OAAA,CAAQ,eAAA;EA+BL,aAAA,CAAc,UAAA,WAAqB,OAAA,CAAQ,aAAA;EA4B3C,cAAA,CACJ,UAAA,WACC,OAAA,CAAQ,uBAAA;EA+BX,sBAAA,CACE,UAAA,UACA,OAAA,GAAU,cAAA,EAAgB,mBAAA,aAC1B,OAAA,GAAU,oBAAA;EAiBZ,iBAAA,CACE,UAAA,UACA,OAAA,GAAU,SAAA,EAAW,aAAA,aACrB,OAAA,GAAU,oBAAA;EAgBZ,kBAAA,CACE,UAAA,UACA,OAAA,GAAU,UAAA,EAAY,uBAAA,kBACtB,OAAA,GAAU,oBAAA;AAAA;AAAA,iBAiBQ,eAAA,CAAgB,IAAA,UAAc,MAAA,GAAS,MAAA,GAAM,OAAA,CAAA,aAAA"}
@@ -1,6 +1,6 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="02fc7276-e4d6-5195-b4ce-5791df961225")}catch(e){}}();
3
- import { a as isSubgraphClass, o as debounce, s as isSubpath } from "../../utils-iibOQ50e.mjs";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0af2e909-88fa-5cc5-b995-62cb8a98d61d")}catch(e){}}();
3
+ import { a as isSubgraphClass, c as isSubpath, o as debounce, s as extractUpgradeManifests } from "../../utils-lHoPB-ft.mjs";
4
4
  import { childLogger } from "document-model";
5
5
  import path from "node:path";
6
6
  import { viteCommonjs } from "@originjs/vite-plugin-commonjs";
@@ -25,13 +25,13 @@ var VitePackageLoader = class VitePackageLoader {
25
25
  this.vite = vite;
26
26
  }
27
27
  getDocumentModelsPath(identifier) {
28
- return path.join(identifier, "./document-models");
28
+ return path.posix.join(identifier, "./document-models");
29
29
  }
30
30
  getSubgraphsPath(identifier) {
31
- return path.join(identifier, "./subgraphs");
31
+ return path.posix.join(identifier, "./subgraphs");
32
32
  }
33
33
  getProcessorsPath(identifier) {
34
- return path.join(identifier, "./processors");
34
+ return path.posix.join(identifier, "./processors");
35
35
  }
36
36
  loadDocumentModels(identifier, immediate = false) {
37
37
  return this.#loadDocumentModelsWithDebounce(immediate, identifier);
@@ -52,6 +52,19 @@ var VitePackageLoader = class VitePackageLoader {
52
52
  }
53
53
  return [];
54
54
  }
55
+ async loadUpgradeManifests(identifier) {
56
+ const candidatePaths = [this.getDocumentModelsPath(identifier), path.posix.join(this.getDocumentModelsPath(identifier), "upgrade-manifests")];
57
+ for (const fullPath of candidatePaths) try {
58
+ const manifests = extractUpgradeManifests(await this.vite.ssrLoadModule(fullPath));
59
+ if (manifests.length > 0) {
60
+ this.logger.verbose(` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`);
61
+ return manifests;
62
+ }
63
+ } catch (e) {
64
+ this.logger.debug(` ➜ No Upgrade Manifests found at ${fullPath} for: ${identifier}`, e);
65
+ }
66
+ return [];
67
+ }
55
68
  async loadSubgraphs(identifier) {
56
69
  const fullPath = this.getSubgraphsPath(identifier);
57
70
  this.logger.verbose("Loading subgraphs from", fullPath);
@@ -96,9 +109,9 @@ var VitePackageLoader = class VitePackageLoader {
96
109
  }
97
110
  onSubgraphsChange(identifier, handler, options) {
98
111
  const subgraphsPath = this.getSubgraphsPath(identifier);
99
- const listener = debounce(async (changedPath) => {
112
+ const listener = async (changedPath) => {
100
113
  if (isSubpath(subgraphsPath, changedPath)) handler(await this.loadSubgraphs(identifier));
101
- }, options?.debounce ?? 100);
114
+ };
102
115
  this.vite.watcher.on("change", listener);
103
116
  return () => {
104
117
  this.vite.watcher.off("change", listener);
@@ -142,4 +155,4 @@ async function startViteServer(root, logger) {
142
155
  export { VitePackageLoader, createViteLogger, startViteServer };
143
156
 
144
157
  //# sourceMappingURL=vite-loader.mjs.map
145
- //# debugId=02fc7276-e4d6-5195-b4ce-5791df961225
158
+ //# debugId=0af2e909-88fa-5cc5-b995-62cb8a98d61d
@@ -1 +1 @@
1
- {"version":3,"file":"vite-loader.mjs","sources":["../../../src/packages/vite-loader.mts"],"sourcesContent":["import { viteCommonjs } from \"@originjs/vite-plugin-commonjs\";\nimport type {\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { childLogger, type ILogger } from \"document-model\";\nimport path from \"node:path\";\nimport { readPackage } from \"read-pkg\";\nimport type { Logger, PluginOption, ViteDevServer } from \"vite\";\nimport { createLogger, createServer } from \"vite\";\nimport { isSubgraphClass } from \"../graphql/utils.js\";\nimport type {\n ISubscribablePackageLoader,\n ISubscriptionOptions,\n} from \"./types.js\";\nimport { debounce, isSubpath } from \"./util.js\";\n\nexport function createViteLogger(logger: ILogger, prefix = \"\") {\n const customLogger = createLogger(\"info\", {\n prefix,\n });\n customLogger.info = logger.info;\n customLogger.warn = logger.warn;\n customLogger.error = logger.error;\n return customLogger;\n}\n\nexport class VitePackageLoader implements ISubscribablePackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"vite-loader\"]);\n\n private readonly vite: ViteDevServer;\n\n readonly name = \"VitePackageLoader\";\n\n static build(vite: ViteDevServer) {\n return new VitePackageLoader(vite);\n }\n\n constructor(vite: ViteDevServer) {\n this.vite = vite;\n }\n\n private getDocumentModelsPath(identifier: string): string {\n return path.join(identifier, \"./document-models\");\n }\n\n private getSubgraphsPath(identifier: string): string {\n return path.join(identifier, \"./subgraphs\");\n }\n\n private getProcessorsPath(identifier: string): string {\n return path.join(identifier, \"./processors\");\n }\n\n public loadDocumentModels(identifier: string, immediate = false) {\n return this.#loadDocumentModelsWithDebounce(immediate, identifier);\n }\n\n #loadDocumentModelsWithDebounce = debounce(\n this.#loadDocumentModels.bind(this),\n 500,\n );\n\n async #loadDocumentModels(\n identifier: string,\n ): Promise<DocumentModelModule[]> {\n const fullPath = this.getDocumentModelsPath(identifier);\n this.logger.debug(\"Loading document models from\", fullPath);\n\n try {\n const localDMs = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n DocumentModelModule\n >;\n\n const exports = Object.values(localDMs);\n\n // duck type\n const documentModels: DocumentModelModule[] = [];\n for (const dm of exports) {\n if (dm.documentModel) {\n documentModels.push(dm);\n }\n }\n\n this.logger.verbose(\n ` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`,\n );\n\n return documentModels;\n } catch (e) {\n this.logger.debug(` ➜ No Document Models found for: ${identifier}`, e);\n }\n\n return [];\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n const fullPath = this.getSubgraphsPath(identifier);\n\n this.logger.verbose(\"Loading subgraphs from\", fullPath);\n\n let localSubgraphs: Record<string, Record<string, SubgraphClass>> = {};\n try {\n localSubgraphs = await this.vite.ssrLoadModule(fullPath);\n } catch (e) {\n this.logger.debug(` ➜ No Subgraphs found for: ${identifier}`, e);\n return [];\n }\n\n const subgraphs: SubgraphClass[] = [];\n for (const [name, subgraph] of Object.entries(localSubgraphs)) {\n const SubgraphClass = subgraph[name];\n if (isSubgraphClass(SubgraphClass)) {\n subgraphs.push(SubgraphClass);\n }\n }\n\n this.logger.debug(\n ` ➜ Loaded ${subgraphs.length} Subgraphs from: ${identifier}`,\n );\n\n return subgraphs;\n }\n\n async loadProcessors(\n identifier: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n const fullPath = this.getProcessorsPath(identifier);\n\n this.logger.verbose(\"Loading processors from\", fullPath);\n\n try {\n const pkgModule = await this.vite.ssrLoadModule(fullPath);\n\n const factory = (\n pkgModule as Record<string, ProcessorFactoryBuilder | undefined>\n )?.processorFactory;\n\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(\n ` ➜ Loaded Processor Factory from: ${identifier}`,\n );\n return factory;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Processor Factory found for: ${identifier}`,\n e,\n );\n }\n\n this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);\n\n // return empty processor factory\n return null;\n }\n\n onDocumentModelsChange(\n identifier: string,\n handler: (documentModels: DocumentModelModule[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const listener = async (changedPath: string) => {\n const documentModelsPath = this.getDocumentModelsPath(identifier);\n if (isSubpath(documentModelsPath, changedPath)) {\n const documentModels = await this.loadDocumentModels(identifier);\n handler(documentModels);\n }\n };\n\n this.vite.watcher.on(\"change\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n };\n }\n\n onSubgraphsChange(\n identifier: string,\n handler: (subgraphs: SubgraphClass[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const subgraphsPath = this.getSubgraphsPath(identifier);\n const listener = debounce(async (changedPath: string) => {\n if (isSubpath(subgraphsPath, changedPath)) {\n const subgraphs = await this.loadSubgraphs(identifier);\n handler(subgraphs);\n }\n }, options?.debounce ?? 100);\n this.vite.watcher.on(\"change\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n };\n }\n\n onProcessorsChange(\n identifier: string,\n handler: (processors: ProcessorFactoryBuilder | null) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const processorsPath = this.getProcessorsPath(identifier);\n const listener = async (changedPath: string) => {\n if (isSubpath(processorsPath, changedPath)) {\n const processors = await this.loadProcessors(identifier);\n handler(processors);\n }\n };\n this.vite.watcher.on(\"change\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n };\n }\n}\n\nexport async function startViteServer(root: string, logger?: Logger) {\n const packageJson = await readPackage({ cwd: root });\n\n const vite = await createServer({\n root,\n configFile: false,\n logger,\n server: { middlewareMode: true, watch: { ignored: [\"**/.ph/**\"] } },\n appType: \"custom\",\n build: {\n rollupOptions: {\n input: [],\n },\n },\n resolve: {\n tsconfigPaths: true,\n alias: {\n [packageJson.name]: root,\n },\n },\n plugins: [\n // cast: the plugin ships types built against an older vite, and the\n // mismatched Plugin type crashes tsc 6 during assignability checking\n viteCommonjs() as PluginOption,\n {\n name: \"suppress-hmr\",\n handleHotUpdate() {\n return []; // return empty array to suppress server refresh\n },\n },\n ],\n });\n\n return vite;\n}\n"],"names":["#loadDocumentModelsWithDebounce","#loadDocumentModels"],"mappings":"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","debug_id":"02fc7276-e4d6-5195-b4ce-5791df961225"}
1
+ {"version":3,"file":"vite-loader.mjs","sources":["../../../src/packages/vite-loader.mts"],"sourcesContent":["import { viteCommonjs } from \"@originjs/vite-plugin-commonjs\";\nimport type {\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger, type ILogger } from \"document-model\";\nimport path from \"node:path\";\nimport { readPackage } from \"read-pkg\";\nimport type { Logger, PluginOption, ViteDevServer } from \"vite\";\nimport { createLogger, createServer } from \"vite\";\nimport { isSubgraphClass } from \"../graphql/utils.js\";\nimport type {\n ISubscribablePackageLoader,\n ISubscriptionOptions,\n} from \"./types.js\";\nimport { debounce, extractUpgradeManifests, isSubpath } from \"./util.js\";\n\nexport function createViteLogger(logger: ILogger, prefix = \"\") {\n const customLogger = createLogger(\"info\", {\n prefix,\n });\n customLogger.info = logger.info;\n customLogger.warn = logger.warn;\n customLogger.error = logger.error;\n return customLogger;\n}\n\nexport class VitePackageLoader implements ISubscribablePackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"vite-loader\"]);\n\n private readonly vite: ViteDevServer;\n\n readonly name = \"VitePackageLoader\";\n\n static build(vite: ViteDevServer) {\n return new VitePackageLoader(vite);\n }\n\n constructor(vite: ViteDevServer) {\n this.vite = vite;\n }\n\n private getDocumentModelsPath(identifier: string): string {\n return path.posix.join(identifier, \"./document-models\");\n }\n\n private getSubgraphsPath(identifier: string): string {\n return path.posix.join(identifier, \"./subgraphs\");\n }\n\n private getProcessorsPath(identifier: string): string {\n return path.posix.join(identifier, \"./processors\");\n }\n\n public loadDocumentModels(identifier: string, immediate = false) {\n return this.#loadDocumentModelsWithDebounce(immediate, identifier);\n }\n\n #loadDocumentModelsWithDebounce = debounce(\n this.#loadDocumentModels.bind(this),\n 500,\n );\n\n async #loadDocumentModels(\n identifier: string,\n ): Promise<DocumentModelModule[]> {\n const fullPath = this.getDocumentModelsPath(identifier);\n this.logger.debug(\"Loading document models from\", fullPath);\n\n try {\n const localDMs = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n DocumentModelModule\n >;\n\n const exports = Object.values(localDMs);\n\n // duck type\n const documentModels: DocumentModelModule[] = [];\n for (const dm of exports) {\n if (dm.documentModel) {\n documentModels.push(dm);\n }\n }\n\n this.logger.verbose(\n ` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`,\n );\n\n return documentModels;\n } catch (e) {\n this.logger.debug(` ➜ No Document Models found for: ${identifier}`, e);\n }\n\n return [];\n }\n\n async loadUpgradeManifests(\n identifier: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n // Projects generated before the aggregate index re-exported the\n // manifests only expose them at document-models/upgrade-manifests, so\n // try both without requiring a regeneration.\n const candidatePaths = [\n this.getDocumentModelsPath(identifier),\n path.posix.join(this.getDocumentModelsPath(identifier), \"upgrade-manifests\"),\n ];\n for (const fullPath of candidatePaths) {\n try {\n const namespace = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n unknown\n >;\n const manifests = extractUpgradeManifests(namespace);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n return manifests;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Upgrade Manifests found at ${fullPath} for: ${identifier}`,\n e,\n );\n }\n }\n return [];\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n const fullPath = this.getSubgraphsPath(identifier);\n\n this.logger.verbose(\"Loading subgraphs from\", fullPath);\n\n let localSubgraphs: Record<string, Record<string, SubgraphClass>> = {};\n try {\n localSubgraphs = await this.vite.ssrLoadModule(fullPath);\n } catch (e) {\n this.logger.debug(` ➜ No Subgraphs found for: ${identifier}`, e);\n return [];\n }\n\n const subgraphs: SubgraphClass[] = [];\n for (const [name, subgraph] of Object.entries(localSubgraphs)) {\n const SubgraphClass = subgraph[name];\n if (isSubgraphClass(SubgraphClass)) {\n subgraphs.push(SubgraphClass);\n }\n }\n\n this.logger.debug(\n ` ➜ Loaded ${subgraphs.length} Subgraphs from: ${identifier}`,\n );\n\n return subgraphs;\n }\n\n async loadProcessors(\n identifier: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n const fullPath = this.getProcessorsPath(identifier);\n\n this.logger.verbose(\"Loading processors from\", fullPath);\n\n try {\n const pkgModule = await this.vite.ssrLoadModule(fullPath);\n\n const factory = (\n pkgModule as Record<string, ProcessorFactoryBuilder | undefined>\n )?.processorFactory;\n\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(\n ` ➜ Loaded Processor Factory from: ${identifier}`,\n );\n return factory;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Processor Factory found for: ${identifier}`,\n e,\n );\n }\n\n this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);\n\n // return empty processor factory\n return null;\n }\n\n onDocumentModelsChange(\n identifier: string,\n handler: (documentModels: DocumentModelModule[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const listener = async (changedPath: string) => {\n const documentModelsPath = this.getDocumentModelsPath(identifier);\n if (isSubpath(documentModelsPath, changedPath)) {\n const documentModels = await this.loadDocumentModels(identifier);\n handler(documentModels);\n }\n };\n\n this.vite.watcher.on(\"change\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n };\n }\n\n onSubgraphsChange(\n identifier: string,\n handler: (subgraphs: SubgraphClass[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const subgraphsPath = this.getSubgraphsPath(identifier);\n const listener = async (changedPath: string) => {\n if (isSubpath(subgraphsPath, changedPath)) {\n const subgraphs = await this.loadSubgraphs(identifier);\n handler(subgraphs);\n }\n };\n this.vite.watcher.on(\"change\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n };\n }\n\n onProcessorsChange(\n identifier: string,\n handler: (processors: ProcessorFactoryBuilder | null) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const processorsPath = this.getProcessorsPath(identifier);\n const listener = async (changedPath: string) => {\n if (isSubpath(processorsPath, changedPath)) {\n const processors = await this.loadProcessors(identifier);\n handler(processors);\n }\n };\n this.vite.watcher.on(\"change\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n };\n }\n}\n\nexport async function startViteServer(root: string, logger?: Logger) {\n const packageJson = await readPackage({ cwd: root });\n\n const vite = await createServer({\n root,\n configFile: false,\n logger,\n server: { middlewareMode: true, watch: { ignored: [\"**/.ph/**\"] } },\n appType: \"custom\",\n build: {\n rollupOptions: {\n input: [],\n },\n },\n resolve: {\n tsconfigPaths: true,\n alias: {\n [packageJson.name]: root,\n },\n },\n plugins: [\n // cast: the plugin ships types built against an older vite, and the\n // mismatched Plugin type crashes tsc 6 during assignability checking\n viteCommonjs() as PluginOption,\n {\n name: \"suppress-hmr\",\n handleHotUpdate() {\n return []; // return empty array to suppress server refresh\n },\n },\n ],\n });\n\n return vite;\n}\n"],"names":["#loadDocumentModelsWithDebounce","#loadDocumentModels"],"mappings":"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","debug_id":"0af2e909-88fa-5cc5-b995-62cb8a98d61d"}
@@ -1,11 +1,16 @@
1
1
  import { ILogger } from "document-model";
2
- import { DocumentModelModule } from "@powerhousedao/shared/document-model";
2
+ import { DocumentModelModule, UpgradeManifest } from "@powerhousedao/shared/document-model";
3
3
  import { ProcessorFactoryBuilder, SubgraphClass } from "@powerhousedao/reactor-api";
4
4
 
5
5
  //#region src/packages/types.d.ts
6
6
  interface IPackageLoader {
7
7
  name: string;
8
8
  loadDocumentModels(identifier: string, immediate?: boolean): Promise<DocumentModelModule[]>;
9
+ /**
10
+ * Loads the upgrade manifests a package exports alongside its document
11
+ * models. Optional: loaders that predate versioned models may omit it.
12
+ */
13
+ loadUpgradeManifests?(identifier: string): Promise<UpgradeManifest<readonly number[]>[]>;
9
14
  loadSubgraphs(identifier: string, immediate?: boolean): Promise<SubgraphClass[]>;
10
15
  loadProcessors(identifier: string, immediate?: boolean): Promise<ProcessorFactoryBuilder | null>;
11
16
  }
@@ -29,9 +34,10 @@ type IPackageManagerOptions = {
29
34
  };
30
35
  type PackageManagerResult = {
31
36
  documentModels: DocumentModelModule[];
37
+ upgradeManifests: UpgradeManifest<readonly number[]>[];
32
38
  subgraphs: Map<string, SubgraphClass[]>;
33
39
  processors: Map<string, ProcessorFactoryBuilder[]>;
34
40
  };
35
41
  //#endregion
36
42
  export { ISubscribablePackageLoader as a, IPackageManagerOptions as i, IPackageLoaderOptions as n, ISubscriptionOptions as o, IPackageManager as r, PackageManagerResult as s, IPackageLoader as t };
37
- //# sourceMappingURL=types-DnHgkahK.d.mts.map
43
+ //# sourceMappingURL=types-D2ZrjmCk.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-D2ZrjmCk.d.mts","names":[],"sources":["../src/packages/types.ts"],"mappings":";;;;;UAUiB,cAAA;EACf,IAAA;EACA,kBAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,mBAAA;EALkB;;;;EAU7B,oBAAA,EACE,UAAA,WACC,OAAA,CAAQ,eAAA;EACX,aAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,aAAA;EACX,cAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,uBAAA;AAAA;AAAA,UAGI,oBAAA;EACf,QAAA;AAAA;AAAA,UAGe,0BAAA,SAAmC,cAAA;EAClD,sBAAA,EACE,UAAA,UACA,OAAA,GAAU,cAAA,EAAgB,mBAAA,aAC1B,OAAA,GAAU,oBAAA;EAEZ,iBAAA,EACE,UAAA,UACA,OAAA,GAAU,SAAA,EAAW,aAAA,aACrB,OAAA,GAAU,oBAAA;EAEZ,kBAAA,EACE,UAAA,UACA,OAAA,GAAU,UAAA,EAAY,uBAAA,kBACtB,OAAA,GAAU,oBAAA;AAAA;AAAA,UAIG,eAAA;EACf,sBAAA,CACE,OAAA,GAAU,cAAA,EAAgB,MAAA,SAAe,mBAAA;AAAA;AAAA,KAIjC,qBAAA;EACV,MAAA,GAAS,OAAA;AAAA;AAAA,KAGC,sBAAA;EACV,QAAA;EACA,UAAA;AAAA;AAAA,KAWU,oBAAA;EACV,cAAA,EAAgB,mBAAA;EAChB,gBAAA,EAAkB,eAAA;EAClB,SAAA,EAAW,GAAA,SAAY,aAAA;EACvB,UAAA,EAAY,GAAA,SAAY,uBAAA;AAAA"}
@@ -1,10 +1,11 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bb45ff30-0d48-5614-9063-64b33d486341")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b3b52862-3211-5b26-8234-217f98a3e3a5")}catch(e){}}();
3
3
  import { gql } from "graphql-tag";
4
4
  import { GraphQLError } from "graphql";
5
- import { DRIVE_AUTH_ERROR_MESSAGES } from "@powerhousedao/reactor";
5
+ import { DRIVE_AUTH_ERROR_MESSAGES, RECOVERABLE_GRAPHQL_ERROR_CODES } from "@powerhousedao/reactor";
6
6
  import { childLogger } from "document-model";
7
7
  import path from "node:path";
8
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
9
  //#region src/graphql/errors.ts
9
10
  /** Caller (authenticated or anonymous) lacks permission for the document. */
10
11
  var ForbiddenError = class extends GraphQLError {
@@ -20,6 +21,45 @@ var AuthenticationRequiredError = class extends GraphQLError {
20
21
  super(`${base}${detail ? ` ${detail}` : ""}`, { extensions: { code: "UNAUTHENTICATED" } });
21
22
  }
22
23
  };
24
+ /**
25
+ * The reactor holds no decision model, so no authorization preflight can be
26
+ * answered.
27
+ *
28
+ * Distinct from a denial, and deliberately so: a caller that cannot get a
29
+ * prediction should render its controls as it did before it asked and let the
30
+ * submit path refuse. Reading this as a denial would disable every control on a
31
+ * switchboard running without authEnforcement. The code is what a client
32
+ * branches on, since the message is not a contract.
33
+ */
34
+ var AuthEvaluationUnsupportedError = class extends GraphQLError {
35
+ constructor() {
36
+ super("Authorization evaluation is unavailable: this reactor runs without the authEnforcement feature flag, so it holds no decision model", { extensions: { code: "AUTH_EVALUATION_UNSUPPORTED" } });
37
+ }
38
+ };
39
+ /**
40
+ * A stored operation cannot be represented in the schema, so it is reported
41
+ * rather than served.
42
+ *
43
+ * The schema declares an action's id, type, timestamp, input and scope
44
+ * non-null; an operation written before the API rejected an action without an
45
+ * id violates that. Left to the executor, the missing value nullifies the
46
+ * action, which bubbles up through the non-null chain until it nullifies the
47
+ * envelope's whole operation list, and the caller receives a partial response
48
+ * beside "Cannot return null for non-nullable field Action.id" - which says
49
+ * nothing about which operation, and which a sync client can only read as a
50
+ * permanent GraphQL rejection, stopping its poll timer for good.
51
+ *
52
+ * Thrown instead, with a code that says the failure is worth polling through:
53
+ * the document holding the operation needs repairing, but the channel serves
54
+ * every other document, and a peer that stopped polling would stop receiving
55
+ * those too. The code is what a client branches on, since the message is not a
56
+ * contract.
57
+ */
58
+ var MalformedStoredOperationError = class extends GraphQLError {
59
+ constructor(detail) {
60
+ super(`Stored operation cannot be served: ${detail}`, { extensions: { code: RECOVERABLE_GRAPHQL_ERROR_CODES.malformedStoredOperation } });
61
+ }
62
+ };
23
63
  //#endregion
24
64
  //#region src/services/authorization.service.ts
25
65
  /**
@@ -197,6 +237,36 @@ function createAuthorizationService(config, documentPermissionService, getParent
197
237
  return new DocumentPermissionsAuthorizationService(documentPermissionService, getParentIds, config);
198
238
  }
199
239
  //#endregion
240
+ //#region src/services/canonical-document-id.ts
241
+ /**
242
+ * Raised when a caller-supplied identifier cannot be resolved to a canonical
243
+ * document id. Carries no detail on purpose: resolution failures must not act
244
+ * as a document-existence oracle, so consumers map this to their generic
245
+ * fail-closed response.
246
+ */
247
+ var CanonicalDocumentIdResolutionError = class extends Error {
248
+ constructor() {
249
+ super("Document identifier could not be resolved");
250
+ this.name = "CanonicalDocumentIdResolutionError";
251
+ }
252
+ };
253
+ /**
254
+ * The sanctioned string-to-CanonicalDocumentId cast: both the GraphQL layer
255
+ * and server routes must resolve caller identifiers through this helper so
256
+ * decision and data layers always agree on the subject document.
257
+ */
258
+ function createCanonicalDocumentIdResolver(client) {
259
+ return async (identifier) => {
260
+ let resolved;
261
+ try {
262
+ resolved = await client.resolveIdOrSlug(identifier);
263
+ } catch {
264
+ throw new CanonicalDocumentIdResolutionError();
265
+ }
266
+ return resolved;
267
+ };
268
+ }
269
+ //#endregion
200
270
  //#region src/graphql/base-subgraph.ts
201
271
  var BaseSubgraph = class {
202
272
  name = "example";
@@ -213,22 +283,27 @@ var BaseSubgraph = class {
213
283
  syncManager;
214
284
  documentPermissionService;
215
285
  authorizationService;
286
+ syncServingGate;
216
287
  /**
217
288
  * Per-request memo of raw identifier to canonical document id, keyed on the
218
289
  * request context object so entries are released when the request ends. Lets
219
290
  * batch resolvers resolve each distinct identifier at most once.
220
291
  */
221
292
  #canonicalIdMemo = /* @__PURE__ */ new WeakMap();
293
+ #resolveCanonical;
222
294
  constructor(args) {
295
+ this.#resolveCanonical = createCanonicalDocumentIdResolver(args.reactorClient);
223
296
  this.reactorClient = args.reactorClient;
224
297
  this.graphqlManager = args.graphqlManager;
225
298
  this.relationalDb = args.relationalDb;
226
299
  this.syncManager = args.syncManager;
227
300
  this.documentPermissionService = args.documentPermissionService;
228
301
  this.authorizationService = args.authorizationService;
302
+ this.syncServingGate = args.syncServingGate;
229
303
  this.path = args.path ?? "";
230
304
  }
231
305
  async onSetup() {}
306
+ async onDisconnect() {}
232
307
  /**
233
308
  * Resolves a caller-supplied identifier (id or slug) to its canonical
234
309
  * document id, memoized per request. Both the decision layer and the data
@@ -245,13 +320,12 @@ var BaseSubgraph = class {
245
320
  }
246
321
  const cached = cache.get(identifier);
247
322
  if (cached !== void 0) return cached;
248
- let resolved;
323
+ let canonical;
249
324
  try {
250
- resolved = await this.reactorClient.resolveIdOrSlug(identifier);
325
+ canonical = await this.#resolveCanonical(identifier);
251
326
  } catch {
252
327
  throw new ForbiddenError();
253
328
  }
254
- const canonical = resolved;
255
329
  cache.set(identifier, canonical);
256
330
  return canonical;
257
331
  }
@@ -285,6 +359,22 @@ var BaseSubgraph = class {
285
359
  return this.authorizationService.canRead(documentId, ctx.user?.address);
286
360
  }
287
361
  /**
362
+ * The principal a request decides as: the authenticated caller's address, and
363
+ * the did:key of the app instance whose token authenticated it.
364
+ *
365
+ * Both, because a policy can name either. The key is what a document records
366
+ * as its creator, so a subject built without one cannot match the creator's
367
+ * standing permission over the auth scope -- the document's own creator would
368
+ * be refused an operation the write path accepts, since a signed action
369
+ * carries the same key. Anonymous callers supply neither.
370
+ */
371
+ viewSubject(ctx) {
372
+ return {
373
+ address: ctx.user?.address,
374
+ key: ctx.user?.appKey
375
+ };
376
+ }
377
+ /**
288
378
  * Asserts read access, resolving a slug first. Returns a handle whose
289
379
  * `fetchIdentifier` the caller reuses for the data fetch; a denial throws.
290
380
  */
@@ -328,6 +418,15 @@ var BaseSubgraph = class {
328
418
  //#endregion
329
419
  //#region src/packages/import-resolver.ts
330
420
  /**
421
+ * Imports a specifier that may be either a bare package specifier or a
422
+ * filesystem path. Absolute paths are converted to file:// URLs, because the
423
+ * ESM loader reads the drive letter in a Windows path as a URL scheme
424
+ * (`import('D:\\...')` fails with ERR_UNSUPPORTED_ESM_URL_SCHEME).
425
+ */
426
+ async function importSpecifier(target) {
427
+ return await (path.isAbsolute(target) ? import(pathToFileURL(target).href) : import(target));
428
+ }
429
+ /**
331
430
  * Attempts to import from suggested Node.js paths
332
431
  */
333
432
  async function tryNodeSuggestedPaths(packageName, subPath) {
@@ -338,10 +437,7 @@ async function tryNodeSuggestedPaths(packageName, subPath) {
338
437
  `${packageName}/dist/${subPath}.js`
339
438
  ];
340
439
  for (const suggestedPath of suggestedPaths) try {
341
- return await import(
342
- /* @vite-ignore */
343
- suggestedPath
344
- );
440
+ return await importSpecifier(suggestedPath);
345
441
  } catch {}
346
442
  return null;
347
443
  }
@@ -352,7 +448,7 @@ async function tryImportMetaResolve(packageName, subPath) {
352
448
  try {
353
449
  const resolvedUrl = import.meta.resolve?.(`${packageName}/package.json`);
354
450
  if (!resolvedUrl) return null;
355
- const packageRoot = path.dirname(new URL(resolvedUrl).pathname);
451
+ const packageRoot = path.dirname(fileURLToPath(resolvedUrl));
356
452
  const pathsToTry = [
357
453
  path.join(packageRoot, "dist", "node", subPath, "index.mjs"),
358
454
  path.join(packageRoot, "dist", "node", `${subPath}.mjs`),
@@ -362,10 +458,7 @@ async function tryImportMetaResolve(packageName, subPath) {
362
458
  path.join(packageRoot, `${subPath}.js`)
363
459
  ];
364
460
  for (const attemptPath of pathsToTry) try {
365
- return await import(
366
- /* @vite-ignore */
367
- attemptPath
368
- );
461
+ return await importSpecifier(attemptPath);
369
462
  } catch {}
370
463
  } catch {}
371
464
  return null;
@@ -401,10 +494,7 @@ function getCommonWorkspacePaths(packageName, subPath) {
401
494
  */
402
495
  async function tryWorkspacePatterns(patterns) {
403
496
  for (const workspacePath of patterns) try {
404
- return await import(
405
- /* @vite-ignore */
406
- workspacePath
407
- );
497
+ return await importSpecifier(workspacePath);
408
498
  } catch {}
409
499
  return null;
410
500
  }
@@ -448,20 +538,37 @@ async function loadProcessors(packageName) {
448
538
  * Returns null if the dependency cannot be loaded.
449
539
  */
450
540
  async function loadDependency(packageName, subPath) {
451
- const fullPath = `${packageName}/${subPath}`;
541
+ const fullPath = path.isAbsolute(packageName) ? pathToFileURL(path.join(packageName, subPath)).href : `${packageName}/${subPath}`;
452
542
  try {
453
543
  return await import(
454
544
  /* @vite-ignore */
455
545
  fullPath
456
546
  );
457
547
  } catch (e) {
458
- if (e instanceof Error && "code" in e && (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "ERR_UNSUPPORTED_DIR_IMPORT")) {
548
+ if (e instanceof Error && "code" in e && (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "ERR_UNSUPPORTED_DIR_IMPORT" || e.code === "ERR_UNSUPPORTED_ESM_URL_SCHEME")) {
459
549
  const result = await resolveLinkedPackage(packageName, subPath);
460
550
  if (result) return result;
461
551
  }
462
552
  throw e;
463
553
  }
464
554
  }
555
+ function isUpgradeManifest(value) {
556
+ return typeof value === "object" && value !== null && "documentType" in value && "supportedVersions" in value && "upgrades" in value;
557
+ }
558
+ /**
559
+ * Collects upgrade manifests from a package's document-models namespace.
560
+ * Handles both the aggregate `upgradeManifests` array export and individual
561
+ * manifest exports; dedupes by documentType.
562
+ */
563
+ function extractUpgradeManifests(namespace) {
564
+ const manifests = /* @__PURE__ */ new Map();
565
+ const add = (value) => {
566
+ if (isUpgradeManifest(value)) manifests.set(value.documentType, value);
567
+ };
568
+ for (const value of Object.values(namespace)) if (Array.isArray(value)) value.forEach(add);
569
+ else add(value);
570
+ return Array.from(manifests.values());
571
+ }
465
572
  function debounce(func, delay = 250) {
466
573
  let timer;
467
574
  return (immediate = false, ...args) => {
@@ -537,7 +644,7 @@ function buildGraphQlDriveDocument(doc) {
537
644
  };
538
645
  }
539
646
  //#endregion
540
- export { isSubgraphClass as a, loadDocumentModels as c, BaseSubgraph as d, AuthorizationPolicy as f, buildGraphqlOperations as i, loadProcessors as l, createAuthorizationService as m, buildGraphQlDriveDocument as n, debounce as o, AuthorizedDocumentHandle as p, buildGraphqlOperation as r, isSubpath as s, buildGraphQlDocument as t, loadSubgraphs as u };
647
+ export { createAuthorizationService as _, isSubgraphClass as a, MalformedStoredOperationError as b, isSubpath as c, loadSubgraphs as d, BaseSubgraph as f, AuthorizedDocumentHandle as g, AuthorizationPolicy as h, buildGraphqlOperations as i, loadDocumentModels as l, createCanonicalDocumentIdResolver as m, buildGraphQlDriveDocument as n, debounce as o, CanonicalDocumentIdResolutionError as p, buildGraphqlOperation as r, extractUpgradeManifests as s, buildGraphQlDocument as t, loadProcessors as u, AuthEvaluationUnsupportedError as v, ForbiddenError as y };
541
648
 
542
- //# sourceMappingURL=utils-iibOQ50e.mjs.map
543
- //# debugId=bb45ff30-0d48-5614-9063-64b33d486341
649
+ //# sourceMappingURL=utils-lHoPB-ft.mjs.map
650
+ //# debugId=b3b52862-3211-5b26-8234-217f98a3e3a5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-lHoPB-ft.mjs","sources":["../src/graphql/errors.ts","../src/services/authorization.service.ts","../src/services/canonical-document-id.ts","../src/graphql/base-subgraph.ts","../src/packages/import-resolver.ts","../src/packages/util.ts","../src/graphql/utils.ts"],"sourcesContent":["import { GraphQLError } from \"graphql\";\nimport {\n DRIVE_AUTH_ERROR_MESSAGES,\n RECOVERABLE_GRAPHQL_ERROR_CODES,\n} from \"@powerhousedao/reactor\";\n\n/** Caller (authenticated or anonymous) lacks permission for the document. */\nexport class ForbiddenError extends GraphQLError {\n constructor(detail = \"\") {\n const base = DRIVE_AUTH_ERROR_MESSAGES.forbidden;\n super(`${base}${detail ? ` ${detail}` : \"\"}`, {\n extensions: { code: \"FORBIDDEN\" },\n });\n }\n}\n\n/** Anonymous caller on an action that requires logging in. */\nexport class AuthenticationRequiredError extends GraphQLError {\n constructor(detail = \"\") {\n const base = DRIVE_AUTH_ERROR_MESSAGES.authenticationRequired;\n super(`${base}${detail ? ` ${detail}` : \"\"}`, {\n extensions: { code: \"UNAUTHENTICATED\" },\n });\n }\n}\n\n/**\n * The reactor holds no decision model, so no authorization preflight can be\n * answered.\n *\n * Distinct from a denial, and deliberately so: a caller that cannot get a\n * prediction should render its controls as it did before it asked and let the\n * submit path refuse. Reading this as a denial would disable every control on a\n * switchboard running without authEnforcement. The code is what a client\n * branches on, since the message is not a contract.\n */\nexport class AuthEvaluationUnsupportedError extends GraphQLError {\n constructor() {\n super(\n \"Authorization evaluation is unavailable: this reactor runs without the \" +\n \"authEnforcement feature flag, so it holds no decision model\",\n { extensions: { code: \"AUTH_EVALUATION_UNSUPPORTED\" } },\n );\n }\n}\n\n/**\n * A stored operation cannot be represented in the schema, so it is reported\n * rather than served.\n *\n * The schema declares an action's id, type, timestamp, input and scope\n * non-null; an operation written before the API rejected an action without an\n * id violates that. Left to the executor, the missing value nullifies the\n * action, which bubbles up through the non-null chain until it nullifies the\n * envelope's whole operation list, and the caller receives a partial response\n * beside \"Cannot return null for non-nullable field Action.id\" - which says\n * nothing about which operation, and which a sync client can only read as a\n * permanent GraphQL rejection, stopping its poll timer for good.\n *\n * Thrown instead, with a code that says the failure is worth polling through:\n * the document holding the operation needs repairing, but the channel serves\n * every other document, and a peer that stopped polling would stop receiving\n * those too. The code is what a client branches on, since the message is not a\n * contract.\n */\nexport class MalformedStoredOperationError extends GraphQLError {\n constructor(detail: string) {\n super(`Stored operation cannot be served: ${detail}`, {\n extensions: {\n code: RECOVERABLE_GRAPHQL_ERROR_CODES.malformedStoredOperation,\n },\n });\n }\n}\n","import type { DocumentPermissionLevel } from \"../utils/db.js\";\nimport type {\n DocumentPermissionService,\n GetParentIdsFn,\n} from \"./document-permission.service.js\";\n\n/**\n * A document id that has been resolved to its canonical form, never a slug.\n *\n * Protection and grant rows are written under the canonical id, while the\n * read/operation data paths accept an id-or-slug identifier. The decision layer\n * must key on the canonical id, so branding it forces every caller to resolve a\n * slug to its id before consulting this service, closing the slug-aliasing\n * bypass (S-C1). The only sanctioned cast from string to CanonicalDocumentId\n * lives in createCanonicalDocumentIdResolver, immediately after the shared\n * resolveIdOrSlug lookup returns.\n */\nexport type CanonicalDocumentId = string & {\n readonly __canonicalDocumentId: unique symbol;\n};\n\n/**\n * Result of a passed per-document authorization check. `fetchIdentifier` is\n * always safe for the data fetch: the canonical id when resolved, or the raw\n * identifier when the check was skipped for a policy-wide caller.\n */\nexport class AuthorizedDocumentHandle {\n private constructor(\n readonly fetchIdentifier: string,\n readonly isResolved: boolean,\n ) {}\n\n static resolved(documentId: CanonicalDocumentId): AuthorizedDocumentHandle {\n return new AuthorizedDocumentHandle(documentId, true);\n }\n\n static skipped(identifier: string): AuthorizedDocumentHandle {\n return new AuthorizedDocumentHandle(identifier, false);\n }\n\n /** The verified canonical id; throws when resolution was skipped. */\n canonicalId(): CanonicalDocumentId {\n if (!this.isResolved) {\n throw new Error(\n \"Canonical document id is unavailable: the authorization check was skipped for a policy-wide caller\",\n );\n }\n return this.fetchIdentifier as CanonicalDocumentId;\n }\n}\n\nexport const AuthorizationPolicy = {\n OPEN: \"OPEN\",\n ADMIN_ONLY: \"ADMIN_ONLY\",\n DOCUMENT_PERMISSIONS: \"DOCUMENT_PERMISSIONS\",\n} as const;\n\nexport type AuthorizationPolicy =\n (typeof AuthorizationPolicy)[keyof typeof AuthorizationPolicy];\n\nexport interface AuthorizationConfig {\n admins: string[];\n defaultProtection: boolean;\n policy: AuthorizationPolicy;\n}\n\n/**\n * Single source of truth for every permission decision. Always present (never\n * null) so callers branch on data, not on the existence of a service.\n *\n * The policy selects an implementation once at boot:\n * - OPEN: authentication disabled — everyone (incl. anonymous) is allowed.\n * - ADMIN_ONLY: authentication on, document permissions off — only ADMINS.\n * - DOCUMENT_PERMISSIONS: the full per-document protection + grant model.\n *\n * Permission inheritance walks the parent-document hierarchy through a\n * parent resolver injected at construction; callers never supply one.\n */\nexport interface IAuthorizationService {\n readonly config: AuthorizationConfig;\n\n /**\n * Whether the user has unrestricted, policy-wide access. Under OPEN this is\n * true for everyone (including anonymous callers) by design: OPEN means \"no\n * restrictions\", and consumers use this check to skip per-document\n * filtering. It does NOT mean the caller is in the ADMINS list.\n */\n isSupremeAdmin(userAddress?: string): boolean;\n\n /**\n * Whether the user may create new documents under the current policy:\n * everyone in OPEN, only admins in ADMIN_ONLY, any authenticated user in\n * DOCUMENT_PERMISSIONS.\n */\n canCreate(userAddress?: string): boolean;\n\n canRead(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n canWrite(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n /**\n * Whether the user administers the document: supreme admin, document\n * owner, or holder of an ADMIN grant.\n */\n canManage(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n canMutate(\n documentId: CanonicalDocumentId,\n operationType: string,\n userAddress?: string,\n ): Promise<boolean>;\n}\n\n/** Shared config holder and admin-list check for the policy strategies. */\nabstract class BaseAuthorizationService implements IAuthorizationService {\n constructor(readonly config: AuthorizationConfig) {}\n\n isSupremeAdmin(userAddress?: string): boolean {\n if (!userAddress) return false;\n return this.config.admins.includes(userAddress.toLowerCase());\n }\n\n abstract canCreate(userAddress?: string): boolean;\n\n abstract canRead(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n abstract canWrite(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n abstract canManage(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n abstract canMutate(\n documentId: CanonicalDocumentId,\n operationType: string,\n userAddress?: string,\n ): Promise<boolean>;\n}\n\n/** OPEN: authentication disabled — everyone (incl. anonymous) is allowed. */\nclass OpenAuthorizationService extends BaseAuthorizationService {\n isSupremeAdmin(): boolean {\n return true;\n }\n\n canCreate(): boolean {\n return true;\n }\n\n canRead(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n canWrite(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n canManage(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n canMutate(): Promise<boolean> {\n return Promise.resolve(true);\n }\n}\n\n/** ADMIN_ONLY: authentication on, document permissions off — only ADMINS. */\nclass AdminOnlyAuthorizationService extends BaseAuthorizationService {\n canCreate(userAddress?: string): boolean {\n return this.isSupremeAdmin(userAddress);\n }\n\n canRead(\n _documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n\n canWrite(\n _documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n\n canManage(\n _documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n\n canMutate(\n _documentId: CanonicalDocumentId,\n _operationType: string,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n}\n\nconst PERMISSION_RANK: Record<DocumentPermissionLevel, number> = {\n READ: 1,\n WRITE: 2,\n ADMIN: 3,\n};\n\nfunction satisfies(\n level: DocumentPermissionLevel | null,\n required: DocumentPermissionLevel,\n): boolean {\n return level !== null && PERMISSION_RANK[level] >= PERMISSION_RANK[required];\n}\n\n/**\n * DOCUMENT_PERMISSIONS: the full per-document protection + grant model.\n *\n * All decisions live here; DocumentPermissionService is the data-access\n * layer underneath (grants, protection rows, owners).\n */\nclass DocumentPermissionsAuthorizationService extends BaseAuthorizationService {\n readonly #permissions: DocumentPermissionService;\n readonly #getParentIds: GetParentIdsFn;\n\n constructor(\n permissions: DocumentPermissionService,\n getParentIds: GetParentIdsFn,\n config: AuthorizationConfig,\n ) {\n super(config);\n this.#permissions = permissions;\n this.#getParentIds = getParentIds;\n }\n\n canCreate(userAddress?: string): boolean {\n return this.isSupremeAdmin(userAddress) || !!userAddress;\n }\n\n canRead(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return this.#canAccess(documentId, \"READ\", userAddress);\n }\n\n canWrite(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return this.#canAccess(documentId, \"WRITE\", userAddress);\n }\n\n canManage(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return this.#isDocumentAdmin(documentId, userAddress);\n }\n\n async canMutate(\n documentId: CanonicalDocumentId,\n operationType: string,\n userAddress?: string,\n ): Promise<boolean> {\n if (this.isSupremeAdmin(userAddress)) return true;\n\n const isRestricted = await this.#permissions.isOperationRestricted(\n documentId,\n operationType,\n );\n if (isRestricted) {\n if (!userAddress) return false;\n if (await this.#isDocumentAdmin(documentId, userAddress)) return true;\n return this.#permissions.hasOperationGrant(\n documentId,\n operationType,\n userAddress,\n );\n }\n\n return this.#canAccess(documentId, \"WRITE\", userAddress);\n }\n\n /**\n * The one \"administers this document\" predicate: supreme admin, document\n * owner, or ADMIN grant on the document itself.\n */\n async #isDocumentAdmin(\n documentId: string,\n userAddress?: string,\n ): Promise<boolean> {\n if (this.isSupremeAdmin(userAddress)) return true;\n if (!userAddress) return false;\n\n const owner = await this.#permissions.getDocumentOwner(documentId);\n if (owner && owner === userAddress.toLowerCase()) return true;\n\n return satisfies(await this.#grantLevel(documentId, userAddress), \"ADMIN\");\n }\n\n /**\n * The one read/write decision shape: supreme admin → unprotected (self or\n * ancestor) → owner → inherited grant of at least the required level.\n */\n async #canAccess(\n documentId: string,\n required: DocumentPermissionLevel,\n userAddress?: string,\n ): Promise<boolean> {\n if (this.isSupremeAdmin(userAddress)) return true;\n\n const isProtected = await this.#permissions.isProtectedWithAncestors(\n documentId,\n this.#getParentIds,\n );\n if (!isProtected) return true;\n if (!userAddress) return false;\n\n const owner = await this.#permissions.getDocumentOwner(documentId);\n if (owner && owner === userAddress.toLowerCase()) return true;\n\n return this.#hasGrantInHierarchy(documentId, userAddress, required);\n }\n\n /** Best grant the user holds on the document. */\n async #grantLevel(\n documentId: string,\n userAddress: string,\n ): Promise<DocumentPermissionLevel | null> {\n return this.#permissions.getUserPermission(documentId, userAddress);\n }\n\n /**\n * Walks the parent hierarchy (with cycle protection) looking for a grant of\n * at least the required level on the document or any ancestor.\n */\n async #hasGrantInHierarchy(\n documentId: string,\n userAddress: string,\n required: DocumentPermissionLevel,\n ): Promise<boolean> {\n const visited = new Set<string>();\n const queue = [documentId];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const level = await this.#grantLevel(current, userAddress);\n if (satisfies(level, required)) return true;\n\n for (const parentId of await this.#getParentIds(current)) {\n if (!visited.has(parentId)) queue.push(parentId);\n }\n }\n\n return false;\n }\n}\n\n/**\n * Selects the strategy for the configured policy. The strategy classes are\n * not exported, so this guard is the only construction path.\n */\nexport function createAuthorizationService(\n config: AuthorizationConfig,\n documentPermissionService?: DocumentPermissionService,\n getParentIds?: GetParentIdsFn,\n): IAuthorizationService {\n if (config.policy === AuthorizationPolicy.OPEN) {\n return new OpenAuthorizationService(config);\n }\n if (config.policy === AuthorizationPolicy.ADMIN_ONLY) {\n return new AdminOnlyAuthorizationService(config);\n }\n if (!documentPermissionService) {\n throw new Error(\n \"DocumentPermissionService is required for the DOCUMENT_PERMISSIONS policy\",\n );\n }\n if (!getParentIds) {\n throw new Error(\n \"A getParentIds resolver is required for the DOCUMENT_PERMISSIONS policy\",\n );\n }\n return new DocumentPermissionsAuthorizationService(\n documentPermissionService,\n getParentIds,\n config,\n );\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport type { CanonicalDocumentId } from \"./authorization.service.js\";\n\n/**\n * Raised when a caller-supplied identifier cannot be resolved to a canonical\n * document id. Carries no detail on purpose: resolution failures must not act\n * as a document-existence oracle, so consumers map this to their generic\n * fail-closed response.\n */\nexport class CanonicalDocumentIdResolutionError extends Error {\n constructor() {\n super(\"Document identifier could not be resolved\");\n this.name = \"CanonicalDocumentIdResolutionError\";\n }\n}\n\nexport type CanonicalDocumentIdResolver = (\n identifier: string,\n) => Promise<CanonicalDocumentId>;\n\n/**\n * The sanctioned string-to-CanonicalDocumentId cast: both the GraphQL layer\n * and server routes must resolve caller identifiers through this helper so\n * decision and data layers always agree on the subject document.\n */\nexport function createCanonicalDocumentIdResolver(\n client: Pick<IReactorClient, \"resolveIdOrSlug\">,\n): CanonicalDocumentIdResolver {\n return async (identifier: string) => {\n let resolved: string;\n try {\n resolved = await client.resolveIdOrSlug(identifier);\n } catch {\n throw new CanonicalDocumentIdResolutionError();\n }\n return resolved as CanonicalDocumentId;\n };\n}\n","import type {\n IReactorClient,\n IRelationalDb,\n ISyncManager,\n SyncScopeGate,\n} from \"@powerhousedao/reactor\";\nimport type { AuthSubject } from \"@powerhousedao/shared/document-model\";\nimport type {\n GraphQLManager,\n ISubgraph,\n SubgraphArgs,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentNode } from \"graphql\";\nimport { ForbiddenError, AuthenticationRequiredError } from \"./errors.js\";\nimport { gql } from \"graphql-tag\";\nimport {\n AuthorizationPolicy,\n AuthorizedDocumentHandle,\n type CanonicalDocumentId,\n type IAuthorizationService,\n} from \"../services/authorization.service.js\";\nimport {\n createCanonicalDocumentIdResolver,\n type CanonicalDocumentIdResolver,\n} from \"../services/canonical-document-id.js\";\nimport type { DocumentPermissionService } from \"../services/document-permission.service.js\";\nimport type { Context } from \"./types.js\";\n\nexport class BaseSubgraph implements ISubgraph {\n name = \"example\";\n path = \"\";\n resolvers: Record<string, any> = {\n Query: {\n hello: () => this.name,\n },\n };\n typeDefs: DocumentNode = gql`\n type Query {\n hello: String\n }\n `;\n reactorClient: IReactorClient;\n graphqlManager: GraphQLManager;\n relationalDb: IRelationalDb;\n syncManager: ISyncManager;\n documentPermissionService?: DocumentPermissionService;\n authorizationService: IAuthorizationService;\n syncServingGate?: SyncScopeGate;\n\n /**\n * Per-request memo of raw identifier to canonical document id, keyed on the\n * request context object so entries are released when the request ends. Lets\n * batch resolvers resolve each distinct identifier at most once.\n */\n readonly #canonicalIdMemo = new WeakMap<\n object,\n Map<string, CanonicalDocumentId>\n >();\n\n readonly #resolveCanonical: CanonicalDocumentIdResolver;\n\n constructor(args: SubgraphArgs) {\n this.#resolveCanonical = createCanonicalDocumentIdResolver(\n args.reactorClient,\n );\n this.reactorClient = args.reactorClient;\n this.graphqlManager = args.graphqlManager;\n this.relationalDb = args.relationalDb;\n this.syncManager = args.syncManager;\n this.documentPermissionService = args.documentPermissionService;\n this.authorizationService = args.authorizationService;\n this.syncServingGate = args.syncServingGate;\n this.path = args.path ?? \"\";\n }\n\n async onSetup() {\n // noop\n }\n\n async onDisconnect(): Promise<void> {\n // noop\n }\n\n // ============================================\n // Shared permission helpers\n // ============================================\n\n /**\n * Resolves a caller-supplied identifier (id or slug) to its canonical\n * document id, memoized per request. Both the decision layer and the data\n * layer must agree on the subject, so this runs the same resolveIdOrSlug\n * lookup the data path uses. A resolution failure (not found, ambiguous, or\n * transient) surfaces as a generic Forbidden, fail-closed, so a bad\n * identifier cannot be used as a document-existence oracle.\n */\n async resolveCanonicalDocumentId(\n identifier: string,\n requestKey: object,\n ): Promise<CanonicalDocumentId> {\n let cache = this.#canonicalIdMemo.get(requestKey);\n if (!cache) {\n cache = new Map<string, CanonicalDocumentId>();\n this.#canonicalIdMemo.set(requestKey, cache);\n }\n\n const cached = cache.get(identifier);\n if (cached !== undefined) return cached;\n\n let canonical: CanonicalDocumentId;\n try {\n canonical = await this.#resolveCanonical(identifier);\n } catch {\n throw new ForbiddenError();\n }\n\n cache.set(identifier, canonical);\n return canonical;\n }\n\n /**\n * Resolves the args' `documentId` to canonical form. Unconditional (unlike the\n * assertCan* helpers, no admin skip): ACL rows are keyed on the canonical id.\n */\n async withCanonicalDocumentId<T extends { documentId: string }>(\n args: T,\n requestKey: object,\n ): Promise<T & { documentId: CanonicalDocumentId }> {\n const documentId = await this.resolveCanonicalDocumentId(\n args.documentId,\n requestKey,\n );\n return { ...args, documentId };\n }\n\n /**\n * Resolves an identifier for a per-document check, or null when the caller has\n * policy-wide access (OPEN or supreme admin) and the check can be skipped.\n * Only DOCUMENT_PERMISSIONS keys on the document id, so other policies fail\n * closed without resolving.\n */\n async #resolveForCheck(\n identifier: string,\n ctx: Context,\n ): Promise<CanonicalDocumentId | null> {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n return null;\n }\n if (\n this.authorizationService.config.policy !==\n AuthorizationPolicy.DOCUMENT_PERMISSIONS\n ) {\n throw new ForbiddenError();\n }\n return this.resolveCanonicalDocumentId(identifier, ctx);\n }\n\n /**\n * Read filter for an already-canonical document id (one sourced from the data\n * layer, such as a fetched document's id). Performs no slug resolution.\n */\n async canReadDocument(\n documentId: CanonicalDocumentId,\n ctx: Context,\n ): Promise<boolean> {\n return this.authorizationService.canRead(documentId, ctx.user?.address);\n }\n\n /**\n * The principal a request decides as: the authenticated caller's address, and\n * the did:key of the app instance whose token authenticated it.\n *\n * Both, because a policy can name either. The key is what a document records\n * as its creator, so a subject built without one cannot match the creator's\n * standing permission over the auth scope -- the document's own creator would\n * be refused an operation the write path accepts, since a signed action\n * carries the same key. Anonymous callers supply neither.\n */\n protected viewSubject(ctx: Context): AuthSubject {\n return { address: ctx.user?.address, key: ctx.user?.appKey };\n }\n\n /**\n * Asserts read access, resolving a slug first. Returns a handle whose\n * `fetchIdentifier` the caller reuses for the data fetch; a denial throws.\n */\n async assertCanRead(\n identifier: string,\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n const documentId = await this.#resolveForCheck(identifier, ctx);\n if (documentId === null)\n return AuthorizedDocumentHandle.skipped(identifier);\n await this.assertCanReadCanonical(documentId, ctx);\n return AuthorizedDocumentHandle.resolved(documentId);\n }\n\n async assertCanWrite(\n identifier: string,\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n const documentId = await this.#resolveForCheck(identifier, ctx);\n if (documentId === null)\n return AuthorizedDocumentHandle.skipped(identifier);\n await this.assertCanWriteCanonical(documentId, ctx);\n return AuthorizedDocumentHandle.resolved(documentId);\n }\n\n async assertCanExecuteOperation(\n identifier: string,\n operationType: string,\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n const documentId = await this.#resolveForCheck(identifier, ctx);\n if (documentId === null)\n return AuthorizedDocumentHandle.skipped(identifier);\n await this.assertCanExecuteOperationCanonical(\n documentId,\n operationType,\n ctx,\n );\n return AuthorizedDocumentHandle.resolved(documentId);\n }\n\n /**\n * Read assertion for an already-canonical document id. No slug resolution;\n * use only with ids sourced from the data layer or already resolved.\n */\n async assertCanReadCanonical(\n documentId: CanonicalDocumentId,\n ctx: Context,\n ): Promise<void> {\n const canRead = await this.authorizationService.canRead(\n documentId,\n ctx.user?.address,\n );\n if (!canRead) {\n throw new ForbiddenError(\"to read this document\");\n }\n }\n\n async assertCanWriteCanonical(\n documentId: CanonicalDocumentId,\n ctx: Context,\n ): Promise<void> {\n const canWrite = await this.authorizationService.canWrite(\n documentId,\n ctx.user?.address,\n );\n if (!canWrite) {\n throw new ForbiddenError(\"to write to this document\");\n }\n }\n\n async assertCanExecuteOperationCanonical(\n documentId: CanonicalDocumentId,\n operationType: string,\n ctx: Context,\n ): Promise<void> {\n const canMutate = await this.authorizationService.canMutate(\n documentId,\n operationType,\n ctx.user?.address,\n );\n if (!canMutate) {\n throw new ForbiddenError(\n `to execute operation \"${operationType}\" on this document`,\n );\n }\n }\n\n assertCanCreate(ctx: Context): void {\n if (this.authorizationService.canCreate(ctx.user?.address)) return;\n if (ctx.user?.address) {\n throw new ForbiddenError(\"to create documents\");\n }\n throw new AuthenticationRequiredError(\"to create documents\");\n }\n}\n","import path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n\n/**\n * Imports a specifier that may be either a bare package specifier or a\n * filesystem path. Absolute paths are converted to file:// URLs, because the\n * ESM loader reads the drive letter in a Windows path as a URL scheme\n * (`import('D:\\\\...')` fails with ERR_UNSUPPORTED_ESM_URL_SCHEME).\n */\nasync function importSpecifier<T>(target: string): Promise<T> {\n const specifier = path.isAbsolute(target)\n ? pathToFileURL(target).href\n : target;\n return (await import(/* @vite-ignore */ specifier)) as T;\n}\n\n/**\n * Attempts to import from suggested Node.js paths\n */\nasync function tryNodeSuggestedPaths<T>(\n packageName: string,\n subPath: string,\n): Promise<T | null> {\n const suggestedPaths = [\n `${packageName}/dist/node/${subPath}/index.mjs`,\n `${packageName}/dist/node/${subPath}.mjs`,\n `${packageName}/dist/${subPath}/index.js`,\n `${packageName}/dist/${subPath}.js`,\n ];\n\n for (const suggestedPath of suggestedPaths) {\n try {\n return await importSpecifier<T>(suggestedPath);\n } catch {\n // Continue to next attempt\n }\n }\n\n return null;\n}\n\n/**\n * Attempts to resolve package using import.meta.resolve\n */\nasync function tryImportMetaResolve<T>(\n packageName: string,\n subPath: string,\n): Promise<T | null> {\n try {\n const resolvedUrl = import.meta.resolve?.(`${packageName}/package.json`);\n if (!resolvedUrl) return null;\n\n // fileURLToPath, not URL.pathname: the latter yields \"/D:/...\" on Windows.\n const packageRoot = path.dirname(fileURLToPath(resolvedUrl));\n const pathsToTry = [\n path.join(packageRoot, \"dist\", \"node\", subPath, \"index.mjs\"),\n path.join(packageRoot, \"dist\", \"node\", `${subPath}.mjs`),\n path.join(packageRoot, \"dist\", subPath, \"index.js\"),\n path.join(packageRoot, \"dist\", `${subPath}.js`),\n path.join(packageRoot, subPath, \"index.js\"),\n path.join(packageRoot, `${subPath}.js`),\n ];\n\n for (const attemptPath of pathsToTry) {\n try {\n return await importSpecifier<T>(attemptPath);\n } catch {\n // Continue to next attempt\n }\n }\n } catch {\n // import.meta.resolve failed\n }\n\n return null;\n}\n\n/**\n * Resolves symlinks in node_modules to find the real package location\n */\nasync function resolveSymlinkedPaths(\n packageName: string,\n subPath: string,\n): Promise<string[]> {\n const packageBaseName = packageName.includes(\"/\")\n ? packageName.split(\"/\").pop()\n : packageName;\n const nodeModulesPatterns = [\n path.join(process.cwd(), \"node_modules\", packageName),\n path.join(process.cwd(), \"node_modules\", packageBaseName || packageName),\n ];\n\n const workspacePatterns: string[] = [];\n\n for (const nodeModulesPath of nodeModulesPatterns) {\n try {\n const fs = await import(\"node:fs\");\n if (fs.existsSync(nodeModulesPath)) {\n const realPath = fs.realpathSync(nodeModulesPath);\n\n workspacePatterns.push(\n path.join(realPath, \"dist\", \"node\", subPath, \"index.mjs\"),\n path.join(realPath, \"dist\", \"node\", `${subPath}.mjs`),\n path.join(realPath, \"dist\", subPath, \"index.js\"),\n path.join(realPath, \"dist\", `${subPath}.js`),\n path.join(realPath, subPath, \"index.js\"),\n path.join(realPath, `${subPath}.js`),\n );\n }\n } catch {\n // Continue to next attempt\n }\n }\n\n return workspacePatterns;\n}\n\n/**\n * Generates common workspace pattern paths\n */\nfunction getCommonWorkspacePaths(\n packageName: string,\n subPath: string,\n): string[] {\n const packageBaseName = packageName.includes(\"/\")\n ? packageName.split(\"/\").pop()\n : packageName;\n const commonRoots = [process.cwd(), path.dirname(process.cwd())];\n\n const workspacePatterns: string[] = [];\n for (const root of commonRoots) {\n workspacePatterns.push(\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n \"node\",\n subPath,\n \"index.mjs\",\n ),\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n \"node\",\n `${subPath}.mjs`,\n ),\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n subPath,\n \"index.js\",\n ),\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n `${subPath}.js`,\n ),\n );\n }\n\n return workspacePatterns;\n}\n\n/**\n * Attempts to import from a list of workspace patterns\n */\nasync function tryWorkspacePatterns<T>(patterns: string[]): Promise<T | null> {\n for (const workspacePath of patterns) {\n try {\n return await importSpecifier<T>(workspacePath);\n } catch {\n // Continue to next attempt\n }\n }\n\n return null;\n}\n\n/**\n * Attempts to resolve linked packages using various fallback strategies\n */\nexport async function resolveLinkedPackage<T>(\n packageName: string,\n subPath: string,\n): Promise<T | null> {\n // Try Node.js suggested paths first\n let result = await tryNodeSuggestedPaths<T>(packageName, subPath);\n if (result) return result;\n\n // Try import.meta.resolve\n result = await tryImportMetaResolve<T>(packageName, subPath);\n if (result) return result;\n\n // Try symlink resolution\n const symlinkPaths = await resolveSymlinkedPaths(packageName, subPath);\n result = await tryWorkspacePatterns<T>(symlinkPaths);\n if (result) return result;\n\n // Try common workspace patterns as final fallback\n const commonPaths = getCommonWorkspacePaths(packageName, subPath);\n result = await tryWorkspacePatterns<T>(commonPaths);\n if (result) return result;\n\n return null;\n}\n","import type {\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport { execSync } from \"node:child_process\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { resolveLinkedPackage } from \"./import-resolver.js\";\n\n// Define the expected module export structures\ntype DocumentModelsExport = Record<string, DocumentModelModule>;\ntype SubgraphsExport = Record<string, Record<string, SubgraphClass>>;\ntype ProcessorsExport = {\n processorFactory?: ProcessorFactoryBuilder;\n processorFactoryLegacy?: ProcessorFactoryBuilder;\n};\n\nconst _logger = childLogger([\"reactor-api\", \"packages/util\"]);\n\nexport const installPackages = (packages: string[]): Promise<void> => {\n for (const packageName of packages) {\n execSync(`ph install ${packageName}`);\n }\n return Promise.resolve();\n};\n\nexport const readManifest = () => {\n const manifest = execSync(`ph manifest`).toString();\n return manifest;\n};\n\n/**\n * Tries to import document models from a package. This function cannot throw.\n */\nexport async function loadDocumentModels(\n packageName: string,\n): Promise<DocumentModelsExport | null> {\n return loadDependency(packageName, \"document-models\");\n}\n\n/**\n * Tries to import subgraphs from a package. This function cannot throw.\n */\nexport async function loadSubgraphs(\n packageName: string,\n): Promise<SubgraphsExport | null> {\n return loadDependency(packageName, \"subgraphs\");\n}\n\n/**\n * Tries to import processors from a package. This function cannot throw.\n */\nexport async function loadProcessors(\n packageName: string,\n): Promise<ProcessorsExport | null> {\n return loadDependency(packageName, \"processors\");\n}\n\n/**\n * Generic dependency loader - tries to import a dependency from a package. This function cannot throw.\n * Returns null if the dependency cannot be loaded.\n */\nasync function loadDependency<T = unknown>(\n packageName: string,\n subPath: string,\n): Promise<T> {\n // A local package is identified by an absolute path, which has to become a\n // file:// URL: the ESM loader reads the drive letter in a Windows path as a\n // URL scheme.\n const fullPath = path.isAbsolute(packageName)\n ? pathToFileURL(path.join(packageName, subPath)).href\n : `${packageName}/${subPath}`;\n\n // Try the standard import first\n try {\n // vite does not support this, but that's okay as we have provided the\n // vite-loader for this purpose\n\n const module = (await import(/* @vite-ignore */ fullPath)) as T;\n return module;\n } catch (e) {\n // Handle module not found errors with fallback resolution.\n // ERR_UNSUPPORTED_ESM_URL_SCHEME joins the list because a directory\n // specifier that is a plain path fails with it on Windows where POSIX\n // reports ERR_UNSUPPORTED_DIR_IMPORT.\n if (\n e instanceof Error &&\n \"code\" in e &&\n (e.code === \"ERR_MODULE_NOT_FOUND\" ||\n e.code === \"ERR_UNSUPPORTED_DIR_IMPORT\" ||\n e.code === \"ERR_UNSUPPORTED_ESM_URL_SCHEME\")\n ) {\n const result = await resolveLinkedPackage<T>(packageName, subPath);\n if (result) return result;\n }\n throw e;\n }\n}\n\nfunction isUpgradeManifest(\n value: unknown,\n): value is UpgradeManifest<readonly number[]> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"documentType\" in value &&\n \"supportedVersions\" in value &&\n \"upgrades\" in value\n );\n}\n\n/**\n * Collects upgrade manifests from a package's document-models namespace.\n * Handles both the aggregate `upgradeManifests` array export and individual\n * manifest exports; dedupes by documentType.\n */\nexport function extractUpgradeManifests(\n namespace: Record<string, unknown>,\n): UpgradeManifest<readonly number[]>[] {\n const manifests = new Map<string, UpgradeManifest<readonly number[]>>();\n const add = (value: unknown) => {\n if (isUpgradeManifest(value)) {\n manifests.set(value.documentType, value);\n }\n };\n for (const value of Object.values(namespace)) {\n if (Array.isArray(value)) {\n value.forEach(add);\n } else {\n add(value);\n }\n }\n return Array.from(manifests.values());\n}\n\nexport function debounce<T extends unknown[], R>(\n func: (...args: T) => Promise<R>,\n delay = 250,\n) {\n let timer: number;\n return (immediate = false, ...args: T) => {\n if (timer) {\n clearTimeout(timer);\n }\n return new Promise<R>((resolve, reject) => {\n if (immediate) {\n func(...args)\n .then(resolve)\n .catch(reject);\n } else {\n timer = setTimeout(() => {\n func(...args)\n .then(resolve)\n .catch(reject);\n }, delay) as unknown as number;\n }\n });\n };\n}\n\nexport function isSubpath(parent: string, dir: string) {\n const relative = path.relative(parent, dir);\n return relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n","import type {\n GqlDocument,\n GqlDriveDocument,\n GqlOperation,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type {\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\n\nexport function isSubgraphClass(\n candidate: unknown,\n): candidate is SubgraphClass {\n if (typeof candidate !== \"function\") return false;\n\n let proto: unknown = Object.getPrototypeOf(candidate);\n while (proto) {\n if (Object.prototype.isPrototypeOf.call(proto, BaseSubgraph)) return true;\n\n proto = Object.getPrototypeOf(proto);\n }\n\n return false;\n}\n\nexport function buildGraphqlOperations(\n operations: Operation[],\n skip: number,\n first: number,\n): GqlOperation[] {\n return operations.slice(skip, skip + first).map(buildGraphqlOperation);\n}\n\nexport function buildGraphqlOperation(operation: Operation): GqlOperation {\n const signer = operation.action.context?.signer;\n return {\n id: operation.id ?? \"\",\n type: operation.action.type,\n index: operation.index,\n timestampUtcMs: operation.timestampUtcMs,\n hash: operation.hash,\n skip: operation.skip,\n inputText:\n typeof operation.action.input === \"string\"\n ? operation.action.input\n : JSON.stringify(operation.action.input),\n error: operation.error,\n context: {\n signer: signer\n ? {\n user: signer.user,\n app: signer.app,\n signatures: signer.signatures.map((sig) =>\n Array.isArray(sig) ? sig.join(\", \") : sig,\n ),\n }\n : undefined,\n },\n };\n}\n\nexport function buildGraphQlDocument(doc: PHDocument): GqlDocument {\n // Return full state with all scopes (auth, document, global, local)\n // This matches the ReactorSubgraph pattern in adapters.ts\n const state = doc.state;\n const initialState = doc.initialState;\n // For stateJSON, use global state for backward compatibility\n const globalState = \"global\" in doc.state ? doc.state.global : {};\n return {\n id: doc.header.id,\n name: doc.header.name,\n documentType: doc.header.documentType,\n revision: doc.header.revision.global || 0,\n createdAtUtcIso: doc.header.createdAtUtcIso,\n lastModifiedAtUtcIso: doc.header.lastModifiedAtUtcIso,\n operations: [],\n stateJSON: globalState as JSON,\n state,\n initialState,\n };\n}\n\nexport function buildGraphQlDriveDocument(\n doc: DocumentDriveDocument,\n): GqlDriveDocument {\n const gqlDoc = buildGraphQlDocument(doc);\n return {\n ...gqlDoc,\n meta: {\n preferredEditor: doc.header.meta?.preferredEditor,\n },\n slug: doc.header.slug,\n state: doc.state.global,\n initialState: doc.state.global,\n };\n}\n"],"names":["#permissions","#getParentIds","#canAccess","#isDocumentAdmin","#grantLevel","#hasGrantInHierarchy","#canonicalIdMemo","#resolveCanonical","#resolveForCheck"],"mappings":";;;;;;;;;;AAOA,IAAa,iBAAb,cAAoC,aAAa;CAC/C,YAAY,SAAS,IAAI;EACvB,MAAM,OAAO,0BAA0B;AACvC,QAAM,GAAG,OAAO,SAAS,IAAI,WAAW,MAAM,EAC5C,YAAY,EAAE,MAAM,aAAa,EAClC,CAAC;;;;AAKN,IAAa,8BAAb,cAAiD,aAAa;CAC5D,YAAY,SAAS,IAAI;EACvB,MAAM,OAAO,0BAA0B;AACvC,QAAM,GAAG,OAAO,SAAS,IAAI,WAAW,MAAM,EAC5C,YAAY,EAAE,MAAM,mBAAmB,EACxC,CAAC;;;;;;;;;;;;;AAcN,IAAa,iCAAb,cAAoD,aAAa;CAC/D,cAAc;AACZ,QACE,sIAEA,EAAE,YAAY,EAAE,MAAM,+BAA+B,EAAE,CACxD;;;;;;;;;;;;;;;;;;;;;;AAuBL,IAAa,gCAAb,cAAmD,aAAa;CAC9D,YAAY,QAAgB;AAC1B,QAAM,sCAAsC,UAAU,EACpD,YAAY,EACV,MAAM,gCAAgC,0BACvC,EACF,CAAC;;;;;;;;;;AC7CN,IAAa,2BAAb,MAAa,yBAAyB;CACpC,YACE,iBACA,YACA;AAFS,OAAA,kBAAA;AACA,OAAA,aAAA;;CAGX,OAAO,SAAS,YAA2D;AACzE,SAAO,IAAI,yBAAyB,YAAY,KAAK;;CAGvD,OAAO,QAAQ,YAA8C;AAC3D,SAAO,IAAI,yBAAyB,YAAY,MAAM;;;CAIxD,cAAmC;AACjC,MAAI,CAAC,KAAK,WACR,OAAM,IAAI,MACR,qGACD;AAEH,SAAO,KAAK;;;AAIhB,MAAa,sBAAsB;CACjC,MAAM;CACN,YAAY;CACZ,sBAAsB;CACvB;;AAoED,IAAe,2BAAf,MAAyE;CACvE,YAAY,QAAsC;AAA7B,OAAA,SAAA;;CAErB,eAAe,aAA+B;AAC5C,MAAI,CAAC,YAAa,QAAO;AACzB,SAAO,KAAK,OAAO,OAAO,SAAS,YAAY,aAAa,CAAC;;;;AA4BjE,IAAM,2BAAN,cAAuC,yBAAyB;CAC9D,iBAA0B;AACxB,SAAO;;CAGT,YAAqB;AACnB,SAAO;;CAGT,UAA4B;AAC1B,SAAO,QAAQ,QAAQ,KAAK;;CAG9B,WAA6B;AAC3B,SAAO,QAAQ,QAAQ,KAAK;;CAG9B,YAA8B;AAC5B,SAAO,QAAQ,QAAQ,KAAK;;CAG9B,YAA8B;AAC5B,SAAO,QAAQ,QAAQ,KAAK;;;;AAKhC,IAAM,gCAAN,cAA4C,yBAAyB;CACnE,UAAU,aAA+B;AACvC,SAAO,KAAK,eAAe,YAAY;;CAGzC,QACE,aACA,aACkB;AAClB,SAAO,QAAQ,QAAQ,KAAK,eAAe,YAAY,CAAC;;CAG1D,SACE,aACA,aACkB;AAClB,SAAO,QAAQ,QAAQ,KAAK,eAAe,YAAY,CAAC;;CAG1D,UACE,aACA,aACkB;AAClB,SAAO,QAAQ,QAAQ,KAAK,eAAe,YAAY,CAAC;;CAG1D,UACE,aACA,gBACA,aACkB;AAClB,SAAO,QAAQ,QAAQ,KAAK,eAAe,YAAY,CAAC;;;AAI5D,MAAM,kBAA2D;CAC/D,MAAM;CACN,OAAO;CACP,OAAO;CACR;AAED,SAAS,UACP,OACA,UACS;AACT,QAAO,UAAU,QAAQ,gBAAgB,UAAU,gBAAgB;;;;;;;;AASrE,IAAM,0CAAN,cAAsD,yBAAyB;CAC7E;CACA;CAEA,YACE,aACA,cACA,QACA;AACA,QAAM,OAAO;AACb,QAAA,cAAoB;AACpB,QAAA,eAAqB;;CAGvB,UAAU,aAA+B;AACvC,SAAO,KAAK,eAAe,YAAY,IAAI,CAAC,CAAC;;CAG/C,QACE,YACA,aACkB;AAClB,SAAO,MAAA,UAAgB,YAAY,QAAQ,YAAY;;CAGzD,SACE,YACA,aACkB;AAClB,SAAO,MAAA,UAAgB,YAAY,SAAS,YAAY;;CAG1D,UACE,YACA,aACkB;AAClB,SAAO,MAAA,gBAAsB,YAAY,YAAY;;CAGvD,MAAM,UACJ,YACA,eACA,aACkB;AAClB,MAAI,KAAK,eAAe,YAAY,CAAE,QAAO;AAM7C,MAJqB,MAAM,MAAA,YAAkB,sBAC3C,YACA,cACD,EACiB;AAChB,OAAI,CAAC,YAAa,QAAO;AACzB,OAAI,MAAM,MAAA,gBAAsB,YAAY,YAAY,CAAE,QAAO;AACjE,UAAO,MAAA,YAAkB,kBACvB,YACA,eACA,YACD;;AAGH,SAAO,MAAA,UAAgB,YAAY,SAAS,YAAY;;;;;;CAO1D,OAAA,gBACE,YACA,aACkB;AAClB,MAAI,KAAK,eAAe,YAAY,CAAE,QAAO;AAC7C,MAAI,CAAC,YAAa,QAAO;EAEzB,MAAM,QAAQ,MAAM,MAAA,YAAkB,iBAAiB,WAAW;AAClE,MAAI,SAAS,UAAU,YAAY,aAAa,CAAE,QAAO;AAEzD,SAAO,UAAU,MAAM,MAAA,WAAiB,YAAY,YAAY,EAAE,QAAQ;;;;;;CAO5E,OAAA,UACE,YACA,UACA,aACkB;AAClB,MAAI,KAAK,eAAe,YAAY,CAAE,QAAO;AAM7C,MAAI,CAJgB,MAAM,MAAA,YAAkB,yBAC1C,YACA,MAAA,aACD,CACiB,QAAO;AACzB,MAAI,CAAC,YAAa,QAAO;EAEzB,MAAM,QAAQ,MAAM,MAAA,YAAkB,iBAAiB,WAAW;AAClE,MAAI,SAAS,UAAU,YAAY,aAAa,CAAE,QAAO;AAEzD,SAAO,MAAA,oBAA0B,YAAY,aAAa,SAAS;;;CAIrE,OAAA,WACE,YACA,aACyC;AACzC,SAAO,MAAA,YAAkB,kBAAkB,YAAY,YAAY;;;;;;CAOrE,OAAA,oBACE,YACA,aACA,UACkB;EAClB,MAAM,0BAAU,IAAI,KAAa;EACjC,MAAM,QAAQ,CAAC,WAAW;AAE1B,SAAO,MAAM,SAAS,GAAG;GACvB,MAAM,UAAU,MAAM,OAAO;AAC7B,OAAI,QAAQ,IAAI,QAAQ,CAAE;AAC1B,WAAQ,IAAI,QAAQ;AAGpB,OAAI,UADU,MAAM,MAAA,WAAiB,SAAS,YAAY,EACrC,SAAS,CAAE,QAAO;AAEvC,QAAK,MAAM,YAAY,MAAM,MAAA,aAAmB,QAAQ,CACtD,KAAI,CAAC,QAAQ,IAAI,SAAS,CAAE,OAAM,KAAK,SAAS;;AAIpD,SAAO;;;;;;;AAQX,SAAgB,2BACd,QACA,2BACA,cACuB;AACvB,KAAI,OAAO,WAAW,oBAAoB,KACxC,QAAO,IAAI,yBAAyB,OAAO;AAE7C,KAAI,OAAO,WAAW,oBAAoB,WACxC,QAAO,IAAI,8BAA8B,OAAO;AAElD,KAAI,CAAC,0BACH,OAAM,IAAI,MACR,4EACD;AAEH,KAAI,CAAC,aACH,OAAM,IAAI,MACR,0EACD;AAEH,QAAO,IAAI,wCACT,2BACA,cACA,OACD;;;;;;;;;;AC9YH,IAAa,qCAAb,cAAwD,MAAM;CAC5D,cAAc;AACZ,QAAM,4CAA4C;AAClD,OAAK,OAAO;;;;;;;;AAahB,SAAgB,kCACd,QAC6B;AAC7B,QAAO,OAAO,eAAuB;EACnC,IAAI;AACJ,MAAI;AACF,cAAW,MAAM,OAAO,gBAAgB,WAAW;UAC7C;AACN,SAAM,IAAI,oCAAoC;;AAEhD,SAAO;;;;;ACPX,IAAa,eAAb,MAA+C;CAC7C,OAAO;CACP,OAAO;CACP,YAAiC,EAC/B,OAAO,EACL,aAAa,KAAK,MACnB,EACF;CACD,WAAyB,GAAG;;;;;CAK5B;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;CAOA,mCAA4B,IAAI,SAG7B;CAEH;CAEA,YAAY,MAAoB;AAC9B,QAAA,mBAAyB,kCACvB,KAAK,cACN;AACD,OAAK,gBAAgB,KAAK;AAC1B,OAAK,iBAAiB,KAAK;AAC3B,OAAK,eAAe,KAAK;AACzB,OAAK,cAAc,KAAK;AACxB,OAAK,4BAA4B,KAAK;AACtC,OAAK,uBAAuB,KAAK;AACjC,OAAK,kBAAkB,KAAK;AAC5B,OAAK,OAAO,KAAK,QAAQ;;CAG3B,MAAM,UAAU;CAIhB,MAAM,eAA8B;;;;;;;;;CAgBpC,MAAM,2BACJ,YACA,YAC8B;EAC9B,IAAI,QAAQ,MAAA,gBAAsB,IAAI,WAAW;AACjD,MAAI,CAAC,OAAO;AACV,2BAAQ,IAAI,KAAkC;AAC9C,SAAA,gBAAsB,IAAI,YAAY,MAAM;;EAG9C,MAAM,SAAS,MAAM,IAAI,WAAW;AACpC,MAAI,WAAW,KAAA,EAAW,QAAO;EAEjC,IAAI;AACJ,MAAI;AACF,eAAY,MAAM,MAAA,iBAAuB,WAAW;UAC9C;AACN,SAAM,IAAI,gBAAgB;;AAG5B,QAAM,IAAI,YAAY,UAAU;AAChC,SAAO;;;;;;CAOT,MAAM,wBACJ,MACA,YACkD;EAClD,MAAM,aAAa,MAAM,KAAK,2BAC5B,KAAK,YACL,WACD;AACD,SAAO;GAAE,GAAG;GAAM;GAAY;;;;;;;;CAShC,OAAA,gBACE,YACA,KACqC;AACrC,MAAI,KAAK,qBAAqB,eAAe,IAAI,MAAM,QAAQ,CAC7D,QAAO;AAET,MACE,KAAK,qBAAqB,OAAO,WACjC,oBAAoB,qBAEpB,OAAM,IAAI,gBAAgB;AAE5B,SAAO,KAAK,2BAA2B,YAAY,IAAI;;;;;;CAOzD,MAAM,gBACJ,YACA,KACkB;AAClB,SAAO,KAAK,qBAAqB,QAAQ,YAAY,IAAI,MAAM,QAAQ;;;;;;;;;;;;CAazE,YAAsB,KAA2B;AAC/C,SAAO;GAAE,SAAS,IAAI,MAAM;GAAS,KAAK,IAAI,MAAM;GAAQ;;;;;;CAO9D,MAAM,cACJ,YACA,KACmC;EACnC,MAAM,aAAa,MAAM,MAAA,gBAAsB,YAAY,IAAI;AAC/D,MAAI,eAAe,KACjB,QAAO,yBAAyB,QAAQ,WAAW;AACrD,QAAM,KAAK,uBAAuB,YAAY,IAAI;AAClD,SAAO,yBAAyB,SAAS,WAAW;;CAGtD,MAAM,eACJ,YACA,KACmC;EACnC,MAAM,aAAa,MAAM,MAAA,gBAAsB,YAAY,IAAI;AAC/D,MAAI,eAAe,KACjB,QAAO,yBAAyB,QAAQ,WAAW;AACrD,QAAM,KAAK,wBAAwB,YAAY,IAAI;AACnD,SAAO,yBAAyB,SAAS,WAAW;;CAGtD,MAAM,0BACJ,YACA,eACA,KACmC;EACnC,MAAM,aAAa,MAAM,MAAA,gBAAsB,YAAY,IAAI;AAC/D,MAAI,eAAe,KACjB,QAAO,yBAAyB,QAAQ,WAAW;AACrD,QAAM,KAAK,mCACT,YACA,eACA,IACD;AACD,SAAO,yBAAyB,SAAS,WAAW;;;;;;CAOtD,MAAM,uBACJ,YACA,KACe;AAKf,MAAI,CAJY,MAAM,KAAK,qBAAqB,QAC9C,YACA,IAAI,MAAM,QACX,CAEC,OAAM,IAAI,eAAe,wBAAwB;;CAIrD,MAAM,wBACJ,YACA,KACe;AAKf,MAAI,CAJa,MAAM,KAAK,qBAAqB,SAC/C,YACA,IAAI,MAAM,QACX,CAEC,OAAM,IAAI,eAAe,4BAA4B;;CAIzD,MAAM,mCACJ,YACA,eACA,KACe;AAMf,MAAI,CALc,MAAM,KAAK,qBAAqB,UAChD,YACA,eACA,IAAI,MAAM,QACX,CAEC,OAAM,IAAI,eACR,yBAAyB,cAAc,oBACxC;;CAIL,gBAAgB,KAAoB;AAClC,MAAI,KAAK,qBAAqB,UAAU,IAAI,MAAM,QAAQ,CAAE;AAC5D,MAAI,IAAI,MAAM,QACZ,OAAM,IAAI,eAAe,sBAAsB;AAEjD,QAAM,IAAI,4BAA4B,sBAAsB;;;;;;;;;;;AC1QhE,eAAe,gBAAmB,QAA4B;AAI5D,QAAQ,OAHU,KAAK,WAAW,OAAO,GAAA,OACrC,cAAc,OAAO,CAAC,QAAA,OACtB;;;;;AAON,eAAe,sBACb,aACA,SACmB;CACnB,MAAM,iBAAiB;EACrB,GAAG,YAAY,aAAa,QAAQ;EACpC,GAAG,YAAY,aAAa,QAAQ;EACpC,GAAG,YAAY,QAAQ,QAAQ;EAC/B,GAAG,YAAY,QAAQ,QAAQ;EAChC;AAED,MAAK,MAAM,iBAAiB,eAC1B,KAAI;AACF,SAAO,MAAM,gBAAmB,cAAc;SACxC;AAKV,QAAO;;;;;AAMT,eAAe,qBACb,aACA,SACmB;AACnB,KAAI;EACF,MAAM,cAAc,OAAO,KAAK,UAAU,GAAG,YAAY,eAAe;AACxE,MAAI,CAAC,YAAa,QAAO;EAGzB,MAAM,cAAc,KAAK,QAAQ,cAAc,YAAY,CAAC;EAC5D,MAAM,aAAa;GACjB,KAAK,KAAK,aAAa,QAAQ,QAAQ,SAAS,YAAY;GAC5D,KAAK,KAAK,aAAa,QAAQ,QAAQ,GAAG,QAAQ,MAAM;GACxD,KAAK,KAAK,aAAa,QAAQ,SAAS,WAAW;GACnD,KAAK,KAAK,aAAa,QAAQ,GAAG,QAAQ,KAAK;GAC/C,KAAK,KAAK,aAAa,SAAS,WAAW;GAC3C,KAAK,KAAK,aAAa,GAAG,QAAQ,KAAK;GACxC;AAED,OAAK,MAAM,eAAe,WACxB,KAAI;AACF,UAAO,MAAM,gBAAmB,YAAY;UACtC;SAIJ;AAIR,QAAO;;;;;AAMT,eAAe,sBACb,aACA,SACmB;CACnB,MAAM,kBAAkB,YAAY,SAAS,IAAI,GAC7C,YAAY,MAAM,IAAI,CAAC,KAAK,GAC5B;CACJ,MAAM,sBAAsB,CAC1B,KAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB,YAAY,EACrD,KAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB,mBAAmB,YAAY,CACzE;CAED,MAAM,oBAA8B,EAAE;AAEtC,MAAK,MAAM,mBAAmB,oBAC5B,KAAI;EACF,MAAM,KAAK,MAAM,OAAO;AACxB,MAAI,GAAG,WAAW,gBAAgB,EAAE;GAClC,MAAM,WAAW,GAAG,aAAa,gBAAgB;AAEjD,qBAAkB,KAChB,KAAK,KAAK,UAAU,QAAQ,QAAQ,SAAS,YAAY,EACzD,KAAK,KAAK,UAAU,QAAQ,QAAQ,GAAG,QAAQ,MAAM,EACrD,KAAK,KAAK,UAAU,QAAQ,SAAS,WAAW,EAChD,KAAK,KAAK,UAAU,QAAQ,GAAG,QAAQ,KAAK,EAC5C,KAAK,KAAK,UAAU,SAAS,WAAW,EACxC,KAAK,KAAK,UAAU,GAAG,QAAQ,KAAK,CACrC;;SAEG;AAKV,QAAO;;;;;AAMT,SAAS,wBACP,aACA,SACU;CACV,MAAM,kBAAkB,YAAY,SAAS,IAAI,GAC7C,YAAY,MAAM,IAAI,CAAC,KAAK,GAC5B;CACJ,MAAM,cAAc,CAAC,QAAQ,KAAK,EAAE,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC;CAEhE,MAAM,oBAA8B,EAAE;AACtC,MAAK,MAAM,QAAQ,YACjB,mBAAkB,KAChB,KAAK,KACH,MACA,YACA,mBAAmB,aACnB,QACA,QACA,SACA,YACD,EACD,KAAK,KACH,MACA,YACA,mBAAmB,aACnB,QACA,QACA,GAAG,QAAQ,MACZ,EACD,KAAK,KACH,MACA,YACA,mBAAmB,aACnB,QACA,SACA,WACD,EACD,KAAK,KACH,MACA,YACA,mBAAmB,aACnB,QACA,GAAG,QAAQ,KACZ,CACF;AAGH,QAAO;;;;;AAMT,eAAe,qBAAwB,UAAuC;AAC5E,MAAK,MAAM,iBAAiB,SAC1B,KAAI;AACF,SAAO,MAAM,gBAAmB,cAAc;SACxC;AAKV,QAAO;;;;;AAMT,eAAsB,qBACpB,aACA,SACmB;CAEnB,IAAI,SAAS,MAAM,sBAAyB,aAAa,QAAQ;AACjE,KAAI,OAAQ,QAAO;AAGnB,UAAS,MAAM,qBAAwB,aAAa,QAAQ;AAC5D,KAAI,OAAQ,QAAO;AAInB,UAAS,MAAM,qBADM,MAAM,sBAAsB,aAAa,QAAQ,CAClB;AACpD,KAAI,OAAQ,QAAO;AAInB,UAAS,MAAM,qBADK,wBAAwB,aAAa,QAAQ,CACd;AACnD,KAAI,OAAQ,QAAO;AAEnB,QAAO;;;;AC5LO,YAAY,CAAC,eAAe,gBAAgB,CAAC;;;;AAiB7D,eAAsB,mBACpB,aACsC;AACtC,QAAO,eAAe,aAAa,kBAAkB;;;;;AAMvD,eAAsB,cACpB,aACiC;AACjC,QAAO,eAAe,aAAa,YAAY;;;;;AAMjD,eAAsB,eACpB,aACkC;AAClC,QAAO,eAAe,aAAa,aAAa;;;;;;AAOlD,eAAe,eACb,aACA,SACY;CAIZ,MAAM,WAAW,KAAK,WAAW,YAAY,GACzC,cAAc,KAAK,KAAK,aAAa,QAAQ,CAAC,CAAC,OAC/C,GAAG,YAAY,GAAG;AAGtB,KAAI;AAKF,SADgB,MAAM;;GAA0B;;UAEzC,GAAG;AAKV,MACE,aAAa,SACb,UAAU,MACT,EAAE,SAAS,0BACV,EAAE,SAAS,gCACX,EAAE,SAAS,mCACb;GACA,MAAM,SAAS,MAAM,qBAAwB,aAAa,QAAQ;AAClE,OAAI,OAAQ,QAAO;;AAErB,QAAM;;;AAIV,SAAS,kBACP,OAC6C;AAC7C,QACE,OAAO,UAAU,YACjB,UAAU,QACV,kBAAkB,SAClB,uBAAuB,SACvB,cAAc;;;;;;;AASlB,SAAgB,wBACd,WACsC;CACtC,MAAM,4BAAY,IAAI,KAAiD;CACvE,MAAM,OAAO,UAAmB;AAC9B,MAAI,kBAAkB,MAAM,CAC1B,WAAU,IAAI,MAAM,cAAc,MAAM;;AAG5C,MAAK,MAAM,SAAS,OAAO,OAAO,UAAU,CAC1C,KAAI,MAAM,QAAQ,MAAM,CACtB,OAAM,QAAQ,IAAI;KAElB,KAAI,MAAM;AAGd,QAAO,MAAM,KAAK,UAAU,QAAQ,CAAC;;AAGvC,SAAgB,SACd,MACA,QAAQ,KACR;CACA,IAAI;AACJ,SAAQ,YAAY,OAAO,GAAG,SAAY;AACxC,MAAI,MACF,cAAa,MAAM;AAErB,SAAO,IAAI,SAAY,SAAS,WAAW;AACzC,OAAI,UACF,MAAK,GAAG,KAAK,CACV,KAAK,QAAQ,CACb,MAAM,OAAO;OAEhB,SAAQ,iBAAiB;AACvB,SAAK,GAAG,KAAK,CACV,KAAK,QAAQ,CACb,MAAM,OAAO;MACf,MAAM;IAEX;;;AAIN,SAAgB,UAAU,QAAgB,KAAa;CACrD,MAAM,WAAW,KAAK,SAAS,QAAQ,IAAI;AAC3C,QAAO,YAAY,CAAC,SAAS,WAAW,KAAK,IAAI,CAAC,KAAK,WAAW,SAAS;;;;AC1J7E,SAAgB,gBACd,WAC4B;AAC5B,KAAI,OAAO,cAAc,WAAY,QAAO;CAE5C,IAAI,QAAiB,OAAO,eAAe,UAAU;AACrD,QAAO,OAAO;AACZ,MAAI,OAAO,UAAU,cAAc,KAAK,OAAO,aAAa,CAAE,QAAO;AAErE,UAAQ,OAAO,eAAe,MAAM;;AAGtC,QAAO;;AAGT,SAAgB,uBACd,YACA,MACA,OACgB;AAChB,QAAO,WAAW,MAAM,MAAM,OAAO,MAAM,CAAC,IAAI,sBAAsB;;AAGxE,SAAgB,sBAAsB,WAAoC;CACxE,MAAM,SAAS,UAAU,OAAO,SAAS;AACzC,QAAO;EACL,IAAI,UAAU,MAAM;EACpB,MAAM,UAAU,OAAO;EACvB,OAAO,UAAU;EACjB,gBAAgB,UAAU;EAC1B,MAAM,UAAU;EAChB,MAAM,UAAU;EAChB,WACE,OAAO,UAAU,OAAO,UAAU,WAC9B,UAAU,OAAO,QACjB,KAAK,UAAU,UAAU,OAAO,MAAM;EAC5C,OAAO,UAAU;EACjB,SAAS,EACP,QAAQ,SACJ;GACE,MAAM,OAAO;GACb,KAAK,OAAO;GACZ,YAAY,OAAO,WAAW,KAAK,QACjC,MAAM,QAAQ,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG,IACvC;GACF,GACD,KAAA,GACL;EACF;;AAGH,SAAgB,qBAAqB,KAA8B;CAGjE,MAAM,QAAQ,IAAI;CAClB,MAAM,eAAe,IAAI;CAEzB,MAAM,cAAc,YAAY,IAAI,QAAQ,IAAI,MAAM,SAAS,EAAE;AACjE,QAAO;EACL,IAAI,IAAI,OAAO;EACf,MAAM,IAAI,OAAO;EACjB,cAAc,IAAI,OAAO;EACzB,UAAU,IAAI,OAAO,SAAS,UAAU;EACxC,iBAAiB,IAAI,OAAO;EAC5B,sBAAsB,IAAI,OAAO;EACjC,YAAY,EAAE;EACd,WAAW;EACX;EACA;EACD;;AAGH,SAAgB,0BACd,KACkB;AAElB,QAAO;EACL,GAFa,qBAAqB,IAAI;EAGtC,MAAM,EACJ,iBAAiB,IAAI,OAAO,MAAM,iBACnC;EACD,MAAM,IAAI,OAAO;EACjB,OAAO,IAAI,MAAM;EACjB,cAAc,IAAI,MAAM;EACzB","debug_id":"b3b52862-3211-5b26-8234-217f98a3e3a5"}