@powerhousedao/reactor-api 6.2.3-dev.2 → 6.2.3-dev.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/{adapter-gateway-apollo-DdamNLPT.mjs → adapter-gateway-apollo-CxJNBVyD.mjs} +7 -8
  2. package/dist/adapter-gateway-apollo-CxJNBVyD.mjs.map +1 -0
  3. package/dist/adapter-gateway-apollo-DowrX6E_.mjs +4 -0
  4. package/dist/{adapter-gateway-mercurius-CLmTtNJC.mjs → adapter-gateway-mercurius-CZVy88Za.mjs} +6 -5
  5. package/dist/adapter-gateway-mercurius-CZVy88Za.mjs.map +1 -0
  6. package/dist/adapter-gateway-stitching-CaZjvRzx.mjs +316 -0
  7. package/dist/adapter-gateway-stitching-CaZjvRzx.mjs.map +1 -0
  8. package/dist/{adapter-http-express-54gdI9bu.mjs → adapter-http-express-B39rPhqH.mjs} +4 -4
  9. package/dist/{adapter-http-express-54gdI9bu.mjs.map → adapter-http-express-B39rPhqH.mjs.map} +1 -1
  10. package/dist/{adapter-http-fastify-DmccBVOe.mjs → adapter-http-fastify-BwXO6rqE.mjs} +4 -4
  11. package/dist/{adapter-http-fastify-DmccBVOe.mjs.map → adapter-http-fastify-BwXO6rqE.mjs.map} +1 -1
  12. package/dist/index.d.mts +303 -18
  13. package/dist/index.d.mts.map +1 -1
  14. package/dist/index.mjs +523 -60
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/{path-normalize-DWWFLiy6.mjs → path-normalize-BOQwY9wR.mjs} +3 -3
  17. package/dist/{path-normalize-DWWFLiy6.mjs.map → path-normalize-BOQwY9wR.mjs.map} +1 -1
  18. package/dist/{utils-XWVecaNn.mjs → pieces-eqj2RKgd.mjs} +95 -5
  19. package/dist/pieces-eqj2RKgd.mjs.map +1 -0
  20. package/dist/src/packages/vite-loader.d.mts +6 -1
  21. package/dist/src/packages/vite-loader.d.mts.map +1 -1
  22. package/dist/src/packages/vite-loader.mjs +65 -6
  23. package/dist/src/packages/vite-loader.mjs.map +1 -1
  24. package/dist/{types-Bz2niABC.d.mts → types-BXjLvTe3.d.mts} +25 -2
  25. package/dist/types-BXjLvTe3.d.mts.map +1 -0
  26. package/package.json +17 -14
  27. package/dist/adapter-gateway-apollo-DdamNLPT.mjs.map +0 -1
  28. package/dist/adapter-gateway-mercurius-CLmTtNJC.mjs.map +0 -1
  29. package/dist/types-Bz2niABC.d.mts.map +0 -1
  30. package/dist/utils-XWVecaNn.mjs.map +0 -1
@@ -12,12 +12,12 @@
12
12
  * shapes regardless of which framework is in use.
13
13
  */
14
14
 
15
- !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]="f2d4c602-31b8-5f1c-aa79-49d1d196b0c0")}catch(e){}}();
15
+ !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]="f73d6dcb-dc2c-52e3-abd2-3653df07260f")}catch(e){}}();
16
16
  function normalizePath(path) {
17
17
  return path.replace(/\/+/g, "/").replace(/\/:(\w+)\?/g, "{/:$1}");
18
18
  }
19
19
  //#endregion
20
20
  export { normalizePath as t };
21
21
 
22
- //# sourceMappingURL=path-normalize-DWWFLiy6.mjs.map
23
- //# debugId=f2d4c602-31b8-5f1c-aa79-49d1d196b0c0
22
+ //# sourceMappingURL=path-normalize-BOQwY9wR.mjs.map
23
+ //# debugId=f73d6dcb-dc2c-52e3-abd2-3653df07260f
@@ -1 +1 @@
1
- {"version":3,"file":"path-normalize-DWWFLiy6.mjs","sources":["../src/graphql/gateway/path-normalize.ts"],"sourcesContent":["/**\n * Normalises a route path for path-to-regexp v8:\n * - Collapses duplicate slashes (e.g. \"//explorer\" → \"/explorer\")\n * - Converts legacy optional-param syntax \"/:param?\" → \"{/:param}\". The\n * slash must move inside the group: in p-r v8 a group whose content\n * begins with \"/\" is what makes the slash and the parameter optional\n * together, while a literal \"/\" left in front of the group compiles to\n * a pattern that matches nothing (and v8 rejects a bare \":param?\").\n *\n * Shared by both http adapters so registry dispatch matches the same path\n * shapes regardless of which framework is in use.\n */\nexport function normalizePath(path: string): string {\n return path.replace(/\\/+/g, \"/\").replace(/\\/:(\\w+)\\?/g, \"{/:$1}\");\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAYA,SAAgB,cAAc,MAAsB;AAClD,QAAO,KAAK,QAAQ,QAAQ,IAAI,CAAC,QAAQ,eAAe,SAAS","debug_id":"f2d4c602-31b8-5f1c-aa79-49d1d196b0c0"}
1
+ {"version":3,"file":"path-normalize-BOQwY9wR.mjs","sources":["../src/graphql/gateway/path-normalize.ts"],"sourcesContent":["/**\n * Normalises a route path for path-to-regexp v8:\n * - Collapses duplicate slashes (e.g. \"//explorer\" → \"/explorer\")\n * - Converts legacy optional-param syntax \"/:param?\" → \"{/:param}\". The\n * slash must move inside the group: in p-r v8 a group whose content\n * begins with \"/\" is what makes the slash and the parameter optional\n * together, while a literal \"/\" left in front of the group compiles to\n * a pattern that matches nothing (and v8 rejects a bare \":param?\").\n *\n * Shared by both http adapters so registry dispatch matches the same path\n * shapes regardless of which framework is in use.\n */\nexport function normalizePath(path: string): string {\n return path.replace(/\\/+/g, \"/\").replace(/\\/:(\\w+)\\?/g, \"{/:$1}\");\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAYA,SAAgB,cAAc,MAAsB;AAClD,QAAO,KAAK,QAAQ,QAAQ,IAAI,CAAC,QAAQ,eAAe,SAAS","debug_id":"f73d6dcb-dc2c-52e3-abd2-3653df07260f"}
@@ -1,11 +1,13 @@
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]="df700b05-17ec-5ac9-b31f-f6f9cfcfa5f5")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="dc22b29d-c034-58d2-843a-dc38009f52ec")}catch(e){}}();
3
3
  import { gql } from "graphql-tag";
4
4
  import { GraphQLError } from "graphql";
5
5
  import { DRIVE_AUTH_ERROR_MESSAGES, RECOVERABLE_GRAPHQL_ERROR_CODES } from "@powerhousedao/reactor";
6
6
  import { childLogger } from "document-model";
7
- import path from "node:path";
7
+ import path, { dirname, isAbsolute, join } from "node:path";
8
+ import { existsSync } from "node:fs";
8
9
  import { fileURLToPath, pathToFileURL } from "node:url";
10
+ import { packageJsonExports } from "@powerhousedao/shared/clis/constants";
9
11
  //#region src/graphql/errors.ts
10
12
  /** Caller (authenticated or anonymous) lacks permission for the document. */
11
13
  var ForbiddenError = class extends GraphQLError {
@@ -647,7 +649,95 @@ function buildGraphQlDriveDocument(doc) {
647
649
  };
648
650
  }
649
651
  //#endregion
