@powerhousedao/reactor-api 6.0.0-dev.15 → 6.0.0-dev.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/codegen.js +1 -1
- package/dist/codegen.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/src/config.d.ts +1 -2
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +1 -5
- package/dist/src/config.js.map +1 -1
- package/dist/src/dev.d.ts +2 -0
- package/dist/src/dev.d.ts.map +1 -0
- package/dist/src/dev.js +51 -0
- package/dist/src/dev.js.map +1 -0
- package/dist/src/graphql/auth/resolvers.d.ts +17 -0
- package/dist/src/graphql/auth/resolvers.d.ts.map +1 -1
- package/dist/src/graphql/auth/resolvers.js +54 -0
- package/dist/src/graphql/auth/resolvers.js.map +1 -1
- package/dist/src/graphql/auth/schema.graphql +27 -5
- package/dist/src/graphql/auth/subgraph.d.ts +25 -0
- package/dist/src/graphql/auth/subgraph.d.ts.map +1 -1
- package/dist/src/graphql/auth/subgraph.js +46 -2
- package/dist/src/graphql/auth/subgraph.js.map +1 -1
- package/dist/src/graphql/base-subgraph.d.ts +11 -4
- package/dist/src/graphql/base-subgraph.d.ts.map +1 -1
- package/dist/src/graphql/base-subgraph.js +94 -2
- package/dist/src/graphql/base-subgraph.js.map +1 -1
- package/dist/src/graphql/document-model-subgraph.d.ts +104 -45
- package/dist/src/graphql/document-model-subgraph.d.ts.map +1 -1
- package/dist/src/graphql/document-model-subgraph.js +323 -91
- package/dist/src/graphql/document-model-subgraph.js.map +1 -1
- package/dist/src/graphql/gateway/adapter-gateway-apollo.d.ts +23 -0
- package/dist/src/graphql/gateway/adapter-gateway-apollo.d.ts.map +1 -0
- package/dist/src/graphql/gateway/adapter-gateway-apollo.js +156 -0
- package/dist/src/graphql/gateway/adapter-gateway-apollo.js.map +1 -0
- package/dist/src/graphql/gateway/adapter-gateway-mercurius.d.ts +17 -0
- package/dist/src/graphql/gateway/adapter-gateway-mercurius.d.ts.map +1 -0
- package/dist/src/graphql/gateway/adapter-gateway-mercurius.js +154 -0
- package/dist/src/graphql/gateway/adapter-gateway-mercurius.js.map +1 -0
- package/dist/src/graphql/gateway/adapter-http-express.d.ts +25 -0
- package/dist/src/graphql/gateway/adapter-http-express.d.ts.map +1 -0
- package/dist/src/graphql/gateway/adapter-http-express.js +163 -0
- package/dist/src/graphql/gateway/adapter-http-express.js.map +1 -0
- package/dist/src/graphql/gateway/adapter-http-fastify.d.ts +23 -0
- package/dist/src/graphql/gateway/adapter-http-fastify.d.ts.map +1 -0
- package/dist/src/graphql/gateway/adapter-http-fastify.js +228 -0
- package/dist/src/graphql/gateway/adapter-http-fastify.js.map +1 -0
- package/dist/src/graphql/gateway/auth-middleware.d.ts +7 -0
- package/dist/src/graphql/gateway/auth-middleware.d.ts.map +1 -0
- package/dist/src/graphql/gateway/auth-middleware.js +15 -0
- package/dist/src/graphql/gateway/auth-middleware.js.map +1 -0
- package/dist/src/graphql/gateway/factory.d.ts +11 -0
- package/dist/src/graphql/gateway/factory.d.ts.map +1 -0
- package/dist/src/graphql/gateway/factory.js +21 -0
- package/dist/src/graphql/gateway/factory.js.map +1 -0
- package/dist/src/graphql/gateway/types.d.ts +100 -0
- package/dist/src/graphql/gateway/types.d.ts.map +1 -0
- package/dist/src/{sync → graphql/gateway}/types.js.map +1 -1
- package/dist/src/graphql/graphql-manager.d.ts +30 -12
- package/dist/src/graphql/graphql-manager.d.ts.map +1 -1
- package/dist/src/graphql/graphql-manager.js +282 -232
- package/dist/src/graphql/graphql-manager.js.map +1 -1
- package/dist/src/graphql/index.d.ts +5 -1
- package/dist/src/graphql/index.d.ts.map +1 -1
- package/dist/src/graphql/index.js +5 -1
- package/dist/src/graphql/index.js.map +1 -1
- package/dist/src/graphql/packages/index.d.ts +2 -0
- package/dist/src/graphql/packages/index.d.ts.map +1 -0
- package/dist/src/graphql/packages/index.js +2 -0
- package/dist/src/graphql/packages/index.js.map +1 -0
- package/dist/src/graphql/packages/resolvers.d.ts +31 -0
- package/dist/src/graphql/packages/resolvers.d.ts.map +1 -0
- package/dist/src/graphql/packages/resolvers.js +37 -0
- package/dist/src/graphql/packages/resolvers.js.map +1 -0
- package/dist/src/graphql/packages/schema.graphql +50 -0
- package/dist/src/graphql/packages/subgraph.d.ts +55 -0
- package/dist/src/graphql/packages/subgraph.d.ts.map +1 -0
- package/dist/src/graphql/packages/subgraph.js +73 -0
- package/dist/src/graphql/packages/subgraph.js.map +1 -0
- package/dist/src/graphql/playground.d.ts.map +1 -1
- package/dist/src/graphql/playground.js +19 -12
- package/dist/src/graphql/playground.js.map +1 -1
- package/dist/src/graphql/reactor/adapters.d.ts +10 -2
- package/dist/src/graphql/reactor/adapters.d.ts.map +1 -1
- package/dist/src/graphql/reactor/adapters.js +36 -1
- package/dist/src/graphql/reactor/adapters.js.map +1 -1
- package/dist/src/graphql/reactor/factory.d.ts +28 -7
- package/dist/src/graphql/reactor/factory.d.ts.map +1 -1
- package/dist/src/graphql/reactor/factory.js +1 -1
- package/dist/src/graphql/reactor/factory.js.map +1 -1
- package/dist/src/graphql/reactor/gen/graphql.d.ts +363 -84
- package/dist/src/graphql/reactor/gen/graphql.d.ts.map +1 -1
- package/dist/src/graphql/reactor/gen/graphql.js +247 -12
- package/dist/src/graphql/reactor/gen/graphql.js.map +1 -1
- package/dist/src/graphql/reactor/index.d.ts +1 -1
- package/dist/src/graphql/reactor/index.d.ts.map +1 -1
- package/dist/src/graphql/reactor/index.js +1 -1
- package/dist/src/graphql/reactor/index.js.map +1 -1
- package/dist/src/graphql/reactor/operations.graphql +193 -3
- package/dist/src/graphql/reactor/requester.with-zod.d.ts.map +1 -1
- package/dist/src/graphql/reactor/requester.with-zod.js +114 -38
- package/dist/src/graphql/reactor/requester.with-zod.js.map +1 -1
- package/dist/src/graphql/reactor/resolvers.d.ts +90 -26
- package/dist/src/graphql/reactor/resolvers.d.ts.map +1 -1
- package/dist/src/graphql/reactor/resolvers.js +258 -77
- package/dist/src/graphql/reactor/resolvers.js.map +1 -1
- package/dist/src/graphql/reactor/schema.graphql +78 -32
- package/dist/src/graphql/reactor/subgraph.d.ts +2 -31
- package/dist/src/graphql/reactor/subgraph.d.ts.map +1 -1
- package/dist/src/graphql/reactor/subgraph.js +139 -213
- package/dist/src/graphql/reactor/subgraph.js.map +1 -1
- package/dist/src/graphql/reactor/validation.d.ts +266 -20
- package/dist/src/graphql/reactor/validation.d.ts.map +1 -1
- package/dist/src/graphql/reactor/validation.js +98 -4
- package/dist/src/graphql/reactor/validation.js.map +1 -1
- package/dist/src/graphql/sse.d.ts +35 -0
- package/dist/src/graphql/sse.d.ts.map +1 -0
- package/dist/src/graphql/sse.js +29 -0
- package/dist/src/graphql/sse.js.map +1 -0
- package/dist/src/graphql/system/index.d.ts +0 -1
- package/dist/src/graphql/system/index.d.ts.map +1 -1
- package/dist/src/graphql/system/index.js +0 -1
- package/dist/src/graphql/system/index.js.map +1 -1
- package/dist/src/graphql/types.d.ts +7 -8
- package/dist/src/graphql/types.d.ts.map +1 -1
- package/dist/src/graphql/utils.d.ts +3 -20
- package/dist/src/graphql/utils.d.ts.map +1 -1
- package/dist/src/graphql/utils.js +7 -35
- package/dist/src/graphql/utils.js.map +1 -1
- package/dist/src/migrations/002_add_document_protection.d.ts +4 -0
- package/dist/src/migrations/002_add_document_protection.d.ts.map +1 -0
- package/dist/src/migrations/002_add_document_protection.js +18 -0
- package/dist/src/migrations/002_add_document_protection.js.map +1 -0
- package/dist/src/migrations/index.d.ts.map +1 -1
- package/dist/src/migrations/index.js +2 -0
- package/dist/src/migrations/index.js.map +1 -1
- package/dist/src/packages/http-loader.d.ts +59 -0
- package/dist/src/packages/http-loader.d.ts.map +1 -0
- package/dist/src/packages/http-loader.js +203 -0
- package/dist/src/packages/http-loader.js.map +1 -0
- package/dist/src/packages/https-hooks.d.mts +37 -0
- package/dist/src/packages/https-hooks.d.mts.map +1 -0
- package/dist/src/packages/https-hooks.mjs +95 -0
- package/dist/src/packages/https-hooks.mjs.map +1 -0
- package/dist/src/packages/import-loader.d.ts +4 -6
- package/dist/src/packages/import-loader.d.ts.map +1 -1
- package/dist/src/packages/import-loader.js +4 -18
- package/dist/src/packages/import-loader.js.map +1 -1
- package/dist/src/packages/package-manager.d.ts +3 -4
- package/dist/src/packages/package-manager.d.ts.map +1 -1
- package/dist/src/packages/package-manager.js +10 -7
- package/dist/src/packages/package-manager.js.map +1 -1
- package/dist/src/packages/types.d.ts +8 -8
- package/dist/src/packages/types.d.ts.map +1 -1
- package/dist/src/packages/util.d.ts +4 -5
- package/dist/src/packages/util.d.ts.map +1 -1
- package/dist/src/packages/util.js +2 -14
- package/dist/src/packages/util.js.map +1 -1
- package/dist/src/packages/vite-loader.d.ts +12 -11
- package/dist/src/packages/vite-loader.d.ts.map +1 -1
- package/dist/src/packages/vite-loader.js +20 -21
- package/dist/src/packages/vite-loader.js.map +1 -1
- package/dist/src/server.d.ts +15 -33
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +164 -244
- package/dist/src/server.js.map +1 -1
- package/dist/src/services/auth.service.d.ts +3 -18
- package/dist/src/services/auth.service.d.ts.map +1 -1
- package/dist/src/services/auth.service.js +38 -72
- package/dist/src/services/auth.service.js.map +1 -1
- package/dist/src/services/authorization.service.d.ts +70 -0
- package/dist/src/services/authorization.service.d.ts.map +1 -0
- package/dist/src/services/authorization.service.js +155 -0
- package/dist/src/services/authorization.service.js.map +1 -0
- package/dist/src/services/document-permission.service.d.ts +47 -7
- package/dist/src/services/document-permission.service.d.ts.map +1 -1
- package/dist/src/services/document-permission.service.js +162 -7
- package/dist/src/services/document-permission.service.js.map +1 -1
- package/dist/src/services/package-management.service.d.ts +32 -0
- package/dist/src/services/package-management.service.d.ts.map +1 -0
- package/dist/src/services/package-management.service.js +95 -0
- package/dist/src/services/package-management.service.js.map +1 -0
- package/dist/src/services/package-storage.d.ts +23 -0
- package/dist/src/services/package-storage.d.ts.map +1 -0
- package/dist/src/services/package-storage.js +19 -0
- package/dist/src/services/package-storage.js.map +1 -0
- package/dist/src/tracing.d.ts.map +1 -1
- package/dist/src/tracing.js +25 -1
- package/dist/src/tracing.js.map +1 -1
- package/dist/src/types.d.ts +13 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/create-schema.d.ts +31 -6
- package/dist/src/utils/create-schema.d.ts.map +1 -1
- package/dist/src/utils/create-schema.js +446 -40
- package/dist/src/utils/create-schema.js.map +1 -1
- package/dist/src/utils/db.d.ts +8 -0
- package/dist/src/utils/db.d.ts.map +1 -1
- package/dist/src/utils/db.js.map +1 -1
- package/dist/test/auth-chain.test.d.ts +12 -0
- package/dist/test/auth-chain.test.d.ts.map +1 -0
- package/dist/test/auth-chain.test.js +157 -0
- package/dist/test/auth-chain.test.js.map +1 -0
- package/dist/test/auth.service.test.d.ts +10 -0
- package/dist/test/auth.service.test.d.ts.map +1 -0
- package/dist/test/auth.service.test.js +141 -0
- package/dist/test/auth.service.test.js.map +1 -0
- package/dist/test/authorization.service.test.d.ts +2 -0
- package/dist/test/authorization.service.test.d.ts.map +1 -0
- package/dist/test/authorization.service.test.js +252 -0
- package/dist/test/authorization.service.test.js.map +1 -0
- package/dist/test/connect-switchboard-reshuffle-convergence.test.d.ts +2 -0
- package/dist/test/connect-switchboard-reshuffle-convergence.test.d.ts.map +1 -0
- package/dist/test/connect-switchboard-reshuffle-convergence.test.js +204 -0
- package/dist/test/connect-switchboard-reshuffle-convergence.test.js.map +1 -0
- package/dist/test/connect-switchboard-sync.test.d.ts +2 -0
- package/dist/test/connect-switchboard-sync.test.d.ts.map +1 -0
- package/dist/test/connect-switchboard-sync.test.js +633 -0
- package/dist/test/connect-switchboard-sync.test.js.map +1 -0
- package/dist/test/document-drive-subgraph.test.d.ts +2 -0
- package/dist/test/document-drive-subgraph.test.d.ts.map +1 -0
- package/dist/test/document-drive-subgraph.test.js +244 -0
- package/dist/test/document-drive-subgraph.test.js.map +1 -0
- package/dist/test/document-model-subgraph-permissions.test.d.ts +2 -0
- package/dist/test/document-model-subgraph-permissions.test.d.ts.map +1 -0
- package/dist/test/document-model-subgraph-permissions.test.js +587 -0
- package/dist/test/document-model-subgraph-permissions.test.js.map +1 -0
- package/dist/test/drive-info-endpoint.test.d.ts +2 -0
- package/dist/test/drive-info-endpoint.test.d.ts.map +1 -0
- package/dist/test/drive-info-endpoint.test.js +123 -0
- package/dist/test/drive-info-endpoint.test.js.map +1 -0
- package/dist/test/fault-injection-sync.test.d.ts +2 -0
- package/dist/test/fault-injection-sync.test.d.ts.map +1 -0
- package/dist/test/fault-injection-sync.test.js +197 -0
- package/dist/test/fault-injection-sync.test.js.map +1 -0
- package/dist/test/gateway/adapter-gateway-apollo.test.d.ts +2 -0
- package/dist/test/gateway/adapter-gateway-apollo.test.d.ts.map +1 -0
- package/dist/test/gateway/adapter-gateway-apollo.test.js +206 -0
- package/dist/test/gateway/adapter-gateway-apollo.test.js.map +1 -0
- package/dist/test/gateway/adapter-gateway-mercurius.test.d.ts +2 -0
- package/dist/test/gateway/adapter-gateway-mercurius.test.d.ts.map +1 -0
- package/dist/test/gateway/adapter-gateway-mercurius.test.js +23 -0
- package/dist/test/gateway/adapter-gateway-mercurius.test.js.map +1 -0
- package/dist/test/gateway/adapter-http-express.test.d.ts +2 -0
- package/dist/test/gateway/adapter-http-express.test.d.ts.map +1 -0
- package/dist/test/gateway/adapter-http-express.test.js +17 -0
- package/dist/test/gateway/adapter-http-express.test.js.map +1 -0
- package/dist/test/gateway/adapter-http-fastify.test.d.ts +2 -0
- package/dist/test/gateway/adapter-http-fastify.test.d.ts.map +1 -0
- package/dist/test/gateway/adapter-http-fastify.test.js +17 -0
- package/dist/test/gateway/adapter-http-fastify.test.js.map +1 -0
- package/dist/test/gateway/auth-middleware.test.d.ts +8 -0
- package/dist/test/gateway/auth-middleware.test.d.ts.map +1 -0
- package/dist/test/gateway/auth-middleware.test.js +73 -0
- package/dist/test/gateway/auth-middleware.test.js.map +1 -0
- package/dist/test/gateway/gateway-adapter-contract.d.ts +30 -0
- package/dist/test/gateway/gateway-adapter-contract.d.ts.map +1 -0
- package/dist/test/gateway/gateway-adapter-contract.js +347 -0
- package/dist/test/gateway/gateway-adapter-contract.js.map +1 -0
- package/dist/test/gateway/http-adapter-contract.d.ts +30 -0
- package/dist/test/gateway/http-adapter-contract.d.ts.map +1 -0
- package/dist/test/gateway/http-adapter-contract.js +277 -0
- package/dist/test/gateway/http-adapter-contract.js.map +1 -0
- package/dist/test/graphql-manager.test.d.ts +12 -0
- package/dist/test/graphql-manager.test.d.ts.map +1 -0
- package/dist/test/graphql-manager.test.js +576 -0
- package/dist/test/graphql-manager.test.js.map +1 -0
- package/dist/test/index.d.ts +0 -1
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +0 -1
- package/dist/test/index.js.map +1 -1
- package/dist/test/permissions-integration.test.js +6 -20
- package/dist/test/permissions-integration.test.js.map +1 -1
- package/dist/test/push-backfill.test.d.ts +2 -0
- package/dist/test/push-backfill.test.d.ts.map +1 -0
- package/dist/test/push-backfill.test.js +299 -0
- package/dist/test/push-backfill.test.js.map +1 -0
- package/dist/test/reactor-adapters.test.js +3 -2
- package/dist/test/reactor-adapters.test.js.map +1 -1
- package/dist/test/reactor-client.test.js +172 -13
- package/dist/test/reactor-client.test.js.map +1 -1
- package/dist/test/reactor-resolvers.test.js +11 -13
- package/dist/test/reactor-resolvers.test.js.map +1 -1
- package/dist/test/reactor-subgraph-permissions.test.js +7 -36
- package/dist/test/reactor-subgraph-permissions.test.js.map +1 -1
- package/dist/test/subscriptions-sse.test.d.ts +2 -0
- package/dist/test/subscriptions-sse.test.d.ts.map +1 -0
- package/dist/test/subscriptions-sse.test.js +264 -0
- package/dist/test/subscriptions-sse.test.js.map +1 -0
- package/dist/test/subscriptions.test.js +2 -0
- package/dist/test/subscriptions.test.js.map +1 -1
- package/dist/test/utils/gql-resolver-bridge.d.ts +4 -1
- package/dist/test/utils/gql-resolver-bridge.d.ts.map +1 -1
- package/dist/test/utils/gql-resolver-bridge.js +36 -7
- package/dist/test/utils/gql-resolver-bridge.js.map +1 -1
- package/dist/test/utils.d.ts +1 -5
- package/dist/test/utils.d.ts.map +1 -1
- package/dist/test/utils.js +0 -10
- package/dist/test/utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +1 -0
- package/dist/vitest.config.js.map +1 -1
- package/package.json +64 -59
- package/dist/src/graphql/drive-subgraph.d.ts +0 -25
- package/dist/src/graphql/drive-subgraph.d.ts.map +0 -1
- package/dist/src/graphql/drive-subgraph.js +0 -487
- package/dist/src/graphql/drive-subgraph.js.map +0 -1
- package/dist/src/graphql/system/system-subgraph.d.ts +0 -49
- package/dist/src/graphql/system/system-subgraph.d.ts.map +0 -1
- package/dist/src/graphql/system/system-subgraph.js +0 -130
- package/dist/src/graphql/system/system-subgraph.js.map +0 -1
- package/dist/src/sync/types.d.ts +0 -10
- package/dist/src/sync/types.d.ts.map +0 -1
- package/dist/src/sync/utils.d.ts +0 -7
- package/dist/src/sync/utils.d.ts.map +0 -1
- package/dist/src/sync/utils.js +0 -78
- package/dist/src/sync/utils.js.map +0 -1
- package/dist/src/utils/auth.d.ts +0 -3
- package/dist/src/utils/auth.d.ts.map +0 -1
- package/dist/src/utils/auth.js +0 -19
- package/dist/src/utils/auth.js.map +0 -1
- package/dist/test/benchmarks/load.bench.d.ts +0 -2
- package/dist/test/benchmarks/load.bench.d.ts.map +0 -1
- package/dist/test/benchmarks/load.bench.js +0 -73
- package/dist/test/benchmarks/load.bench.js.map +0 -1
- package/dist/test/benchmarks/sync.bench.d.ts +0 -2
- package/dist/test/benchmarks/sync.bench.d.ts.map +0 -1
- package/dist/test/benchmarks/sync.bench.js +0 -119
- package/dist/test/benchmarks/sync.bench.js.map +0 -1
- package/dist/test/drive-handlers.d.ts +0 -4
- package/dist/test/drive-handlers.d.ts.map +0 -1
- package/dist/test/drive-handlers.js +0 -39
- package/dist/test/drive-handlers.js.map +0 -1
- package/dist/test/drive-subgraph-permissions.test.d.ts +0 -2
- package/dist/test/drive-subgraph-permissions.test.d.ts.map +0 -1
- package/dist/test/drive-subgraph-permissions.test.js +0 -195
- package/dist/test/drive-subgraph-permissions.test.js.map +0 -1
- package/dist/test/drive.test.d.ts +0 -2
- package/dist/test/drive.test.d.ts.map +0 -1
- package/dist/test/drive.test.js +0 -142
- package/dist/test/drive.test.js.map +0 -1
- package/dist/test/identity-integration.test.d.ts +0 -2
- package/dist/test/identity-integration.test.d.ts.map +0 -1
- package/dist/test/identity-integration.test.js +0 -349
- package/dist/test/identity-integration.test.js.map +0 -1
- package/dist/test/pull-responder-transmitter.test.d.ts +0 -2
- package/dist/test/pull-responder-transmitter.test.d.ts.map +0 -1
- package/dist/test/pull-responder-transmitter.test.js +0 -220
- package/dist/test/pull-responder-transmitter.test.js.map +0 -1
- package/dist/test/push-transmitter.test.d.ts +0 -2
- package/dist/test/push-transmitter.test.d.ts.map +0 -1
- package/dist/test/push-transmitter.test.js +0 -179
- package/dist/test/push-transmitter.test.js.map +0 -1
- package/dist/test/system.test.d.ts +0 -2
- package/dist/test/system.test.d.ts.map +0 -1
- package/dist/test/system.test.js +0 -211
- package/dist/test/system.test.js.map +0 -1
- package/dist/test/three-reactor-gql-sync.test.d.ts +0 -2
- package/dist/test/three-reactor-gql-sync.test.d.ts.map +0 -1
- package/dist/test/three-reactor-gql-sync.test.js +0 -368
- package/dist/test/three-reactor-gql-sync.test.js.map +0 -1
- package/dist/test/two-reactor-gql-sync.test.d.ts +0 -2
- package/dist/test/two-reactor-gql-sync.test.d.ts.map +0 -1
- package/dist/test/two-reactor-gql-sync.test.js +0 -348
- package/dist/test/two-reactor-gql-sync.test.js.map +0 -1
- /package/dist/src/{sync → graphql/gateway}/types.js +0 -0
|
@@ -1,33 +1,13 @@
|
|
|
1
|
-
import { ApolloGateway, LocalCompose, RemoteGraphQLDataSource, } from "@apollo/gateway";
|
|
2
|
-
import { ApolloServer } from "@apollo/server";
|
|
3
|
-
import { ApolloServerPluginInlineTraceDisabled } from "@apollo/server/plugin/disabled";
|
|
4
|
-
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
|
|
5
|
-
import { ApolloServerPluginLandingPageLocalDefault } from "@apollo/server/plugin/landingPage/default";
|
|
6
|
-
import { expressMiddleware } from "@as-integrations/express4";
|
|
7
|
-
import bodyParser from "body-parser";
|
|
8
|
-
import cors from "cors";
|
|
9
|
-
import { childLogger, debounce } from "document-drive";
|
|
10
|
-
import { Router } from "express";
|
|
11
1
|
import path from "node:path";
|
|
12
|
-
import {
|
|
2
|
+
import { match } from "path-to-regexp";
|
|
3
|
+
import { debounce } from "../packages/util.js";
|
|
13
4
|
import { AuthService } from "../services/auth.service.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
5
|
+
import { getAuthContext, } from "./gateway/auth-middleware.js";
|
|
6
|
+
import { buildSubgraphSchemaModule, createMergedSchema, createSchema, } from "../utils/create-schema.js";
|
|
7
|
+
import { DocumentModelSubgraph } from "./document-model-subgraph.js";
|
|
8
|
+
import { createGraphQLSSEHandler } from "./sse.js";
|
|
17
9
|
import { useServer } from "./websocket.js";
|
|
18
|
-
|
|
19
|
-
willSendRequest(options) {
|
|
20
|
-
const { authorization } = options.context.headers;
|
|
21
|
-
// console.log("context", options.context.headers.authorization);
|
|
22
|
-
if (authorization && options?.request.http) {
|
|
23
|
-
options.request.http.headers.set("authorization", authorization);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const DOCUMENT_MODELS_TO_EXCLUDE = [
|
|
28
|
-
"powerhouse/document-model",
|
|
29
|
-
"powerhouse/document-drive",
|
|
30
|
-
];
|
|
10
|
+
const DOCUMENT_MODELS_TO_EXCLUDE = [];
|
|
31
11
|
/**
|
|
32
12
|
* Check if a document model has any operations with valid schemas.
|
|
33
13
|
* Document models without valid operation schemas cannot generate valid subgraph schemas.
|
|
@@ -36,128 +16,153 @@ function hasOperationSchemas(documentModel) {
|
|
|
36
16
|
const specification = documentModel.documentModel.global.specifications.at(-1);
|
|
37
17
|
if (!specification)
|
|
38
18
|
return false;
|
|
39
|
-
// Check if any operation has a schema with actual GraphQL type definitions
|
|
40
19
|
const hasValidSchema = (schema) => schema && /\b(input|type|enum|union|interface)\s+\w+/.test(schema);
|
|
41
20
|
return specification.modules.some((module) => module.operations.some((op) => hasValidSchema(op.schema)));
|
|
42
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Filter document models to keep only the latest version of each unique document model.
|
|
24
|
+
*/
|
|
25
|
+
function filterLatestDocumentModelVersions(documentModels) {
|
|
26
|
+
const latestByName = new Map();
|
|
27
|
+
for (const documentModel of documentModels) {
|
|
28
|
+
const name = documentModel.documentModel.global.name;
|
|
29
|
+
const existing = latestByName.get(name);
|
|
30
|
+
if (!existing) {
|
|
31
|
+
latestByName.set(name, documentModel);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const currentVersion = documentModel.documentModel.global.specifications.at(-1)?.version ?? 0;
|
|
35
|
+
const existingVersion = existing.documentModel.global.specifications.at(-1)?.version ?? 0;
|
|
36
|
+
if (currentVersion > existingVersion) {
|
|
37
|
+
latestByName.set(name, documentModel);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Array.from(latestByName.values());
|
|
41
|
+
}
|
|
43
42
|
const DefaultFeatureFlags = {
|
|
44
43
|
enableDocumentModelSubgraphs: true,
|
|
45
44
|
};
|
|
46
45
|
export class GraphQLManager {
|
|
47
46
|
path;
|
|
48
|
-
app;
|
|
49
47
|
httpServer;
|
|
50
48
|
wsServer;
|
|
51
|
-
reactor;
|
|
52
49
|
reactorClient;
|
|
53
50
|
relationalDb;
|
|
54
51
|
analyticsStore;
|
|
55
52
|
syncManager;
|
|
53
|
+
logger;
|
|
54
|
+
httpAdapter;
|
|
55
|
+
gatewayAdapter;
|
|
56
56
|
authConfig;
|
|
57
57
|
documentPermissionService;
|
|
58
58
|
featureFlags;
|
|
59
59
|
port;
|
|
60
|
+
authorizationService;
|
|
60
61
|
initialized = false;
|
|
61
|
-
coreRouter = Router();
|
|
62
62
|
coreSubgraphsMap = new Map();
|
|
63
|
-
reactorRouter = Router();
|
|
64
63
|
contextFields = {};
|
|
65
64
|
subgraphs = new Map();
|
|
66
65
|
authService = null;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
constructor(path, app, httpServer, wsServer, reactor, reactorClient, relationalDb, analyticsStore, syncManager, authConfig, documentPermissionService, featureFlags = DefaultFeatureFlags, port = 4001) {
|
|
66
|
+
subgraphWsDisposers = new Map();
|
|
67
|
+
#authMiddleware;
|
|
68
|
+
/** Cached document models for schema generation - updated on init and regenerate */
|
|
69
|
+
cachedDocumentModels = [];
|
|
70
|
+
subgraphHandlerCache = new Map();
|
|
71
|
+
constructor(path, httpServer, wsServer, reactorClient, relationalDb, analyticsStore, syncManager, logger, httpAdapter, gatewayAdapter, authConfig, documentPermissionService, featureFlags = DefaultFeatureFlags, port = 4001, authorizationService) {
|
|
74
72
|
this.path = path;
|
|
75
|
-
this.app = app;
|
|
76
73
|
this.httpServer = httpServer;
|
|
77
74
|
this.wsServer = wsServer;
|
|
78
|
-
this.reactor = reactor;
|
|
79
75
|
this.reactorClient = reactorClient;
|
|
80
76
|
this.relationalDb = relationalDb;
|
|
81
77
|
this.analyticsStore = analyticsStore;
|
|
82
78
|
this.syncManager = syncManager;
|
|
79
|
+
this.logger = logger;
|
|
80
|
+
this.httpAdapter = httpAdapter;
|
|
81
|
+
this.gatewayAdapter = gatewayAdapter;
|
|
83
82
|
this.authConfig = authConfig;
|
|
84
83
|
this.documentPermissionService = documentPermissionService;
|
|
85
84
|
this.featureFlags = featureFlags;
|
|
86
85
|
this.port = port;
|
|
86
|
+
this.authorizationService = authorizationService;
|
|
87
87
|
if (this.authConfig) {
|
|
88
88
|
this.authService = new AuthService(this.authConfig);
|
|
89
|
-
this.setAdditionalContextFields(this.authService.getAdditionalContextFields());
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
|
-
async init(coreSubgraphs) {
|
|
91
|
+
async init(coreSubgraphs, authMiddleware) {
|
|
92
|
+
this.#authMiddleware = authMiddleware;
|
|
93
93
|
this.logger.debug(`Initializing Subgraph Manager...`);
|
|
94
94
|
// check if Document Drive model is available
|
|
95
|
-
const
|
|
95
|
+
const modulesResult = await this.reactorClient.getDocumentModelModules();
|
|
96
|
+
const models = modulesResult.results;
|
|
97
|
+
// Cache models for schema generation
|
|
98
|
+
this.cachedDocumentModels = models;
|
|
96
99
|
const driveModel = models.find((it) => it.documentModel.global.name === "DocumentDrive");
|
|
97
100
|
if (!driveModel) {
|
|
98
101
|
throw new Error("DocumentDrive model required");
|
|
99
102
|
}
|
|
100
|
-
this.
|
|
101
|
-
this.
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
isUser: (address) => !req.auth_enabled
|
|
133
|
-
? true
|
|
134
|
-
: (req.users
|
|
135
|
-
?.map((a) => a.toLowerCase())
|
|
136
|
-
.includes(address.toLowerCase() ?? "") ?? false),
|
|
137
|
-
isGuest: (address) => !req.auth_enabled
|
|
138
|
-
? true
|
|
139
|
-
: (req.guests
|
|
140
|
-
?.map((a) => a.toLowerCase())
|
|
141
|
-
.includes(address.toLowerCase() ?? "") ?? false),
|
|
142
|
-
});
|
|
143
|
-
this.reactorRouter(req, res, next);
|
|
103
|
+
await this.gatewayAdapter.start(this.httpServer);
|
|
104
|
+
this.httpAdapter.setupMiddleware({ bodyLimit: "50mb" });
|
|
105
|
+
// Register REST endpoint for drive info as a framework-agnostic FetchHandler.
|
|
106
|
+
const driveRoutePath = path.join(this.path, "d/:drive");
|
|
107
|
+
const driveMatcher = match(driveRoutePath);
|
|
108
|
+
this.httpAdapter.mount(driveRoutePath, async (request) => {
|
|
109
|
+
const url = new URL(request.url);
|
|
110
|
+
const matched = driveMatcher(url.pathname);
|
|
111
|
+
const driveIdOrSlug = matched ? matched.params.drive : undefined;
|
|
112
|
+
if (!driveIdOrSlug) {
|
|
113
|
+
return Response.json({ error: "Drive ID or slug is required" }, { status: 400 });
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const driveDoc = await this.reactorClient.get(driveIdOrSlug);
|
|
117
|
+
const forwardedProto = request.headers.get("x-forwarded-proto");
|
|
118
|
+
const protocol = (forwardedProto ?? url.protocol.replace(":", "")) + ":";
|
|
119
|
+
const host = request.headers.get("host") ?? "";
|
|
120
|
+
const basePath = this.path === "/" ? "" : this.path;
|
|
121
|
+
const graphqlEndpoint = `${protocol}//${host}${basePath}/graphql/r`;
|
|
122
|
+
return Response.json({
|
|
123
|
+
id: driveDoc.header.id,
|
|
124
|
+
slug: driveDoc.header.slug,
|
|
125
|
+
meta: driveDoc.header.meta,
|
|
126
|
+
name: driveDoc.state.global.name,
|
|
127
|
+
icon: driveDoc.state.global.icon ?? undefined,
|
|
128
|
+
...(graphqlEndpoint && { graphqlEndpoint }),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
this.logger.debug(`Drive not found: ${driveIdOrSlug}`, error);
|
|
133
|
+
return Response.json({ error: "Drive not found" }, { status: 404 });
|
|
134
|
+
}
|
|
144
135
|
});
|
|
136
|
+
this.logger.info(`Registered REST endpoint: GET ${driveRoutePath}`);
|
|
145
137
|
await this.#setupCoreSubgraphs("graphql", coreSubgraphs);
|
|
146
138
|
if (this.featureFlags.enableDocumentModelSubgraphs) {
|
|
147
|
-
await this.#setupDocumentModelSubgraphs("graphql",
|
|
139
|
+
await this.#setupDocumentModelSubgraphs("graphql", models);
|
|
148
140
|
}
|
|
149
|
-
this
|
|
150
|
-
if (this.featureFlags.enableDocumentModelSubgraphs) {
|
|
151
|
-
this.#setupDocumentModelSubgraphs("graphql", documentModels)
|
|
152
|
-
.then(() => this.updateRouter())
|
|
153
|
-
.catch((error) => this.logger.error(error));
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
this.updateRouter().catch((error) => this.logger.error(error));
|
|
157
|
-
}
|
|
158
|
-
});
|
|
141
|
+
await this.#createSupergraphGateway();
|
|
159
142
|
return this.updateRouter();
|
|
160
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Regenerate document model subgraphs when models are dynamically loaded.
|
|
146
|
+
* Fetches current modules from reactor client (source of truth).
|
|
147
|
+
*/
|
|
148
|
+
async regenerateDocumentModelSubgraphs() {
|
|
149
|
+
if (!this.featureFlags.enableDocumentModelSubgraphs) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const modulesResult = await this.reactorClient.getDocumentModelModules();
|
|
154
|
+
const models = modulesResult.results;
|
|
155
|
+
// Update cached models for schema generation
|
|
156
|
+
this.cachedDocumentModels = models;
|
|
157
|
+
await this.#setupDocumentModelSubgraphs("graphql", models);
|
|
158
|
+
await this.updateRouter();
|
|
159
|
+
this.logger.info("Regenerated document model subgraphs with @count models", models.length);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.logger.error("Failed to regenerate document model subgraphs", error);
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
161
166
|
async #setupCoreSubgraphs(supergraph, coreSubgraphs) {
|
|
162
167
|
for (const subgraph of coreSubgraphs) {
|
|
163
168
|
try {
|
|
@@ -167,87 +172,100 @@ export class GraphQLManager {
|
|
|
167
172
|
this.logger.error(`Failed to setup core subgraph ${subgraph.name}`, error);
|
|
168
173
|
}
|
|
169
174
|
}
|
|
170
|
-
|
|
171
|
-
await this.registerSubgraph(DriveSubgraph, undefined, true);
|
|
172
|
-
return this.#setupSubgraphs(this.coreSubgraphsMap, this.coreRouter);
|
|
175
|
+
return this.#setupSubgraphs(this.coreSubgraphsMap);
|
|
173
176
|
}
|
|
174
177
|
async #setupDocumentModelSubgraphs(supergraph, documentModels) {
|
|
175
|
-
|
|
178
|
+
const latestDocumentModels = filterLatestDocumentModelVersions(documentModels);
|
|
179
|
+
for (const documentModel of latestDocumentModels) {
|
|
176
180
|
if (DOCUMENT_MODELS_TO_EXCLUDE.includes(documentModel.documentModel.global.id)) {
|
|
177
|
-
continue;
|
|
181
|
+
continue;
|
|
178
182
|
}
|
|
179
183
|
if (!hasOperationSchemas(documentModel)) {
|
|
180
|
-
continue;
|
|
184
|
+
continue;
|
|
181
185
|
}
|
|
182
186
|
try {
|
|
183
|
-
const subgraphInstance = new
|
|
187
|
+
const subgraphInstance = new DocumentModelSubgraph(documentModel, {
|
|
184
188
|
relationalDb: this.relationalDb,
|
|
185
189
|
analyticsStore: this.analyticsStore,
|
|
186
|
-
reactor: this.reactor,
|
|
187
190
|
reactorClient: this.reactorClient,
|
|
188
191
|
graphqlManager: this,
|
|
189
192
|
syncManager: this.syncManager,
|
|
190
193
|
path: this.path,
|
|
191
194
|
documentPermissionService: this.documentPermissionService,
|
|
195
|
+
authorizationService: this.authorizationService,
|
|
192
196
|
});
|
|
193
197
|
await this.#addSubgraphInstance(subgraphInstance, supergraph, false);
|
|
194
198
|
}
|
|
195
199
|
catch (error) {
|
|
196
200
|
this.logger.error(`Failed to setup document model subgraph for ${documentModel.documentModel.global.id}`, error instanceof Error ? error.message : error);
|
|
197
|
-
this.logger.debug(error);
|
|
201
|
+
this.logger.debug("@error", error);
|
|
198
202
|
}
|
|
199
203
|
}
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
// Document model subgraph instances are added to this.subgraphs above.
|
|
205
|
+
// Their handlers are wired in _updateRouter() → #setupSubgraphs(this.subgraphs),
|
|
206
|
+
// which is called at the end of init() via updateRouter(). We intentionally do
|
|
207
|
+
// NOT call #setupSubgraphs(this.coreSubgraphsMap) here - doing so would
|
|
208
|
+
// create duplicate Apollo servers for the same core-subgraph schemas, which
|
|
209
|
+
// in the new IGatewayAdapter architecture hangs #waitForServer and blocks init().
|
|
203
210
|
}
|
|
204
211
|
async #addSubgraphInstance(subgraphInstance, supergraph = "", core = false) {
|
|
205
|
-
await subgraphInstance.onSetup?.();
|
|
206
212
|
const subgraphsMap = core ? this.coreSubgraphsMap : this.subgraphs;
|
|
207
213
|
const subgraphs = subgraphsMap.get(supergraph) ?? [];
|
|
208
214
|
const existingSubgraph = subgraphs.find((it) => it.name === subgraphInstance.name);
|
|
215
|
+
if (existingSubgraph) {
|
|
216
|
+
this.logger.debug(`Skipping duplicate subgraph: ${subgraphInstance.name}`);
|
|
217
|
+
return existingSubgraph;
|
|
218
|
+
}
|
|
219
|
+
await subgraphInstance.onSetup?.();
|
|
209
220
|
subgraphs.push(subgraphInstance);
|
|
210
221
|
subgraphsMap.set(supergraph, subgraphs);
|
|
211
|
-
// also add to global graphql supergraph
|
|
212
222
|
if (supergraph !== "" && supergraph !== "graphql") {
|
|
213
223
|
subgraphsMap.get("graphql")?.push(subgraphInstance);
|
|
214
224
|
}
|
|
215
|
-
|
|
216
|
-
if (!existingSubgraph) {
|
|
217
|
-
this.logger.info(logMessage);
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
this.logger.debug(logMessage);
|
|
221
|
-
}
|
|
225
|
+
this.logger.info(`Registered ${this.path.endsWith("/") ? this.path : this.path + "/"}${supergraph ? supergraph + "/" : ""}${subgraphInstance.name} subgraph.`);
|
|
222
226
|
return subgraphInstance;
|
|
223
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Register a pre-constructed subgraph instance.
|
|
230
|
+
* Use this when you need to pass custom dependencies to a subgraph.
|
|
231
|
+
*/
|
|
232
|
+
async registerSubgraphInstance(subgraphInstance, supergraph = "", core = false) {
|
|
233
|
+
return this.#addSubgraphInstance(subgraphInstance, supergraph, core);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Get the base path used for subgraph registration.
|
|
237
|
+
*/
|
|
238
|
+
getBasePath() {
|
|
239
|
+
return this.path;
|
|
240
|
+
}
|
|
224
241
|
async registerSubgraph(subgraph, supergraph = "", core = false) {
|
|
225
242
|
const subgraphInstance = new subgraph({
|
|
226
243
|
relationalDb: this.relationalDb,
|
|
227
244
|
analyticsStore: this.analyticsStore,
|
|
228
|
-
reactor: this.reactor,
|
|
229
245
|
reactorClient: this.reactorClient,
|
|
230
246
|
graphqlManager: this,
|
|
231
247
|
syncManager: this.syncManager,
|
|
232
248
|
path: this.path,
|
|
233
249
|
documentPermissionService: this.documentPermissionService,
|
|
250
|
+
authorizationService: this.authorizationService,
|
|
234
251
|
});
|
|
235
252
|
return this.#addSubgraphInstance(subgraphInstance, supergraph, core);
|
|
236
253
|
}
|
|
237
254
|
updateRouter = debounce(this._updateRouter.bind(this), 1000);
|
|
238
255
|
async _updateRouter() {
|
|
239
256
|
this.logger.debug("Updating router");
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
257
|
+
await this.#setupSubgraphs(this.subgraphs);
|
|
258
|
+
try {
|
|
259
|
+
await this.gatewayAdapter.updateSupergraph();
|
|
260
|
+
this.logger.debug("Updated Apollo Gateway supergraph");
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
this.logger.error("Failed to update Apollo Gateway supergraph", error);
|
|
264
|
+
}
|
|
265
|
+
// Refresh the supergraph-level SSE handler so it picks up
|
|
266
|
+
// any newly registered subscription-enabled subgraphs.
|
|
267
|
+
const superGraphPath = path.join(this.path, "graphql");
|
|
268
|
+
this.#setupSupergraphSSE(superGraphPath);
|
|
251
269
|
}
|
|
252
270
|
getAdditionalContextFields = () => {
|
|
253
271
|
return this.contextFields;
|
|
@@ -264,7 +282,6 @@ export class GraphQLManager {
|
|
|
264
282
|
const context = {
|
|
265
283
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
266
284
|
headers: connectionParams,
|
|
267
|
-
driveServer: this.reactor,
|
|
268
285
|
db: this.relationalDb,
|
|
269
286
|
...this.getAdditionalContextFields(),
|
|
270
287
|
};
|
|
@@ -273,6 +290,29 @@ export class GraphQLManager {
|
|
|
273
290
|
}
|
|
274
291
|
return context;
|
|
275
292
|
}
|
|
293
|
+
#makeContextFactory() {
|
|
294
|
+
return (request) => {
|
|
295
|
+
const authCtx = getAuthContext(request);
|
|
296
|
+
const headers = {};
|
|
297
|
+
request.headers.forEach((v, k) => {
|
|
298
|
+
headers[k] = v;
|
|
299
|
+
});
|
|
300
|
+
return Promise.resolve({
|
|
301
|
+
headers,
|
|
302
|
+
db: this.relationalDb,
|
|
303
|
+
...this.getAdditionalContextFields(),
|
|
304
|
+
user: authCtx?.user,
|
|
305
|
+
isAdmin: authCtx
|
|
306
|
+
? (addr) => !authCtx.auth_enabled
|
|
307
|
+
? true
|
|
308
|
+
: authCtx.admins.includes(addr.toLowerCase())
|
|
309
|
+
: () => true,
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
#makeWsContextFactory() {
|
|
314
|
+
return (connectionParams) => this.#createWebSocketContext(connectionParams);
|
|
315
|
+
}
|
|
276
316
|
setSupergraph(supergraph, subgraphs) {
|
|
277
317
|
this.subgraphs.set(supergraph, subgraphs);
|
|
278
318
|
const globalSubgraphs = this.subgraphs.get("graphql");
|
|
@@ -286,6 +326,13 @@ export class GraphQLManager {
|
|
|
286
326
|
}
|
|
287
327
|
async shutdown() {
|
|
288
328
|
this.logger.info("Shutting down GraphQL Manager");
|
|
329
|
+
// Dispose per-subgraph WebSocket handlers before closing the WS server.
|
|
330
|
+
for (const disposer of this.subgraphWsDisposers.values()) {
|
|
331
|
+
await disposer.dispose();
|
|
332
|
+
}
|
|
333
|
+
this.subgraphWsDisposers.clear();
|
|
334
|
+
// Stop all Apollo servers (per-subgraph + federation gateway) via the adapter.
|
|
335
|
+
await this.gatewayAdapter.stop();
|
|
289
336
|
return new Promise((resolve) => {
|
|
290
337
|
this.wsServer.close(() => {
|
|
291
338
|
this.logger.info("WebSocket server closed");
|
|
@@ -293,58 +340,53 @@ export class GraphQLManager {
|
|
|
293
340
|
});
|
|
294
341
|
});
|
|
295
342
|
}
|
|
296
|
-
#createApolloServer(schema) {
|
|
297
|
-
return new ApolloServer({
|
|
298
|
-
schema,
|
|
299
|
-
logger: this.apolloLogger,
|
|
300
|
-
introspection: true,
|
|
301
|
-
plugins: [
|
|
302
|
-
ApolloServerPluginInlineTraceDisabled(),
|
|
303
|
-
ApolloServerPluginLandingPageLocalDefault(),
|
|
304
|
-
],
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
async #waitForServer(server) {
|
|
308
|
-
try {
|
|
309
|
-
server.assertStarted("waitForServer");
|
|
310
|
-
return true;
|
|
311
|
-
}
|
|
312
|
-
catch {
|
|
313
|
-
await setTimeout(100);
|
|
314
|
-
return this.#waitForServer(server);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
343
|
#getSubgraphPath(subgraph, supergraph) {
|
|
318
344
|
return path.join(subgraph.path ?? "", supergraph, subgraph.name);
|
|
319
345
|
}
|
|
320
|
-
async #setupSubgraphs(subgraphsMap
|
|
346
|
+
async #setupSubgraphs(subgraphsMap) {
|
|
321
347
|
for (const [supergraph, subgraphs] of subgraphsMap.entries()) {
|
|
322
348
|
for (const subgraph of subgraphs) {
|
|
323
349
|
this.logger.debug(`Setting up subgraph ${subgraph.name}`);
|
|
350
|
+
const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);
|
|
324
351
|
try {
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
//
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
352
|
+
// Skip if handler already cached - subgraphs are deduplicated by name
|
|
353
|
+
// in #addSubgraphInstance, so a cached path means the schema is unchanged.
|
|
354
|
+
// This prevents unbounded schema/server creation across repeated
|
|
355
|
+
// _updateRouter() calls. The handler was already mounted on first setup,
|
|
356
|
+
// so no re-mount is needed.
|
|
357
|
+
if (this.subgraphHandlerCache.has(subgraphPath)) {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
const schema = createSchema(this.cachedDocumentModels, subgraph.resolvers, subgraph.typeDefs);
|
|
361
|
+
const rawHandler = await this.gatewayAdapter.createHandler(schema, this.#makeContextFactory());
|
|
362
|
+
const fetchHandler = this.#authMiddleware
|
|
363
|
+
? this.#authMiddleware(rawHandler)
|
|
364
|
+
: rawHandler;
|
|
365
|
+
this.subgraphHandlerCache.set(subgraphPath, fetchHandler);
|
|
366
|
+
this.httpAdapter.mount(subgraphPath, fetchHandler);
|
|
331
367
|
if (subgraph.hasSubscriptions) {
|
|
332
|
-
|
|
333
|
-
schema,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
|
|
368
|
+
try {
|
|
369
|
+
const wsDisposer = this.gatewayAdapter.attachWebSocket(this.wsServer, schema, this.#makeWsContextFactory());
|
|
370
|
+
this.subgraphWsDisposers.set(subgraphPath, wsDisposer);
|
|
371
|
+
this.logger.debug(`WebSocket subscriptions enabled for ${subgraph.name}`);
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
this.logger.error("Failed to setup websocket for subgraph @name at path @path: @error", subgraph.name, subgraphPath, error);
|
|
375
|
+
}
|
|
376
|
+
// Set up SSE (Server-Sent Events) transport alongside WebSocket.
|
|
377
|
+
// Clients can use SSE by sending POST requests with
|
|
378
|
+
// Accept: text/event-stream to the /stream sub-path.
|
|
379
|
+
try {
|
|
380
|
+
this.#setupSSEHandler(schema, subgraphPath);
|
|
381
|
+
this.logger.debug(`SSE subscriptions enabled for ${subgraph.name}`);
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
this.logger.error("Failed to setup SSE for subgraph @name at path @path: @error", subgraph.name, subgraphPath, error);
|
|
385
|
+
}
|
|
341
386
|
}
|
|
342
|
-
const path = this.#getSubgraphPath(subgraph, supergraph);
|
|
343
|
-
this.#setupApolloExpressMiddleware(server, router, path);
|
|
344
387
|
}
|
|
345
388
|
catch (error) {
|
|
346
|
-
this.logger.error(
|
|
347
|
-
this.logger.error(error);
|
|
389
|
+
this.logger.error("Failed to setup subgraph @name at path @path: @error", subgraph.name, subgraphPath, error);
|
|
348
390
|
}
|
|
349
391
|
}
|
|
350
392
|
}
|
|
@@ -359,75 +401,83 @@ export class GraphQLManager {
|
|
|
359
401
|
continue;
|
|
360
402
|
}
|
|
361
403
|
for (const subgraph of subgraphs) {
|
|
362
|
-
const
|
|
363
|
-
subgraphsMap.set(
|
|
404
|
+
const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);
|
|
405
|
+
subgraphsMap.set(subgraphPath, subgraph);
|
|
364
406
|
}
|
|
365
407
|
}
|
|
366
408
|
return subgraphsMap;
|
|
367
409
|
}
|
|
368
410
|
#buildSubgraphSchemaModule(subgraph) {
|
|
369
|
-
return buildSubgraphSchemaModule(this.
|
|
411
|
+
return buildSubgraphSchemaModule(this.cachedDocumentModels, subgraph.resolvers, subgraph.typeDefs);
|
|
370
412
|
}
|
|
371
|
-
|
|
413
|
+
#getSubgraphDefinitions() {
|
|
372
414
|
const subgraphs = this.#getAllSubgraphs();
|
|
415
|
+
const herokuOrLocal = process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME
|
|
416
|
+
? `https://${process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME}`
|
|
417
|
+
: `http://localhost:${this.port}`;
|
|
418
|
+
return Array.from(subgraphs.entries()).map(([subgraphPath, subgraph]) => ({
|
|
419
|
+
name: subgraphPath.replace("/", ":"),
|
|
420
|
+
typeDefs: this.#buildSubgraphSchemaModule(subgraph).typeDefs,
|
|
421
|
+
url: `${herokuOrLocal}${subgraphPath}`,
|
|
422
|
+
}));
|
|
423
|
+
}
|
|
424
|
+
async #createSupergraphGateway() {
|
|
425
|
+
const superGraphPath = path.join(this.path, "graphql");
|
|
426
|
+
const rawHandler = await this.gatewayAdapter.createSupergraphHandler(() => this.#getSubgraphDefinitions(), this.httpServer, this.#makeContextFactory());
|
|
427
|
+
const fetchHandler = this.#authMiddleware
|
|
428
|
+
? this.#authMiddleware(rawHandler)
|
|
429
|
+
: rawHandler;
|
|
430
|
+
this.httpAdapter.mount(superGraphPath, fetchHandler);
|
|
431
|
+
// Set up SSE subscriptions at the supergraph level (/graphql/stream).
|
|
432
|
+
// Build a subscription schema from all subgraphs that define subscriptions.
|
|
433
|
+
this.#setupSupergraphSSE(superGraphPath);
|
|
434
|
+
if (!this.initialized) {
|
|
435
|
+
this.logger.info(`Registered ${superGraphPath} supergraph `);
|
|
436
|
+
this.initialized = true;
|
|
437
|
+
}
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Set up an SSE subscription endpoint at the supergraph level.
|
|
442
|
+
* Merges the schemas of all subscription-enabled subgraphs so that
|
|
443
|
+
* clients can subscribe at /graphql/stream without knowing individual
|
|
444
|
+
* subgraph paths.
|
|
445
|
+
*/
|
|
446
|
+
#setupSupergraphSSE(superGraphPath) {
|
|
447
|
+
const allSubgraphs = this.#getAllSubgraphs();
|
|
448
|
+
const modules = Array.from(allSubgraphs.values())
|
|
449
|
+
.filter((subgraph) => subgraph.hasSubscriptions)
|
|
450
|
+
.map((subgraph) => this.#buildSubgraphSchemaModule(subgraph));
|
|
451
|
+
if (modules.length === 0) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
373
454
|
try {
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const serviceList = Array.from(subgraphs.entries()).map(([path, subgraph]) => ({
|
|
378
|
-
name: path.replace("/", ":"),
|
|
379
|
-
typeDefs: this.#buildSubgraphSchemaModule(subgraph).typeDefs,
|
|
380
|
-
url: `${herokuOrLocal}${path}`,
|
|
381
|
-
}));
|
|
382
|
-
const gateway = new ApolloGateway({
|
|
383
|
-
supergraphSdl: new LocalCompose({
|
|
384
|
-
localServiceList: serviceList,
|
|
385
|
-
}),
|
|
386
|
-
buildService: (serviceConfig) => {
|
|
387
|
-
return new AuthenticatedDataSource(serviceConfig);
|
|
388
|
-
},
|
|
389
|
-
});
|
|
390
|
-
const server = new ApolloServer({
|
|
391
|
-
gateway,
|
|
392
|
-
logger: this.apolloLogger,
|
|
393
|
-
introspection: true,
|
|
394
|
-
plugins: [
|
|
395
|
-
ApolloServerPluginDrainHttpServer({
|
|
396
|
-
httpServer: this.httpServer,
|
|
397
|
-
}),
|
|
398
|
-
ApolloServerPluginInlineTraceDisabled(),
|
|
399
|
-
ApolloServerPluginLandingPageLocalDefault(),
|
|
400
|
-
],
|
|
401
|
-
});
|
|
402
|
-
await server.start();
|
|
403
|
-
await this.#waitForServer(server);
|
|
404
|
-
const superGraphPath = path.join(this.path, "graphql");
|
|
405
|
-
this.#setupApolloExpressMiddleware(server, this.reactorRouter, superGraphPath);
|
|
406
|
-
if (!this.initialized) {
|
|
407
|
-
this.logger.info(`Registered ${superGraphPath} supergraph `);
|
|
408
|
-
this.initialized = true;
|
|
409
|
-
}
|
|
410
|
-
return server;
|
|
455
|
+
const mergedSchema = createMergedSchema(modules);
|
|
456
|
+
this.#setupSSEHandler(mergedSchema, superGraphPath);
|
|
457
|
+
this.logger.debug(`SSE subscriptions enabled at supergraph level (merged from ${modules.length} subgraph(s))`);
|
|
411
458
|
}
|
|
412
|
-
catch (
|
|
413
|
-
|
|
414
|
-
this.logger.error(e.message);
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
this.logger.error("Could not create Apollo Gateway", e);
|
|
418
|
-
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
this.logger.error("Failed to setup supergraph SSE: @error", error);
|
|
419
461
|
}
|
|
420
462
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
463
|
+
/**
|
|
464
|
+
* Set up a GraphQL-over-SSE handler at `<basePath>/stream`.
|
|
465
|
+
*
|
|
466
|
+
* Clients subscribe by sending a POST with `Accept: text/event-stream`
|
|
467
|
+
* to the `/stream` sub-path. Authentication is handled by the normal
|
|
468
|
+
* Express middleware (Authorization header), unlike WebSocket which
|
|
469
|
+
* needs its own connectionParams-based auth.
|
|
470
|
+
*/
|
|
471
|
+
#setupSSEHandler(schema, basePath) {
|
|
472
|
+
const ssePath = basePath + "/stream";
|
|
473
|
+
const rawHandler = createGraphQLSSEHandler({
|
|
474
|
+
schema,
|
|
475
|
+
contextFactory: this.#makeContextFactory(),
|
|
476
|
+
});
|
|
477
|
+
const handler = this.#authMiddleware
|
|
478
|
+
? this.#authMiddleware(rawHandler)
|
|
479
|
+
: rawHandler;
|
|
480
|
+
this.httpAdapter.mount(ssePath, handler, { exact: true });
|
|
431
481
|
}
|
|
432
482
|
}
|
|
433
483
|
//# sourceMappingURL=graphql-manager.js.map
|