@powerhousedao/reactor-api 6.1.0-dev.2 → 6.1.0-dev.20
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-DO4ui7AV.mjs → adapter-http-express-D5OpUIbV.mjs} +6 -4
- package/dist/adapter-http-express-D5OpUIbV.mjs.map +1 -0
- package/dist/index.d.mts +34 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +125 -47
- package/dist/index.mjs.map +1 -1
- package/dist/src/packages/https-hooks.d.mts.map +1 -1
- package/dist/src/packages/https-hooks.mjs +18 -8
- package/dist/src/packages/https-hooks.mjs.map +1 -1
- package/dist/utils-BFkbSO_H.mjs +2 -2
- package/dist/utils-BFkbSO_H.mjs.map +1 -1
- package/package.json +14 -13
- package/dist/adapter-http-express-DO4ui7AV.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"https-hooks.d.mts","names":[],"sources":["../../../src/packages/https-hooks.mts"],"mappings":";;;;;KAQK,cAAA;EAAmB,SAAA;EAAoB,UAAA;AAAA;AAAA,KACvC,aAAA;EACH,GAAA;EACA,YAAA;EACA,MAAA;AAAA;AAAA,KAEG,WAAA,IACH,SAAA,UACA,OAAA,EAAS,cAAA,KACN,OAAA,CAAQ,aAAA;AAAA,KAER,WAAA;EAAgB,MAAA;AAAA;AAAA,KAChB,UAAA;EAAe,MAAA;EAAgB,YAAA;EAAwB,MAAA;AAAA;AAAA,KACvD,QAAA,IAAY,GAAA,UAAa,OAAA,EAAS,WAAA,KAAgB,OAAA,CAAQ,UAAA;;;;iBAKzC,OAAA,CACpB,SAAA,UACA,OAAA,EAAS,cAAA,EACT,WAAA,EAAa,WAAA,GACZ,OAAA,CAAQ,aAAA;;;;
|
|
1
|
+
{"version":3,"file":"https-hooks.d.mts","names":[],"sources":["../../../src/packages/https-hooks.mts"],"mappings":";;;;;KAQK,cAAA;EAAmB,SAAA;EAAoB,UAAA;AAAA;AAAA,KACvC,aAAA;EACH,GAAA;EACA,YAAA;EACA,MAAA;AAAA;AAAA,KAEG,WAAA,IACH,SAAA,UACA,OAAA,EAAS,cAAA,KACN,OAAA,CAAQ,aAAA;AAAA,KAER,WAAA;EAAgB,MAAA;AAAA;AAAA,KAChB,UAAA;EAAe,MAAA;EAAgB,YAAA;EAAwB,MAAA;AAAA;AAAA,KACvD,QAAA,IAAY,GAAA,UAAa,OAAA,EAAS,WAAA,KAAgB,OAAA,CAAQ,UAAA;;;;iBAKzC,OAAA,CACpB,SAAA,UACA,OAAA,EAAS,cAAA,EACT,WAAA,EAAa,WAAA,GACZ,OAAA,CAAQ,aAAA;;;;iBAiEW,IAAA,CACpB,GAAA,UACA,OAAA,EAAS,WAAA,EACT,QAAA,EAAU,QAAA,GACT,OAAA,CAAQ,UAAA;;;;cA0EE,cAAA"}
|
|
@@ -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]="0a57348f-eab9-5103-83ff-b067482a7ea8")}catch(e){}}();
|
|
3
3
|
import { get } from "node:http";
|
|
4
4
|
import { get as get$1 } from "node:https";
|
|
5
5
|
//#region src/packages/https-hooks.mts
|
|
@@ -19,12 +19,22 @@ async function resolve(specifier, context, nextResolve) {
|
|
|
19
19
|
format: "module"
|
|
20
20
|
};
|
|
21
21
|
if (parentURL && (parentURL.startsWith("https://") || parentURL.startsWith("http://"))) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if (!specifier.startsWith("/") && !/^[a-z][a-z0-9+.-]*:/i.test(specifier)) {
|
|
23
|
+
const { pathToFileURL } = await import("node:url");
|
|
24
|
+
const consumerRoot = pathToFileURL(process.cwd() + "/").href;
|
|
25
|
+
try {
|
|
26
|
+
return await nextResolve(specifier, {
|
|
27
|
+
...context,
|
|
28
|
+
parentURL: consumerRoot
|
|
29
|
+
});
|
|
30
|
+
} catch (e) {
|
|
31
|
+
if (e?.code !== "ERR_MODULE_NOT_FOUND") throw e;
|
|
32
|
+
return nextResolve(specifier, {
|
|
33
|
+
...context,
|
|
34
|
+
parentURL: import.meta.url
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
28
38
|
}
|
|
29
39
|
return nextResolve(specifier, context);
|
|
30
40
|
}
|
|
@@ -79,4 +89,4 @@ const httpsHooksPath = import.meta.url;
|
|
|
79
89
|
export { httpsHooksPath, load, resolve };
|
|
80
90
|
|
|
81
91
|
//# sourceMappingURL=https-hooks.mjs.map
|
|
82
|
-
//# debugId=
|
|
92
|
+
//# debugId=0a57348f-eab9-5103-83ff-b067482a7ea8
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"https-hooks.mjs","sources":["../../../src/packages/https-hooks.mts"],"sourcesContent":["import { get as httpGet } from \"node:http\";\nimport { get } from \"node:https\";\n\n/**\n * Node.js module loader hooks that enable importing from HTTP/HTTPS URLs.\n * See: https://nodejs.org/docs/latest-v24.x/api/module.html#import-from-https\n */\n\ntype ResolveContext = { parentURL?: string; conditions?: string[] };\ntype ResolveResult = {\n url: string;\n shortCircuit?: boolean;\n format?: string;\n};\ntype NextResolve = (\n specifier: string,\n context: ResolveContext,\n) => Promise<ResolveResult>;\n\ntype LoadContext = { format?: string };\ntype LoadResult = { format: string; shortCircuit?: boolean; source: string };\ntype NextLoad = (url: string, context: LoadContext) => Promise<LoadResult>;\n\n/**\n * Resolve hook: resolves relative specifiers against HTTP/HTTPS parent URLs.\n */\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve,\n): Promise<ResolveResult> {\n const { parentURL } = context;\n\n // If the specifier is already an HTTP(S) URL, resolve it directly\n if (specifier.startsWith(\"https://\") || specifier.startsWith(\"http://\")) {\n return { url: specifier, shortCircuit: true, format: \"module\" };\n }\n\n // If the parent is an HTTP(S) URL and specifier is relative, resolve against it.\n // Only handle relative specifiers (./ or ../), not bare package specifiers.\n if (\n parentURL &&\n (parentURL.startsWith(\"https://\") || parentURL.startsWith(\"http://\")) &&\n (specifier.startsWith(\"./\") || specifier.startsWith(\"../\"))\n ) {\n const resolved = new URL(specifier, parentURL).href;\n return { url: resolved, shortCircuit: true, format: \"module\" };\n }\n\n //
|
|
1
|
+
{"version":3,"file":"https-hooks.mjs","sources":["../../../src/packages/https-hooks.mts"],"sourcesContent":["import { get as httpGet } from \"node:http\";\nimport { get } from \"node:https\";\n\n/**\n * Node.js module loader hooks that enable importing from HTTP/HTTPS URLs.\n * See: https://nodejs.org/docs/latest-v24.x/api/module.html#import-from-https\n */\n\ntype ResolveContext = { parentURL?: string; conditions?: string[] };\ntype ResolveResult = {\n url: string;\n shortCircuit?: boolean;\n format?: string;\n};\ntype NextResolve = (\n specifier: string,\n context: ResolveContext,\n) => Promise<ResolveResult>;\n\ntype LoadContext = { format?: string };\ntype LoadResult = { format: string; shortCircuit?: boolean; source: string };\ntype NextLoad = (url: string, context: LoadContext) => Promise<LoadResult>;\n\n/**\n * Resolve hook: resolves relative specifiers against HTTP/HTTPS parent URLs.\n */\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve,\n): Promise<ResolveResult> {\n const { parentURL } = context;\n\n // If the specifier is already an HTTP(S) URL, resolve it directly\n if (specifier.startsWith(\"https://\") || specifier.startsWith(\"http://\")) {\n return { url: specifier, shortCircuit: true, format: \"module\" };\n }\n\n // If the parent is an HTTP(S) URL and specifier is relative, resolve against it.\n // Only handle relative specifiers (./ or ../), not bare package specifiers.\n if (\n parentURL &&\n (parentURL.startsWith(\"https://\") || parentURL.startsWith(\"http://\")) &&\n (specifier.startsWith(\"./\") || specifier.startsWith(\"../\"))\n ) {\n const resolved = new URL(specifier, parentURL).href;\n return { url: resolved, shortCircuit: true, format: \"module\" };\n }\n\n // Bare specifiers from HTTP modules need a node_modules root to resolve\n // against. Under pnpm's strict isolation the deps a registry-built bundle\n // needs split into two classes:\n // - Peer deps the *consumer* declared (react, react-dom, graphql, …) —\n // live at the consumer project root.\n // - Things reactor-api keeps external by design (the reactor-api package\n // itself, for class identity; internal helpers) — live in reactor-api's\n // own tree.\n // Neither root sees the other under strict mode, so try the consumer first\n // (its declared peers win on version) and fall back to reactor-api's tree.\n //\n // At this point: specifier is not an http(s):// URL (branch 1) and not\n // relative (branch 2). Only redirect bare package specifiers; let absolute\n // paths and other URL schemes (e.g. \"node:fs\", \"file://…\") fall through.\n if (\n parentURL &&\n (parentURL.startsWith(\"https://\") || parentURL.startsWith(\"http://\"))\n ) {\n const isBareSpecifier =\n !specifier.startsWith(\"/\") && !/^[a-z][a-z0-9+.-]*:/i.test(specifier);\n if (isBareSpecifier) {\n const { pathToFileURL } = await import(\"node:url\");\n const consumerRoot = pathToFileURL(process.cwd() + \"/\").href;\n try {\n return await nextResolve(specifier, {\n ...context,\n parentURL: consumerRoot,\n });\n } catch (e) {\n const code = (e as NodeJS.ErrnoException | undefined)?.code;\n if (code !== \"ERR_MODULE_NOT_FOUND\") throw e;\n return nextResolve(specifier, {\n ...context,\n parentURL: import.meta.url,\n });\n }\n }\n }\n\n // Let Node.js handle all other specifiers\n return nextResolve(specifier, context);\n}\n\n/**\n * Load hook: fetches module source from HTTP/HTTPS URLs.\n */\nexport async function load(\n url: string,\n context: LoadContext,\n nextLoad: NextLoad,\n): Promise<LoadResult> {\n // Handle HTTPS URLs\n if (url.startsWith(\"https://\")) {\n const source = await fetchModule(url, get);\n return {\n format: \"module\",\n shortCircuit: true,\n source: patchCreateRequire(source),\n };\n }\n\n // Handle HTTP URLs (for local development)\n if (url.startsWith(\"http://\")) {\n const source = await fetchModule(url, httpGet);\n return {\n format: \"module\",\n shortCircuit: true,\n source: patchCreateRequire(source),\n };\n }\n\n // Let Node.js handle all other URLs\n return nextLoad(url, context);\n}\n\n/**\n * Rewrite `createRequire(import.meta.url)` in HTTP-loaded modules so that\n * `createRequire` receives a local file URL instead of an HTTP URL it cannot handle.\n */\nfunction patchCreateRequire(source: string): string {\n return source.replace(\n /createRequire\\(import\\.meta\\.url\\)/g,\n `createRequire(new URL(\"file://\" + process.cwd() + \"/\"))`,\n );\n}\n\nfunction fetchModule(\n url: string,\n getter: typeof get | typeof httpGet,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n getter(url, (res) => {\n // Handle redirects\n if (\n res.statusCode &&\n res.statusCode >= 300 &&\n res.statusCode < 400 &&\n res.headers.location\n ) {\n const redirectUrl = res.headers.location;\n const redirectGetter = redirectUrl.startsWith(\"https://\")\n ? get\n : httpGet;\n fetchModule(redirectUrl, redirectGetter).then(resolve).catch(reject);\n return;\n }\n\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`Failed to fetch ${url}: ${res.statusCode}`));\n return;\n }\n\n let data = \"\";\n res.setEncoding(\"utf8\");\n res.on(\"data\", (chunk) => (data += chunk));\n res.on(\"end\", () => resolve(data));\n res.on(\"error\", reject);\n }).on(\"error\", reject);\n });\n}\n\n/**\n * Path to this hooks file for use with node:module register()\n */\nexport const httpsHooksPath: string = import.meta.url;\n"],"names":["get","httpGet"],"mappings":";;;;;;;;AA0BA,eAAsB,QACpB,WACA,SACA,aACwB;CACxB,MAAM,EAAE,cAAc;AAGtB,KAAI,UAAU,WAAW,WAAW,IAAI,UAAU,WAAW,UAAU,CACrE,QAAO;EAAE,KAAK;EAAW,cAAc;EAAM,QAAQ;EAAU;AAKjE,KACE,cACC,UAAU,WAAW,WAAW,IAAI,UAAU,WAAW,UAAU,MACnE,UAAU,WAAW,KAAK,IAAI,UAAU,WAAW,MAAM,EAG1D,QAAO;EAAE,KADQ,IAAI,IAAI,WAAW,UAAU,CAAC;EACvB,cAAc;EAAM,QAAQ;EAAU;AAiBhE,KACE,cACC,UAAU,WAAW,WAAW,IAAI,UAAU,WAAW,UAAU;MAGlE,CAAC,UAAU,WAAW,IAAI,IAAI,CAAC,uBAAuB,KAAK,UAAU,EAClD;GACnB,MAAM,EAAE,kBAAkB,MAAM,OAAO;GACvC,MAAM,eAAe,cAAc,QAAQ,KAAK,GAAG,IAAI,CAAC;AACxD,OAAI;AACF,WAAO,MAAM,YAAY,WAAW;KAClC,GAAG;KACH,WAAW;KACZ,CAAC;YACK,GAAG;AAEV,QADc,GAAyC,SAC1C,uBAAwB,OAAM;AAC3C,WAAO,YAAY,WAAW;KAC5B,GAAG;KACH,WAAW,OAAO,KAAK;KACxB,CAAC;;;;AAMR,QAAO,YAAY,WAAW,QAAQ;;;;;AAMxC,eAAsB,KACpB,KACA,SACA,UACqB;AAErB,KAAI,IAAI,WAAW,WAAW,CAE5B,QAAO;EACL,QAAQ;EACR,cAAc;EACd,QAAQ,mBAJK,MAAM,YAAY,KAAKA,MAAI,CAIN;EACnC;AAIH,KAAI,IAAI,WAAW,UAAU,CAE3B,QAAO;EACL,QAAQ;EACR,cAAc;EACd,QAAQ,mBAJK,MAAM,YAAY,KAAKC,IAAQ,CAIV;EACnC;AAIH,QAAO,SAAS,KAAK,QAAQ;;;;;;AAO/B,SAAS,mBAAmB,QAAwB;AAClD,QAAO,OAAO,QACZ,uCACA,0DACD;;AAGH,SAAS,YACP,KACA,QACiB;AACjB,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,SAAO,MAAM,QAAQ;AAEnB,OACE,IAAI,cACJ,IAAI,cAAc,OAClB,IAAI,aAAa,OACjB,IAAI,QAAQ,UACZ;IACA,MAAM,cAAc,IAAI,QAAQ;AAIhC,gBAAY,aAHW,YAAY,WAAW,WAAW,GACrDD,QACAC,IACoC,CAAC,KAAK,QAAQ,CAAC,MAAM,OAAO;AACpE;;AAGF,OAAI,IAAI,cAAc,IAAI,cAAc,KAAK;AAC3C,2BAAO,IAAI,MAAM,mBAAmB,IAAI,IAAI,IAAI,aAAa,CAAC;AAC9D;;GAGF,IAAI,OAAO;AACX,OAAI,YAAY,OAAO;AACvB,OAAI,GAAG,SAAS,UAAW,QAAQ,MAAO;AAC1C,OAAI,GAAG,aAAa,QAAQ,KAAK,CAAC;AAClC,OAAI,GAAG,SAAS,OAAO;IACvB,CAAC,GAAG,SAAS,OAAO;GACtB;;;;;AAMJ,MAAa,iBAAyB,OAAO,KAAK","debug_id":"0a57348f-eab9-5103-83ff-b067482a7ea8"}
|
package/dist/utils-BFkbSO_H.mjs
CHANGED
|
@@ -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]="f64c0238-0280-5fb7-9cf2-93c99d05e219")}catch(e){}}();
|
|
3
3
|
import { gql } from "graphql-tag";
|
|
4
4
|
import { GraphQLError } from "graphql";
|
|
5
5
|
import { childLogger } from "document-model";
|
|
@@ -293,4 +293,4 @@ function buildGraphQlDriveDocument(doc) {
|
|
|
293
293
|
export { isSubgraphClass as a, loadDocumentModels as c, BaseSubgraph as d, buildGraphqlOperations as i, loadProcessors as l, buildGraphQlDriveDocument as n, debounce as o, buildGraphqlOperation as r, isSubpath as s, buildGraphQlDocument as t, loadSubgraphs as u };
|
|
294
294
|
|
|
295
295
|
//# sourceMappingURL=utils-BFkbSO_H.mjs.map
|
|
296
|
-
//# debugId=
|
|
296
|
+
//# debugId=f64c0238-0280-5fb7-9cf2-93c99d05e219
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils-BFkbSO_H.mjs","sources":["../src/graphql/base-subgraph.ts","../src/packages/import-resolver.ts","../src/packages/util.ts","../src/graphql/utils.ts"],"sourcesContent":["import type {\n IReactorClient,\n IRelationalDb,\n ISyncManager,\n} from \"@powerhousedao/reactor\";\nimport type {\n GraphQLManager,\n ISubgraph,\n SubgraphArgs,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentNode } from \"graphql\";\nimport { GraphQLError } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nimport type { AuthorizationService } from \"../services/authorization.service.js\";\nimport type {\n DocumentPermissionService,\n GetParentIdsFn,\n} from \"../services/document-permission.service.js\";\nimport type { Context } from \"./types.js\";\n\nexport class BaseSubgraph implements ISubgraph {\n name = \"example\";\n path = \"\";\n resolvers: Record<string, any> = {\n Query: {\n hello: () => this.name,\n },\n };\n typeDefs: DocumentNode = gql`\n type Query {\n hello: String\n }\n `;\n reactorClient: IReactorClient;\n graphqlManager: GraphQLManager;\n relationalDb: IRelationalDb;\n syncManager: ISyncManager;\n documentPermissionService?: DocumentPermissionService;\n authorizationService?: AuthorizationService;\n\n constructor(args: SubgraphArgs) {\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.path = args.path ?? \"\";\n }\n\n async onSetup() {\n // noop\n }\n\n // ============================================\n // Shared permission helpers\n // ============================================\n\n protected getParentIdsFn(): GetParentIdsFn {\n return async (documentId: string): Promise<string[]> => {\n try {\n const result = await this.reactorClient.getIncomingRelationships(\n documentId,\n \"child\",\n );\n return result.results.map((doc) => doc.header.id);\n } catch {\n return [];\n }\n };\n }\n\n protected hasGlobalAdminAccess(ctx: Context): boolean {\n return !!ctx.isAdmin?.(ctx.user?.address ?? \"\");\n }\n\n protected async canReadDocument(\n documentId: string,\n ctx: Context,\n ): Promise<boolean> {\n if (this.authorizationService) {\n return this.authorizationService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n }\n if (this.hasGlobalAdminAccess(ctx)) return true;\n if (this.documentPermissionService) {\n return this.documentPermissionService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n }\n return false;\n }\n\n protected async assertCanRead(\n documentId: string,\n ctx: Context,\n ): Promise<void> {\n if (this.authorizationService) {\n const canRead = await this.authorizationService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canRead) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to read this document\",\n );\n }\n return;\n }\n // Legacy fallback\n if (!this.hasGlobalAdminAccess(ctx)) {\n if (this.documentPermissionService) {\n const canRead = await this.documentPermissionService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canRead) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to read this document\",\n );\n }\n } else {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to read this document\",\n );\n }\n }\n }\n\n protected async assertCanWrite(\n documentId: string,\n ctx: Context,\n ): Promise<void> {\n if (this.authorizationService) {\n const canWrite = await this.authorizationService.canWrite(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canWrite) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to write to this document\",\n );\n }\n return;\n }\n // Legacy fallback\n if (!this.hasGlobalAdminAccess(ctx)) {\n if (this.documentPermissionService) {\n const canWrite = await this.documentPermissionService.canWrite(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canWrite) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to write to this document\",\n );\n }\n } else {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to write to this document\",\n );\n }\n }\n }\n\n protected async assertCanExecuteOperation(\n documentId: string,\n operationType: string,\n ctx: Context,\n ): Promise<void> {\n if (this.authorizationService) {\n const canMutate = await this.authorizationService.canMutate(\n documentId,\n operationType,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canMutate) {\n throw new GraphQLError(\n `Forbidden: insufficient permissions to execute operation \"${operationType}\" on this document`,\n );\n }\n return;\n }\n // Legacy fallback\n if (!this.documentPermissionService) return;\n if (ctx.isAdmin?.(ctx.user?.address ?? \"\")) return;\n const isRestricted =\n await this.documentPermissionService.isOperationRestricted(\n documentId,\n operationType,\n );\n if (isRestricted) {\n const canExecute =\n await this.documentPermissionService.canExecuteOperation(\n documentId,\n operationType,\n ctx.user?.address,\n );\n if (!canExecute) {\n throw new GraphQLError(\n `Forbidden: insufficient permissions to execute operation \"${operationType}\" on this document`,\n );\n }\n }\n }\n}\n","import path from \"node:path\";\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 import(/* @vite-ignore */ suggestedPath)) as T;\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 const packageRoot = path.dirname(new URL(resolvedUrl).pathname);\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 import(/* @vite-ignore */ attemptPath)) as T;\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 import(/* @vite-ignore */ workspacePath)) as T;\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 { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport { execSync } from \"node:child_process\";\nimport path from \"node:path\";\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 = async (packages: string[]) => {\n for (const packageName of packages) {\n execSync(`ph install ${packageName}`);\n }\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 const fullPath = `${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 if (\n e instanceof Error &&\n \"code\" in e &&\n (e.code === \"ERR_MODULE_NOT_FOUND\" ||\n e.code === \"ERR_UNSUPPORTED_DIR_IMPORT\")\n ) {\n const result = await resolveLinkedPackage<T>(packageName, subPath);\n if (result) return result;\n }\n throw e;\n }\n}\n\nexport function debounce<T extends unknown[], R>(\n func: (...args: T) => Promise<R>,\n delay = 250,\n) {\n let timer: number;\n return (immediate = false, ...args: T) => {\n if (timer) {\n clearTimeout(timer);\n }\n return new Promise<R>((resolve, reject) => {\n if (immediate) {\n func(...args)\n .then(resolve)\n .catch(reject);\n } else {\n timer = setTimeout(() => {\n func(...args)\n .then(resolve)\n .catch(reject);\n }, delay) as unknown as number;\n }\n });\n };\n}\n\nexport function isSubpath(parent: string, dir: string) {\n const relative = path.relative(parent, dir);\n return relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n","import type {\n GqlDocument,\n GqlDriveDocument,\n GqlOperation,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type {\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\n\nexport function isSubgraphClass(\n candidate: unknown,\n): candidate is SubgraphClass {\n if (typeof candidate !== \"function\") return false;\n\n let proto: unknown = Object.getPrototypeOf(candidate);\n while (proto) {\n if (Object.prototype.isPrototypeOf.call(proto, BaseSubgraph)) return true;\n\n proto = Object.getPrototypeOf(proto);\n }\n\n return false;\n}\n\nexport function buildGraphqlOperations(\n operations: Operation[],\n skip: number,\n first: number,\n): GqlOperation[] {\n return operations.slice(skip, skip + first).map(buildGraphqlOperation);\n}\n\nexport function buildGraphqlOperation(operation: Operation): GqlOperation {\n const signer = operation.action.context?.signer;\n return {\n id: operation.id ?? \"\",\n type: operation.action.type,\n index: operation.index,\n timestampUtcMs: operation.timestampUtcMs,\n hash: operation.hash,\n skip: operation.skip,\n inputText:\n typeof operation.action.input === \"string\"\n ? operation.action.input\n : JSON.stringify(operation.action.input),\n error: operation.error,\n context: {\n signer: signer\n ? {\n user: signer.user,\n app: signer.app,\n signatures: signer.signatures.map((sig) =>\n Array.isArray(sig) ? sig.join(\", \") : sig,\n ),\n }\n : undefined,\n },\n };\n}\n\nexport function buildGraphQlDocument(doc: PHDocument): GqlDocument {\n // Return full state with all scopes (auth, document, global, local)\n // This matches the ReactorSubgraph pattern in adapters.ts\n const state = doc.state;\n const initialState = doc.initialState;\n // For stateJSON, use global state for backward compatibility\n const globalState = \"global\" in doc.state ? doc.state.global : {};\n return {\n id: doc.header.id,\n name: doc.header.name,\n documentType: doc.header.documentType,\n revision: doc.header.revision.global || 0,\n createdAtUtcIso: doc.header.createdAtUtcIso,\n lastModifiedAtUtcIso: doc.header.lastModifiedAtUtcIso,\n operations: [],\n stateJSON: globalState as JSON,\n state,\n initialState,\n };\n}\n\nexport function buildGraphQlDriveDocument(\n doc: DocumentDriveDocument,\n): GqlDriveDocument {\n const gqlDoc = buildGraphQlDocument(doc);\n return {\n ...gqlDoc,\n meta: {\n preferredEditor: doc.header.meta?.preferredEditor,\n },\n slug: doc.header.slug,\n state: doc.state.global,\n initialState: doc.state.global,\n };\n}\n"],"names":[],"mappings":"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","debug_id":"e8b85da7-0078-579c-8d72-5c00006a8107"}
|
|
1
|
+
{"version":3,"file":"utils-BFkbSO_H.mjs","sources":["../src/graphql/base-subgraph.ts","../src/packages/import-resolver.ts","../src/packages/util.ts","../src/graphql/utils.ts"],"sourcesContent":["import type {\n IReactorClient,\n IRelationalDb,\n ISyncManager,\n} from \"@powerhousedao/reactor\";\nimport type {\n GraphQLManager,\n ISubgraph,\n SubgraphArgs,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentNode } from \"graphql\";\nimport { GraphQLError } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nimport type { AuthorizationService } from \"../services/authorization.service.js\";\nimport type {\n DocumentPermissionService,\n GetParentIdsFn,\n} from \"../services/document-permission.service.js\";\nimport type { Context } from \"./types.js\";\n\nexport class BaseSubgraph implements ISubgraph {\n name = \"example\";\n path = \"\";\n resolvers: Record<string, any> = {\n Query: {\n hello: () => this.name,\n },\n };\n typeDefs: DocumentNode = gql`\n type Query {\n hello: String\n }\n `;\n reactorClient: IReactorClient;\n graphqlManager: GraphQLManager;\n relationalDb: IRelationalDb;\n syncManager: ISyncManager;\n documentPermissionService?: DocumentPermissionService;\n authorizationService?: AuthorizationService;\n\n constructor(args: SubgraphArgs) {\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.path = args.path ?? \"\";\n }\n\n async onSetup() {\n // noop\n }\n\n // ============================================\n // Shared permission helpers\n // ============================================\n\n protected getParentIdsFn(): GetParentIdsFn {\n return async (documentId: string): Promise<string[]> => {\n try {\n const result = await this.reactorClient.getIncomingRelationships(\n documentId,\n \"child\",\n );\n return result.results.map((doc) => doc.header.id);\n } catch {\n return [];\n }\n };\n }\n\n protected hasGlobalAdminAccess(ctx: Context): boolean {\n return !!ctx.isAdmin?.(ctx.user?.address ?? \"\");\n }\n\n protected async canReadDocument(\n documentId: string,\n ctx: Context,\n ): Promise<boolean> {\n if (this.authorizationService) {\n return this.authorizationService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n }\n if (this.hasGlobalAdminAccess(ctx)) return true;\n if (this.documentPermissionService) {\n return this.documentPermissionService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n }\n return false;\n }\n\n protected async assertCanRead(\n documentId: string,\n ctx: Context,\n ): Promise<void> {\n if (this.authorizationService) {\n const canRead = await this.authorizationService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canRead) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to read this document\",\n );\n }\n return;\n }\n // Legacy fallback\n if (!this.hasGlobalAdminAccess(ctx)) {\n if (this.documentPermissionService) {\n const canRead = await this.documentPermissionService.canRead(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canRead) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to read this document\",\n );\n }\n } else {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to read this document\",\n );\n }\n }\n }\n\n protected async assertCanWrite(\n documentId: string,\n ctx: Context,\n ): Promise<void> {\n if (this.authorizationService) {\n const canWrite = await this.authorizationService.canWrite(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canWrite) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to write to this document\",\n );\n }\n return;\n }\n // Legacy fallback\n if (!this.hasGlobalAdminAccess(ctx)) {\n if (this.documentPermissionService) {\n const canWrite = await this.documentPermissionService.canWrite(\n documentId,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canWrite) {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to write to this document\",\n );\n }\n } else {\n throw new GraphQLError(\n \"Forbidden: insufficient permissions to write to this document\",\n );\n }\n }\n }\n\n protected async assertCanExecuteOperation(\n documentId: string,\n operationType: string,\n ctx: Context,\n ): Promise<void> {\n if (this.authorizationService) {\n const canMutate = await this.authorizationService.canMutate(\n documentId,\n operationType,\n ctx.user?.address,\n this.getParentIdsFn(),\n );\n if (!canMutate) {\n throw new GraphQLError(\n `Forbidden: insufficient permissions to execute operation \"${operationType}\" on this document`,\n );\n }\n return;\n }\n // Legacy fallback\n if (!this.documentPermissionService) return;\n if (ctx.isAdmin?.(ctx.user?.address ?? \"\")) return;\n const isRestricted =\n await this.documentPermissionService.isOperationRestricted(\n documentId,\n operationType,\n );\n if (isRestricted) {\n const canExecute =\n await this.documentPermissionService.canExecuteOperation(\n documentId,\n operationType,\n ctx.user?.address,\n );\n if (!canExecute) {\n throw new GraphQLError(\n `Forbidden: insufficient permissions to execute operation \"${operationType}\" on this document`,\n );\n }\n }\n }\n}\n","import path from \"node:path\";\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 import(/* @vite-ignore */ suggestedPath)) as T;\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 const packageRoot = path.dirname(new URL(resolvedUrl).pathname);\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 import(/* @vite-ignore */ attemptPath)) as T;\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 import(/* @vite-ignore */ workspacePath)) as T;\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 { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport { execSync } from \"node:child_process\";\nimport path from \"node:path\";\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 const fullPath = `${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 if (\n e instanceof Error &&\n \"code\" in e &&\n (e.code === \"ERR_MODULE_NOT_FOUND\" ||\n e.code === \"ERR_UNSUPPORTED_DIR_IMPORT\")\n ) {\n const result = await resolveLinkedPackage<T>(packageName, subPath);\n if (result) return result;\n }\n throw e;\n }\n}\n\nexport function debounce<T extends unknown[], R>(\n func: (...args: T) => Promise<R>,\n delay = 250,\n) {\n let timer: number;\n return (immediate = false, ...args: T) => {\n if (timer) {\n clearTimeout(timer);\n }\n return new Promise<R>((resolve, reject) => {\n if (immediate) {\n func(...args)\n .then(resolve)\n .catch(reject);\n } else {\n timer = setTimeout(() => {\n func(...args)\n .then(resolve)\n .catch(reject);\n }, delay) as unknown as number;\n }\n });\n };\n}\n\nexport function isSubpath(parent: string, dir: string) {\n const relative = path.relative(parent, dir);\n return relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n","import type {\n GqlDocument,\n GqlDriveDocument,\n GqlOperation,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type {\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\n\nexport function isSubgraphClass(\n candidate: unknown,\n): candidate is SubgraphClass {\n if (typeof candidate !== \"function\") return false;\n\n let proto: unknown = Object.getPrototypeOf(candidate);\n while (proto) {\n if (Object.prototype.isPrototypeOf.call(proto, BaseSubgraph)) return true;\n\n proto = Object.getPrototypeOf(proto);\n }\n\n return false;\n}\n\nexport function buildGraphqlOperations(\n operations: Operation[],\n skip: number,\n first: number,\n): GqlOperation[] {\n return operations.slice(skip, skip + first).map(buildGraphqlOperation);\n}\n\nexport function buildGraphqlOperation(operation: Operation): GqlOperation {\n const signer = operation.action.context?.signer;\n return {\n id: operation.id ?? \"\",\n type: operation.action.type,\n index: operation.index,\n timestampUtcMs: operation.timestampUtcMs,\n hash: operation.hash,\n skip: operation.skip,\n inputText:\n typeof operation.action.input === \"string\"\n ? operation.action.input\n : JSON.stringify(operation.action.input),\n error: operation.error,\n context: {\n signer: signer\n ? {\n user: signer.user,\n app: signer.app,\n signatures: signer.signatures.map((sig) =>\n Array.isArray(sig) ? sig.join(\", \") : sig,\n ),\n }\n : undefined,\n },\n };\n}\n\nexport function buildGraphQlDocument(doc: PHDocument): GqlDocument {\n // Return full state with all scopes (auth, document, global, local)\n // This matches the ReactorSubgraph pattern in adapters.ts\n const state = doc.state;\n const initialState = doc.initialState;\n // For stateJSON, use global state for backward compatibility\n const globalState = \"global\" in doc.state ? doc.state.global : {};\n return {\n id: doc.header.id,\n name: doc.header.name,\n documentType: doc.header.documentType,\n revision: doc.header.revision.global || 0,\n createdAtUtcIso: doc.header.createdAtUtcIso,\n lastModifiedAtUtcIso: doc.header.lastModifiedAtUtcIso,\n operations: [],\n stateJSON: globalState as JSON,\n state,\n initialState,\n };\n}\n\nexport function buildGraphQlDriveDocument(\n doc: DocumentDriveDocument,\n): GqlDriveDocument {\n const gqlDoc = buildGraphQlDocument(doc);\n return {\n ...gqlDoc,\n meta: {\n preferredEditor: doc.header.meta?.preferredEditor,\n },\n slug: doc.header.slug,\n state: doc.state.global,\n initialState: doc.state.global,\n };\n}\n"],"names":[],"mappings":"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","debug_id":"f64c0238-0280-5fb7-9cf2-93c99d05e219"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/reactor-api",
|
|
3
|
-
"version": "6.1.0-dev.
|
|
3
|
+
"version": "6.1.0-dev.20",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -65,18 +65,18 @@
|
|
|
65
65
|
"read-pkg": "10.1.0",
|
|
66
66
|
"ws": "^8.18.3",
|
|
67
67
|
"zod": "4.3.6",
|
|
68
|
-
"@powerhousedao/analytics-engine-core": "6.1.0-dev.
|
|
69
|
-
"@powerhousedao/analytics-engine-
|
|
70
|
-
"@powerhousedao/
|
|
71
|
-
"@powerhousedao/
|
|
72
|
-
"@powerhousedao/pglite-fs": "6.1.0-dev.
|
|
73
|
-
"@powerhousedao/reactor": "6.1.0-dev.
|
|
74
|
-
"@powerhousedao/reactor-attachments": "6.1.0-dev.
|
|
75
|
-
"@powerhousedao/reactor-drive": "6.1.0-dev.
|
|
76
|
-
"@powerhousedao/shared": "6.1.0-dev.
|
|
77
|
-
"@renown/sdk": "6.1.0-dev.
|
|
78
|
-
"document-model": "6.1.0-dev.
|
|
79
|
-
"@powerhousedao/reactor-mcp": "6.1.0-dev.
|
|
68
|
+
"@powerhousedao/analytics-engine-core": "6.1.0-dev.20",
|
|
69
|
+
"@powerhousedao/analytics-engine-pg": "6.1.0-dev.20",
|
|
70
|
+
"@powerhousedao/analytics-engine-graphql": "6.1.0-dev.20",
|
|
71
|
+
"@powerhousedao/config": "6.1.0-dev.20",
|
|
72
|
+
"@powerhousedao/pglite-fs": "6.1.0-dev.20",
|
|
73
|
+
"@powerhousedao/reactor": "6.1.0-dev.20",
|
|
74
|
+
"@powerhousedao/reactor-attachments": "6.1.0-dev.20",
|
|
75
|
+
"@powerhousedao/reactor-drive": "6.1.0-dev.20",
|
|
76
|
+
"@powerhousedao/shared": "6.1.0-dev.20",
|
|
77
|
+
"@renown/sdk": "6.1.0-dev.20",
|
|
78
|
+
"document-model": "6.1.0-dev.20",
|
|
79
|
+
"@powerhousedao/reactor-mcp": "6.1.0-dev.20"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@fastify/cors": "^11.0.1",
|
|
@@ -141,6 +141,7 @@
|
|
|
141
141
|
"build": "tsdown",
|
|
142
142
|
"lint": "eslint",
|
|
143
143
|
"test": "vitest --run",
|
|
144
|
+
"test:integration": "RUN_HUB_SPOKE_INTEGRATION=1 vitest --run test/hub-spoke-catchup.integration.test.ts",
|
|
144
145
|
"bench": "vitest bench",
|
|
145
146
|
"codegen": "graphql-codegen --config codegen.ts && prettier --write src/graphql/reactor/gen/*.ts && eslint --fix src/graphql/reactor/gen/*.ts --no-warn-ignored",
|
|
146
147
|
"codegen:watch": "graphql-codegen --config codegen.ts --watch",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-http-express-DO4ui7AV.mjs","sources":["../src/graphql/gateway/adapter-http-express.ts"],"sourcesContent":["import bodyParser from \"body-parser\";\nimport cors from \"cors\";\nimport type { CorsOptions } from \"cors\";\nimport devcert from \"devcert\";\nimport type express from \"express\";\nimport type { Express } from \"express\";\nimport { Router } from \"express\";\nimport expressLib from \"express\";\nimport type { IRouter } from \"express\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport path from \"node:path\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type { FetchHandler, IHttpAdapter, TlsOptions } from \"./types.js\";\n\nexport class ExpressHttpAdapter implements IHttpAdapter {\n readonly #app: Express;\n readonly #router: IRouter;\n readonly #handlers = new Map<\n string,\n { handler: FetchHandler; matcher: MatchFunction<ParamData> }\n >();\n\n constructor(existingApp?: Express) {\n this.#app = existingApp ?? expressLib();\n this.#router = Router();\n this.#app.use(this.#router);\n }\n\n setupSentryErrorHandler(sentry: object): void {\n const s = sentry as {\n setupExpressErrorHandler(app: Express): void;\n };\n s.setupExpressErrorHandler(this.#app);\n }\n\n get handle(): unknown {\n return this.#app;\n }\n\n mountRawMiddleware(middleware: unknown): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#app.use(middleware as any);\n }\n\n mountNodeRoute(\n method: \"DELETE\" | \"GET\" | \"HEAD\" | \"POST\" | \"PUT\",\n path: string,\n handler: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n ) => void,\n ): void {\n const m = method.toLowerCase() as\n | \"delete\"\n | \"get\"\n | \"head\"\n | \"post\"\n | \"put\";\n this.#app[m](path, (req: express.Request, res: express.Response) =>\n handler(req, res, req.body as unknown),\n );\n }\n\n setupMiddleware({\n corsOptions,\n bodyLimit = \"50mb\",\n }: {\n corsOptions?: CorsOptions;\n bodyLimit?: string;\n }): void {\n this.#router.use(cors(corsOptions));\n this.#router.use(bodyParser.json({ limit: bodyLimit }));\n this.#router.use(\n bodyParser.urlencoded({ extended: true, limit: bodyLimit }),\n );\n\n // Dispatcher registered AFTER bodyParser so req.body is populated when it fires.\n this.#router.use((req, res, next) => {\n for (const { handler, matcher } of this.#handlers.values()) {\n if (matcher(req.path)) {\n this.#serveFetchHandler(handler, req, res, next);\n return;\n }\n }\n next();\n });\n }\n\n mount(\n path: string,\n handler: FetchHandler,\n { exact = false }: { exact?: boolean } = {},\n ): void {\n if (exact) {\n this.#router.use(path, (req, res, next) =>\n this.#serveFetchHandler(handler, req, res, next),\n );\n } else {\n // Exact match - stored in the internal dispatch map\n this.#handlers.set(path, {\n handler,\n matcher: match(path),\n });\n }\n }\n\n getRoute(\n routePath: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): void {\n this.#app.get(routePath, (req, res) => {\n const protocol = req.protocol;\n const host = req.get(\"host\") ?? \"localhost\";\n const url = `${protocol}://${host}${req.originalUrl}`;\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n }\n }\n const fetchRequest = new Request(url, { method: \"GET\", headers });\n Promise.resolve(handler(fetchRequest))\n .then(async (response) => {\n res.status(response.status);\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n res.send(await response.text());\n })\n .catch((err: unknown) => {\n res.status(500).send(String(err));\n });\n });\n }\n\n async listen(port: number, tls?: TlsOptions): Promise<http.Server> {\n let server: http.Server;\n\n if (tls === true) {\n const { cert, key } = (await devcert.certificateFor(\"localhost\")) as {\n cert: Buffer;\n key: Buffer;\n };\n if (!cert || !key) {\n throw new Error(\"Invalid certificate generated\");\n }\n server = https.createServer({ cert, key }, this.#app);\n } else if (tls && \"keyPath\" in tls) {\n const currentDir = process.cwd();\n server = https.createServer(\n {\n key: fs.readFileSync(path.join(currentDir, tls.keyPath)),\n cert: fs.readFileSync(path.join(currentDir, tls.certPath)),\n },\n this.#app,\n );\n } else if (tls && \"cert\" in tls) {\n server = https.createServer({ cert: tls.cert, key: tls.key }, this.#app);\n } else {\n server = http.createServer(this.#app);\n }\n\n return new Promise<http.Server>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, () => {\n server.off(\"error\", reject);\n resolve(server);\n });\n });\n }\n\n #serveFetchHandler(\n handler: FetchHandler,\n req: express.Request,\n res: express.Response,\n next: express.NextFunction,\n ): void {\n // Build the full URL for the Fetch Request\n const protocol = req.protocol;\n const host = req.get(\"host\") ?? \"localhost\";\n const url = `${protocol}://${host}${req.originalUrl}`;\n\n // Convert Node.js incoming headers to Fetch Headers\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n }\n }\n\n // bodyParser has already run, so req.body is a parsed JS value.\n // Re-serialize it so the Fetch Request body stream is readable.\n let body: string | undefined;\n if (\n req.method !== \"GET\" &&\n req.method !== \"HEAD\" &&\n req.body !== undefined\n ) {\n body = JSON.stringify(req.body);\n }\n\n const fetchRequest = new Request(url, {\n method: req.method,\n headers,\n body,\n });\n\n Promise.resolve(handler(fetchRequest))\n .then(async (response) => {\n res.status(response.status);\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n const responseBody = await response.text();\n res.send(responseBody);\n })\n .catch(next);\n }\n}\n\nexport function createExpressHttpAdapter(existingApp?: Express): {\n adapter: IHttpAdapter;\n} {\n return { adapter: new ExpressHttpAdapter(existingApp) };\n}\n"],"names":["#app","#router","#handlers","#serveFetchHandler"],"mappings":"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","debug_id":"c2b574f7-cae6-5b39-aba7-5ea03cd99a0b"}
|