650
- export { createAuthorizationService as _, isSubgraphClass as a, MalformedStoredOperationError as b, isSubpath as c, loadSubgraphs as d, BaseSubgraph as f, AuthorizedDocumentHandle as g, AuthorizationPolicy as h, buildGraphqlOperations as i, loadDocumentModels as l, createCanonicalDocumentIdResolver as m, buildGraphQlDriveDocument as n, debounce as o, CanonicalDocumentIdResolutionError as p, buildGraphqlOperation as r, extractUpgradeManifests as s, buildGraphQlDocument as t, loadProcessors as u, AuthEvaluationUnsupportedError as v, ForbiddenError as y };
652
+ //#region src/packages/pieces.ts
653
+ /** The sub-entry every loader asks a package for its pieces through. */
654
+ const PIECES_SUBPATH = "pieces";
655
+ const BUILT_PIECE_LIST = packageJsonExports["./pieces"].node;
656
+ /** Where a package keeps its piece sources, for telling unbuilt from absent. */
657
+ const PIECE_SOURCE_LIST = join(PIECES_SUBPATH, "index.ts");
658
+ /** The nearest enclosing package.json, which `exports` usually hides. */
659
+ function packageRootOf(dir) {
660
+ let current = dir;
661
+ while (!existsSync(join(current, "package.json"))) {
662
+ const parent = dirname(current);
663
+ if (parent === current) return void 0;
664
+ current = parent;
665
+ }
666
+ return current;
667
+ }
668
+ function pieceListLocation(identifier) {
669
+ if (isAbsolute(identifier)) return {
670
+ root: identifier,
671
+ listPath: join(identifier, BUILT_PIECE_LIST)
672
+ };
673
+ const listPath = fileURLToPath(import.meta.resolve(`${identifier}/${PIECES_SUBPATH}`));
674
+ const root = packageRootOf(dirname(listPath));
675
+ if (!root) throw new Error(`No package.json above ${listPath}`);
676
+ return {
677
+ root,
678
+ listPath
679
+ };
680
+ }
681
+ function locatePieces(declared, context) {
682
+ const { root, identifier, logger } = context;
683
+ const located = [];
684
+ for (const piece of declared) {
685
+ const where = piece.entry ?? piece.bundle;
686
+ if (typeof where !== "string" || where === "") {
687
+ logger.warn("Piece @piece of @pkg declares neither a bundle nor an entry", piece.name, identifier);
688
+ continue;
689
+ }
690
+ const path = isAbsolute(where) ? where : join(root, where);
691
+ if (!(piece.entry ? existsSync(path) : existsSync(join(path, "package.json")))) {
692
+ logger.warn("Piece @piece of @pkg is declared but not built at @path", piece.name, identifier, path);
693
+ continue;
694
+ }
695
+ located.push({
696
+ name: piece.name,
697
+ version: piece.version,
698
+ ...piece.entry ? { entryPath: path } : { bundleDir: path }
699
+ });
700
+ }
701
+ return located;
702
+ }
703
+ function declaredPieces(module, identifier, logger) {
704
+ const namespace = module ?? {};
705
+ const declared = namespace.pieces ?? namespace.default;
706
+ if (!Array.isArray(declared)) {
707
+ logger.warn("The pieces list of @pkg exports no \"pieces\" array; it contributes none", identifier);
708
+ return;
709
+ }
710
+ return declared;
711
+ }
712
+ function piecesFromCdnList(module, baseUrl, identifier, logger) {
713
+ const declared = declaredPieces(module, identifier, logger);
714
+ if (!declared) return [];
715
+ const located = [];
716
+ for (const piece of declared) {
717
+ const where = piece.entry ?? piece.bundle;
718
+ if (typeof where !== "string" || where === "") {
719
+ logger.warn("Piece @piece of @pkg declares neither a bundle nor an entry", piece.name, identifier);
720
+ continue;
721
+ }
722
+ located.push({
723
+ name: piece.name,
724
+ version: piece.version,
725
+ entryUrl: `${baseUrl}${where.replace(/^dist\/node\/pieces\//, "")}`
726
+ });
727
+ }
728
+ return located;
729
+ }
730
+ function piecesFromListModule(module, context) {
731
+ const namespace = module ?? {};
732
+ const declared = namespace.pieces ?? namespace.default;
733
+ if (!Array.isArray(declared)) {
734
+ context.logger.warn("The pieces list of @pkg exports no \"pieces\" array; it contributes none", context.identifier);
735
+ return [];
736
+ }
737
+ return locatePieces(declared, context);
738
+ }
739
+ //#endregion
740
+ export { createAuthorizationService as C, MalformedStoredOperationError as D, ForbiddenError as E, AuthorizedDocumentHandle as S, AuthenticationRequiredError as T, loadSubgraphs as _, piecesFromCdnList as a, createCanonicalDocumentIdResolver as b, buildGraphQlDriveDocument as c, isSubgraphClass as d, debounce as f, loadProcessors as g, loadDocumentModels as h, pieceListLocation as i, buildGraphqlOperation as l, isSubpath as m, PIECES_SUBPATH as n, piecesFromListModule as o, extractUpgradeManifests as p, PIECE_SOURCE_LIST as r, buildGraphQlDocument as s, BUILT_PIECE_LIST as t, buildGraphqlOperations as u, BaseSubgraph as v, AuthEvaluationUnsupportedError as w, AuthorizationPolicy as x, CanonicalDocumentIdResolutionError as y };
651
741
 
