@powerhousedao/reactor-api 6.0.0-dev.11 → 6.0.0-dev.110
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 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- 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-http-express.d.ts +23 -0
- package/dist/src/graphql/gateway/adapter-http-express.d.ts.map +1 -0
- package/dist/src/graphql/gateway/adapter-http-express.js +155 -0
- package/dist/src/graphql/gateway/adapter-http-express.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 +15 -0
- package/dist/src/graphql/gateway/factory.js.map +1 -0
- package/dist/src/graphql/gateway/types.d.ts +84 -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 +31 -12
- package/dist/src/graphql/graphql-manager.d.ts.map +1 -1
- package/dist/src/graphql/graphql-manager.js +284 -228
- 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 +22 -1
- 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 +355 -76
- package/dist/src/graphql/reactor/gen/graphql.d.ts.map +1 -1
- package/dist/src/graphql/reactor/gen/graphql.js +245 -10
- 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 +191 -1
- 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 +275 -77
- package/dist/src/graphql/reactor/resolvers.js.map +1 -1
- package/dist/src/graphql/reactor/schema.graphql +76 -30
- 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 +133 -210
- 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 +42 -0
- package/dist/src/graphql/sse.d.ts.map +1 -0
- package/dist/src/graphql/sse.js +33 -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 +68 -0
- package/dist/src/packages/http-loader.d.ts.map +1 -0
- package/dist/src/packages/http-loader.js +176 -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 +88 -0
- package/dist/src/packages/https-hooks.mjs.map +1 -0
- package/dist/src/packages/import-loader.d.ts +3 -4
- package/dist/src/packages/import-loader.d.ts.map +1 -1
- package/dist/src/packages/import-loader.js +6 -12
- 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 +2 -2
- package/dist/src/packages/package-manager.js.map +1 -1
- package/dist/src/packages/types.d.ts +9 -6
- package/dist/src/packages/types.d.ts.map +1 -1
- package/dist/src/packages/util.d.ts +4 -4
- package/dist/src/packages/util.d.ts.map +1 -1
- package/dist/src/packages/util.js +2 -2
- package/dist/src/packages/util.js.map +1 -1
- package/dist/src/packages/vite-loader.d.ts +8 -7
- package/dist/src/packages/vite-loader.d.ts.map +1 -1
- package/dist/src/packages/vite-loader.js +20 -8
- package/dist/src/packages/vite-loader.js.map +1 -1
- package/dist/src/server.d.ts +15 -28
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +137 -167
- package/dist/src/server.js.map +1 -1
- package/dist/src/services/auth.service.d.ts +11 -15
- package/dist/src/services/auth.service.d.ts.map +1 -1
- package/dist/src/services/auth.service.js +61 -40
- 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 +19 -1
- package/dist/src/tracing.js.map +1 -1
- package/dist/src/types.d.ts +14 -6
- 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 +451 -43
- 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/src/utils/drive-url.d.ts +2 -0
- package/dist/src/utils/drive-url.d.ts.map +1 -0
- package/dist/src/utils/drive-url.js +3 -0
- package/dist/src/utils/drive-url.js.map +1 -0
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -0
- package/dist/src/utils/index.js.map +1 -1
- 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 +582 -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-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/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 +226 -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 +488 -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/package.json +52 -58
- 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,126 +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
|
+
port;
|
|
60
|
+
authorizationService;
|
|
59
61
|
initialized = false;
|
|
60
|
-
coreRouter = Router();
|
|
61
62
|
coreSubgraphsMap = new Map();
|
|
62
|
-
reactorRouter = Router();
|
|
63
63
|
contextFields = {};
|
|
64
64
|
subgraphs = new Map();
|
|
65
65
|
authService = null;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
constructor(path, app, httpServer, wsServer, reactor, reactorClient, relationalDb, analyticsStore, syncManager, authConfig, documentPermissionService, featureFlags = DefaultFeatureFlags) {
|
|
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) {
|
|
73
72
|
this.path = path;
|
|
74
|
-
this.app = app;
|
|
75
73
|
this.httpServer = httpServer;
|
|
76
74
|
this.wsServer = wsServer;
|
|
77
|
-
this.reactor = reactor;
|
|
78
75
|
this.reactorClient = reactorClient;
|
|
79
76
|
this.relationalDb = relationalDb;
|
|
80
77
|
this.analyticsStore = analyticsStore;
|
|
81
78
|
this.syncManager = syncManager;
|
|
79
|
+
this.logger = logger;
|
|
80
|
+
this.httpAdapter = httpAdapter;
|
|
81
|
+
this.gatewayAdapter = gatewayAdapter;
|
|
82
82
|
this.authConfig = authConfig;
|
|
83
83
|
this.documentPermissionService = documentPermissionService;
|
|
84
84
|
this.featureFlags = featureFlags;
|
|
85
|
+
this.port = port;
|
|
86
|
+
this.authorizationService = authorizationService;
|
|
85
87
|
if (this.authConfig) {
|
|
86
88
|
this.authService = new AuthService(this.authConfig);
|
|
87
|
-
this.setAdditionalContextFields(this.authService.getAdditionalContextFields());
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
|
-
async init(coreSubgraphs) {
|
|
91
|
+
async init(coreSubgraphs, authMiddleware) {
|
|
92
|
+
this.#authMiddleware = authMiddleware;
|
|
91
93
|
this.logger.debug(`Initializing Subgraph Manager...`);
|
|
92
94
|
// check if Document Drive model is available
|
|
93
|
-
const
|
|
95
|
+
const modulesResult = await this.reactorClient.getDocumentModelModules();
|
|
96
|
+
const models = modulesResult.results;
|
|
97
|
+
// Cache models for schema generation
|
|
98
|
+
this.cachedDocumentModels = models;
|
|
94
99
|
const driveModel = models.find((it) => it.documentModel.global.name === "DocumentDrive");
|
|
95
100
|
if (!driveModel) {
|
|
96
101
|
throw new Error("DocumentDrive model required");
|
|
97
102
|
}
|
|
98
|
-
this.
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
this.
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
isUser: (address) => !req.auth_enabled
|
|
131
|
-
? true
|
|
132
|
-
: (req.users
|
|
133
|
-
?.map((a) => a.toLowerCase())
|
|
134
|
-
.includes(address.toLowerCase() ?? "") ?? false),
|
|
135
|
-
isGuest: (address) => !req.auth_enabled
|
|
136
|
-
? true
|
|
137
|
-
: (req.guests
|
|
138
|
-
?.map((a) => a.toLowerCase())
|
|
139
|
-
.includes(address.toLowerCase() ?? "") ?? false),
|
|
140
|
-
});
|
|
141
|
-
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
|
+
}
|
|
142
135
|
});
|
|
136
|
+
this.logger.info(`Registered REST endpoint: GET ${driveRoutePath}`);
|
|
143
137
|
await this.#setupCoreSubgraphs("graphql", coreSubgraphs);
|
|
144
138
|
if (this.featureFlags.enableDocumentModelSubgraphs) {
|
|
145
|
-
await this.#setupDocumentModelSubgraphs("graphql",
|
|
139
|
+
await this.#setupDocumentModelSubgraphs("graphql", models);
|
|
146
140
|
}
|
|
147
|
-
this
|
|
148
|
-
if (this.featureFlags.enableDocumentModelSubgraphs) {
|
|
149
|
-
this.#setupDocumentModelSubgraphs("graphql", documentModels)
|
|
150
|
-
.then(() => this.updateRouter())
|
|
151
|
-
.catch((error) => this.logger.error(error));
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
this.updateRouter().catch((error) => this.logger.error(error));
|
|
155
|
-
}
|
|
156
|
-
});
|
|
141
|
+
await this.#createSupergraphGateway();
|
|
157
142
|
return this.updateRouter();
|
|
158
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
|
+
}
|
|
159
166
|
async #setupCoreSubgraphs(supergraph, coreSubgraphs) {
|
|
160
167
|
for (const subgraph of coreSubgraphs) {
|
|
161
168
|
try {
|
|
@@ -165,87 +172,100 @@ export class GraphQLManager {
|
|
|
165
172
|
this.logger.error(`Failed to setup core subgraph ${subgraph.name}`, error);
|
|
166
173
|
}
|
|
167
174
|
}
|
|
168
|
-
|
|
169
|
-
await this.registerSubgraph(DriveSubgraph, undefined, true);
|
|
170
|
-
return this.#setupSubgraphs(this.coreSubgraphsMap, this.coreRouter);
|
|
175
|
+
return this.#setupSubgraphs(this.coreSubgraphsMap);
|
|
171
176
|
}
|
|
172
177
|
async #setupDocumentModelSubgraphs(supergraph, documentModels) {
|
|
173
|
-
|
|
178
|
+
const latestDocumentModels = filterLatestDocumentModelVersions(documentModels);
|
|
179
|
+
for (const documentModel of latestDocumentModels) {
|
|
174
180
|
if (DOCUMENT_MODELS_TO_EXCLUDE.includes(documentModel.documentModel.global.id)) {
|
|
175
|
-
continue;
|
|
181
|
+
continue;
|
|
176
182
|
}
|
|
177
183
|
if (!hasOperationSchemas(documentModel)) {
|
|
178
|
-
continue;
|
|
184
|
+
continue;
|
|
179
185
|
}
|
|
180
186
|
try {
|
|
181
|
-
const subgraphInstance = new
|
|
187
|
+
const subgraphInstance = new DocumentModelSubgraph(documentModel, {
|
|
182
188
|
relationalDb: this.relationalDb,
|
|
183
189
|
analyticsStore: this.analyticsStore,
|
|
184
|
-
reactor: this.reactor,
|
|
185
190
|
reactorClient: this.reactorClient,
|
|
186
191
|
graphqlManager: this,
|
|
187
192
|
syncManager: this.syncManager,
|
|
188
193
|
path: this.path,
|
|
189
194
|
documentPermissionService: this.documentPermissionService,
|
|
195
|
+
authorizationService: this.authorizationService,
|
|
190
196
|
});
|
|
191
197
|
await this.#addSubgraphInstance(subgraphInstance, supergraph, false);
|
|
192
198
|
}
|
|
193
199
|
catch (error) {
|
|
194
200
|
this.logger.error(`Failed to setup document model subgraph for ${documentModel.documentModel.global.id}`, error instanceof Error ? error.message : error);
|
|
195
|
-
this.logger.debug(error);
|
|
201
|
+
this.logger.debug("@error", error);
|
|
196
202
|
}
|
|
197
203
|
}
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
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().
|
|
201
210
|
}
|
|
202
211
|
async #addSubgraphInstance(subgraphInstance, supergraph = "", core = false) {
|
|
203
|
-
await subgraphInstance.onSetup?.();
|
|
204
212
|
const subgraphsMap = core ? this.coreSubgraphsMap : this.subgraphs;
|
|
205
213
|
const subgraphs = subgraphsMap.get(supergraph) ?? [];
|
|
206
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?.();
|
|
207
220
|
subgraphs.push(subgraphInstance);
|
|
208
221
|
subgraphsMap.set(supergraph, subgraphs);
|
|
209
|
-
// also add to global graphql supergraph
|
|
210
222
|
if (supergraph !== "" && supergraph !== "graphql") {
|
|
211
223
|
subgraphsMap.get("graphql")?.push(subgraphInstance);
|
|
212
224
|
}
|
|
213
|
-
|
|
214
|
-
if (!existingSubgraph) {
|
|
215
|
-
this.logger.info(logMessage);
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
this.logger.debug(logMessage);
|
|
219
|
-
}
|
|
225
|
+
this.logger.info(`Registered ${this.path.endsWith("/") ? this.path : this.path + "/"}${supergraph ? supergraph + "/" : ""}${subgraphInstance.name} subgraph.`);
|
|
220
226
|
return subgraphInstance;
|
|
221
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
|
+
}
|
|
222
241
|
async registerSubgraph(subgraph, supergraph = "", core = false) {
|
|
223
242
|
const subgraphInstance = new subgraph({
|
|
224
243
|
relationalDb: this.relationalDb,
|
|
225
244
|
analyticsStore: this.analyticsStore,
|
|
226
|
-
reactor: this.reactor,
|
|
227
245
|
reactorClient: this.reactorClient,
|
|
228
246
|
graphqlManager: this,
|
|
229
247
|
syncManager: this.syncManager,
|
|
230
248
|
path: this.path,
|
|
231
249
|
documentPermissionService: this.documentPermissionService,
|
|
250
|
+
authorizationService: this.authorizationService,
|
|
232
251
|
});
|
|
233
252
|
return this.#addSubgraphInstance(subgraphInstance, supergraph, core);
|
|
234
253
|
}
|
|
235
254
|
updateRouter = debounce(this._updateRouter.bind(this), 1000);
|
|
236
255
|
async _updateRouter() {
|
|
237
256
|
this.logger.debug("Updating router");
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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);
|
|
249
269
|
}
|
|
250
270
|
getAdditionalContextFields = () => {
|
|
251
271
|
return this.contextFields;
|
|
@@ -262,7 +282,6 @@ export class GraphQLManager {
|
|
|
262
282
|
const context = {
|
|
263
283
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
264
284
|
headers: connectionParams,
|
|
265
|
-
driveServer: this.reactor,
|
|
266
285
|
db: this.relationalDb,
|
|
267
286
|
...this.getAdditionalContextFields(),
|
|
268
287
|
};
|
|
@@ -271,6 +290,29 @@ export class GraphQLManager {
|
|
|
271
290
|
}
|
|
272
291
|
return context;
|
|
273
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
|
+
}
|
|
274
316
|
setSupergraph(supergraph, subgraphs) {
|
|
275
317
|
this.subgraphs.set(supergraph, subgraphs);
|
|
276
318
|
const globalSubgraphs = this.subgraphs.get("graphql");
|
|
@@ -284,6 +326,13 @@ export class GraphQLManager {
|
|
|
284
326
|
}
|
|
285
327
|
async shutdown() {
|
|
286
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();
|
|
287
336
|
return new Promise((resolve) => {
|
|
288
337
|
this.wsServer.close(() => {
|
|
289
338
|
this.logger.info("WebSocket server closed");
|
|
@@ -291,58 +340,53 @@ export class GraphQLManager {
|
|
|
291
340
|
});
|
|
292
341
|
});
|
|
293
342
|
}
|
|
294
|
-
#createApolloServer(schema) {
|
|
295
|
-
return new ApolloServer({
|
|
296
|
-
schema,
|
|
297
|
-
logger: this.apolloLogger,
|
|
298
|
-
introspection: true,
|
|
299
|
-
plugins: [
|
|
300
|
-
ApolloServerPluginInlineTraceDisabled(),
|
|
301
|
-
ApolloServerPluginLandingPageLocalDefault(),
|
|
302
|
-
],
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
async #waitForServer(server) {
|
|
306
|
-
try {
|
|
307
|
-
server.assertStarted("waitForServer");
|
|
308
|
-
return true;
|
|
309
|
-
}
|
|
310
|
-
catch {
|
|
311
|
-
await setTimeout(100);
|
|
312
|
-
return this.#waitForServer(server);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
343
|
#getSubgraphPath(subgraph, supergraph) {
|
|
316
344
|
return path.join(subgraph.path ?? "", supergraph, subgraph.name);
|
|
317
345
|
}
|
|
318
|
-
async #setupSubgraphs(subgraphsMap
|
|
346
|
+
async #setupSubgraphs(subgraphsMap) {
|
|
319
347
|
for (const [supergraph, subgraphs] of subgraphsMap.entries()) {
|
|
320
348
|
for (const subgraph of subgraphs) {
|
|
321
349
|
this.logger.debug(`Setting up subgraph ${subgraph.name}`);
|
|
350
|
+
const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);
|
|
322
351
|
try {
|
|
323
|
-
//
|
|
324
|
-
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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);
|
|
329
367
|
if (subgraph.hasSubscriptions) {
|
|
330
|
-
|
|
331
|
-
schema,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
|
|
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
|
+
}
|
|
339
386
|
}
|
|
340
|
-
const path = this.#getSubgraphPath(subgraph, supergraph);
|
|
341
|
-
this.#setupApolloExpressMiddleware(server, router, path);
|
|
342
387
|
}
|
|
343
388
|
catch (error) {
|
|
344
|
-
this.logger.error(
|
|
345
|
-
this.logger.error(error);
|
|
389
|
+
this.logger.error("Failed to setup subgraph @name at path @path: @error", subgraph.name, subgraphPath, error);
|
|
346
390
|
}
|
|
347
391
|
}
|
|
348
392
|
}
|
|
@@ -357,75 +401,87 @@ export class GraphQLManager {
|
|
|
357
401
|
continue;
|
|
358
402
|
}
|
|
359
403
|
for (const subgraph of subgraphs) {
|
|
360
|
-
const
|
|
361
|
-
subgraphsMap.set(
|
|
404
|
+
const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);
|
|
405
|
+
subgraphsMap.set(subgraphPath, subgraph);
|
|
362
406
|
}
|
|
363
407
|
}
|
|
364
408
|
return subgraphsMap;
|
|
365
409
|
}
|
|
366
410
|
#buildSubgraphSchemaModule(subgraph) {
|
|
367
|
-
return buildSubgraphSchemaModule(this.
|
|
411
|
+
return buildSubgraphSchemaModule(this.cachedDocumentModels, subgraph.resolvers, subgraph.typeDefs);
|
|
368
412
|
}
|
|
369
|
-
|
|
413
|
+
#getSubgraphDefinitions() {
|
|
370
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
|
+
}
|
|
371
454
|
try {
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const serviceList = Array.from(subgraphs.entries()).map(([path, subgraph]) => ({
|
|
376
|
-
name: path.replace("/", ":"),
|
|
377
|
-
typeDefs: this.#buildSubgraphSchemaModule(subgraph).typeDefs,
|
|
378
|
-
url: `${herokuOrLocal}${path}`,
|
|
379
|
-
}));
|
|
380
|
-
const gateway = new ApolloGateway({
|
|
381
|
-
supergraphSdl: new LocalCompose({
|
|
382
|
-
localServiceList: serviceList,
|
|
383
|
-
}),
|
|
384
|
-
buildService: (serviceConfig) => {
|
|
385
|
-
return new AuthenticatedDataSource(serviceConfig);
|
|
386
|
-
},
|
|
387
|
-
});
|
|
388
|
-
const server = new ApolloServer({
|
|
389
|
-
gateway,
|
|
390
|
-
logger: this.apolloLogger,
|
|
391
|
-
introspection: true,
|
|
392
|
-
plugins: [
|
|
393
|
-
ApolloServerPluginDrainHttpServer({
|
|
394
|
-
httpServer: this.httpServer,
|
|
395
|
-
}),
|
|
396
|
-
ApolloServerPluginInlineTraceDisabled(),
|
|
397
|
-
ApolloServerPluginLandingPageLocalDefault(),
|
|
398
|
-
],
|
|
399
|
-
});
|
|
400
|
-
await server.start();
|
|
401
|
-
await this.#waitForServer(server);
|
|
402
|
-
const superGraphPath = path.join(this.path, "graphql");
|
|
403
|
-
this.#setupApolloExpressMiddleware(server, this.reactorRouter, superGraphPath);
|
|
404
|
-
if (!this.initialized) {
|
|
405
|
-
this.logger.info(`Registered ${superGraphPath} supergraph `);
|
|
406
|
-
this.initialized = true;
|
|
407
|
-
}
|
|
408
|
-
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))`);
|
|
409
458
|
}
|
|
410
|
-
catch (
|
|
411
|
-
|
|
412
|
-
this.logger.error(e.message);
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
this.logger.error("Could not create Apollo Gateway", e);
|
|
416
|
-
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
this.logger.error("Failed to setup supergraph SSE: @error", error);
|
|
417
461
|
}
|
|
418
462
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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 sseHandler = createGraphQLSSEHandler({
|
|
474
|
+
schema,
|
|
475
|
+
contextFactory: (req) => ({
|
|
422
476
|
headers: req.headers,
|
|
423
|
-
driveId: req.params
|
|
424
|
-
driveServer: this.reactor,
|
|
477
|
+
driveId: req.params?.drive ?? undefined,
|
|
425
478
|
db: this.relationalDb,
|
|
426
479
|
...this.getAdditionalContextFields(),
|
|
427
480
|
}),
|
|
428
|
-
})
|
|
481
|
+
});
|
|
482
|
+
// SSE handler is Express-specific; mount directly on the underlying app.
|
|
483
|
+
// TODO: replace sse.ts with a Fetch API handler so this can use httpAdapter.mount()
|
|
484
|
+
this.httpAdapter.handle.use(ssePath, sseHandler);
|
|
429
485
|
}
|
|
430
486
|
}
|
|
431
487
|
//# sourceMappingURL=graphql-manager.js.map
|