@powerhousedao/reactor-api 6.2.3-dev.43 → 6.2.3-dev.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapter-http-express-CWqziB1p.mjs → adapter-http-express-P0t-mdMV.mjs} +6 -6
- package/dist/{adapter-http-express-CWqziB1p.mjs.map → adapter-http-express-P0t-mdMV.mjs.map} +1 -1
- package/dist/{adapter-http-fastify-CYZQ6FFv.mjs → adapter-http-fastify-D0OP5q9K.mjs} +6 -6
- package/dist/{adapter-http-fastify-CYZQ6FFv.mjs.map → adapter-http-fastify-D0OP5q9K.mjs.map} +1 -1
- package/dist/index.d.mts +33 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +62 -66
- package/dist/index.mjs.map +1 -1
- package/dist/pglite-node-Ow9i5Rb4.mjs +573 -0
- package/dist/pglite-node-Ow9i5Rb4.mjs.map +1 -0
- package/dist/src/packages/vite-loader.d.mts.map +1 -1
- package/dist/src/packages/vite-loader.mjs +5 -9
- package/dist/src/packages/vite-loader.mjs.map +1 -1
- package/dist/src/pglite/pglite-node.d.mts +130 -0
- package/dist/src/pglite/pglite-node.d.mts.map +1 -0
- package/dist/src/pglite/pglite-node.mjs +4 -0
- package/dist/{pieces-DRY6haAO.mjs → subgraph-extraction-DTFoN_bS.mjs} +93 -6
- package/dist/subgraph-extraction-DTFoN_bS.mjs.map +1 -0
- package/package.json +18 -14
- package/dist/pieces-DRY6haAO.mjs.map +0 -1
|
@@ -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]="
|
|
3
|
-
import { a as
|
|
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]="647a32d0-3e32-5241-8c60-6c1d9d1e7ec5")}catch(e){}}();
|
|
3
|
+
import { _ as isSubpath, a as packageRootOf, c as piecesFromListModule, g as extractUpgradeManifests, h as debounce, l as extractDocumentModels, n as BUILT_PIECE_LIST, o as pieceListLocation, r as PIECES_SUBPATH, t as extractSubgraphs } from "../../subgraph-extraction-DTFoN_bS.mjs";
|
|
4
4
|
import { childLogger } from "document-model";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
@@ -92,7 +92,7 @@ var VitePackageLoader = class VitePackageLoader {
|
|
|
92
92
|
this.logger.debug("Loading document models from", this.getDocumentModelsPath(identifier));
|
|
93
93
|
const loaded = await this.#load(identifier, "document-models");
|
|
94
94
|
if (!loaded) return [];
|
|
95
|
-
const documentModels =
|
|
95
|
+
const documentModels = extractDocumentModels(loaded.namespace);
|
|
96
96
|
this.logger.verbose(` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`);
|
|
97
97
|
return documentModels;
|
|
98
98
|
}
|
|
@@ -112,11 +112,7 @@ var VitePackageLoader = class VitePackageLoader {
|
|
|
112
112
|
this.logger.verbose("Loading subgraphs from", this.getSubgraphsPath(identifier));
|
|
113
113
|
const loaded = await this.#load(identifier, "subgraphs");
|
|
114
114
|
if (!loaded) return [];
|
|
115
|
-
const subgraphs =
|
|
116
|
-
for (const [name, subgraph] of Object.entries(loaded.namespace)) {
|
|
117
|
-
const SubgraphClass = subgraph[name];
|
|
118
|
-
if (isSubgraphClass(SubgraphClass)) subgraphs.push(SubgraphClass);
|
|
119
|
-
}
|
|
115
|
+
const subgraphs = extractSubgraphs(loaded.namespace);
|
|
120
116
|
this.logger.debug(` ➜ Loaded ${subgraphs.length} Subgraphs from: ${identifier}`);
|
|
121
117
|
return subgraphs;
|
|
122
118
|
}
|
|
@@ -235,4 +231,4 @@ async function startViteServer(root, logger) {
|
|
|
235
231
|
export { VitePackageLoader, createViteLogger, startViteServer };
|
|
236
232
|
|
|
237
233
|
//# sourceMappingURL=vite-loader.mjs.map
|
|
238
|
-
//# debugId=
|
|
234
|
+
//# debugId=647a32d0-3e32-5241-8c60-6c1d9d1e7ec5
|
|
@@ -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 {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger, type ILogger } from \"document-model\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { readPackage } from \"read-pkg\";\nimport type { Logger, PluginOption, ViteDevServer } from \"vite\";\nimport { createLogger, createServer } from \"vite\";\nimport { isSubgraphClass } from \"../graphql/utils.js\";\nimport {\n BUILT_PIECE_LIST,\n PIECES_SUBPATH,\n packageRootOf,\n pieceListLocation,\n piecesFromListModule,\n} from \"./pieces.js\";\nimport type {\n ISubscribablePackageLoader,\n ISubscriptionOptions,\n PackagePieceEntry,\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 // Wrapped rather than assigned: the logger methods are bound to their own\n // instance, and re-homing them onto Vite's logger object made every Vite\n // log line throw.\n //\n // Vite's text goes through as a replacement, never as the format string: it\n // is somebody else's prose, not a template. `ILogger` substitutes `@token`,\n // and Vite log lines are full of npm scopes, so `pre-transforming\n // @powerhousedao/design-system` came out as `pre-transforming\n // null/design-system`. Substituting into `@line` instead emits it verbatim.\n //\n // Vite's second argument is dropped for the same reason. It is `LogOptions`\n // -- `{ clear, timestamp }` -- and forwarding it made it the replacement for\n // whatever `@token` the line happened to contain, or got appended as JSON.\n // Only `error` keeps it, where it carries the error itself.\n customLogger.info = (msg) => logger.info(\"@line\", msg);\n customLogger.warn = (msg) => logger.warn(\"@line\", msg);\n customLogger.error = (msg, options) =>\n options?.error\n ? logger.error(\"@line\", msg, options.error)\n : logger.error(\"@line\", msg);\n return customLogger;\n}\n\nexport interface VitePackageLoaderOptions {\n /** Modules, as paths or file URLs, whose dependencies a package the project\n * does not install may resolve from. This loader's own module always is. */\n resolveFrom?: string[];\n}\n\ninterface LoadedModule {\n id: string;\n namespace: Record<string, unknown>;\n}\n\nexport class VitePackageLoader implements ISubscribablePackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"vite-loader\"]);\n\n private readonly vite: ViteDevServer;\n\n private readonly importers: string[];\n\n readonly name = \"VitePackageLoader\";\n\n static build(vite: ViteDevServer, options?: VitePackageLoaderOptions) {\n return new VitePackageLoader(vite, options);\n }\n\n constructor(vite: ViteDevServer, options: VitePackageLoaderOptions = {}) {\n this.vite = vite;\n this.importers = [...(options.resolveFrom ?? []), import.meta.url].map(\n (from) => (from.startsWith(\"file:\") ? fileURLToPath(from) : from),\n );\n }\n\n // The project first, then the host's own dependencies. A bare name or a path\n // Vite cannot resolve is a package without that module, not an error.\n async #resolve(identifier: string, subpath: string) {\n const aliased = path.isAbsolute(identifier)\n ? undefined\n : this.aliasedRoot(identifier);\n const specifier = path.posix.join(aliased ?? identifier, subpath);\n const bare = !aliased && !path.isAbsolute(identifier);\n const importers = bare ? [undefined, ...this.importers] : [undefined];\n const container = this.vite.environments.ssr.pluginContainer;\n for (const importer of importers) {\n try {\n const resolved = await container.resolveId(specifier, importer);\n if (resolved && !resolved.external) return resolved.id;\n } catch (e) {\n this.logger.debug(\"Could not resolve @specifier: @error\", specifier, e);\n }\n }\n return undefined;\n }\n\n // Resolved before it is loaded, so only a module that exists and fails is\n // reported; one a package does not have is a debug-level miss.\n async #load(\n identifier: string,\n subpath: string,\n ): Promise<LoadedModule | undefined> {\n const id = await this.#resolve(identifier, subpath);\n if (id === undefined) {\n this.logger.debug(\"No @subpath module in @pkg\", subpath, identifier);\n return undefined;\n }\n try {\n const namespace = (await this.vite.ssrLoadModule(id)) as Record<\n string,\n unknown\n >;\n return { id, namespace };\n } catch (e) {\n this.logger.error(\n \"Failed to load @subpath of @pkg from @id: @error\",\n subpath,\n identifier,\n id,\n e instanceof Error ? e.message : e,\n );\n return undefined;\n }\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 private getPiecesPath(identifier: string): string {\n return path.posix.join(identifier, `./${PIECES_SUBPATH}`);\n }\n\n // The dev server aliases the local project by its own package name, so a\n // package that is this project is rooted at the source tree vite serves.\n private aliasedRoot(identifier: string): string | undefined {\n const alias = this.vite.config.resolve.alias;\n const entries = Array.isArray(alias) ? alias : [];\n const hit = entries.find((entry) => entry.find === identifier);\n return typeof hit?.replacement === \"string\" ? hit.replacement : undefined;\n }\n\n // What a declared piece path is relative to. Not the module vite loaded: a\n // list read from source still points at the built output beside it.\n private pieceRoot(identifier: string, listId?: string): string | undefined {\n if (!path.isAbsolute(identifier)) {\n const aliased = this.aliasedRoot(identifier);\n if (aliased) return aliased;\n // A built list resolved from wherever the package is installed.\n if (listId) return packageRootOf(path.dirname(listId));\n }\n try {\n return pieceListLocation(identifier).root;\n } catch {\n return undefined;\n }\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 this.logger.debug(\n \"Loading document models from\",\n this.getDocumentModelsPath(identifier),\n );\n const loaded = await this.#load(identifier, \"document-models\");\n if (!loaded) return [];\n\n // duck type\n const documentModels = Object.values(loaded.namespace).filter(\n (dm): dm is DocumentModelModule =>\n dm !== null && typeof dm === \"object\" && \"documentModel\" in dm,\n );\n this.logger.verbose(\n ` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`,\n );\n return documentModels;\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.\n for (const subpath of [\n \"document-models\",\n \"document-models/upgrade-manifests\",\n ]) {\n const loaded = await this.#load(identifier, subpath);\n if (!loaded) continue;\n const manifests = extractUpgradeManifests(loaded.namespace);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n return manifests;\n }\n }\n return [];\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n this.logger.verbose(\n \"Loading subgraphs from\",\n this.getSubgraphsPath(identifier),\n );\n const loaded = await this.#load(identifier, \"subgraphs\");\n if (!loaded) return [];\n\n const subgraphs: SubgraphClass[] = [];\n for (const [name, subgraph] of Object.entries(\n loaded.namespace as Record<string, Record<string, SubgraphClass>>,\n )) {\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 this.logger.verbose(\n \"Loading processors from\",\n this.getProcessorsPath(identifier),\n );\n const loaded = await this.#load(identifier, \"processors\");\n const factory = loaded?.namespace.processorFactory;\n if (typeof factory === \"function\") {\n this.logger.verbose(` ➜ Loaded Processor Factory from: ${identifier}`);\n return factory as ProcessorFactoryBuilder;\n }\n\n this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);\n return null;\n }\n\n // The list only, never a piece: in dev it is usually the TypeScript source,\n // and what it names is still the built bundle a worker will load.\n async loadPieces(identifier: string): Promise<PackagePieceEntry[]> {\n this.logger.verbose(\"Loading pieces from\", this.getPiecesPath(identifier));\n const loaded = await this.#load(identifier, PIECES_SUBPATH);\n if (!loaded) return [];\n\n const root = this.pieceRoot(identifier, loaded.id);\n if (root === undefined) {\n this.logger.debug(` ➜ No package root found for: ${identifier}`);\n return [];\n }\n\n const pieces = piecesFromListModule(loaded.namespace, {\n root,\n identifier,\n logger: this.logger,\n });\n this.logger.debug(\n ` ➜ Loaded ${pieces.length} Pieces from: ${identifier}`,\n );\n return pieces;\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 // \"change\" alone misses files that are created or deleted: a removed\n // document-models/ entry would never report an empty result, and the\n // package's registered models would leak.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", 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 // \"change\" alone misses files that are created or deleted: a removed\n // subgraphs/ entry would never report an empty result, and the\n // package's registered subgraphs would leak.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", 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 // \"change\" alone misses files that are created or deleted: a removed\n // processors/ entry would never report an empty result, and the\n // package's registered processor factories would leak.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", listener);\n };\n }\n\n onPiecesChange(\n identifier: string,\n handler: (pieces: PackagePieceEntry[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n // Both the source list and the build output: the list says which pieces a\n // package ships, and only the build decides whether one is there to run.\n const watched = [this.getPiecesPath(identifier)];\n const root = this.pieceRoot(identifier);\n if (root !== undefined) {\n watched.push(path.dirname(path.resolve(root, BUILT_PIECE_LIST)));\n }\n const listener = async (changedPath: string) => {\n if (!watched.some((dir) => isSubpath(dir, changedPath))) return;\n handler(await this.loadPieces(identifier));\n };\n // \"change\" alone misses files that are created or deleted, and a piece\n // appearing for the first time is exactly the build this watches for.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", 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":[],"mappings":"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","debug_id":"33a7684d-ff05-56ac-b4f5-910a2adca3e5"}
|
|
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 { fileURLToPath } from \"node:url\";\nimport { readPackage } from \"read-pkg\";\nimport type { Logger, PluginOption, ViteDevServer } from \"vite\";\nimport { createLogger, createServer } from \"vite\";\nimport { extractDocumentModels } from \"./document-model-detection.js\";\nimport { extractSubgraphs } from \"./subgraph-extraction.js\";\nimport {\n BUILT_PIECE_LIST,\n PIECES_SUBPATH,\n packageRootOf,\n pieceListLocation,\n piecesFromListModule,\n} from \"./pieces.js\";\nimport type {\n ISubscribablePackageLoader,\n ISubscriptionOptions,\n PackagePieceEntry,\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 // Wrapped rather than assigned: the logger methods are bound to their own\n // instance, and re-homing them onto Vite's logger object made every Vite\n // log line throw.\n //\n // Vite's text goes through as a replacement, never as the format string: it\n // is somebody else's prose, not a template. `ILogger` substitutes `@token`,\n // and Vite log lines are full of npm scopes, so `pre-transforming\n // @powerhousedao/design-system` came out as `pre-transforming\n // null/design-system`. Substituting into `@line` instead emits it verbatim.\n //\n // Vite's second argument is dropped for the same reason. It is `LogOptions`\n // -- `{ clear, timestamp }` -- and forwarding it made it the replacement for\n // whatever `@token` the line happened to contain, or got appended as JSON.\n // Only `error` keeps it, where it carries the error itself.\n customLogger.info = (msg) => logger.info(\"@line\", msg);\n customLogger.warn = (msg) => logger.warn(\"@line\", msg);\n customLogger.error = (msg, options) =>\n options?.error\n ? logger.error(\"@line\", msg, options.error)\n : logger.error(\"@line\", msg);\n return customLogger;\n}\n\nexport interface VitePackageLoaderOptions {\n /** Modules, as paths or file URLs, whose dependencies a package the project\n * does not install may resolve from. This loader's own module always is. */\n resolveFrom?: string[];\n}\n\ninterface LoadedModule {\n id: string;\n namespace: Record<string, unknown>;\n}\n\nexport class VitePackageLoader implements ISubscribablePackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"vite-loader\"]);\n\n private readonly vite: ViteDevServer;\n\n private readonly importers: string[];\n\n readonly name = \"VitePackageLoader\";\n\n static build(vite: ViteDevServer, options?: VitePackageLoaderOptions) {\n return new VitePackageLoader(vite, options);\n }\n\n constructor(vite: ViteDevServer, options: VitePackageLoaderOptions = {}) {\n this.vite = vite;\n this.importers = [...(options.resolveFrom ?? []), import.meta.url].map(\n (from) => (from.startsWith(\"file:\") ? fileURLToPath(from) : from),\n );\n }\n\n // The project first, then the host's own dependencies. A bare name or a path\n // Vite cannot resolve is a package without that module, not an error.\n async #resolve(identifier: string, subpath: string) {\n const aliased = path.isAbsolute(identifier)\n ? undefined\n : this.aliasedRoot(identifier);\n const specifier = path.posix.join(aliased ?? identifier, subpath);\n const bare = !aliased && !path.isAbsolute(identifier);\n const importers = bare ? [undefined, ...this.importers] : [undefined];\n const container = this.vite.environments.ssr.pluginContainer;\n for (const importer of importers) {\n try {\n const resolved = await container.resolveId(specifier, importer);\n if (resolved && !resolved.external) return resolved.id;\n } catch (e) {\n this.logger.debug(\"Could not resolve @specifier: @error\", specifier, e);\n }\n }\n return undefined;\n }\n\n // Resolved before it is loaded, so only a module that exists and fails is\n // reported; one a package does not have is a debug-level miss.\n async #load(\n identifier: string,\n subpath: string,\n ): Promise<LoadedModule | undefined> {\n const id = await this.#resolve(identifier, subpath);\n if (id === undefined) {\n this.logger.debug(\"No @subpath module in @pkg\", subpath, identifier);\n return undefined;\n }\n try {\n const namespace = (await this.vite.ssrLoadModule(id)) as Record<\n string,\n unknown\n >;\n return { id, namespace };\n } catch (e) {\n this.logger.error(\n \"Failed to load @subpath of @pkg from @id: @error\",\n subpath,\n identifier,\n id,\n e instanceof Error ? e.message : e,\n );\n return undefined;\n }\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 private getPiecesPath(identifier: string): string {\n return path.posix.join(identifier, `./${PIECES_SUBPATH}`);\n }\n\n // The dev server aliases the local project by its own package name, so a\n // package that is this project is rooted at the source tree vite serves.\n private aliasedRoot(identifier: string): string | undefined {\n const alias = this.vite.config.resolve.alias;\n const entries = Array.isArray(alias) ? alias : [];\n const hit = entries.find((entry) => entry.find === identifier);\n return typeof hit?.replacement === \"string\" ? hit.replacement : undefined;\n }\n\n // What a declared piece path is relative to. Not the module vite loaded: a\n // list read from source still points at the built output beside it.\n private pieceRoot(identifier: string, listId?: string): string | undefined {\n if (!path.isAbsolute(identifier)) {\n const aliased = this.aliasedRoot(identifier);\n if (aliased) return aliased;\n // A built list resolved from wherever the package is installed.\n if (listId) return packageRootOf(path.dirname(listId));\n }\n try {\n return pieceListLocation(identifier).root;\n } catch {\n return undefined;\n }\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 this.logger.debug(\n \"Loading document models from\",\n this.getDocumentModelsPath(identifier),\n );\n const loaded = await this.#load(identifier, \"document-models\");\n if (!loaded) return [];\n\n const documentModels = extractDocumentModels(loaded.namespace);\n this.logger.verbose(\n ` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`,\n );\n return documentModels;\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.\n for (const subpath of [\n \"document-models\",\n \"document-models/upgrade-manifests\",\n ]) {\n const loaded = await this.#load(identifier, subpath);\n if (!loaded) continue;\n const manifests = extractUpgradeManifests(loaded.namespace);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n return manifests;\n }\n }\n return [];\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n this.logger.verbose(\n \"Loading subgraphs from\",\n this.getSubgraphsPath(identifier),\n );\n const loaded = await this.#load(identifier, \"subgraphs\");\n if (!loaded) return [];\n\n const subgraphs = extractSubgraphs(loaded.namespace);\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 this.logger.verbose(\n \"Loading processors from\",\n this.getProcessorsPath(identifier),\n );\n const loaded = await this.#load(identifier, \"processors\");\n const factory = loaded?.namespace.processorFactory;\n if (typeof factory === \"function\") {\n this.logger.verbose(` ➜ Loaded Processor Factory from: ${identifier}`);\n return factory as ProcessorFactoryBuilder;\n }\n\n this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);\n return null;\n }\n\n // The list only, never a piece: in dev it is usually the TypeScript source,\n // and what it names is still the built bundle a worker will load.\n async loadPieces(identifier: string): Promise<PackagePieceEntry[]> {\n this.logger.verbose(\"Loading pieces from\", this.getPiecesPath(identifier));\n const loaded = await this.#load(identifier, PIECES_SUBPATH);\n if (!loaded) return [];\n\n const root = this.pieceRoot(identifier, loaded.id);\n if (root === undefined) {\n this.logger.debug(` ➜ No package root found for: ${identifier}`);\n return [];\n }\n\n const pieces = piecesFromListModule(loaded.namespace, {\n root,\n identifier,\n logger: this.logger,\n });\n this.logger.debug(\n ` ➜ Loaded ${pieces.length} Pieces from: ${identifier}`,\n );\n return pieces;\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 // \"change\" alone misses files that are created or deleted: a removed\n // document-models/ entry would never report an empty result, and the\n // package's registered models would leak.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", 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 // \"change\" alone misses files that are created or deleted: a removed\n // subgraphs/ entry would never report an empty result, and the\n // package's registered subgraphs would leak.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", 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 // \"change\" alone misses files that are created or deleted: a removed\n // processors/ entry would never report an empty result, and the\n // package's registered processor factories would leak.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", listener);\n };\n }\n\n onPiecesChange(\n identifier: string,\n handler: (pieces: PackagePieceEntry[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n // Both the source list and the build output: the list says which pieces a\n // package ships, and only the build decides whether one is there to run.\n const watched = [this.getPiecesPath(identifier)];\n const root = this.pieceRoot(identifier);\n if (root !== undefined) {\n watched.push(path.dirname(path.resolve(root, BUILT_PIECE_LIST)));\n }\n const listener = async (changedPath: string) => {\n if (!watched.some((dir) => isSubpath(dir, changedPath))) return;\n handler(await this.loadPieces(identifier));\n };\n // \"change\" alone misses files that are created or deleted, and a piece\n // appearing for the first time is exactly the build this watches for.\n this.vite.watcher.on(\"change\", listener);\n this.vite.watcher.on(\"add\", listener);\n this.vite.watcher.on(\"unlink\", listener);\n\n return () => {\n this.vite.watcher.off(\"change\", listener);\n this.vite.watcher.off(\"add\", listener);\n this.vite.watcher.off(\"unlink\", 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":[],"mappings":"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","debug_id":"647a32d0-3e32-5241-8c60-6c1d9d1e7ec5"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { ILogger } from "document-model";
|
|
2
|
+
import nodeFs from "node:fs";
|
|
3
|
+
import { PGlite } from "@electric-sql/pglite";
|
|
4
|
+
import { NodeFS } from "@electric-sql/pglite/nodefs";
|
|
5
|
+
//#region src/pglite/maintenance.d.ts
|
|
6
|
+
export declare const DEFAULT_MAINTENANCE_INTERVAL_MS: number;
|
|
7
|
+
export declare const DEFAULT_VACUUM_FULL_ABOVE_BYTES: number;
|
|
8
|
+
type MaintenanceOutcome = "vacuum" | "vacuum-full" | "idle" | "not-ready" | "in-transaction" | "failed";
|
|
9
|
+
interface MaintenanceLogger {
|
|
10
|
+
warn(message: string): void;
|
|
11
|
+
}
|
|
12
|
+
interface MaintenanceOptions {
|
|
13
|
+
/** VACUUM + CHECKPOINT cadence; PGlite has no autovacuum. Default 5 min; 0 disables. */
|
|
14
|
+
intervalMs?: number;
|
|
15
|
+
/** First pass runs VACUUM FULL when `base/` exceeds this at open. Default 256 MB; 0 disables. */
|
|
16
|
+
vacuumFullAboveBytes?: number;
|
|
17
|
+
logger?: MaintenanceLogger;
|
|
18
|
+
}
|
|
19
|
+
export declare class PgliteMaintenance {
|
|
20
|
+
private readonly intervalMs;
|
|
21
|
+
private readonly vacuumFullAboveBytes;
|
|
22
|
+
private readonly logger?;
|
|
23
|
+
private pg?;
|
|
24
|
+
private label;
|
|
25
|
+
private closing;
|
|
26
|
+
private syncsSinceMaintenance;
|
|
27
|
+
private vacuumFullPending;
|
|
28
|
+
private timer?;
|
|
29
|
+
private inFlight?;
|
|
30
|
+
constructor(options?: MaintenanceOptions);
|
|
31
|
+
get scheduled(): boolean;
|
|
32
|
+
get running(): boolean;
|
|
33
|
+
start(pg: PGlite, label: string, baseBytes: number): void;
|
|
34
|
+
noteSync(): void;
|
|
35
|
+
stop(): Promise<void>;
|
|
36
|
+
run(): Promise<MaintenanceOutcome>;
|
|
37
|
+
private schedule;
|
|
38
|
+
private cancel;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/pglite/durable-node-fs.d.ts
|
|
42
|
+
type NodeFsClass = typeof NodeFS;
|
|
43
|
+
interface DurableNodeFsOptions {
|
|
44
|
+
/** Default true; `PH_PGLITE_FSYNC=0` turns it off (power-loss durability off). */
|
|
45
|
+
fsync?: boolean;
|
|
46
|
+
/** Default 5 min; 0 disables. */
|
|
47
|
+
maintenanceIntervalMs?: number;
|
|
48
|
+
/** `base/` size at open; default 256 MB; 0 disables. */
|
|
49
|
+
vacuumFullAboveBytes?: number;
|
|
50
|
+
logger?: {
|
|
51
|
+
warn(message: string): void;
|
|
52
|
+
};
|
|
53
|
+
/** Emscripten abort (a Postgres PANIC, e.g. ENOSPC on WAL). */
|
|
54
|
+
onAbort?: (what: unknown) => void;
|
|
55
|
+
hostFs?: Pick<typeof nodeFs, "fsyncSync" | "fdatasyncSync">;
|
|
56
|
+
}
|
|
57
|
+
type DurableNodeFs = InstanceType<NodeFsClass> & {
|
|
58
|
+
readonly maintenance: PgliteMaintenance;
|
|
59
|
+
};
|
|
60
|
+
export declare function resolvePgliteFsync(env: Record<string, string | undefined>): boolean;
|
|
61
|
+
/** Built over the passed-in class so PG16 dirs on `pglite-legacy-02` get the same behaviour. */
|
|
62
|
+
export declare function createDurableNodeFs(Base: NodeFsClass, dataDir: string, options?: DurableNodeFsOptions): DurableNodeFs;
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/pglite/sync-tree.d.ts
|
|
65
|
+
interface SyncTreeHostFs {
|
|
66
|
+
fsyncSync(fd: number): void;
|
|
67
|
+
}
|
|
68
|
+
interface SyncTreeResult {
|
|
69
|
+
files: number;
|
|
70
|
+
dirs: number;
|
|
71
|
+
}
|
|
72
|
+
/** One pass over a finished tree; interleaving fsync with writes costs seconds. */
|
|
73
|
+
export declare function syncTree(root: string, hostFs?: SyncTreeHostFs): SyncTreeResult;
|
|
74
|
+
/** fsyncs a directory's entries; false where the platform refuses (Windows). */
|
|
75
|
+
export declare function syncDirectory(dir: string, hostFs?: SyncTreeHostFs): boolean;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/pglite/snapshot-reader.d.ts
|
|
78
|
+
export declare const SNAPSHOT_FILE_NAME = "snapshot.bin";
|
|
79
|
+
interface ExtractSnapshotOptions {
|
|
80
|
+
chunkSize?: number;
|
|
81
|
+
/** Default true: one fsync pass over the tree after the last write. */
|
|
82
|
+
sync?: boolean;
|
|
83
|
+
hostFs?: SyncTreeHostFs;
|
|
84
|
+
}
|
|
85
|
+
interface ExtractedSnapshot {
|
|
86
|
+
pgVersionMajor: number;
|
|
87
|
+
/** `global/pg_control` bytes; absent only in synthetic trees. */
|
|
88
|
+
pgControl?: Buffer;
|
|
89
|
+
/** Entries written to disk; skipped entries are not counted. */
|
|
90
|
+
entries: number;
|
|
91
|
+
/** Size of the snapshot file. */
|
|
92
|
+
bytes: number;
|
|
93
|
+
}
|
|
94
|
+
/** Unpacks a snapshot into the existing `outDir`. */
|
|
95
|
+
export declare function extractSnapshot(snapshotPath: string, outDir: string, options?: ExtractSnapshotOptions): Promise<ExtractedSnapshot>;
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/pglite/convert-snapshot-dir.d.ts
|
|
98
|
+
interface VerifyHandle {
|
|
99
|
+
query<T>(sql: string): Promise<{
|
|
100
|
+
rows: T[];
|
|
101
|
+
}>;
|
|
102
|
+
close(): Promise<void>;
|
|
103
|
+
}
|
|
104
|
+
type ConversionStep = "extract" | "verify" | "renameOld" | "renameNew" | "removeOld";
|
|
105
|
+
interface ConversionDeps {
|
|
106
|
+
/** Opens `dataDir` with the stock NodeFS of the PGlite module for `major`. */
|
|
107
|
+
openForVerify: (major: number, dataDir: string) => Promise<VerifyHandle>;
|
|
108
|
+
logger: ILogger;
|
|
109
|
+
/** Test hook: throw after a named step to simulate a crash there. */
|
|
110
|
+
afterStep?: (step: ConversionStep) => void | Promise<void>;
|
|
111
|
+
hostFs?: SyncTreeHostFs;
|
|
112
|
+
}
|
|
113
|
+
/** Settles the debris of an interrupted conversion; runs before it at boot. */
|
|
114
|
+
export declare function recoverConversion(dir: string, deps: ConversionDeps): Promise<void>;
|
|
115
|
+
/** Extracts into `.converting`, verifies by opening it, swaps through `.old`. */
|
|
116
|
+
export declare function convertSnapshotDir(dir: string, deps: ConversionDeps): Promise<"converted" | "none">;
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/pglite/preflight.d.ts
|
|
119
|
+
/** PG major of the pinned @electric-sql/pglite; it exports none, so the test checks initdb. */
|
|
120
|
+
export declare const CURRENT_PGLITE_MAJOR = 17;
|
|
121
|
+
/** `openForVerify` over the loaded PGlite module only. */
|
|
122
|
+
export declare function openCurrentPgliteForVerify(major: number, dataDir: string): Promise<VerifyHandle>;
|
|
123
|
+
/** Converts a snapshot store and clears the files a previous run leaves behind. */
|
|
124
|
+
export declare function preparePgliteDataDir(dir: string, deps: ConversionDeps): Promise<void>;
|
|
125
|
+
/** PGlite leaves `postmaster.pid` after every close and `pg_wal/xlogtemp.*` after some. */
|
|
126
|
+
export declare function removeStalePgliteFiles(dir: string, logger: Pick<ILogger, "debug">): Promise<void>;
|
|
127
|
+
//#endregion
|
|
128
|
+
export type { ConversionDeps, ConversionStep, DurableNodeFs, DurableNodeFsOptions, ExtractSnapshotOptions, ExtractedSnapshot, MaintenanceLogger, MaintenanceOptions, MaintenanceOutcome, NodeFsClass, SyncTreeHostFs, SyncTreeResult, VerifyHandle };
|
|
129
|
+
export {};
|
|
130
|
+
//# sourceMappingURL=pglite-node.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pglite-node.d.mts","names":[],"sources":["../../../src/pglite/maintenance.ts","../../../src/pglite/durable-node-fs.ts","../../../src/pglite/sync-tree.ts","../../../src/pglite/snapshot-reader.ts","../../../src/pglite/convert-snapshot-dir.ts","../../../src/pglite/preflight.ts"],"mappings":";;;;;qBAIa;qBACA;KAGD;UAQK;EACf,KAAK;;UAGU;;EAEf;;EAEA;EACA,SAAS;;qBAGE;mBACM;mBACA;mBACA;UAET;UACA;UACA;UACA;UACA;UACA;UACA;EAER,YAAY,UAAS;MAYjB;MAIA;EAIJ,MAAM,IAAI,QAAQ,eAAe;EAQjC;EAIM,QAAQ;EAMR,OAAO,QAAQ;UA+Cb;UAoBA;;;;KC1IE,qBAAqB;UAKhB;;EAEf;;EAEA;;EAEA;EACA;IAAW,KAAK;;;EAEhB,WAAW;EACX,SAAS,YAAY;;KAGX,gBAAgB,aAAa;WAC9B,aAAa;;wBAGR,mBACd,KAAK;;wBAmES,oBACd,MAAM,aACN,iBACA,UAAS,uBACR;;;UCnGc;EACf,UAAU;;UAGK;EACf;EACA;;;wBAIc,SACd,cACA,SAAQ,iBACP;;wBA+Ba,cACd,aACA,SAAQ;;;qBC3CG;UASI;EACf;;EAEA;EACA,SAAS;;UAGM;EACf;;EAEA,YAAY;;EAEZ;;EAEA;;;wBAIoB,gBACpB,sBACA,gBACA,UAAS,yBACR,QAAQ;;;UC/BM;EACf,MAAM,GAAG,cAAc;IAAU,MAAM;;EACvC,SAAS;;KAGC;UAOK;;EAEf,gBAAgB,eAAe,oBAAoB,QAAQ;EAC3D,QAAQ;;EAER,aAAa,MAAM,0BAA0B;EAC7C,SAAS;;;wBA6BW,kBACpB,aACA,MAAM,iBACL;;wBA6CmB,mBACpB,aACA,MAAM,iBACL;;;;qBC3FU;;wBAGS,2BACpB,eACA,kBACC,QAAQ;;wBAYW,qBACpB,aACA,MAAM,iBACL;;wBAOmB,uBACpB,aACA,QAAQ,KAAK,oBACZ"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { a as convertSnapshotDir, c as extractSnapshot, d as syncDirectory, f as syncTree, h as PgliteMaintenance, i as removeStalePgliteFiles, l as createDurableNodeFs, m as DEFAULT_VACUUM_FULL_ABOVE_BYTES, n as openCurrentPgliteForVerify, o as recoverConversion, p as DEFAULT_MAINTENANCE_INTERVAL_MS, r as preparePgliteDataDir, s as SNAPSHOT_FILE_NAME, t as CURRENT_PGLITE_MAJOR, u as resolvePgliteFsync } from "../../pglite-node-Ow9i5Rb4.mjs";
|
|
2
|
+
export { CURRENT_PGLITE_MAJOR, DEFAULT_MAINTENANCE_INTERVAL_MS, DEFAULT_VACUUM_FULL_ABOVE_BYTES, PgliteMaintenance, SNAPSHOT_FILE_NAME, convertSnapshotDir, createDurableNodeFs, extractSnapshot, openCurrentPgliteForVerify, preparePgliteDataDir, recoverConversion, removeStalePgliteFiles, resolvePgliteFsync, syncDirectory, syncTree };
|
|
3
|
+
!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]="6dd4c09b-2fd7-5402-83f6-a92c933064b1")}catch(e){}}();
|
|
4
|
+
//# debugId=6dd4c09b-2fd7-5402-83f6-a92c933064b1
|
|
@@ -1,5 +1,5 @@
|
|
|
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]="
|
|
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]="17c0a5a3-a356-551f-9500-bdab5f8930f9")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { gql } from "graphql-tag";
|
|
5
5
|
import { GraphQLError } from "graphql";
|
|
@@ -608,6 +608,30 @@ async function loadDependency(packageName, subPath) {
|
|
|
608
608
|
throw e;
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
|
+
/**
|
|
612
|
+
* The subgraphs a package's `powerhouse.manifest.json` declares, when the
|
|
613
|
+
* manifest is reachable — which it is for a package identified by an
|
|
614
|
+
* absolute path (how every local project reaches the loaders). Lets the
|
|
615
|
+
* package manager warn when a manifest promises subgraphs and the loaders
|
|
616
|
+
* deliver none, instead of failing silently. For a bare package name the
|
|
617
|
+
* manifest would have to be resolved through the module system; until a
|
|
618
|
+
* caller needs that, a bare name answers [] rather than guessing.
|
|
619
|
+
*/
|
|
620
|
+
function manifestDeclaredSubgraphs(identifier) {
|
|
621
|
+
if (!path.isAbsolute(identifier)) return [];
|
|
622
|
+
try {
|
|
623
|
+
const raw = readFileSync(path.join(identifier, "powerhouse.manifest.json"), "utf-8");
|
|
624
|
+
const manifest = JSON.parse(raw);
|
|
625
|
+
if (!Array.isArray(manifest.subgraphs)) return [];
|
|
626
|
+
return manifest.subgraphs.map((subgraph) => {
|
|
627
|
+
if (typeof subgraph !== "object" || subgraph === null) return;
|
|
628
|
+
const { id, name } = subgraph;
|
|
629
|
+
return id ?? name;
|
|
630
|
+
}).filter((value) => typeof value === "string" && value.length > 0);
|
|
631
|
+
} catch {
|
|
632
|
+
return [];
|
|
633
|
+
}
|
|
634
|
+
}
|
|
611
635
|
function isUpgradeManifest(value) {
|
|
612
636
|
return typeof value === "object" && value !== null && "documentType" in value && "supportedVersions" in value && "upgrades" in value;
|
|
613
637
|
}
|
|
@@ -646,8 +670,9 @@ function isSubpath(parent, dir) {
|
|
|
646
670
|
function isSubgraphClass(candidate) {
|
|
647
671
|
if (typeof candidate !== "function") return false;
|
|
648
672
|
let proto = Object.getPrototypeOf(candidate);
|
|
649
|
-
while (proto) {
|
|
650
|
-
if (
|
|
673
|
+
while (typeof proto === "function") {
|
|
674
|
+
if (proto === BaseSubgraph) return true;
|
|
675
|
+
if (proto.name === "BaseSubgraph") return true;
|
|
651
676
|
proto = Object.getPrototypeOf(proto);
|
|
652
677
|
}
|
|
653
678
|
return false;
|
|
@@ -700,6 +725,30 @@ function buildGraphQlDriveDocument(doc) {
|
|
|
700
725
|
};
|
|
701
726
|
}
|
|
702
727
|
//#endregion
|
|
728
|
+
//#region src/packages/document-model-detection.ts
|
|
729
|
+
/**
|
|
730
|
+
* The one acceptance rule for a package's `document-models` module.
|
|
731
|
+
*
|
|
732
|
+
* The three package loaders duck-typed this independently and disagreed on
|
|
733
|
+
* one case: the http loader required `documentModel` to be non-null, while
|
|
734
|
+
* the import and vite loaders accepted any object merely carrying the key,
|
|
735
|
+
* so an export shaped `{ documentModel: null }` registered as a model under
|
|
736
|
+
* two loaders and vanished under the third. The strict rule is the correct
|
|
737
|
+
* one — a module without its documentModel cannot define a document type —
|
|
738
|
+
* and this predicate is now the single rule all three share, the same way
|
|
739
|
+
* extractSubgraphs unified the subgraph rule.
|
|
740
|
+
*/
|
|
741
|
+
function isDocumentModelModule(candidate) {
|
|
742
|
+
if (candidate === null || typeof candidate !== "object") return false;
|
|
743
|
+
if (!("documentModel" in candidate)) return false;
|
|
744
|
+
const model = candidate.documentModel;
|
|
745
|
+
return model !== null && model !== void 0;
|
|
746
|
+
}
|
|
747
|
+
/** Collects the document-model modules among a namespace's exports. */
|
|
748
|
+
function extractDocumentModels(namespace) {
|
|
749
|
+
return Object.values(namespace).filter(isDocumentModelModule);
|
|
750
|
+
}
|
|
751
|
+
//#endregion
|
|
703
752
|
//#region src/packages/pieces.ts
|
|
704
753
|
/** The sub-entry every loader asks a package for its pieces through. */
|
|
705
754
|
const PIECES_SUBPATH = "pieces";
|
|
@@ -815,7 +864,45 @@ function piecesFromListModule(module, context) {
|
|
|
815
864
|
});
|
|
816
865
|
}
|
|
817
866
|
//#endregion
|
|
818
|
-
|
|
867
|
+
//#region src/packages/subgraph-extraction.ts
|
|
868
|
+
/**
|
|
869
|
+
* The one acceptance rule for a package's `subgraphs` module.
|
|
870
|
+
*
|
|
871
|
+
* All three package loaders (vite, import, http) consume the same generated
|
|
872
|
+
* `subgraphs/index` file, and each used to apply its own rule — the vite
|
|
873
|
+
* loader required a namespace whose alias equalled the class name inside it,
|
|
874
|
+
* the http loader took any function one level deep, and the import loader
|
|
875
|
+
* took every nested value. An export that registered under one loader could
|
|
876
|
+
* silently vanish under another (the codegen-does-not-register-subgraphs
|
|
877
|
+
* report). This is now the single rule they all share:
|
|
878
|
+
*
|
|
879
|
+
* - an export that is itself a subgraph class is accepted (named or default
|
|
880
|
+
* export of the class);
|
|
881
|
+
* - any subgraph class among the values of an exported object is accepted
|
|
882
|
+
* (a `export * as Alias from ...` namespace under any alias, or a
|
|
883
|
+
* default-exported object of classes);
|
|
884
|
+
* - everything else — constants, configs, functions and classes that do not
|
|
885
|
+
* extend BaseSubgraph — is dropped.
|
|
886
|
+
*
|
|
887
|
+
* Codegen emits `export * as <ClassName> from "./<dir>/index.js"`
|
|
888
|
+
* (makeSubgraphsIndexFile in packages/codegen), which the namespace branch
|
|
889
|
+
* accepts regardless of the alias; hand-written packages may re-export a
|
|
890
|
+
* class directly, which the direct branch accepts. A class reached through
|
|
891
|
+
* both branches is returned once.
|
|
892
|
+
*/
|
|
893
|
+
function extractSubgraphs(namespace) {
|
|
894
|
+
const found = [];
|
|
895
|
+
const add = (candidate) => {
|
|
896
|
+
if (isSubgraphClass(candidate) && !found.includes(candidate)) found.push(candidate);
|
|
897
|
+
};
|
|
898
|
+
for (const value of Object.values(namespace)) {
|
|
899
|
+
add(value);
|
|
900
|
+
if (value !== null && typeof value === "object") for (const inner of Object.values(value)) add(inner);
|
|
901
|
+
}
|
|
902
|
+
return found;
|
|
903
|
+
}
|
|
904
|
+
//#endregion
|
|
905
|
+
export { AuthenticationRequiredError as A, callerSubject as C, AuthorizedDocumentHandle as D, AuthorizationPolicy as E, MalformedStoredOperationError as M, RefusalNotRecordedError as N, createAuthorizationService as O, BaseSubgraph as S, createCanonicalDocumentIdResolver as T, isSubpath as _, packageRootOf as a, loadSubgraphs as b, piecesFromListModule as c, buildGraphQlDriveDocument as d, buildGraphqlOperation as f, extractUpgradeManifests as g, debounce as h, PIECE_SOURCE_LIST as i, ForbiddenError as j, AuthEvaluationUnsupportedError as k, extractDocumentModels as l, isSubgraphClass as m, BUILT_PIECE_LIST as n, pieceListLocation as o, buildGraphqlOperations as p, PIECES_SUBPATH as r, piecesFromCdnList as s, extractSubgraphs as t, buildGraphQlDocument as u, loadDocumentModels as v, CanonicalDocumentIdResolutionError as w, manifestDeclaredSubgraphs as x, loadProcessors as y };
|
|
819
906
|
|
|
820
|
-
//# sourceMappingURL=
|
|
821
|
-
//# debugId=
|
|
907
|
+
//# sourceMappingURL=subgraph-extraction-DTFoN_bS.mjs.map
|
|
908
|
+
//# debugId=17c0a5a3-a356-551f-9500-bdab5f8930f9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgraph-extraction-DTFoN_bS.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","../src/packages/document-model-detection.ts","../src/packages/pieces.ts","../src/packages/subgraph-extraction.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\n/**\n * The marker refusals a poll carried were not recorded, so the poll fails.\n * The code is recoverable: the client keeps polling and reports them again.\n */\nexport class RefusalNotRecordedError extends GraphQLError {\n constructor(cause: unknown) {\n super(\"A reported marker refusal was not recorded; report it again\", {\n originalError: cause instanceof Error ? cause : new Error(String(cause)),\n extensions: {\n code: RECOVERABLE_GRAPHQL_ERROR_CODES.refusalNotRecorded,\n },\n });\n }\n}\n","import { PURGE_DOCUMENT } from \"@powerhousedao/shared/document-model\";\nimport 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 // A purge marker needs a document admin whatever the operation rows say.\n if (operationType === PURGE_DOCUMENT) {\n return this.#isDocumentAdmin(documentId, userAddress);\n }\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 { IAttachmentClient } from \"@powerhousedao/reactor-attachments/client\";\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 { IAttachmentClientProvider } from \"../services/authorized-attachment.service.js\";\nimport type { DocumentPermissionService } from \"../services/document-permission.service.js\";\nimport type { Context } from \"./types.js\";\n\n/**\n * The subject a request reads as: its address and the app key its token\n * carries. Anonymous is an empty subject, never the host's signer.\n */\nexport function callerSubject(user: Context[\"user\"]): AuthSubject {\n return { address: user?.address, key: user?.appKey };\n}\n\nexport class BaseSubgraph implements ISubgraph {\n name = \"example\";\n // The host's base path as injected by the GraphQL manager. Routing\n // ignores it: the manager mounts every subgraph under its own base path.\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 /** This package's namespaced slice of the HTTP surface. */\n readonly http: SubgraphArgs[\"http\"];\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 readonly #attachments?: IAttachmentClientProvider;\n\n readonly #attachmentClientMemo = new WeakMap<object, IAttachmentClient>();\n\n constructor(args: SubgraphArgs) {\n this.#resolveCanonical = createCanonicalDocumentIdResolver(\n args.reactorClient,\n );\n this.http = args.http;\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 this.#attachments = args.attachments;\n }\n\n /**\n * An attachment client bound to this request's caller, memoized per request.\n *\n * @throws Error when the host provides no attachment client to subgraphs.\n */\n attachmentsFor(ctx: Context): IAttachmentClient {\n if (!this.#attachments) {\n throw new Error(\"This host provides no attachment client to subgraphs\");\n }\n let client = this.#attachmentClientMemo.get(ctx);\n if (!client) {\n client = this.#attachments.forSubject(callerSubject(ctx.user));\n this.#attachmentClientMemo.set(ctx, client);\n }\n return client;\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 callerSubject(ctx.user);\n }\n\n /** Whether a listing would serve the document to the caller; fails closed. */\n protected async servesDocument(\n documentId: string,\n ctx: Context,\n ): Promise<boolean> {\n if (!documentId) {\n return false;\n }\n try {\n return await this.reactorClient.isServed(documentId, {\n subject: this.viewSubject(ctx),\n });\n } catch {\n return false;\n }\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 { readFileSync } from \"node:fs\";\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\n/**\n * The subgraphs a package's `powerhouse.manifest.json` declares, when the\n * manifest is reachable — which it is for a package identified by an\n * absolute path (how every local project reaches the loaders). Lets the\n * package manager warn when a manifest promises subgraphs and the loaders\n * deliver none, instead of failing silently. For a bare package name the\n * manifest would have to be resolved through the module system; until a\n * caller needs that, a bare name answers [] rather than guessing.\n */\nexport function manifestDeclaredSubgraphs(identifier: string): string[] {\n if (!path.isAbsolute(identifier)) return [];\n try {\n const raw = readFileSync(\n path.join(identifier, \"powerhouse.manifest.json\"),\n \"utf-8\",\n );\n const manifest = JSON.parse(raw) as { subgraphs?: unknown };\n if (!Array.isArray(manifest.subgraphs)) return [];\n return manifest.subgraphs\n .map((subgraph: unknown) => {\n if (typeof subgraph !== \"object\" || subgraph === null) {\n return undefined;\n }\n const { id, name } = subgraph as { id?: unknown; name?: unknown };\n return id ?? name;\n })\n .filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n );\n } catch {\n // No manifest, or an unreadable one: nothing was promised, so nothing\n // to warn about.\n return [];\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 // Walk the candidate's constructor chain. Identity first: package builds\n // keep `@powerhousedao/reactor-api` external precisely so every subgraph\n // extends this very BaseSubgraph (see nodeNeverBundle in\n // packages/shared/clis/build-config.mts). The name check is the fallback\n // for a module graph that carries its own copy — a project served by the\n // vite dev server resolves reactor-api from its own node_modules, which\n // need not be the host's instance.\n //\n // The previous version asked `isPrototypeOf` in the wrong direction\n // (whether the candidate's proto was in BaseSubgraph's chain), which\n // `Function.prototype` always satisfies — so every function passed, and\n // junk exports registered as subgraphs.\n let proto: unknown = Object.getPrototypeOf(candidate);\n while (typeof proto === \"function\") {\n if (proto === BaseSubgraph) return true;\n if (proto.name === \"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","import type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\n\n/**\n * The one acceptance rule for a package's `document-models` module.\n *\n * The three package loaders duck-typed this independently and disagreed on\n * one case: the http loader required `documentModel` to be non-null, while\n * the import and vite loaders accepted any object merely carrying the key,\n * so an export shaped `{ documentModel: null }` registered as a model under\n * two loaders and vanished under the third. The strict rule is the correct\n * one — a module without its documentModel cannot define a document type —\n * and this predicate is now the single rule all three share, the same way\n * extractSubgraphs unified the subgraph rule.\n */\nexport function isDocumentModelModule(\n candidate: unknown,\n): candidate is DocumentModelModule {\n if (candidate === null || typeof candidate !== \"object\") return false;\n if (!(\"documentModel\" in candidate)) return false;\n const model = (candidate as { documentModel: unknown }).documentModel;\n return model !== null && model !== undefined;\n}\n\n/** Collects the document-model modules among a namespace's exports. */\nexport function extractDocumentModels(\n namespace: Record<string, unknown>,\n): DocumentModelModule[] {\n return Object.values(namespace).filter(isDocumentModelModule);\n}\n","// The pieces a package ships, located on disk for a host that never runs them.\n\n// Only the list module is ever imported here: it holds no piece code, and a\n// piece itself runs in a forked worker, handed the path this reports.\nimport { packageJsonExports } from \"@powerhousedao/shared/clis/constants\";\nimport type { ILogger } from \"document-model\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, isAbsolute, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { PackagePiece, PackagePieceEntry } from \"./types.js\";\n\n/** The sub-entry every loader asks a package for its pieces through. */\nexport const PIECES_SUBPATH = \"pieces\";\n\n// Where the node build leaves the list, read from the export map a generated\n// package ships so the build and the host cannot disagree about the path.\nexport const BUILT_PIECE_LIST = packageJsonExports[\"./pieces\"].node;\n\n/** Where a package keeps its piece sources, for telling unbuilt from absent. */\nexport const PIECE_SOURCE_LIST = join(PIECES_SUBPATH, \"index.ts\");\n\n/** The nearest enclosing package.json, which `exports` usually hides. */\nexport function packageRootOf(dir: string): string | undefined {\n let current = dir;\n while (!existsSync(join(current, \"package.json\"))) {\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n return current;\n}\n\nexport interface PieceListLocation {\n /** Absolute; a declared entry is relative to it. */\n root: string;\n /** Absolute path of the list module, built or not. */\n listPath: string;\n}\n\n// Resolved from this module first, then from the host's own dependencies,\n// which is where document models are found too; the first error is the one kept.\nfunction resolvePieceList(specifier: string, hostDir: string): string {\n try {\n return fileURLToPath(import.meta.resolve(specifier));\n } catch (error) {\n try {\n return createRequire(join(hostDir, \"package.json\")).resolve(specifier);\n } catch {\n throw error;\n }\n }\n}\n\n// Where a package's piece list sits and what its entries are relative to. A\n// path identifier is its own root; a name resolves as a host would import it.\nexport function pieceListLocation(\n identifier: string,\n hostDir = process.cwd(),\n): PieceListLocation {\n if (isAbsolute(identifier)) {\n return { root: identifier, listPath: join(identifier, BUILT_PIECE_LIST) };\n }\n // Left to throw, with the ESM resolver's error codes: they're what the\n // package manager reads a miss from.\n const listPath = resolvePieceList(`${identifier}/${PIECES_SUBPATH}`, hostDir);\n const root = packageRootOf(dirname(listPath));\n if (!root) {\n throw new Error(`No package.json above ${listPath}`);\n }\n return { root, listPath };\n}\n\n// A piece's version is its package's, so it is read from the package root.\nexport function packageVersionAt(root: string): string | undefined {\n try {\n const pkg = JSON.parse(\n readFileSync(join(root, \"package.json\"), \"utf8\"),\n ) as { version?: unknown };\n return typeof pkg.version === \"string\" && pkg.version !== \"\"\n ? pkg.version\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n// A declared piece counts only once its code is on disk: one nobody built is\n// reported rather than dropped, because a block type names it either way.\nexport function locatePieces(\n declared: readonly PackagePiece[],\n context: {\n root: string;\n identifier: string;\n logger: ILogger;\n version: string;\n },\n): PackagePieceEntry[] {\n const { root, identifier, logger, version } = context;\n const located: PackagePieceEntry[] = [];\n for (const piece of declared) {\n const where = piece.entry ?? piece.bundle;\n if (typeof where !== \"string\" || where === \"\") {\n // Every name goes through a logger value: `@`-prefixed tokens are\n // substituted, so a scoped one printed inline comes out as null/pack.\n logger.warn(\n \"Piece @piece of @pkg declares neither a bundle nor an entry\",\n piece.name,\n identifier,\n );\n continue;\n }\n const path = isAbsolute(where) ? where : join(root, where);\n const present = piece.entry\n ? existsSync(path)\n : existsSync(join(path, \"package.json\"));\n if (!present) {\n logger.warn(\n \"Piece @piece of @pkg is declared but not built at @path\",\n piece.name,\n identifier,\n path,\n );\n continue;\n }\n located.push({\n name: piece.name,\n version,\n ...(piece.entry ? { entryPath: path } : { bundleDir: path }),\n });\n }\n return located;\n}\n\n// A package's `pieces` array, however the list module was obtained.\nfunction declaredPieces(\n module: unknown,\n identifier: string,\n logger: ILogger,\n): PackagePiece[] | undefined {\n const namespace = (module ?? {}) as { pieces?: unknown; default?: unknown };\n const declared = namespace.pieces ?? namespace.default;\n if (!Array.isArray(declared)) {\n logger.warn(\n 'The pieces list of @pkg exports no \"pieces\" array; it contributes none',\n identifier,\n );\n return undefined;\n }\n return declared as PackagePiece[];\n}\n\n// The same list, served by a registry rather than read off a disk. Nothing is\n// checked for existence here: the CDN is asked when the piece is run.\n\n// `entry` is relative to the package root while the CDN serves beneath\n// `dist/`, so that prefix comes off before the base is applied.\nexport function piecesFromCdnList(\n module: unknown,\n baseUrl: string,\n identifier: string,\n logger: ILogger,\n version: string,\n): PackagePieceEntry[] {\n const declared = declaredPieces(module, identifier, logger);\n if (!declared) return [];\n const located: PackagePieceEntry[] = [];\n for (const piece of declared) {\n const where = piece.entry ?? piece.bundle;\n if (typeof where !== \"string\" || where === \"\") {\n logger.warn(\n \"Piece @piece of @pkg declares neither a bundle nor an entry\",\n piece.name,\n identifier,\n );\n continue;\n }\n located.push({\n name: piece.name,\n version,\n entryUrl: `${baseUrl}${where.replace(/^dist\\/node\\/pieces\\//, \"\")}`,\n });\n }\n return located;\n}\n\n// What a loaded list module contributes. A module without a `pieces` array is\n// not a list, and saying so beats reporting the package as shipping none.\nexport function piecesFromListModule(\n module: unknown,\n context: { root: string; identifier: string; logger: ILogger },\n): PackagePieceEntry[] {\n const namespace = (module ?? {}) as { pieces?: unknown; default?: unknown };\n const declared = namespace.pieces ?? namespace.default;\n if (!Array.isArray(declared)) {\n context.logger.warn(\n 'The pieces list of @pkg exports no \"pieces\" array; it contributes none',\n context.identifier,\n );\n return [];\n }\n const version = packageVersionAt(context.root);\n if (!version) {\n context.logger.warn(\n \"@pkg has no version in @root/package.json, and a piece takes its package's version; its pieces contribute none\",\n context.identifier,\n context.root,\n );\n return [];\n }\n return locatePieces(declared as PackagePiece[], { ...context, version });\n}\n","import type { SubgraphClass } from \"@powerhousedao/reactor-api\";\nimport { isSubgraphClass } from \"../graphql/utils.js\";\n\n/**\n * The one acceptance rule for a package's `subgraphs` module.\n *\n * All three package loaders (vite, import, http) consume the same generated\n * `subgraphs/index` file, and each used to apply its own rule — the vite\n * loader required a namespace whose alias equalled the class name inside it,\n * the http loader took any function one level deep, and the import loader\n * took every nested value. An export that registered under one loader could\n * silently vanish under another (the codegen-does-not-register-subgraphs\n * report). This is now the single rule they all share:\n *\n * - an export that is itself a subgraph class is accepted (named or default\n * export of the class);\n * - any subgraph class among the values of an exported object is accepted\n * (a `export * as Alias from ...` namespace under any alias, or a\n * default-exported object of classes);\n * - everything else — constants, configs, functions and classes that do not\n * extend BaseSubgraph — is dropped.\n *\n * Codegen emits `export * as <ClassName> from \"./<dir>/index.js\"`\n * (makeSubgraphsIndexFile in packages/codegen), which the namespace branch\n * accepts regardless of the alias; hand-written packages may re-export a\n * class directly, which the direct branch accepts. A class reached through\n * both branches is returned once.\n */\nexport function extractSubgraphs(\n namespace: Record<string, unknown>,\n): SubgraphClass[] {\n const found: SubgraphClass[] = [];\n const add = (candidate: unknown) => {\n if (isSubgraphClass(candidate) && !found.includes(candidate)) {\n found.push(candidate);\n }\n };\n for (const value of Object.values(namespace)) {\n add(value);\n if (value !== null && typeof value === \"object\") {\n for (const inner of Object.values(value)) {\n add(inner);\n }\n }\n }\n return found;\n}\n"],"names":[],"mappings":"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","debug_id":"17c0a5a3-a356-551f-9500-bdab5f8930f9"}
|