652
- //# sourceMappingURL=utils-XWVecaNn.mjs.map
653
- //# debugId=df700b05-17ec-5ac9-b31f-f6f9cfcfa5f5
742
+ //# sourceMappingURL=pieces-eqj2RKgd.mjs.map
743
+ //# debugId=dc22b29d-c034-58d2-843a-dc38009f52ec
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pieces-eqj2RKgd.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/pieces.ts"],"sourcesContent":["import { GraphQLError } from \"graphql\";\nimport {\n DRIVE_AUTH_ERROR_MESSAGES,\n RECOVERABLE_GRAPHQL_ERROR_CODES,\n} from \"@powerhousedao/reactor\";\n\n/** Caller (authenticated or anonymous) lacks permission for the document. */\nexport class ForbiddenError extends GraphQLError {\n constructor(detail = \"\") {\n const base = DRIVE_AUTH_ERROR_MESSAGES.forbidden;\n super(`${base}${detail ? ` ${detail}` : \"\"}`, {\n extensions: { code: \"FORBIDDEN\" },\n });\n }\n}\n\n/** Anonymous caller on an action that requires logging in. */\nexport class AuthenticationRequiredError extends GraphQLError {\n constructor(detail = \"\") {\n const base = DRIVE_AUTH_ERROR_MESSAGES.authenticationRequired;\n super(`${base}${detail ? ` ${detail}` : \"\"}`, {\n extensions: { code: \"UNAUTHENTICATED\" },\n });\n }\n}\n\n/**\n * The reactor holds no decision model, so no authorization preflight can be\n * answered.\n *\n * Distinct from a denial, and deliberately so: a caller that cannot get a\n * prediction should render its controls as it did before it asked and let the\n * submit path refuse. Reading this as a denial would disable every control on a\n * switchboard running without authEnforcement. The code is what a client\n * branches on, since the message is not a contract.\n */\nexport class AuthEvaluationUnsupportedError extends GraphQLError {\n constructor() {\n super(\n \"Authorization evaluation is unavailable: this reactor runs without the \" +\n \"authEnforcement feature flag, so it holds no decision model\",\n { extensions: { code: \"AUTH_EVALUATION_UNSUPPORTED\" } },\n );\n }\n}\n\n/**\n * A stored operation cannot be represented in the schema, so it is reported\n * rather than served.\n *\n * The schema declares an action's id, type, timestamp, input and scope\n * non-null; an operation written before the API rejected an action without an\n * id violates that. Left to the executor, the missing value nullifies the\n * action, which bubbles up through the non-null chain until it nullifies the\n * envelope's whole operation list, and the caller receives a partial response\n * beside \"Cannot return null for non-nullable field Action.id\" - which says\n * nothing about which operation, and which a sync client can only read as a\n * permanent GraphQL rejection, stopping its poll timer for good.\n *\n * Thrown instead, with a code that says the failure is worth polling through:\n * the document holding the operation needs repairing, but the channel serves\n * every other document, and a peer that stopped polling would stop receiving\n * those too. The code is what a client branches on, since the message is not a\n * contract.\n */\nexport class MalformedStoredOperationError extends GraphQLError {\n constructor(detail: string) {\n super(`Stored operation cannot be served: ${detail}`, {\n extensions: {\n code: RECOVERABLE_GRAPHQL_ERROR_CODES.malformedStoredOperation,\n },\n });\n }\n}\n","import type { DocumentPermissionLevel } from \"../utils/db.js\";\nimport type {\n DocumentPermissionService,\n GetParentIdsFn,\n} from \"./document-permission.service.js\";\n\n/**\n * A document id that has been resolved to its canonical form, never a slug.\n *\n * Protection and grant rows are written under the canonical id, while the\n * read/operation data paths accept an id-or-slug identifier. The decision layer\n * must key on the canonical id, so branding it forces every caller to resolve a\n * slug to its id before consulting this service, closing the slug-aliasing\n * bypass (S-C1). The only sanctioned cast from string to CanonicalDocumentId\n * lives in createCanonicalDocumentIdResolver, immediately after the shared\n * resolveIdOrSlug lookup returns.\n */\nexport type CanonicalDocumentId = string & {\n readonly __canonicalDocumentId: unique symbol;\n};\n\n/**\n * Result of a passed per-document authorization check. `fetchIdentifier` is\n * always safe for the data fetch: the canonical id when resolved, or the raw\n * identifier when the check was skipped for a policy-wide caller.\n */\nexport class AuthorizedDocumentHandle {\n private constructor(\n readonly fetchIdentifier: string,\n readonly isResolved: boolean,\n ) {}\n\n static resolved(documentId: CanonicalDocumentId): AuthorizedDocumentHandle {\n return new AuthorizedDocumentHandle(documentId, true);\n }\n\n static skipped(identifier: string): AuthorizedDocumentHandle {\n return new AuthorizedDocumentHandle(identifier, false);\n }\n\n /** The verified canonical id; throws when resolution was skipped. */\n canonicalId(): CanonicalDocumentId {\n if (!this.isResolved) {\n throw new Error(\n \"Canonical document id is unavailable: the authorization check was skipped for a policy-wide caller\",\n );\n }\n return this.fetchIdentifier as CanonicalDocumentId;\n }\n}\n\nexport const AuthorizationPolicy = {\n OPEN: \"OPEN\",\n ADMIN_ONLY: \"ADMIN_ONLY\",\n DOCUMENT_PERMISSIONS: \"DOCUMENT_PERMISSIONS\",\n} as const;\n\nexport type AuthorizationPolicy =\n (typeof AuthorizationPolicy)[keyof typeof AuthorizationPolicy];\n\nexport interface AuthorizationConfig {\n admins: string[];\n defaultProtection: boolean;\n policy: AuthorizationPolicy;\n}\n\n/**\n * Single source of truth for every permission decision. Always present (never\n * null) so callers branch on data, not on the existence of a service.\n *\n * The policy selects an implementation once at boot:\n * - OPEN: authentication disabled — everyone (incl. anonymous) is allowed.\n * - ADMIN_ONLY: authentication on, document permissions off — only ADMINS.\n * - DOCUMENT_PERMISSIONS: the full per-document protection + grant model.\n *\n * Permission inheritance walks the parent-document hierarchy through a\n * parent resolver injected at construction; callers never supply one.\n */\nexport interface IAuthorizationService {\n readonly config: AuthorizationConfig;\n\n /**\n * Whether the user has unrestricted, policy-wide access. Under OPEN this is\n * true for everyone (including anonymous callers) by design: OPEN means \"no\n * restrictions\", and consumers use this check to skip per-document\n * filtering. It does NOT mean the caller is in the ADMINS list.\n */\n isSupremeAdmin(userAddress?: string): boolean;\n\n /**\n * Whether the user may create new documents under the current policy:\n * everyone in OPEN, only admins in ADMIN_ONLY, any authenticated user in\n * DOCUMENT_PERMISSIONS.\n */\n canCreate(userAddress?: string): boolean;\n\n canRead(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n canWrite(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n /**\n * Whether the user administers the document: supreme admin, document\n * owner, or holder of an ADMIN grant.\n */\n canManage(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n canMutate(\n documentId: CanonicalDocumentId,\n operationType: string,\n userAddress?: string,\n ): Promise<boolean>;\n}\n\n/** Shared config holder and admin-list check for the policy strategies. */\nabstract class BaseAuthorizationService implements IAuthorizationService {\n constructor(readonly config: AuthorizationConfig) {}\n\n isSupremeAdmin(userAddress?: string): boolean {\n if (!userAddress) return false;\n return this.config.admins.includes(userAddress.toLowerCase());\n }\n\n abstract canCreate(userAddress?: string): boolean;\n\n abstract canRead(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n abstract canWrite(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n abstract canManage(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean>;\n\n abstract canMutate(\n documentId: CanonicalDocumentId,\n operationType: string,\n userAddress?: string,\n ): Promise<boolean>;\n}\n\n/** OPEN: authentication disabled — everyone (incl. anonymous) is allowed. */\nclass OpenAuthorizationService extends BaseAuthorizationService {\n isSupremeAdmin(): boolean {\n return true;\n }\n\n canCreate(): boolean {\n return true;\n }\n\n canRead(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n canWrite(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n canManage(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n canMutate(): Promise<boolean> {\n return Promise.resolve(true);\n }\n}\n\n/** ADMIN_ONLY: authentication on, document permissions off — only ADMINS. */\nclass AdminOnlyAuthorizationService extends BaseAuthorizationService {\n canCreate(userAddress?: string): boolean {\n return this.isSupremeAdmin(userAddress);\n }\n\n canRead(\n _documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n\n canWrite(\n _documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n\n canManage(\n _documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n\n canMutate(\n _documentId: CanonicalDocumentId,\n _operationType: string,\n userAddress?: string,\n ): Promise<boolean> {\n return Promise.resolve(this.isSupremeAdmin(userAddress));\n }\n}\n\nconst PERMISSION_RANK: Record<DocumentPermissionLevel, number> = {\n READ: 1,\n WRITE: 2,\n ADMIN: 3,\n};\n\nfunction satisfies(\n level: DocumentPermissionLevel | null,\n required: DocumentPermissionLevel,\n): boolean {\n return level !== null && PERMISSION_RANK[level] >= PERMISSION_RANK[required];\n}\n\n/**\n * DOCUMENT_PERMISSIONS: the full per-document protection + grant model.\n *\n * All decisions live here; DocumentPermissionService is the data-access\n * layer underneath (grants, protection rows, owners).\n */\nclass DocumentPermissionsAuthorizationService extends BaseAuthorizationService {\n readonly #permissions: DocumentPermissionService;\n readonly #getParentIds: GetParentIdsFn;\n\n constructor(\n permissions: DocumentPermissionService,\n getParentIds: GetParentIdsFn,\n config: AuthorizationConfig,\n ) {\n super(config);\n this.#permissions = permissions;\n this.#getParentIds = getParentIds;\n }\n\n canCreate(userAddress?: string): boolean {\n return this.isSupremeAdmin(userAddress) || !!userAddress;\n }\n\n canRead(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return this.#canAccess(documentId, \"READ\", userAddress);\n }\n\n canWrite(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return this.#canAccess(documentId, \"WRITE\", userAddress);\n }\n\n canManage(\n documentId: CanonicalDocumentId,\n userAddress?: string,\n ): Promise<boolean> {\n return this.#isDocumentAdmin(documentId, userAddress);\n }\n\n async canMutate(\n documentId: CanonicalDocumentId,\n operationType: string,\n userAddress?: string,\n ): Promise<boolean> {\n if (this.isSupremeAdmin(userAddress)) return true;\n\n const isRestricted = await this.#permissions.isOperationRestricted(\n documentId,\n operationType,\n );\n if (isRestricted) {\n if (!userAddress) return false;\n if (await this.#isDocumentAdmin(documentId, userAddress)) return true;\n return this.#permissions.hasOperationGrant(\n documentId,\n operationType,\n userAddress,\n );\n }\n\n return this.#canAccess(documentId, \"WRITE\", userAddress);\n }\n\n /**\n * The one \"administers this document\" predicate: supreme admin, document\n * owner, or ADMIN grant on the document itself.\n */\n async #isDocumentAdmin(\n documentId: string,\n userAddress?: string,\n ): Promise<boolean> {\n if (this.isSupremeAdmin(userAddress)) return true;\n if (!userAddress) return false;\n\n const owner = await this.#permissions.getDocumentOwner(documentId);\n if (owner && owner === userAddress.toLowerCase()) return true;\n\n return satisfies(await this.#grantLevel(documentId, userAddress), \"ADMIN\");\n }\n\n /**\n * The one read/write decision shape: supreme admin → unprotected (self or\n * ancestor) → owner → inherited grant of at least the required level.\n */\n async #canAccess(\n documentId: string,\n required: DocumentPermissionLevel,\n userAddress?: string,\n ): Promise<boolean> {\n if (this.isSupremeAdmin(userAddress)) return true;\n\n const isProtected = await this.#permissions.isProtectedWithAncestors(\n documentId,\n this.#getParentIds,\n );\n if (!isProtected) return true;\n if (!userAddress) return false;\n\n const owner = await this.#permissions.getDocumentOwner(documentId);\n if (owner && owner === userAddress.toLowerCase()) return true;\n\n return this.#hasGrantInHierarchy(documentId, userAddress, required);\n }\n\n /** Best grant the user holds on the document. */\n async #grantLevel(\n documentId: string,\n userAddress: string,\n ): Promise<DocumentPermissionLevel | null> {\n return this.#permissions.getUserPermission(documentId, userAddress);\n }\n\n /**\n * Walks the parent hierarchy (with cycle protection) looking for a grant of\n * at least the required level on the document or any ancestor.\n */\n async #hasGrantInHierarchy(\n documentId: string,\n userAddress: string,\n required: DocumentPermissionLevel,\n ): Promise<boolean> {\n const visited = new Set<string>();\n const queue = [documentId];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const level = await this.#grantLevel(current, userAddress);\n if (satisfies(level, required)) return true;\n\n for (const parentId of await this.#getParentIds(current)) {\n if (!visited.has(parentId)) queue.push(parentId);\n }\n }\n\n return false;\n }\n}\n\n/**\n * Selects the strategy for the configured policy. The strategy classes are\n * not exported, so this guard is the only construction path.\n */\nexport function createAuthorizationService(\n config: AuthorizationConfig,\n documentPermissionService?: DocumentPermissionService,\n getParentIds?: GetParentIdsFn,\n): IAuthorizationService {\n if (config.policy === AuthorizationPolicy.OPEN) {\n return new OpenAuthorizationService(config);\n }\n if (config.policy === AuthorizationPolicy.ADMIN_ONLY) {\n return new AdminOnlyAuthorizationService(config);\n }\n if (!documentPermissionService) {\n throw new Error(\n \"DocumentPermissionService is required for the DOCUMENT_PERMISSIONS policy\",\n );\n }\n if (!getParentIds) {\n throw new Error(\n \"A getParentIds resolver is required for the DOCUMENT_PERMISSIONS policy\",\n );\n }\n return new DocumentPermissionsAuthorizationService(\n documentPermissionService,\n getParentIds,\n config,\n );\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport type { CanonicalDocumentId } from \"./authorization.service.js\";\n\n/**\n * Raised when a caller-supplied identifier cannot be resolved to a canonical\n * document id. Carries no detail on purpose: resolution failures must not act\n * as a document-existence oracle, so consumers map this to their generic\n * fail-closed response.\n */\nexport class CanonicalDocumentIdResolutionError extends Error {\n constructor() {\n super(\"Document identifier could not be resolved\");\n this.name = \"CanonicalDocumentIdResolutionError\";\n }\n}\n\nexport type CanonicalDocumentIdResolver = (\n identifier: string,\n) => Promise<CanonicalDocumentId>;\n\n/**\n * The sanctioned string-to-CanonicalDocumentId cast: both the GraphQL layer\n * and server routes must resolve caller identifiers through this helper so\n * decision and data layers always agree on the subject document.\n */\nexport function createCanonicalDocumentIdResolver(\n client: Pick<IReactorClient, \"resolveIdOrSlug\">,\n): CanonicalDocumentIdResolver {\n return async (identifier: string) => {\n let resolved: string;\n try {\n resolved = await client.resolveIdOrSlug(identifier);\n } catch {\n throw new CanonicalDocumentIdResolutionError();\n }\n return resolved as CanonicalDocumentId;\n };\n}\n","import type {\n IReactorClient,\n IRelationalDb,\n ISyncManager,\n SyncScopeGate,\n} from \"@powerhousedao/reactor\";\nimport type { AuthSubject } from \"@powerhousedao/shared/document-model\";\nimport type {\n GraphQLManager,\n ISubgraph,\n SubgraphArgs,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentNode } from \"graphql\";\nimport { ForbiddenError, AuthenticationRequiredError } from \"./errors.js\";\nimport { gql } from \"graphql-tag\";\nimport {\n AuthorizationPolicy,\n AuthorizedDocumentHandle,\n type CanonicalDocumentId,\n type IAuthorizationService,\n} from \"../services/authorization.service.js\";\nimport {\n createCanonicalDocumentIdResolver,\n type CanonicalDocumentIdResolver,\n} from \"../services/canonical-document-id.js\";\nimport type { DocumentPermissionService } from \"../services/document-permission.service.js\";\nimport type { Context } from \"./types.js\";\n\nexport class BaseSubgraph implements ISubgraph {\n name = \"example\";\n // 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 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 }\n\n async onSetup() {\n // noop\n }\n\n async onDisconnect(): Promise<void> {\n // noop\n }\n\n // ============================================\n // Shared permission helpers\n // ============================================\n\n /**\n * Resolves a caller-supplied identifier (id or slug) to its canonical\n * document id, memoized per request. Both the decision layer and the data\n * layer must agree on the subject, so this runs the same resolveIdOrSlug\n * lookup the data path uses. A resolution failure (not found, ambiguous, or\n * transient) surfaces as a generic Forbidden, fail-closed, so a bad\n * identifier cannot be used as a document-existence oracle.\n */\n async resolveCanonicalDocumentId(\n identifier: string,\n requestKey: object,\n ): Promise<CanonicalDocumentId> {\n let cache = this.#canonicalIdMemo.get(requestKey);\n if (!cache) {\n cache = new Map<string, CanonicalDocumentId>();\n this.#canonicalIdMemo.set(requestKey, cache);\n }\n\n const cached = cache.get(identifier);\n if (cached !== undefined) return cached;\n\n let canonical: CanonicalDocumentId;\n try {\n canonical = await this.#resolveCanonical(identifier);\n } catch {\n throw new ForbiddenError();\n }\n\n cache.set(identifier, canonical);\n return canonical;\n }\n\n /**\n * Resolves the args' `documentId` to canonical form. Unconditional (unlike the\n * assertCan* helpers, no admin skip): ACL rows are keyed on the canonical id.\n */\n async withCanonicalDocumentId<T extends { documentId: string }>(\n args: T,\n requestKey: object,\n ): Promise<T & { documentId: CanonicalDocumentId }> {\n const documentId = await this.resolveCanonicalDocumentId(\n args.documentId,\n requestKey,\n );\n return { ...args, documentId };\n }\n\n /**\n * Resolves an identifier for a per-document check, or null when the caller has\n * policy-wide access (OPEN or supreme admin) and the check can be skipped.\n * Only DOCUMENT_PERMISSIONS keys on the document id, so other policies fail\n * closed without resolving.\n */\n async #resolveForCheck(\n identifier: string,\n ctx: Context,\n ): Promise<CanonicalDocumentId | null> {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n return null;\n }\n if (\n this.authorizationService.config.policy !==\n AuthorizationPolicy.DOCUMENT_PERMISSIONS\n ) {\n throw new ForbiddenError();\n }\n return this.resolveCanonicalDocumentId(identifier, ctx);\n }\n\n /**\n * Read filter for an already-canonical document id (one sourced from the data\n * layer, such as a fetched document's id). Performs no slug resolution.\n */\n async canReadDocument(\n documentId: CanonicalDocumentId,\n ctx: Context,\n ): Promise<boolean> {\n return this.authorizationService.canRead(documentId, ctx.user?.address);\n }\n\n /**\n * The principal a request decides as: the authenticated caller's address, and\n * the did:key of the app instance whose token authenticated it.\n *\n * Both, because a policy can name either. The key is what a document records\n * as its creator, so a subject built without one cannot match the creator's\n * standing permission over the auth scope -- the document's own creator would\n * be refused an operation the write path accepts, since a signed action\n * carries the same key. Anonymous callers supply neither.\n */\n protected viewSubject(ctx: Context): AuthSubject {\n return { address: ctx.user?.address, key: ctx.user?.appKey };\n }\n\n /**\n * Asserts read access, resolving a slug first. Returns a handle whose\n * `fetchIdentifier` the caller reuses for the data fetch; a denial throws.\n */\n async assertCanRead(\n identifier: string,\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n const documentId = await this.#resolveForCheck(identifier, ctx);\n if (documentId === null)\n return AuthorizedDocumentHandle.skipped(identifier);\n await this.assertCanReadCanonical(documentId, ctx);\n return AuthorizedDocumentHandle.resolved(documentId);\n }\n\n async assertCanWrite(\n identifier: string,\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n const documentId = await this.#resolveForCheck(identifier, ctx);\n if (documentId === null)\n return AuthorizedDocumentHandle.skipped(identifier);\n await this.assertCanWriteCanonical(documentId, ctx);\n return AuthorizedDocumentHandle.resolved(documentId);\n }\n\n async assertCanExecuteOperation(\n identifier: string,\n operationType: string,\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n const documentId = await this.#resolveForCheck(identifier, ctx);\n if (documentId === null)\n return AuthorizedDocumentHandle.skipped(identifier);\n await this.assertCanExecuteOperationCanonical(\n documentId,\n operationType,\n ctx,\n );\n return AuthorizedDocumentHandle.resolved(documentId);\n }\n\n /**\n * Read assertion for an already-canonical document id. No slug resolution;\n * use only with ids sourced from the data layer or already resolved.\n */\n async assertCanReadCanonical(\n documentId: CanonicalDocumentId,\n ctx: Context,\n ): Promise<void> {\n const canRead = await this.authorizationService.canRead(\n documentId,\n ctx.user?.address,\n );\n if (!canRead) {\n throw new ForbiddenError(\"to read this document\");\n }\n }\n\n async assertCanWriteCanonical(\n documentId: CanonicalDocumentId,\n ctx: Context,\n ): Promise<void> {\n const canWrite = await this.authorizationService.canWrite(\n documentId,\n ctx.user?.address,\n );\n if (!canWrite) {\n throw new ForbiddenError(\"to write to this document\");\n }\n }\n\n async assertCanExecuteOperationCanonical(\n documentId: CanonicalDocumentId,\n operationType: string,\n ctx: Context,\n ): Promise<void> {\n const canMutate = await this.authorizationService.canMutate(\n documentId,\n operationType,\n ctx.user?.address,\n );\n if (!canMutate) {\n throw new ForbiddenError(\n `to execute operation \"${operationType}\" on this document`,\n );\n }\n }\n\n assertCanCreate(ctx: Context): void {\n if (this.authorizationService.canCreate(ctx.user?.address)) return;\n if (ctx.user?.address) {\n throw new ForbiddenError(\"to create documents\");\n }\n throw new AuthenticationRequiredError(\"to create documents\");\n }\n}\n","import path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n\n/**\n * Imports a specifier that may be either a bare package specifier or a\n * filesystem path. Absolute paths are converted to file:// URLs, because the\n * ESM loader reads the drive letter in a Windows path as a URL scheme\n * (`import('D:\\\\...')` fails with ERR_UNSUPPORTED_ESM_URL_SCHEME).\n */\nasync function importSpecifier<T>(target: string): Promise<T> {\n const specifier = path.isAbsolute(target)\n ? pathToFileURL(target).href\n : target;\n return (await import(/* @vite-ignore */ specifier)) as T;\n}\n\n/**\n * Attempts to import from suggested Node.js paths\n */\nasync function tryNodeSuggestedPaths<T>(\n packageName: string,\n subPath: string,\n): Promise<T | null> {\n const suggestedPaths = [\n `${packageName}/dist/node/${subPath}/index.mjs`,\n `${packageName}/dist/node/${subPath}.mjs`,\n `${packageName}/dist/${subPath}/index.js`,\n `${packageName}/dist/${subPath}.js`,\n ];\n\n for (const suggestedPath of suggestedPaths) {\n try {\n return await importSpecifier<T>(suggestedPath);\n } catch {\n // Continue to next attempt\n }\n }\n\n return null;\n}\n\n/**\n * Attempts to resolve package using import.meta.resolve\n */\nasync function tryImportMetaResolve<T>(\n packageName: string,\n subPath: string,\n): Promise<T | null> {\n try {\n const resolvedUrl = import.meta.resolve?.(`${packageName}/package.json`);\n if (!resolvedUrl) return null;\n\n // fileURLToPath, not URL.pathname: the latter yields \"/D:/...\" on Windows.\n const packageRoot = path.dirname(fileURLToPath(resolvedUrl));\n const pathsToTry = [\n path.join(packageRoot, \"dist\", \"node\", subPath, \"index.mjs\"),\n path.join(packageRoot, \"dist\", \"node\", `${subPath}.mjs`),\n path.join(packageRoot, \"dist\", subPath, \"index.js\"),\n path.join(packageRoot, \"dist\", `${subPath}.js`),\n path.join(packageRoot, subPath, \"index.js\"),\n path.join(packageRoot, `${subPath}.js`),\n ];\n\n for (const attemptPath of pathsToTry) {\n try {\n return await importSpecifier<T>(attemptPath);\n } catch {\n // Continue to next attempt\n }\n }\n } catch {\n // import.meta.resolve failed\n }\n\n return null;\n}\n\n/**\n * Resolves symlinks in node_modules to find the real package location\n */\nasync function resolveSymlinkedPaths(\n packageName: string,\n subPath: string,\n): Promise<string[]> {\n const packageBaseName = packageName.includes(\"/\")\n ? packageName.split(\"/\").pop()\n : packageName;\n const nodeModulesPatterns = [\n path.join(process.cwd(), \"node_modules\", packageName),\n path.join(process.cwd(), \"node_modules\", packageBaseName || packageName),\n ];\n\n const workspacePatterns: string[] = [];\n\n for (const nodeModulesPath of nodeModulesPatterns) {\n try {\n const fs = await import(\"node:fs\");\n if (fs.existsSync(nodeModulesPath)) {\n const realPath = fs.realpathSync(nodeModulesPath);\n\n workspacePatterns.push(\n path.join(realPath, \"dist\", \"node\", subPath, \"index.mjs\"),\n path.join(realPath, \"dist\", \"node\", `${subPath}.mjs`),\n path.join(realPath, \"dist\", subPath, \"index.js\"),\n path.join(realPath, \"dist\", `${subPath}.js`),\n path.join(realPath, subPath, \"index.js\"),\n path.join(realPath, `${subPath}.js`),\n );\n }\n } catch {\n // Continue to next attempt\n }\n }\n\n return workspacePatterns;\n}\n\n/**\n * Generates common workspace pattern paths\n */\nfunction getCommonWorkspacePaths(\n packageName: string,\n subPath: string,\n): string[] {\n const packageBaseName = packageName.includes(\"/\")\n ? packageName.split(\"/\").pop()\n : packageName;\n const commonRoots = [process.cwd(), path.dirname(process.cwd())];\n\n const workspacePatterns: string[] = [];\n for (const root of commonRoots) {\n workspacePatterns.push(\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n \"node\",\n subPath,\n \"index.mjs\",\n ),\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n \"node\",\n `${subPath}.mjs`,\n ),\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n subPath,\n \"index.js\",\n ),\n path.join(\n root,\n \"packages\",\n packageBaseName || packageName,\n \"dist\",\n `${subPath}.js`,\n ),\n );\n }\n\n return workspacePatterns;\n}\n\n/**\n * Attempts to import from a list of workspace patterns\n */\nasync function tryWorkspacePatterns<T>(patterns: string[]): Promise<T | null> {\n for (const workspacePath of patterns) {\n try {\n return await importSpecifier<T>(workspacePath);\n } catch {\n // Continue to next attempt\n }\n }\n\n return null;\n}\n\n/**\n * Attempts to resolve linked packages using various fallback strategies\n */\nexport async function resolveLinkedPackage<T>(\n packageName: string,\n subPath: string,\n): Promise<T | null> {\n // Try Node.js suggested paths first\n let result = await tryNodeSuggestedPaths<T>(packageName, subPath);\n if (result) return result;\n\n // Try import.meta.resolve\n result = await tryImportMetaResolve<T>(packageName, subPath);\n if (result) return result;\n\n // Try symlink resolution\n const symlinkPaths = await resolveSymlinkedPaths(packageName, subPath);\n result = await tryWorkspacePatterns<T>(symlinkPaths);\n if (result) return result;\n\n // Try common workspace patterns as final fallback\n const commonPaths = getCommonWorkspacePaths(packageName, subPath);\n result = await tryWorkspacePatterns<T>(commonPaths);\n if (result) return result;\n\n return null;\n}\n","import type {\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport { execSync } from \"node:child_process\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { resolveLinkedPackage } from \"./import-resolver.js\";\n\n// Define the expected module export structures\ntype DocumentModelsExport = Record<string, DocumentModelModule>;\ntype SubgraphsExport = Record<string, Record<string, SubgraphClass>>;\ntype ProcessorsExport = {\n processorFactory?: ProcessorFactoryBuilder;\n processorFactoryLegacy?: ProcessorFactoryBuilder;\n};\n\nconst _logger = childLogger([\"reactor-api\", \"packages/util\"]);\n\nexport const installPackages = (packages: string[]): Promise<void> => {\n for (const packageName of packages) {\n execSync(`ph install ${packageName}`);\n }\n return Promise.resolve();\n};\n\nexport const readManifest = () => {\n const manifest = execSync(`ph manifest`).toString();\n return manifest;\n};\n\n/**\n * Tries to import document models from a package. This function cannot throw.\n */\nexport async function loadDocumentModels(\n packageName: string,\n): Promise<DocumentModelsExport | null> {\n return loadDependency(packageName, \"document-models\");\n}\n\n/**\n * Tries to import subgraphs from a package. This function cannot throw.\n */\nexport async function loadSubgraphs(\n packageName: string,\n): Promise<SubgraphsExport | null> {\n return loadDependency(packageName, \"subgraphs\");\n}\n\n/**\n * Tries to import processors from a package. This function cannot throw.\n */\nexport async function loadProcessors(\n packageName: string,\n): Promise<ProcessorsExport | null> {\n return loadDependency(packageName, \"processors\");\n}\n\n/**\n * Generic dependency loader - tries to import a dependency from a package. This function cannot throw.\n * Returns null if the dependency cannot be loaded.\n */\nasync function loadDependency<T = unknown>(\n packageName: string,\n subPath: string,\n): Promise<T> {\n // A local package is identified by an absolute path, which has to become a\n // file:// URL: the ESM loader reads the drive letter in a Windows path as a\n // URL scheme.\n const fullPath = path.isAbsolute(packageName)\n ? pathToFileURL(path.join(packageName, subPath)).href\n : `${packageName}/${subPath}`;\n\n // Try the standard import first\n try {\n // vite does not support this, but that's okay as we have provided the\n // vite-loader for this purpose\n\n const module = (await import(/* @vite-ignore */ fullPath)) as T;\n return module;\n } catch (e) {\n // Handle module not found errors with fallback resolution.\n // ERR_UNSUPPORTED_ESM_URL_SCHEME joins the list because a directory\n // specifier that is a plain path fails with it on Windows where POSIX\n // reports ERR_UNSUPPORTED_DIR_IMPORT.\n if (\n e instanceof Error &&\n \"code\" in e &&\n (e.code === \"ERR_MODULE_NOT_FOUND\" ||\n e.code === \"ERR_UNSUPPORTED_DIR_IMPORT\" ||\n e.code === \"ERR_UNSUPPORTED_ESM_URL_SCHEME\")\n ) {\n const result = await resolveLinkedPackage<T>(packageName, subPath);\n if (result) return result;\n }\n throw e;\n }\n}\n\nfunction isUpgradeManifest(\n value: unknown,\n): value is UpgradeManifest<readonly number[]> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"documentType\" in value &&\n \"supportedVersions\" in value &&\n \"upgrades\" in value\n );\n}\n\n/**\n * Collects upgrade manifests from a package's document-models namespace.\n * Handles both the aggregate `upgradeManifests` array export and individual\n * manifest exports; dedupes by documentType.\n */\nexport function extractUpgradeManifests(\n namespace: Record<string, unknown>,\n): UpgradeManifest<readonly number[]>[] {\n const manifests = new Map<string, UpgradeManifest<readonly number[]>>();\n const add = (value: unknown) => {\n if (isUpgradeManifest(value)) {\n manifests.set(value.documentType, value);\n }\n };\n for (const value of Object.values(namespace)) {\n if (Array.isArray(value)) {\n value.forEach(add);\n } else {\n add(value);\n }\n }\n return Array.from(manifests.values());\n}\n\nexport function debounce<T extends unknown[], R>(\n func: (...args: T) => Promise<R>,\n delay = 250,\n) {\n let timer: number;\n return (immediate = false, ...args: T) => {\n if (timer) {\n clearTimeout(timer);\n }\n return new Promise<R>((resolve, reject) => {\n if (immediate) {\n func(...args)\n .then(resolve)\n .catch(reject);\n } else {\n timer = setTimeout(() => {\n func(...args)\n .then(resolve)\n .catch(reject);\n }, delay) as unknown as number;\n }\n });\n };\n}\n\nexport function isSubpath(parent: string, dir: string) {\n const relative = path.relative(parent, dir);\n return relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n","import type {\n GqlDocument,\n GqlDriveDocument,\n GqlOperation,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type {\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\n\nexport function isSubgraphClass(\n candidate: unknown,\n): candidate is SubgraphClass {\n if (typeof candidate !== \"function\") return false;\n\n let proto: unknown = Object.getPrototypeOf(candidate);\n while (proto) {\n if (Object.prototype.isPrototypeOf.call(proto, BaseSubgraph)) return true;\n\n proto = Object.getPrototypeOf(proto);\n }\n\n return false;\n}\n\nexport function buildGraphqlOperations(\n operations: Operation[],\n skip: number,\n first: number,\n): GqlOperation[] {\n return operations.slice(skip, skip + first).map(buildGraphqlOperation);\n}\n\nexport function buildGraphqlOperation(operation: Operation): GqlOperation {\n const signer = operation.action.context?.signer;\n return {\n id: operation.id ?? \"\",\n type: operation.action.type,\n index: operation.index,\n timestampUtcMs: operation.timestampUtcMs,\n hash: operation.hash,\n skip: operation.skip,\n inputText:\n typeof operation.action.input === \"string\"\n ? operation.action.input\n : JSON.stringify(operation.action.input),\n error: operation.error,\n context: {\n signer: signer\n ? {\n user: signer.user,\n app: signer.app,\n signatures: signer.signatures.map((sig) =>\n Array.isArray(sig) ? sig.join(\", \") : sig,\n ),\n }\n : undefined,\n },\n };\n}\n\nexport function buildGraphQlDocument(doc: PHDocument): GqlDocument {\n // Return full state with all scopes (auth, document, global, local)\n // This matches the ReactorSubgraph pattern in adapters.ts\n const state = doc.state;\n const initialState = doc.initialState;\n // For stateJSON, use global state for backward compatibility\n const globalState = \"global\" in doc.state ? doc.state.global : {};\n return {\n id: doc.header.id,\n name: doc.header.name,\n documentType: doc.header.documentType,\n revision: doc.header.revision.global || 0,\n createdAtUtcIso: doc.header.createdAtUtcIso,\n lastModifiedAtUtcIso: doc.header.lastModifiedAtUtcIso,\n operations: [],\n stateJSON: globalState as JSON,\n state,\n initialState,\n };\n}\n\nexport function buildGraphQlDriveDocument(\n doc: DocumentDriveDocument,\n): GqlDriveDocument {\n const gqlDoc = buildGraphQlDocument(doc);\n return {\n ...gqlDoc,\n meta: {\n preferredEditor: doc.header.meta?.preferredEditor,\n },\n slug: doc.header.slug,\n state: doc.state.global,\n initialState: doc.state.global,\n };\n}\n","// 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 } from \"node:fs\";\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// 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(identifier: string): PieceListLocation {\n if (isAbsolute(identifier)) {\n return { root: identifier, listPath: join(identifier, BUILT_PIECE_LIST) };\n }\n // Left to throw, and through the ESM resolver rather than require's: its\n // error codes are the ones the package manager reads a miss from.\n const listPath = fileURLToPath(\n import.meta.resolve(`${identifier}/${PIECES_SUBPATH}`),\n );\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 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: { root: string; identifier: string; logger: ILogger },\n): PackagePieceEntry[] {\n const { root, identifier, logger } = 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: piece.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): 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: piece.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 return locatePieces(declared as PackagePiece[], context);\n}\n"],"names":["#permissions","#getParentIds","#canAccess","#isDocumentAdmin","#grantLevel","#hasGrantInHierarchy","#canonicalIdMemo","#resolveCanonical","#resolveForCheck"],"mappings":"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","debug_id":"dc22b29d-c034-58d2-843a-dc38009f52ec"}
@@ -1,4 +1,4 @@
1
- import { a as ISubscribablePackageLoader, o as ISubscriptionOptions } from "../../types-Bz2niABC.mjs";
1
+ import { o as ISubscribablePackageLoader, s as ISubscriptionOptions, u as PackagePieceEntry } from "../../types-BXjLvTe3.mjs";
2
2
  import { ILogger } from "document-model";
3
3
  import { DocumentModelModule, UpgradeManifest } from "@powerhousedao/shared/document-model";
4
4
  import { Logger, ViteDevServer } from "vite";
@@ -16,13 +16,18 @@ declare class VitePackageLoader implements ISubscribablePackageLoader {
16
16
  private getDocumentModelsPath;
17
17
  private getSubgraphsPath;
18
18
  private getProcessorsPath;
19
+ private getPiecesPath;
20
+ private aliasedRoot;
21
+ private pieceRoot;
19
22
  loadDocumentModels(identifier: string, immediate?: boolean): Promise<DocumentModelModule[]>;
20
23
  loadUpgradeManifests(identifier: string): Promise<UpgradeManifest<readonly number[]>[]>;
21
24
  loadSubgraphs(identifier: string): Promise<SubgraphClass[]>;
22
25
  loadProcessors(identifier: string): Promise<ProcessorFactoryBuilder | null>;
26
+ loadPieces(identifier: string): Promise<PackagePieceEntry[]>;
23
27
  onDocumentModelsChange(identifier: string, handler: (documentModels: DocumentModelModule[]) => void, options?: ISubscriptionOptions): () => void;
24
28
  onSubgraphsChange(identifier: string, handler: (subgraphs: SubgraphClass[]) => void, options?: ISubscriptionOptions): () => void;
25
29
  onProcessorsChange(identifier: string, handler: (processors: ProcessorFactoryBuilder | null) => void, options?: ISubscriptionOptions): () => void;
30
+ onPiecesChange(identifier: string, handler: (pieces: PackagePieceEntry[]) => void, options?: ISubscriptionOptions): () => void;
26
31
  }
27
32
  declare function startViteServer(root: string, logger?: Logger): Promise<ViteDevServer>;
28
33
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"vite-loader.d.mts","names":[],"sources":["../../../src/packages/vite-loader.mts"],"mappings":";;;;;;;iBAqBgB,gBAAA,CAAiB,MAAA,EAAQ,OAAA,EAAS,MAAA,YAAW,MAAA;AAAA,cAUhD,iBAAA,YAA6B,0BAAA;EAAA;mBACvB,MAAA;EAAA,iBAEA,IAAA;EAAA,SAER,IAAA;EAAA,OAEF,KAAA,CAAM,IAAA,EAAM,aAAA,GAAa,iBAAA;cAIpB,IAAA,EAAM,aAAA;EAAA,QAIV,qBAAA;EAAA,QAIA,gBAAA;EAAA,QAIA,iBAAA;EAID,kBAAA,CAAmB,UAAA,UAAoB,SAAA,aAAiB,OAAA,CAAA,mBAAA;EA2CzD,oBAAA,CACJ,UAAA,WACC,OAAA,CAAQ,eAAA;EA+BL,aAAA,CAAc,UAAA,WAAqB,OAAA,CAAQ,aAAA;EA4B3C,cAAA,CACJ,UAAA,WACC,OAAA,CAAQ,uBAAA;EA+BX,sBAAA,CACE,UAAA,UACA,OAAA,GAAU,cAAA,EAAgB,mBAAA,aAC1B,OAAA,GAAU,oBAAA;EAwBZ,iBAAA,CACE,UAAA,UACA,OAAA,GAAU,SAAA,EAAW,aAAA,aACrB,OAAA,GAAU,oBAAA;EAuBZ,kBAAA,CACE,UAAA,UACA,OAAA,GAAU,UAAA,EAAY,uBAAA,kBACtB,OAAA,GAAU,oBAAA;AAAA;AAAA,iBAwBQ,eAAA,CAAgB,IAAA,UAAc,MAAA,GAAS,MAAA,GAAM,OAAA,CAAA,aAAA"}
1
+ {"version":3,"file":"vite-loader.d.mts","names":[],"sources":["../../../src/packages/vite-loader.mts"],"mappings":";;;;;;;iBA4BgB,gBAAA,CAAiB,MAAA,EAAQ,OAAA,EAAS,MAAA,YAAW,MAAA;AAAA,cA2BhD,iBAAA,YAA6B,0BAAA;EAAA;mBACvB,MAAA;EAAA,iBAEA,IAAA;EAAA,SAER,IAAA;EAAA,OAEF,KAAA,CAAM,IAAA,EAAM,aAAA,GAAa,iBAAA;cAIpB,IAAA,EAAM,aAAA;EAAA,QAIV,qBAAA;EAAA,QAIA,gBAAA;EAAA,QAIA,iBAAA;EAAA,QAIA,aAAA;EAAA,QAMA,WAAA;EAAA,QASA,SAAA;EAYD,kBAAA,CAAmB,UAAA,UAAoB,SAAA,aAAiB,OAAA,CAAA,mBAAA;EA2CzD,oBAAA,CACJ,UAAA,WACC,OAAA,CAAQ,eAAA;EA+BL,aAAA,CAAc,UAAA,WAAqB,OAAA,CAAQ,aAAA;EA4B3C,cAAA,CACJ,UAAA,WACC,OAAA,CAAQ,uBAAA;EAiCL,UAAA,CAAW,UAAA,WAAqB,OAAA,CAAQ,iBAAA;EA6B9C,sBAAA,CACE,UAAA,UACA,OAAA,GAAU,cAAA,EAAgB,mBAAA,aAC1B,OAAA,GAAU,oBAAA;EAwBZ,iBAAA,CACE,UAAA,UACA,OAAA,GAAU,SAAA,EAAW,aAAA,aACrB,OAAA,GAAU,oBAAA;EAuBZ,kBAAA,CACE,UAAA,UACA,OAAA,GAAU,UAAA,EAAY,uBAAA,kBACtB,OAAA,GAAU,oBAAA;EAuBZ,cAAA,CACE,UAAA,UACA,OAAA,GAAU,MAAA,EAAQ,iBAAA,aAClB,OAAA,GAAU,oBAAA;AAAA;AAAA,iBA2BQ,eAAA,CAAgB,IAAA,UAAc,MAAA,GAAS,MAAA,GAAM,OAAA,CAAA,aAAA"}
@@ -1,6 +1,6 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e3971ec2-a824-5da6-9a2a-805e72db81bf")}catch(e){}}();
3
- import { a as isSubgraphClass, c as isSubpath, o as debounce, s as extractUpgradeManifests } from "../../utils-XWVecaNn.mjs";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="357b1ab4-fb03-5a36-8191-3308ef8404df")}catch(e){}}();
3
+ import { d as isSubgraphClass, f as debounce, i as pieceListLocation, m as isSubpath, n as PIECES_SUBPATH, o as piecesFromListModule, p as extractUpgradeManifests, t as BUILT_PIECE_LIST } from "../../pieces-eqj2RKgd.mjs";
4
4
  import { childLogger } from "document-model";
5
5
  import path from "node:path";
6
6
  import { viteCommonjs } from "@originjs/vite-plugin-commonjs";
@@ -9,9 +9,9 @@ import { createLogger, createServer } from "vite";
9
9
  //#region src/packages/vite-loader.mts
10
10
  function createViteLogger(logger, prefix = "") {
11
11
  const customLogger = createLogger("info", { prefix });
12
- customLogger.info = logger.info;
13
- customLogger.warn = logger.warn;
14
- customLogger.error = logger.error;
12
+ customLogger.info = (msg) => logger.info("@line", msg);
13
+ customLogger.warn = (msg) => logger.warn("@line", msg);
14
+ customLogger.error = (msg, options) => options?.error ? logger.error("@line", msg, options.error) : logger.error("@line", msg);
15
15
  return customLogger;
16
16
  }
17
17
  var VitePackageLoader = class VitePackageLoader {
@@ -33,6 +33,25 @@ var VitePackageLoader = class VitePackageLoader {
33
33
  getProcessorsPath(identifier) {
34
34
  return path.posix.join(identifier, "./processors");
35
35
  }
36
+ getPiecesPath(identifier) {
37
+ return path.posix.join(identifier, `./${PIECES_SUBPATH}`);
38
+ }
39
+ aliasedRoot(identifier) {
40
+ const alias = this.vite.config.resolve.alias;
41
+ const hit = (Array.isArray(alias) ? alias : []).find((entry) => entry.find === identifier);
42
+ return typeof hit?.replacement === "string" ? hit.replacement : void 0;
43
+ }
44
+ pieceRoot(identifier) {
45
+ if (!path.isAbsolute(identifier)) {
46
+ const aliased = this.aliasedRoot(identifier);
47
+ if (aliased) return aliased;
48
+ }
49
+ try {
50
+ return pieceListLocation(identifier).root;
51
+ } catch {
52
+ return;
53
+ }
54
+ }
36
55
  loadDocumentModels(identifier, immediate = false) {
37
56
  return this.#loadDocumentModelsWithDebounce(immediate, identifier);
38
57
  }
@@ -98,6 +117,29 @@ var VitePackageLoader = class VitePackageLoader {
98
117
  this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);
99
118
  return null;
100
119
  }
120
+ async loadPieces(identifier) {
121
+ const root = this.pieceRoot(identifier);
122
+ if (root === void 0) {
123
+ this.logger.debug(` ➜ No package root found for: ${identifier}`);
124
+ return [];
125
+ }
126
+ const fullPath = this.getPiecesPath(identifier);
127
+ this.logger.verbose("Loading pieces from", fullPath);
128
+ let module;
129
+ try {
130
+ module = await this.vite.ssrLoadModule(fullPath);
131
+ } catch (e) {
132
+ this.logger.debug(` ➜ No pieces found for: ${identifier}`, e);
133
+ return [];
134
+ }
135
+ const pieces = piecesFromListModule(module, {
136
+ root,
137
+ identifier,
138
+ logger: this.logger
139
+ });
140
+ this.logger.debug(` ➜ Loaded ${pieces.length} Pieces from: ${identifier}`);
141
+ return pieces;
142
+ }
101
143
  onDocumentModelsChange(identifier, handler, options) {
102
144
  const listener = async (changedPath) => {
103
145
  if (isSubpath(this.getDocumentModelsPath(identifier), changedPath)) handler(await this.loadDocumentModels(identifier));
@@ -139,6 +181,23 @@ var VitePackageLoader = class VitePackageLoader {
139
181
  this.vite.watcher.off("unlink", listener);
140
182
  };
141
183
  }
184
+ onPiecesChange(identifier, handler, options) {
185
+ const watched = [this.getPiecesPath(identifier)];
186
+ const root = this.pieceRoot(identifier);
187
+ if (root !== void 0) watched.push(path.dirname(path.resolve(root, BUILT_PIECE_LIST)));
188
+ const listener = async (changedPath) => {
189
+ if (!watched.some((dir) => isSubpath(dir, changedPath))) return;
190
+ handler(await this.loadPieces(identifier));
191
+ };
192
+ this.vite.watcher.on("change", listener);
193
+ this.vite.watcher.on("add", listener);
194
+ this.vite.watcher.on("unlink", listener);
195
+ return () => {
196
+ this.vite.watcher.off("change", listener);
197
+ this.vite.watcher.off("add", listener);
198
+ this.vite.watcher.off("unlink", listener);
199
+ };
200
+ }
142
201
  };
143
202
  async function startViteServer(root, logger) {
144
203
  return await createServer({
@@ -167,4 +226,4 @@ async function startViteServer(root, logger) {
167
226
  export { VitePackageLoader, createViteLogger, startViteServer };
168
227
 
169
228
  //# sourceMappingURL=vite-loader.mjs.map
170
- //# debugId=e3971ec2-a824-5da6-9a2a-805e72db81bf
229
+ //# debugId=357b1ab4-fb03-5a36-8191-3308ef8404df
@@ -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 { readPackage } from \"read-pkg\";\nimport type { Logger, PluginOption, ViteDevServer } from \"vite\";\nimport { createLogger, createServer } from \"vite\";\nimport { isSubgraphClass } from \"../graphql/utils.js\";\nimport type {\n ISubscribablePackageLoader,\n ISubscriptionOptions,\n} from \"./types.js\";\nimport { debounce, extractUpgradeManifests, isSubpath } from \"./util.js\";\n\nexport function createViteLogger(logger: ILogger, prefix = \"\") {\n const customLogger = createLogger(\"info\", {\n prefix,\n });\n customLogger.info = logger.info;\n customLogger.warn = logger.warn;\n customLogger.error = logger.error;\n return customLogger;\n}\n\nexport class VitePackageLoader implements ISubscribablePackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"vite-loader\"]);\n\n private readonly vite: ViteDevServer;\n\n readonly name = \"VitePackageLoader\";\n\n static build(vite: ViteDevServer) {\n return new VitePackageLoader(vite);\n }\n\n constructor(vite: ViteDevServer) {\n this.vite = vite;\n }\n\n private getDocumentModelsPath(identifier: string): string {\n return path.posix.join(identifier, \"./document-models\");\n }\n\n private getSubgraphsPath(identifier: string): string {\n return path.posix.join(identifier, \"./subgraphs\");\n }\n\n private getProcessorsPath(identifier: string): string {\n return path.posix.join(identifier, \"./processors\");\n }\n\n public loadDocumentModels(identifier: string, immediate = false) {\n return this.#loadDocumentModelsWithDebounce(immediate, identifier);\n }\n\n #loadDocumentModelsWithDebounce = debounce(\n this.#loadDocumentModels.bind(this),\n 500,\n );\n\n async #loadDocumentModels(\n identifier: string,\n ): Promise<DocumentModelModule[]> {\n const fullPath = this.getDocumentModelsPath(identifier);\n this.logger.debug(\"Loading document models from\", fullPath);\n\n try {\n const localDMs = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n DocumentModelModule\n >;\n\n const exports = Object.values(localDMs);\n\n // duck type\n const documentModels: DocumentModelModule[] = [];\n for (const dm of exports) {\n if (dm.documentModel) {\n documentModels.push(dm);\n }\n }\n\n this.logger.verbose(\n ` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`,\n );\n\n return documentModels;\n } catch (e) {\n this.logger.debug(` ➜ No Document Models found for: ${identifier}`, e);\n }\n\n return [];\n }\n\n async loadUpgradeManifests(\n identifier: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n // Projects generated before the aggregate index re-exported the\n // manifests only expose them at document-models/upgrade-manifests, so\n // try both without requiring a regeneration.\n const candidatePaths = [\n this.getDocumentModelsPath(identifier),\n path.posix.join(this.getDocumentModelsPath(identifier), \"upgrade-manifests\"),\n ];\n for (const fullPath of candidatePaths) {\n try {\n const namespace = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n unknown\n >;\n const manifests = extractUpgradeManifests(namespace);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n return manifests;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Upgrade Manifests found at ${fullPath} for: ${identifier}`,\n e,\n );\n }\n }\n return [];\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n const fullPath = this.getSubgraphsPath(identifier);\n\n this.logger.verbose(\"Loading subgraphs from\", fullPath);\n\n let localSubgraphs: Record<string, Record<string, SubgraphClass>> = {};\n try {\n localSubgraphs = await this.vite.ssrLoadModule(fullPath);\n } catch (e) {\n this.logger.debug(` ➜ No Subgraphs found for: ${identifier}`, e);\n return [];\n }\n\n const subgraphs: SubgraphClass[] = [];\n for (const [name, subgraph] of Object.entries(localSubgraphs)) {\n const SubgraphClass = subgraph[name];\n if (isSubgraphClass(SubgraphClass)) {\n subgraphs.push(SubgraphClass);\n }\n }\n\n this.logger.debug(\n ` ➜ Loaded ${subgraphs.length} Subgraphs from: ${identifier}`,\n );\n\n return subgraphs;\n }\n\n async loadProcessors(\n identifier: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n const fullPath = this.getProcessorsPath(identifier);\n\n this.logger.verbose(\"Loading processors from\", fullPath);\n\n try {\n const pkgModule = await this.vite.ssrLoadModule(fullPath);\n\n const factory = (\n pkgModule as Record<string, ProcessorFactoryBuilder | undefined>\n )?.processorFactory;\n\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(\n ` ➜ Loaded Processor Factory from: ${identifier}`,\n );\n return factory;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Processor Factory found for: ${identifier}`,\n e,\n );\n }\n\n this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);\n\n // return empty processor factory\n return null;\n }\n\n onDocumentModelsChange(\n identifier: string,\n handler: (documentModels: DocumentModelModule[]) => void,\n options?: ISubscriptionOptions,\n ): () => void {\n const listener = async (changedPath: string) => {\n const documentModelsPath = this.getDocumentModelsPath(identifier);\n if (isSubpath(documentModelsPath, changedPath)) {\n const documentModels = await this.loadDocumentModels(identifier);\n handler(documentModels);\n }\n };\n\n // \"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\nexport async function startViteServer(root: string, logger?: Logger) {\n const packageJson = await readPackage({ cwd: root });\n\n const vite = await createServer({\n root,\n configFile: false,\n logger,\n server: { middlewareMode: true, watch: { ignored: [\"**/.ph/**\"] } },\n appType: \"custom\",\n build: {\n rollupOptions: {\n input: [],\n },\n },\n resolve: {\n tsconfigPaths: true,\n alias: {\n [packageJson.name]: root,\n },\n },\n plugins: [\n // cast: the plugin ships types built against an older vite, and the\n // mismatched Plugin type crashes tsc 6 during assignability checking\n viteCommonjs() as PluginOption,\n {\n name: \"suppress-hmr\",\n handleHotUpdate() {\n return []; // return empty array to suppress server refresh\n },\n },\n ],\n });\n\n return vite;\n}\n"],"names":["#loadDocumentModelsWithDebounce","#loadDocumentModels"],"mappings":"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","debug_id":"e3971ec2-a824-5da6-9a2a-805e72db81bf"}
1
+ {"version":3,"file":"vite-loader.mjs","sources":["../../../src/packages/vite-loader.mts"],"sourcesContent":["import { viteCommonjs } from \"@originjs/vite-plugin-commonjs\";\nimport type {\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger, type ILogger } from \"document-model\";\nimport path from \"node:path\";\nimport { readPackage } from \"read-pkg\";\nimport type { Logger, PluginOption, ViteDevServer } from \"vite\";\nimport { createLogger, createServer } from \"vite\";\nimport { isSubgraphClass } from \"../graphql/utils.js\";\nimport {\n BUILT_PIECE_LIST,\n PIECES_SUBPATH,\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 class VitePackageLoader implements ISubscribablePackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"vite-loader\"]);\n\n private readonly vite: ViteDevServer;\n\n readonly name = \"VitePackageLoader\";\n\n static build(vite: ViteDevServer) {\n return new VitePackageLoader(vite);\n }\n\n constructor(vite: ViteDevServer) {\n this.vite = vite;\n }\n\n private getDocumentModelsPath(identifier: string): string {\n return path.posix.join(identifier, \"./document-models\");\n }\n\n private getSubgraphsPath(identifier: string): string {\n return path.posix.join(identifier, \"./subgraphs\");\n }\n\n private getProcessorsPath(identifier: string): string {\n return path.posix.join(identifier, \"./processors\");\n }\n\n 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): string | undefined {\n if (!path.isAbsolute(identifier)) {\n const aliased = this.aliasedRoot(identifier);\n if (aliased) return aliased;\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 const fullPath = this.getDocumentModelsPath(identifier);\n this.logger.debug(\"Loading document models from\", fullPath);\n\n try {\n const localDMs = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n DocumentModelModule\n >;\n\n const exports = Object.values(localDMs);\n\n // duck type\n const documentModels: DocumentModelModule[] = [];\n for (const dm of exports) {\n if (dm.documentModel) {\n documentModels.push(dm);\n }\n }\n\n this.logger.verbose(\n ` ➜ Loaded ${documentModels.length} Document Models from: ${identifier}`,\n );\n\n return documentModels;\n } catch (e) {\n this.logger.debug(` ➜ No Document Models found for: ${identifier}`, e);\n }\n\n return [];\n }\n\n async loadUpgradeManifests(\n identifier: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n // Projects generated before the aggregate index re-exported the\n // manifests only expose them at document-models/upgrade-manifests, so\n // try both without requiring a regeneration.\n const candidatePaths = [\n this.getDocumentModelsPath(identifier),\n path.posix.join(this.getDocumentModelsPath(identifier), \"upgrade-manifests\"),\n ];\n for (const fullPath of candidatePaths) {\n try {\n const namespace = (await this.vite.ssrLoadModule(fullPath)) as Record<\n string,\n unknown\n >;\n const manifests = extractUpgradeManifests(namespace);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n return manifests;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Upgrade Manifests found at ${fullPath} for: ${identifier}`,\n e,\n );\n }\n }\n return [];\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n const fullPath = this.getSubgraphsPath(identifier);\n\n this.logger.verbose(\"Loading subgraphs from\", fullPath);\n\n let localSubgraphs: Record<string, Record<string, SubgraphClass>> = {};\n try {\n localSubgraphs = await this.vite.ssrLoadModule(fullPath);\n } catch (e) {\n this.logger.debug(` ➜ No Subgraphs found for: ${identifier}`, e);\n return [];\n }\n\n const subgraphs: SubgraphClass[] = [];\n for (const [name, subgraph] of Object.entries(localSubgraphs)) {\n const SubgraphClass = subgraph[name];\n if (isSubgraphClass(SubgraphClass)) {\n subgraphs.push(SubgraphClass);\n }\n }\n\n this.logger.debug(\n ` ➜ Loaded ${subgraphs.length} Subgraphs from: ${identifier}`,\n );\n\n return subgraphs;\n }\n\n async loadProcessors(\n identifier: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n const fullPath = this.getProcessorsPath(identifier);\n\n this.logger.verbose(\"Loading processors from\", fullPath);\n\n try {\n const pkgModule = await this.vite.ssrLoadModule(fullPath);\n\n const factory = (\n pkgModule as Record<string, ProcessorFactoryBuilder | undefined>\n )?.processorFactory;\n\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(\n ` ➜ Loaded Processor Factory from: ${identifier}`,\n );\n return factory;\n }\n } catch (e) {\n this.logger.debug(\n ` ➜ No Processor Factory found for: ${identifier}`,\n e,\n );\n }\n\n this.logger.verbose(` ➜ No Processor Factory found for: ${identifier}`);\n\n // return empty processor factory\n return null;\n }\n\n // 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 const root = this.pieceRoot(identifier);\n if (root === undefined) {\n this.logger.debug(` ➜ No package root found for: ${identifier}`);\n return [];\n }\n\n const fullPath = this.getPiecesPath(identifier);\n this.logger.verbose(\"Loading pieces from\", fullPath);\n\n let module: unknown;\n try {\n module = await this.vite.ssrLoadModule(fullPath);\n } catch (e) {\n this.logger.debug(` ➜ No pieces found for: ${identifier}`, e);\n return [];\n }\n\n const pieces = piecesFromListModule(module, {\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":["#loadDocumentModelsWithDebounce","#loadDocumentModels"],"mappings":"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","debug_id":"357b1ab4-fb03-5a36-8191-3308ef8404df"}
@@ -3,6 +3,21 @@ import { DocumentModelModule, UpgradeManifest } from "@powerhousedao/shared/docu
3
3
  import { ProcessorFactoryBuilder, SubgraphClass } from "@powerhousedao/reactor-api";
4
4
 
5
5
  //#region src/packages/types.d.ts
6
+ interface PackagePiece {
7
+ name: string;
8
+ version: string;
9
+ /** Built output, relative to the package root: a directory in npm shape. */
10
+ bundle?: string;
11
+ /** Built output, relative to the package root: a single module file. */
12
+ entry?: string;
13
+ }
14
+ interface PackagePieceEntry {
15
+ name: string;
16
+ version: string;
17
+ entryPath?: string;
18
+ bundleDir?: string;
19
+ entryUrl?: string;
20
+ }
6
21
  interface IPackageLoader {
7
22
  name: string;
8
23
  loadDocumentModels(identifier: string, immediate?: boolean): Promise<DocumentModelModule[]>;
@@ -13,6 +28,8 @@ interface IPackageLoader {
13
28
  loadUpgradeManifests?(identifier: string): Promise<UpgradeManifest<readonly number[]>[]>;
14
29
  loadSubgraphs(identifier: string, immediate?: boolean): Promise<SubgraphClass[]>;
15
30
  loadProcessors(identifier: string, immediate?: boolean): Promise<ProcessorFactoryBuilder | null>;
31
+ /** The pieces a package ships, each located absolutely on this disk. */
32
+ loadPieces(identifier: string, immediate?: boolean): Promise<PackagePieceEntry[]>;
16
33
  }
17
34
  interface ISubscriptionOptions {
18
35
  debounce?: number;
@@ -21,6 +38,7 @@ interface ISubscribablePackageLoader extends IPackageLoader {
21
38
  onDocumentModelsChange?(identifier: string, handler: (documentModels: DocumentModelModule[]) => void, options?: ISubscriptionOptions): () => void;
22
39
  onSubgraphsChange?(identifier: string, handler: (subgraphs: SubgraphClass[]) => void, options?: ISubscriptionOptions): () => void;
23
40
  onProcessorsChange?(identifier: string, handler: (processors: ProcessorFactoryBuilder | null) => void, options?: ISubscriptionOptions): () => void;
41
+ onPiecesChange?(identifier: string, handler: (pieces: PackagePieceEntry[]) => void, options?: ISubscriptionOptions): () => void;
24
42
  }
25
43
  interface IPackageManager {
26
44
  onDocumentModelsChange(handler: (documentModels: Record<string, DocumentModelModule[]>) => void): void;
@@ -42,7 +60,12 @@ type PackageManagerResult = {
42
60
  upgradeManifests: UpgradeManifest<readonly number[]>[];
43
61
  subgraphs: Map<string, SubgraphClass[]>;
44
62
  processors: Map<string, ProcessorFactoryBuilder[]>;
63
+ pieces: Map<string, PackagePieceEntry[]>;
45
64
  };
65
+ interface IPackagePieceSource {
66
+ getPieces(): Map<string, PackagePieceEntry[]>;
67
+ onPiecesChange(handler: (pieces: Map<string, PackagePieceEntry[]>) => void): void;
68
+ }
46
69
  //#endregion
47
- export { ISubscribablePackageLoader as a, IPackageManagerOptions as i, IPackageLoaderOptions as n, ISubscriptionOptions as o, IPackageManager as r, PackageManagerResult as s, IPackageLoader as t };
48
- //# sourceMappingURL=types-Bz2niABC.d.mts.map
70
+ export { IPackagePieceSource as a, PackageManagerResult as c, IPackageManagerOptions as i, PackagePiece as l, IPackageLoaderOptions as n, ISubscribablePackageLoader as o, IPackageManager as r, ISubscriptionOptions as s, IPackageLoader as t, PackagePieceEntry as u };
71
+ //# sourceMappingURL=types-BXjLvTe3.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-BXjLvTe3.d.mts","names":[],"sources":["../src/packages/types.ts"],"mappings":";;;;;UAYiB,YAAA;EACf,IAAA;EACA,OAAA;EAF2B;EAI3B,MAAA;EAJ2B;EAM3B,KAAA;AAAA;AAAA,UAQe,iBAAA;EACf,IAAA;EACA,OAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;AAAA;AAAA,UAGe,cAAA;EACf,IAAA;EACA,kBAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,mBAAA;EAVX;;;;EAeA,oBAAA,EACE,UAAA,WACC,OAAA,CAAQ,eAAA;EACX,aAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,aAAA;EACX,cAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,uBAAA;;EAEX,UAAA,CACE,UAAA,UACA,SAAA,aACC,OAAA,CAAQ,iBAAA;AAAA;AAAA,UAGI,oBAAA;EACf,QAAA;AAAA;AAAA,UAGe,0BAAA,SAAmC,cAAA;EAClD,sBAAA,EACE,UAAA,UACA,OAAA,GAAU,cAAA,EAAgB,mBAAA,aAC1B,OAAA,GAAU,oBAAA;EAEZ,iBAAA,EACE,UAAA,UACA,OAAA,GAAU,SAAA,EAAW,aAAA,aACrB,OAAA,GAAU,oBAAA;EAEZ,kBAAA,EACE,UAAA,UACA,OAAA,GAAU,UAAA,EAAY,uBAAA,kBACtB,OAAA,GAAU,oBAAA;EAEZ,cAAA,EACE,UAAA,UACA,OAAA,GAAU,MAAA,EAAQ,iBAAA,aAClB,OAAA,GAAU,oBAAA;AAAA;AAAA,UAIG,eAAA;EACf,sBAAA,CACE,OAAA,GAAU,cAAA,EAAgB,MAAA,SAAe,mBAAA;EAvD3C;;;;EA6DA,aAAA,CAAc,WAAA;AAAA;AAAA,KAGJ,qBAAA;EACV,MAAA,GAAS,OAAA;AAAA;AAAA,KAGC,sBAAA;EACV,QAAA;EACA,UAAA;AAAA;AAAA,KAWU,oBAAA;EACV,cAAA,EAAgB,mBAAA;EAChB,gBAAA,EAAkB,eAAA;EAClB,SAAA,EAAW,GAAA,SAAY,aAAA;EACvB,UAAA,EAAY,GAAA,SAAY,uBAAA;EACxB,MAAA,EAAQ,GAAA,SAAY,iBAAA;AAAA;AAAA,UAKL,mBAAA;EACf,SAAA,IAAa,GAAA,SAAY,iBAAA;EACzB,cAAA,CACE,OAAA,GAAU,MAAA,EAAQ,GAAA,SAAY,iBAAA;AAAA"}