@undefineds.co/xpod 0.4.10 → 0.4.12
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/config/components-ignore.json +5 -1
- package/config/notifications.json +68 -0
- package/config/xpod.base.json +9 -11
- package/dist/ai/service/AiCredentialSecret.d.ts +30 -0
- package/dist/ai/service/AiCredentialSecret.js +120 -0
- package/dist/ai/service/CredentialReaderImpl.d.ts +18 -0
- package/dist/ai/service/CredentialReaderImpl.js +81 -5
- package/dist/ai/service/CredentialReaderImpl.jsonld +42 -2
- package/dist/ai/service/EmbeddingModelPolicy.d.ts +79 -0
- package/dist/ai/service/EmbeddingModelPolicy.js +134 -0
- package/dist/ai/service/EmbeddingProviderError.js +6 -0
- package/dist/ai/service/EmbeddingServiceImpl.d.ts +13 -1
- package/dist/ai/service/EmbeddingServiceImpl.js +18 -5
- package/dist/ai/service/EmbeddingServiceImpl.jsonld +35 -0
- package/dist/ai/service/index.d.ts +2 -0
- package/dist/ai/service/index.js +2 -0
- package/dist/api/ai-gateway/connect/index.d.ts +20 -2
- package/dist/api/ai-gateway/connect/index.js +162 -16
- package/dist/api/ai-gateway/credentials/AiCredentialSecretDecoder.d.ts +12 -0
- package/dist/api/ai-gateway/credentials/AiCredentialSecretDecoder.js +30 -0
- package/dist/api/ai-gateway/errors.d.ts +1 -1
- package/dist/api/ai-gateway/models/GatewayEmbeddingModelCatalog.d.ts +11 -0
- package/dist/api/ai-gateway/models/GatewayEmbeddingModelCatalog.js +31 -0
- package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +7 -3
- package/dist/api/ai-gateway/models/ProviderCustomModelsService.d.ts +18 -0
- package/dist/api/ai-gateway/models/ProviderCustomModelsService.js +23 -0
- package/dist/api/ai-gateway/models/ProviderModelDiscoveryAdapters.d.ts +3 -1
- package/dist/api/ai-gateway/models/ProviderModelDiscoveryAdapters.js +2 -45
- package/dist/api/ai-gateway/models/ProviderModelSelectionService.d.ts +10 -0
- package/dist/api/ai-gateway/models/ProviderModelSelectionService.js +57 -20
- package/dist/api/ai-gateway/models/ProviderModelType.d.ts +28 -0
- package/dist/api/ai-gateway/models/ProviderModelType.js +34 -0
- package/dist/api/ai-gateway/models/ProviderModelsAdapter.d.ts +10 -0
- package/dist/api/ai-gateway/models/ProviderModelsAdapter.js +3 -4
- package/dist/api/ai-gateway/models/index.d.ts +1 -0
- package/dist/api/ai-gateway/models/index.js +3 -1
- package/dist/api/ai-gateway/providers/CustomRuntimeAdapter.d.ts +7 -0
- package/dist/api/ai-gateway/providers/CustomRuntimeAdapter.js +9 -2
- package/dist/api/ai-gateway/providers/ModelsDevCatalog.d.ts +7 -1
- package/dist/api/ai-gateway/providers/ModelsDevCatalog.js +4 -10
- package/dist/api/ai-gateway/providers/ProviderRegistry.d.ts +107 -0
- package/dist/api/ai-gateway/providers/ProviderRegistry.js +244 -21
- package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.d.ts +5 -0
- package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.js +5 -1
- package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.d.ts +12 -4
- package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.js +11 -11
- package/dist/api/ai-gateway/routing/ModelRouter.d.ts +14 -0
- package/dist/api/ai-gateway/routing/ModelRouter.js +43 -4
- package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.d.ts +9 -1
- package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.js +3 -27
- package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.js +0 -3
- package/dist/api/auth/index.d.ts +1 -0
- package/dist/api/auth/index.js +1 -1
- package/dist/api/chatkit/pod-store.d.ts +31 -0
- package/dist/api/chatkit/pod-store.js +132 -8
- package/dist/api/container/common.js +24 -4
- package/dist/api/container/routes.js +17 -2
- package/dist/api/container/types.d.ts +3 -1
- package/dist/api/handlers/AdminHandler.d.ts +13 -0
- package/dist/api/handlers/AdminHandler.js +47 -18
- package/dist/api/handlers/AiConfigHandler.d.ts +6 -0
- package/dist/api/handlers/AiConfigHandler.js +28 -0
- package/dist/api/handlers/AiGatewayManagementHandler.js +36 -0
- package/dist/api/runs/RdfRunContextRetriever.d.ts +14 -0
- package/dist/api/runs/RdfRunContextRetriever.js +41 -5
- package/dist/api/runtime.js +2 -1
- package/dist/cli/commands/secret.d.ts +1 -0
- package/dist/cli/commands/secret.js +25 -7
- package/dist/components/components.jsonld +3 -1
- package/dist/components/context.jsonld +53 -1
- package/dist/http/SubgraphSparqlHttpHandler.d.ts +59 -2
- package/dist/http/SubgraphSparqlHttpHandler.js +145 -13
- package/dist/http/SubgraphSparqlHttpHandler.jsonld +37 -0
- package/dist/identity/drizzle/AccountRoleRepository.d.ts +30 -2
- package/dist/identity/drizzle/AccountRoleRepository.js +163 -15
- package/dist/identity/drizzle/EdgeNodeRepository.d.ts +0 -12
- package/dist/identity/drizzle/EdgeNodeRepository.js +5 -13
- package/dist/identity/drizzle/PodLookupRepository.d.ts +58 -4
- package/dist/identity/drizzle/PodLookupRepository.js +248 -105
- package/dist/identity/drizzle/db.d.ts +19 -0
- package/dist/identity/drizzle/db.js +39 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -3
- package/dist/logging/log-file.d.ts +17 -0
- package/dist/logging/log-file.js +69 -0
- package/dist/main.js +2 -1
- package/dist/notifications/NotificationChannelSweeper.d.ts +50 -0
- package/dist/notifications/NotificationChannelSweeper.js +131 -0
- package/dist/notifications/NotificationChannelSweeper.jsonld +136 -0
- package/dist/notifications/ReclaimingWebSocket2023Storer.d.ts +25 -0
- package/dist/notifications/ReclaimingWebSocket2023Storer.js +56 -0
- package/dist/notifications/ReclaimingWebSocket2023Storer.jsonld +77 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/runtime/Proxy.d.ts +37 -0
- package/dist/runtime/Proxy.js +88 -16
- package/dist/runtime/bootstrap.js +2 -1
- package/dist/runtime/upgrade/BunNativeUpgradeRelay.d.ts +116 -0
- package/dist/runtime/upgrade/BunNativeUpgradeRelay.js +423 -0
- package/dist/runtime/upgrade/UpgradeHandshake.d.ts +63 -0
- package/dist/runtime/upgrade/UpgradeHandshake.js +199 -0
- package/dist/runtime/upgrade/WebSocketFrames.d.ts +67 -0
- package/dist/runtime/upgrade/WebSocketFrames.js +224 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.js +8 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.d.ts +11 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.js +27 -10
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +7 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +13 -11
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectDialog.js +1 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsList.js +10 -6
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.js +29 -3
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMainHeader.js +18 -3
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +16 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +92 -20
- package/node_modules/@undefineds.co/ai-connections/dist/AiCopyButton.d.ts +35 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiCopyButton.js +45 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +71 -11
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialRow.js +9 -7
- package/node_modules/@undefineds.co/ai-connections/dist/AiEndpointList.d.ts +23 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiEndpointList.js +24 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +13 -4
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +35 -38
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.d.ts +21 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.js +51 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiInfoTooltip.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiInfoTooltip.js +16 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiModelCatalog.d.ts +175 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiModelCatalog.js +133 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.js +2 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.js +13 -64
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.d.ts +21 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.js +12 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiRowAction.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiRowAction.js +12 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiSortableCredentialList.js +2 -1
- package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.d.ts +7 -0
- package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.js +6 -0
- package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.d.ts +36 -5
- package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.js +52 -9
- package/node_modules/@undefineds.co/ai-connections/dist/client/normalize.js +30 -3
- package/node_modules/@undefineds.co/ai-connections/dist/client/types.d.ts +21 -1
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.d.ts +1 -3
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.js +3 -7
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/index.cjs +9 -7
- package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.d.ts +46 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.js +231 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collections.d.ts +119 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collections.js +173 -0
- package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +71 -5
- package/node_modules/@undefineds.co/ai-connections/dist/controller.js +285 -16
- package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.d.ts +5 -0
- package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.js +8 -3
- package/node_modules/@undefineds.co/ai-connections/dist/credential-storage.d.ts +59 -0
- package/node_modules/@undefineds.co/ai-connections/dist/credential-storage.js +131 -0
- package/node_modules/@undefineds.co/ai-connections/dist/endpoint-urls.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/endpoint-urls.js +20 -0
- package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.d.ts +14 -0
- package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.js +20 -0
- package/node_modules/@undefineds.co/ai-connections/dist/index.d.ts +8 -0
- package/node_modules/@undefineds.co/ai-connections/dist/index.js +8 -0
- package/node_modules/@undefineds.co/ai-connections/dist/manifest.js +1 -1
- package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.d.ts +14 -0
- package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.js +17 -0
- package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.cjs +68 -1
- package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.d.ts +75 -1
- package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.js +119 -0
- package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.d.ts +5 -0
- package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.js +5 -0
- package/node_modules/@undefineds.co/ai-connections/dist/service-access.js +2 -27
- package/node_modules/@undefineds.co/ai-connections/package.json +1 -0
- package/node_modules/@undefineds.co/extension-sdk/dist/manifest.d.ts +1 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/manifest.js +2 -0
- package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +150 -0
- package/node_modules/@undefineds.co/extension-sdk/package.json +2 -1
- package/node_modules/@undefineds.co/models/README.md +1 -1
- package/node_modules/@undefineds.co/models/dist/ai-config/index.d.ts +3 -3
- package/node_modules/@undefineds.co/models/dist/ai-gateway.schema.d.ts +5 -0
- package/node_modules/@undefineds.co/models/dist/ai-gateway.schema.js +9 -0
- package/node_modules/@undefineds.co/models/dist/ai-runtime.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/approval.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/audit.presentation.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/capture.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/chat-project.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/chat.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/control-request.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/conversation-share.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/credential.schema.d.ts +12 -0
- package/node_modules/@undefineds.co/models/dist/credential.schema.js +15 -1
- package/node_modules/@undefineds.co/models/dist/discovery/index.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/discovery/providers.json +248 -7
- package/node_modules/@undefineds.co/models/dist/discovery/types.d.ts +31 -0
- package/node_modules/@undefineds.co/models/dist/extension/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/favorite/index.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/fixtures/contracts-chat-contact.d.ts +5 -5
- package/node_modules/@undefineds.co/models/dist/import/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/index.d.ts +73 -73
- package/node_modules/@undefineds.co/models/dist/index.js +1 -1
- package/node_modules/@undefineds.co/models/dist/input-request.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/knowledge/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/message.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/namespaces.js +5 -0
- package/node_modules/@undefineds.co/models/dist/pod-storage-descriptor.d.ts +4815 -26
- package/node_modules/@undefineds.co/models/dist/pod-storage-descriptor.js +482 -132
- package/node_modules/@undefineds.co/models/dist/schema.d.ts +4 -0
- package/node_modules/@undefineds.co/models/dist/session/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/settings/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/sidecar/persistence-mapping.d.ts +5 -5
- package/node_modules/@undefineds.co/models/dist/thread.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/types/message-block.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/vocab/_namespaces.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/vocab/index.d.ts +10 -10
- package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.d.ts +1 -0
- package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.js +1 -0
- package/node_modules/@undefineds.co/models/package.json +4 -2
- package/node_modules/@undefineds.co/pod-collections/README.md +71 -0
- package/node_modules/@undefineds.co/pod-collections/dist/diff.d.ts +85 -0
- package/node_modules/@undefineds.co/pod-collections/dist/diff.js +166 -0
- package/node_modules/@undefineds.co/pod-collections/dist/feed.d.ts +17 -0
- package/node_modules/@undefineds.co/pod-collections/dist/feed.js +27 -0
- package/node_modules/@undefineds.co/pod-collections/dist/index.cjs +1042 -0
- package/node_modules/@undefineds.co/pod-collections/dist/index.d.ts +37 -0
- package/node_modules/@undefineds.co/pod-collections/dist/index.js +89 -0
- package/node_modules/@undefineds.co/pod-collections/dist/layout.d.ts +75 -0
- package/node_modules/@undefineds.co/pod-collections/dist/layout.js +173 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mapping.d.ts +78 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mapping.js +287 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mutations.d.ts +83 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mutations.js +273 -0
- package/node_modules/@undefineds.co/pod-collections/dist/react.d.ts +21 -0
- package/node_modules/@undefineds.co/pod-collections/dist/react.js +22 -0
- package/node_modules/@undefineds.co/pod-collections/dist/read.d.ts +65 -0
- package/node_modules/@undefineds.co/pod-collections/dist/read.js +31 -0
- package/node_modules/@undefineds.co/pod-collections/dist/sync.d.ts +66 -0
- package/node_modules/@undefineds.co/pod-collections/dist/sync.js +260 -0
- package/node_modules/@undefineds.co/pod-collections/dist/types.d.ts +155 -0
- package/node_modules/@undefineds.co/pod-collections/dist/types.js +9 -0
- package/node_modules/@undefineds.co/pod-collections/package.json +42 -0
- package/node_modules/@undefineds.co/shared-ui/dist/index.d.ts +0 -1
- package/node_modules/@undefineds.co/shared-ui/dist/index.js +0 -1
- package/package.json +15 -7
- package/static/app/assets/main.css +1 -1
- package/static/app/assets/main.js +12 -13
- package/static/auth-callback/assets/AiConfigContext-DnQs1ZpW.js +1 -0
- package/static/auth-callback/assets/AiConfigPage-DOtvlxH0.js +1 -0
- package/static/auth-callback/assets/DocumentProcessingPanel-BS2voQgL.js +1 -0
- package/static/auth-callback/assets/IndexLifecyclePanel-Cvt0cJtN.js +1 -0
- package/static/auth-callback/assets/{IndexSubjectPanel-C4YG0whI.js → IndexSubjectPanel-Dhf01GqF.js} +1 -1
- package/static/auth-callback/assets/ModelAssignmentsPanel-BJutWaAF.js +1 -0
- package/static/auth-callback/assets/ModelsPage-BRS0sje3.js +11 -0
- package/static/auth-callback/assets/{NetworkPage-Cbdn_P1e.js → NetworkPage-B3qBfANA.js} +2 -2
- package/static/auth-callback/assets/{PaneListHeader-jy70Q00L.js → PaneListHeader-QQeJGTp4.js} +1 -1
- package/static/auth-callback/assets/SearchIndexingPanel-MyNUSEwT.js +1 -0
- package/static/auth-callback/assets/{StatusSubjectPanel-hfjoB5aS.js → StatusSubjectPanel-DQkEVsFs.js} +1 -1
- package/static/{settings/assets/StatusWorkspace-CKD_Rzdr.js → auth-callback/assets/StatusWorkspace-Dkv63Uwk.js} +1 -1
- package/static/auth-callback/assets/SystemSettingsPage-TIsUfX5d.js +1 -0
- package/static/auth-callback/assets/SystemSettingsSubjectPanel-BJWEt2-7.js +33 -0
- package/static/auth-callback/assets/XpodAiConnectionsPodStore-BJiXm-PF.js +3 -0
- package/static/auth-callback/assets/{activity-BcsZZxxw.js → activity-5hNeNKnL.js} +1 -1
- package/static/auth-callback/assets/admin-C6qCRFiY.js +1 -0
- package/static/auth-callback/assets/ai-connections-CryuHGKW.js +1 -0
- package/static/auth-callback/assets/{auth-callback-atKg_oig.js → auth-callback-CAFZ3R0B.js} +80 -84
- package/static/auth-callback/assets/auth-callback-rk080mvG.css +1 -0
- package/static/auth-callback/assets/{badge-BWbRHThQ.js → badge-CAIPI0CB.js} +1 -1
- package/static/auth-callback/assets/collection-runtime-D9s7h9YA.js +1 -0
- package/static/auth-callback/assets/dialog-BjA109aX.js +1 -0
- package/static/auth-callback/assets/{download-BmvG1Vya.js → download-B3Up5W2G.js} +1 -1
- package/static/auth-callback/assets/{external-link-DZ34d3g3.js → external-link-BTXgSPzB.js} +1 -1
- package/static/auth-callback/assets/index-BppXlxcp.js +41 -0
- package/static/auth-callback/assets/index-CirW4CJf.js +1 -0
- package/static/auth-callback/assets/index-DlLYWOhw.js +4 -0
- package/static/auth-callback/assets/{index-browser-B9Z7GU-T.js → index-browser-DtU38ni3.js} +1 -1
- package/static/auth-callback/assets/{key-round-tjP76Se-.js → key-round-CQCOrZ7x.js} +1 -1
- package/static/auth-callback/assets/layout-DB3pMyTl.js +1 -0
- package/static/auth-callback/assets/pod-collections-host-KnnGFZHL.js +8 -0
- package/static/auth-callback/assets/{rotate-ccw-C_L5ZLx1.js → rotate-ccw-C1zM2KtS.js} +1 -1
- package/static/auth-callback/assets/settings-projection-CUkyprDQ.js +1 -0
- package/static/auth-callback/assets/{skeleton-C7tGDQIs.js → skeleton-Cqp7_M9-.js} +1 -1
- package/static/auth-callback/assets/{waypoints-VMNQlWdU.js → waypoints-Bj6gAUSQ.js} +1 -1
- package/static/auth-callback/assets/{workspace-layout-SAp6BtYK.js → workspace-layout-DK8mDzrY.js} +1 -1
- package/static/auth-callback/auth-callback.html +2 -2
- package/static/dashboard/assets/AiConfigContext-BsE7MqX8.js +1 -0
- package/static/dashboard/assets/AiConfigPage-DvM-lRXa.js +1 -0
- package/static/dashboard/assets/DocumentProcessingPanel-BPfdlfuf.js +1 -0
- package/static/dashboard/assets/IndexLifecyclePanel--m0AGxvh.js +1 -0
- package/static/dashboard/assets/{IndexSubjectPanel-DQFPP6-p.js → IndexSubjectPanel-Bb7m1k3d.js} +1 -1
- package/static/dashboard/assets/ModelAssignmentsPanel-BLi_zbMa.js +1 -0
- package/static/dashboard/assets/ModelsPage-CxdpgnfR.js +11 -0
- package/static/dashboard/assets/{NetworkPage-CHQ3YxIB.js → NetworkPage-BAIPw-D_.js} +2 -2
- package/static/dashboard/assets/{PaneListHeader-DsXemAdR.js → PaneListHeader-BBCMei0r.js} +1 -1
- package/static/dashboard/assets/SearchIndexingPanel-Ck4Y-xjR.js +1 -0
- package/static/dashboard/assets/{StatusSubjectPanel-D3PGEYT4.js → StatusSubjectPanel-D1KWfAXE.js} +1 -1
- package/static/dashboard/assets/{StatusWorkspace-BcpePYUW.js → StatusWorkspace-JbA5gzXx.js} +1 -1
- package/static/dashboard/assets/SystemSettingsPage-BbwQWsSR.js +1 -0
- package/static/dashboard/assets/SystemSettingsSubjectPanel-N117nMt5.js +33 -0
- package/static/dashboard/assets/XpodAiConnectionsPodStore-CdDOb4SV.js +18 -0
- package/static/dashboard/assets/{activity-j5zrznu-.js → activity-DX1I96o_.js} +1 -1
- package/static/dashboard/assets/admin-C6qCRFiY.js +1 -0
- package/static/dashboard/assets/ai-connections-DwCRqOQa.js +1 -0
- package/static/dashboard/assets/{badge-CzeBdG7h.js → badge-k2vhtDqH.js} +1 -1
- package/static/dashboard/assets/collection-runtime-BFQ8teQJ.js +1 -0
- package/static/dashboard/assets/{dashboard-D-xANHk1.js → dashboard-DWZ-fmCT.js} +105 -109
- package/static/dashboard/assets/dashboard-rk080mvG.css +1 -0
- package/static/dashboard/assets/dialog-1CCw-iHT.js +1 -0
- package/static/dashboard/assets/{download-IcNdEZWi.js → download-C6-SNY1q.js} +1 -1
- package/static/dashboard/assets/{external-link-DxBxK8Vu.js → external-link-BgPcZ_j2.js} +1 -1
- package/static/dashboard/assets/index-6LcIUIYO.js +1 -0
- package/static/dashboard/assets/index-D7A8U6Pt.js +41 -0
- package/static/dashboard/assets/index-UD6QOE7H.js +4 -0
- package/static/dashboard/assets/{key-round-D1K7warM.js → key-round-BOd7Jo0Q.js} +1 -1
- package/static/dashboard/assets/layout-DB3pMyTl.js +1 -0
- package/static/dashboard/assets/pod-collections-host-KnnGFZHL.js +8 -0
- package/static/dashboard/assets/{rotate-ccw-CcN1N6p9.js → rotate-ccw-CCgJqsvx.js} +1 -1
- package/static/dashboard/assets/settings-projection-CUkyprDQ.js +1 -0
- package/static/dashboard/assets/{skeleton-CKnmJMUH.js → skeleton-Bc7abAn5.js} +1 -1
- package/static/dashboard/assets/{waypoints-DuZPO_wu.js → waypoints-s-opmJxx.js} +1 -1
- package/static/dashboard/assets/{workspace-layout-BUj3wZ_m.js → workspace-layout-DqIQeTBV.js} +1 -1
- package/static/dashboard/dashboard.html +2 -2
- package/static/settings/assets/AiConfigContext-BB9KZySa.js +1 -0
- package/static/settings/assets/AiConfigPage-DGSXUkLs.js +1 -0
- package/static/settings/assets/DocumentProcessingPanel-Da2Re6Rg.js +1 -0
- package/static/settings/assets/IndexLifecyclePanel-BSZuIzgr.js +1 -0
- package/static/settings/assets/{IndexSubjectPanel-73sM16Ma.js → IndexSubjectPanel-CFd0ay-r.js} +1 -1
- package/static/settings/assets/ModelAssignmentsPanel-CSAryvWJ.js +1 -0
- package/static/settings/assets/ModelsPage-BQwCwLHU.js +11 -0
- package/static/settings/assets/{NetworkPage-i6j-M2RY.js → NetworkPage-BKymvsQc.js} +2 -2
- package/static/settings/assets/{PaneListHeader-DpqC0jd5.js → PaneListHeader-Bjh3hRdQ.js} +1 -1
- package/static/settings/assets/SearchIndexingPanel-MjKL5QLU.js +1 -0
- package/static/settings/assets/{StatusSubjectPanel-Dv4q3PGh.js → StatusSubjectPanel-Bvl6K4mx.js} +1 -1
- package/static/settings/assets/StatusWorkspace-B0NzrP--.js +1 -0
- package/static/settings/assets/SystemSettingsPage-D2z6Z4FE.js +1 -0
- package/static/settings/assets/SystemSettingsSubjectPanel-4sxma4X4.js +33 -0
- package/static/settings/assets/XpodAiConnectionsPodStore-BkNQ8fZx.js +3 -0
- package/static/settings/assets/{activity-DaFkk8f3.js → activity-CgJJGpjx.js} +1 -1
- package/static/settings/assets/admin-C6qCRFiY.js +1 -0
- package/static/settings/assets/ai-connections-CryuHGKW.js +1 -0
- package/static/settings/assets/{badge-d5SHdc-x.js → badge-C4NypVyT.js} +1 -1
- package/static/settings/assets/collection-runtime-CTLCDxAi.js +1 -0
- package/static/settings/assets/dialog-Csq0vWUi.js +1 -0
- package/static/settings/assets/{download-CpkwomDr.js → download-DaLJJ-Wp.js} +1 -1
- package/static/settings/assets/{external-link-_4YT42Mf.js → external-link--w_iW5Au.js} +1 -1
- package/static/settings/assets/index-B0mQa59b.js +4 -0
- package/static/settings/assets/index-BukHiu4y.js +1 -0
- package/static/settings/assets/index-COmVnZi2.js +41 -0
- package/static/settings/assets/{index-browser-B06xjBdZ.js → index-browser-BGpvHwD0.js} +1 -1
- package/static/settings/assets/{key-round-Dlqmp1Kq.js → key-round-Bk4YRjBu.js} +1 -1
- package/static/settings/assets/layout-DB3pMyTl.js +1 -0
- package/static/settings/assets/pod-collections-host-KnnGFZHL.js +8 -0
- package/static/settings/assets/{rotate-ccw-TAY65xWT.js → rotate-ccw-TCabbqsr.js} +1 -1
- package/static/settings/assets/{settings-ExBXGgbj.js → settings-CJWpdbNC.js} +105 -109
- package/static/settings/assets/settings-projection-CUkyprDQ.js +1 -0
- package/static/settings/assets/settings-rk080mvG.css +1 -0
- package/static/settings/assets/{skeleton-DKIWjNr9.js → skeleton-JDHYVe7t.js} +1 -1
- package/static/settings/assets/{waypoints-9erLIxyR.js → waypoints-DDvEl-MU.js} +1 -1
- package/static/settings/assets/{workspace-layout-CYXfYIa3.js → workspace-layout-DV5QU30U.js} +1 -1
- package/static/settings/settings.html +2 -2
- package/node_modules/@undefineds.co/shared-ui/dist/oidc-consent.d.ts +0 -54
- package/node_modules/@undefineds.co/shared-ui/dist/oidc-consent.js +0 -21
- package/static/auth-callback/assets/AiConfigContext-C81deMM9.js +0 -1
- package/static/auth-callback/assets/AiConfigPage-evWI8T56.js +0 -1
- package/static/auth-callback/assets/DocumentProcessingPanel-B9GrDEMe.js +0 -1
- package/static/auth-callback/assets/IndexLifecyclePanel-qCo8ABQZ.js +0 -1
- package/static/auth-callback/assets/ModelAssignmentsPanel-DG7Lxh3t.js +0 -1
- package/static/auth-callback/assets/ModelsPage-CgEuqE6p.js +0 -10
- package/static/auth-callback/assets/SearchIndexingPanel-ByU3u7kp.js +0 -1
- package/static/auth-callback/assets/StatusWorkspace-BZd617sV.js +0 -1
- package/static/auth-callback/assets/SystemSettingsPage-BirzWAQM.js +0 -1
- package/static/auth-callback/assets/SystemSettingsSubjectPanel-CmsVWNCx.js +0 -31
- package/static/auth-callback/assets/admin-BU4m6Ko2.js +0 -1
- package/static/auth-callback/assets/ai-connections-CHNTKemd.js +0 -1
- package/static/auth-callback/assets/auth-callback-C_7MUXJb.css +0 -1
- package/static/auth-callback/assets/index-BpV1hsqs.js +0 -4
- package/static/auth-callback/assets/index-D9oE6FXK.js +0 -41
- package/static/dashboard/assets/AiConfigContext-De-OtAWo.js +0 -1
- package/static/dashboard/assets/AiConfigPage-macP4Mop.js +0 -1
- package/static/dashboard/assets/DocumentProcessingPanel-C5ObvCCl.js +0 -1
- package/static/dashboard/assets/IndexLifecyclePanel-xVNa2l40.js +0 -1
- package/static/dashboard/assets/ModelAssignmentsPanel-DMOATFpQ.js +0 -1
- package/static/dashboard/assets/ModelsPage-91UbnETA.js +0 -25
- package/static/dashboard/assets/SearchIndexingPanel-Dh70PNFZ.js +0 -1
- package/static/dashboard/assets/SystemSettingsPage-BiN5GcKx.js +0 -1
- package/static/dashboard/assets/SystemSettingsSubjectPanel-B9QrSiFp.js +0 -31
- package/static/dashboard/assets/admin-BU4m6Ko2.js +0 -1
- package/static/dashboard/assets/ai-connections-CHNTKemd.js +0 -1
- package/static/dashboard/assets/dashboard-C_7MUXJb.css +0 -1
- package/static/dashboard/assets/index-FWZ-s52O.js +0 -41
- package/static/dashboard/assets/index-ZiQZ96oC.js +0 -4
- package/static/settings/assets/AiConfigContext-C0cQMPfG.js +0 -1
- package/static/settings/assets/AiConfigPage-CPhB4iFb.js +0 -1
- package/static/settings/assets/DocumentProcessingPanel-sYI7OpuH.js +0 -1
- package/static/settings/assets/IndexLifecyclePanel-yj8iyiT8.js +0 -1
- package/static/settings/assets/ModelAssignmentsPanel-BFIgUX5v.js +0 -1
- package/static/settings/assets/ModelsPage-BdppXl7E.js +0 -10
- package/static/settings/assets/SearchIndexingPanel-BlPnrkT3.js +0 -1
- package/static/settings/assets/SystemSettingsPage-CiOm2NzV.js +0 -1
- package/static/settings/assets/SystemSettingsSubjectPanel-Cd-GECon.js +0 -31
- package/static/settings/assets/admin-BU4m6Ko2.js +0 -1
- package/static/settings/assets/ai-connections-CHNTKemd.js +0 -1
- package/static/settings/assets/index-BFi9yn7_.js +0 -41
- package/static/settings/assets/index-BGgEhIUy.js +0 -4
- package/static/settings/assets/settings-C_7MUXJb.css +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LOG_FILE_PATTERN = exports.LOG_FILE_NAME_PATTERN = exports.LOG_DIRECTORY = void 0;
|
|
7
|
+
exports.resolveLogFilePattern = resolveLogFilePattern;
|
|
8
|
+
exports.resolveCurrentLogFile = resolveCurrentLogFile;
|
|
9
|
+
/**
|
|
10
|
+
* Canonical location of the runtime log file.
|
|
11
|
+
*
|
|
12
|
+
* Every writer (main entry, runtime bootstrap, API service) and every reader
|
|
13
|
+
* (admin diagnostics) resolves the path through this module. When the reader
|
|
14
|
+
* guessed its own file names instead, the Logs page reported "no log file"
|
|
15
|
+
* while the runtime kept writing to one.
|
|
16
|
+
*/
|
|
17
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
/** Directory, relative to the runtime working directory. */
|
|
20
|
+
exports.LOG_DIRECTORY = 'logs';
|
|
21
|
+
/** File name template; the rotating transport substitutes `%DATE%`. */
|
|
22
|
+
exports.LOG_FILE_NAME_PATTERN = 'xpod-%DATE%.log';
|
|
23
|
+
/** Both segments, for callers that join them onto a working directory themselves. */
|
|
24
|
+
exports.LOG_FILE_PATTERN = `${exports.LOG_DIRECTORY}/${exports.LOG_FILE_NAME_PATTERN}`;
|
|
25
|
+
/** Concrete files the template produces, including rotated siblings such as `xpod-2026-09-13.log.2`. */
|
|
26
|
+
const CONCRETE_LOG_FILE_NAME = /^xpod-.*\.log(\.\d+)?$/;
|
|
27
|
+
/** Absolute path template handed to the logging transport. */
|
|
28
|
+
function resolveLogFilePattern(cwd = process.cwd()) {
|
|
29
|
+
return node_path_1.default.join(cwd, exports.LOG_DIRECTORY, exports.LOG_FILE_NAME_PATTERN);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The log file currently being appended to, or `null` when the runtime has not
|
|
33
|
+
* written one yet.
|
|
34
|
+
*
|
|
35
|
+
* Daily rotation produces one file per date and size rotation keeps older
|
|
36
|
+
* segments as `.log.N` next to it, so the live file is identified by
|
|
37
|
+
* modification time rather than by name.
|
|
38
|
+
*/
|
|
39
|
+
function resolveCurrentLogFile(cwd = process.cwd()) {
|
|
40
|
+
const directory = node_path_1.default.join(cwd, exports.LOG_DIRECTORY);
|
|
41
|
+
let names;
|
|
42
|
+
try {
|
|
43
|
+
names = node_fs_1.default.readdirSync(directory);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
let newest = null;
|
|
49
|
+
for (const name of names) {
|
|
50
|
+
if (!CONCRETE_LOG_FILE_NAME.test(name))
|
|
51
|
+
continue;
|
|
52
|
+
const file = node_path_1.default.join(directory, name);
|
|
53
|
+
let mtimeMs;
|
|
54
|
+
try {
|
|
55
|
+
const stats = node_fs_1.default.statSync(file);
|
|
56
|
+
if (!stats.isFile())
|
|
57
|
+
continue;
|
|
58
|
+
mtimeMs = stats.mtimeMs;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!newest || mtimeMs > newest.mtimeMs) {
|
|
64
|
+
newest = { file, mtimeMs };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return newest?.file ?? null;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=log-file.js.map
|
package/dist/main.js
CHANGED
|
@@ -17,6 +17,7 @@ const css_process_1 = require("./runtime/css-process");
|
|
|
17
17
|
const oidc_issuer_1 = require("./runtime/oidc-issuer");
|
|
18
18
|
const AuthMode_1 = require("./authorization/AuthMode");
|
|
19
19
|
const ConfigurableLoggerFactory_1 = require("./logging/ConfigurableLoggerFactory");
|
|
20
|
+
const log_file_1 = require("./logging/log-file");
|
|
20
21
|
const supervisor_1 = require("./supervisor");
|
|
21
22
|
const js_runtime_1 = require("./runtime/js-runtime");
|
|
22
23
|
const database_url_1 = require("./runtime/database-url");
|
|
@@ -27,7 +28,7 @@ const EXIT_INTERNAL_ERROR = 50;
|
|
|
27
28
|
let logger = (0, global_logger_factory_1.getLoggerFor)('Main');
|
|
28
29
|
function initLogger() {
|
|
29
30
|
const loggerFactory = new ConfigurableLoggerFactory_1.ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {
|
|
30
|
-
fileName:
|
|
31
|
+
fileName: (0, log_file_1.resolveLogFilePattern)(),
|
|
31
32
|
showLocation: true,
|
|
32
33
|
});
|
|
33
34
|
(0, global_logger_factory_1.setGlobalLoggerFactory)(loggerFactory);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Finalizable, KeyValueStorage, NotificationChannelStorage, WebSocketMap } from '@solid/community-server';
|
|
2
|
+
import { Initializer } from '@solid/community-server';
|
|
3
|
+
/** 默认清扫间隔(分钟)。同时是“新建但尚未连上 socket”的通道的宽限期。 */
|
|
4
|
+
export declare const NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES = 5;
|
|
5
|
+
/**
|
|
6
|
+
* 回收没有活动 socket 的通知通道。
|
|
7
|
+
*
|
|
8
|
+
* 背景:CSS 的 `WebSocket2023Storer` 只在 socket 关闭时把它从内存 map 中移除,通道记录留在
|
|
9
|
+
* `SubscriptionStorage` 里直到 `endAt` 过期(默认 2 周);客户端 DELETE 失败、页面崩溃、
|
|
10
|
+
* 进程被强杀等情况都会留下再也无人使用、也无人回收的通道。`ReclaimingWebSocket2023Storer`
|
|
11
|
+
* 覆盖了正常关闭的路径,本组件负责其余部分:
|
|
12
|
+
*
|
|
13
|
+
* 1. 启动时清扫一次:进程刚起来,内存 map 必然为空,任何持久化的通道都不可能还有活动 socket;
|
|
14
|
+
* 2. 之后每 {@link NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES} 分钟清扫一次:无 socket 的通道
|
|
15
|
+
* 需要连续两次被判定为孤儿才删除,避免误删“刚 POST 出来、socket 还在握手”的通道。
|
|
16
|
+
*
|
|
17
|
+
* 只回收本实例 `baseUrl` 下的通道:通道 id 由本实例的订阅路由生成,Cloud 集群中共享
|
|
18
|
+
* `internal_kv` 的其他节点(若存在)的通道由各自实例负责,这里不做跨实例删除。
|
|
19
|
+
* 与 socket 归属相关的限制(同一个 baseUrl 被多个 CSS 进程共享时无法判断通道是否在别的进程里存活)
|
|
20
|
+
* 见 `docs/COMPONENTS.md`。
|
|
21
|
+
*/
|
|
22
|
+
export declare class NotificationChannelSweeper extends Initializer implements Finalizable {
|
|
23
|
+
protected readonly logger: import("global-logger-factory").Logger<unknown>;
|
|
24
|
+
private readonly channelStorage;
|
|
25
|
+
private readonly channelIndex;
|
|
26
|
+
private readonly socketMap;
|
|
27
|
+
private readonly baseUrl;
|
|
28
|
+
private readonly intervalMs;
|
|
29
|
+
/** 见过一次、但当时没有活动 socket 的通道 id;下一次仍是孤儿才回收。 */
|
|
30
|
+
private readonly awaitingSecondLook;
|
|
31
|
+
private timer?;
|
|
32
|
+
private sweeping;
|
|
33
|
+
constructor(storage: NotificationChannelStorage, channelIndex: KeyValueStorage<string, unknown>, socketMap: WebSocketMap, baseUrl: string, intervalMinutes?: number);
|
|
34
|
+
/**
|
|
35
|
+
* CSS 启动序列的一部分(在 HTTP server 开始监听之前执行):先做一次启动清扫,再挂上有界的周期任务。
|
|
36
|
+
*
|
|
37
|
+
* 实测同一次 CSS 启动里本方法会被调用两次(配置图里只出现一次)。这里做成幂等:重复调用既不重复清扫,
|
|
38
|
+
* 也不重复注册定时器——两个定时器会让“连续两次判定”退化成相隔几百毫秒的两次判定,等于没有宽限期。
|
|
39
|
+
*/
|
|
40
|
+
handle(): Promise<void>;
|
|
41
|
+
finalize(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* 执行一次清扫,返回被回收的通道数量。
|
|
44
|
+
*
|
|
45
|
+
* @param initial - 启动清扫:内存中还没有任何 socket,因此无 socket 的通道一律视为孤儿。
|
|
46
|
+
*/
|
|
47
|
+
sweep(initial?: boolean): Promise<number>;
|
|
48
|
+
/** 枚举本实例 baseUrl 下的通道记录。topic 索引行(值是 id 数组)不是通道,跳过。 */
|
|
49
|
+
private listOwnedChannels;
|
|
50
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotificationChannelSweeper = exports.NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES = void 0;
|
|
4
|
+
const community_server_1 = require("@solid/community-server");
|
|
5
|
+
const global_logger_factory_1 = require("global-logger-factory");
|
|
6
|
+
/** 默认清扫间隔(分钟)。同时是“新建但尚未连上 socket”的通道的宽限期。 */
|
|
7
|
+
exports.NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES = 5;
|
|
8
|
+
function isNotificationChannel(value) {
|
|
9
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
const candidate = value;
|
|
13
|
+
return typeof candidate.id === 'string' && typeof candidate.topic === 'string';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 回收没有活动 socket 的通知通道。
|
|
17
|
+
*
|
|
18
|
+
* 背景:CSS 的 `WebSocket2023Storer` 只在 socket 关闭时把它从内存 map 中移除,通道记录留在
|
|
19
|
+
* `SubscriptionStorage` 里直到 `endAt` 过期(默认 2 周);客户端 DELETE 失败、页面崩溃、
|
|
20
|
+
* 进程被强杀等情况都会留下再也无人使用、也无人回收的通道。`ReclaimingWebSocket2023Storer`
|
|
21
|
+
* 覆盖了正常关闭的路径,本组件负责其余部分:
|
|
22
|
+
*
|
|
23
|
+
* 1. 启动时清扫一次:进程刚起来,内存 map 必然为空,任何持久化的通道都不可能还有活动 socket;
|
|
24
|
+
* 2. 之后每 {@link NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES} 分钟清扫一次:无 socket 的通道
|
|
25
|
+
* 需要连续两次被判定为孤儿才删除,避免误删“刚 POST 出来、socket 还在握手”的通道。
|
|
26
|
+
*
|
|
27
|
+
* 只回收本实例 `baseUrl` 下的通道:通道 id 由本实例的订阅路由生成,Cloud 集群中共享
|
|
28
|
+
* `internal_kv` 的其他节点(若存在)的通道由各自实例负责,这里不做跨实例删除。
|
|
29
|
+
* 与 socket 归属相关的限制(同一个 baseUrl 被多个 CSS 进程共享时无法判断通道是否在别的进程里存活)
|
|
30
|
+
* 见 `docs/COMPONENTS.md`。
|
|
31
|
+
*/
|
|
32
|
+
class NotificationChannelSweeper extends community_server_1.Initializer {
|
|
33
|
+
constructor(storage, channelIndex, socketMap, baseUrl, intervalMinutes = exports.NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES) {
|
|
34
|
+
super();
|
|
35
|
+
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
36
|
+
/** 见过一次、但当时没有活动 socket 的通道 id;下一次仍是孤儿才回收。 */
|
|
37
|
+
this.awaitingSecondLook = new Set();
|
|
38
|
+
this.sweeping = false;
|
|
39
|
+
this.channelStorage = storage;
|
|
40
|
+
this.channelIndex = channelIndex;
|
|
41
|
+
this.socketMap = socketMap;
|
|
42
|
+
// 通道 id 是 `<baseUrl>/.notifications/...`;补上结尾斜杠,避免 `https://pod.example`
|
|
43
|
+
// 匹配到 `https://pod.example.evil/...`。
|
|
44
|
+
this.baseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
45
|
+
this.intervalMs = intervalMinutes * 60 * 1000;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* CSS 启动序列的一部分(在 HTTP server 开始监听之前执行):先做一次启动清扫,再挂上有界的周期任务。
|
|
49
|
+
*
|
|
50
|
+
* 实测同一次 CSS 启动里本方法会被调用两次(配置图里只出现一次)。这里做成幂等:重复调用既不重复清扫,
|
|
51
|
+
* 也不重复注册定时器——两个定时器会让“连续两次判定”退化成相隔几百毫秒的两次判定,等于没有宽限期。
|
|
52
|
+
*/
|
|
53
|
+
async handle() {
|
|
54
|
+
if (this.timer) {
|
|
55
|
+
this.logger.debug('Notification channel sweep is already scheduled; ignoring duplicate initializer call');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
await this.sweep(true);
|
|
59
|
+
this.timer = (0, community_server_1.setSafeInterval)(this.logger, 'Failed to reclaim orphaned notification channels', async () => {
|
|
60
|
+
await this.sweep(false);
|
|
61
|
+
}, this.intervalMs);
|
|
62
|
+
// 不阻止进程退出:清扫只是运维兜底,不是常驻工作。
|
|
63
|
+
this.timer.unref();
|
|
64
|
+
this.logger.info(`Notification channel sweep scheduled every ${this.intervalMs / 60_000} minute(s)`);
|
|
65
|
+
}
|
|
66
|
+
async finalize() {
|
|
67
|
+
if (this.timer) {
|
|
68
|
+
clearInterval(this.timer);
|
|
69
|
+
this.timer = undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 执行一次清扫,返回被回收的通道数量。
|
|
74
|
+
*
|
|
75
|
+
* @param initial - 启动清扫:内存中还没有任何 socket,因此无 socket 的通道一律视为孤儿。
|
|
76
|
+
*/
|
|
77
|
+
async sweep(initial = false) {
|
|
78
|
+
if (this.sweeping) {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
this.sweeping = true;
|
|
82
|
+
try {
|
|
83
|
+
const channels = await this.listOwnedChannels();
|
|
84
|
+
const reclaimed = [];
|
|
85
|
+
for (const channel of channels.values()) {
|
|
86
|
+
if (this.socketMap.has(channel.id)) {
|
|
87
|
+
this.awaitingSecondLook.delete(channel.id);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (!initial && !this.awaitingSecondLook.has(channel.id)) {
|
|
91
|
+
this.awaitingSecondLook.add(channel.id);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (await this.channelStorage.delete(channel.id)) {
|
|
95
|
+
reclaimed.push(channel.id);
|
|
96
|
+
}
|
|
97
|
+
this.awaitingSecondLook.delete(channel.id);
|
|
98
|
+
}
|
|
99
|
+
// 已经被其他路径删除的通道不必再留在这里。
|
|
100
|
+
for (const id of [...this.awaitingSecondLook]) {
|
|
101
|
+
if (!channels.has(id)) {
|
|
102
|
+
this.awaitingSecondLook.delete(id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (reclaimed.length > 0) {
|
|
106
|
+
this.logger.info(`Reclaimed ${reclaimed.length} notification channel(s) without a live WebSocket`);
|
|
107
|
+
this.logger.debug(`Reclaimed notification channels: ${reclaimed.join(', ')}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.logger.debug(`Notification channel sweep found no orphan among ${channels.size} channel(s)`);
|
|
111
|
+
}
|
|
112
|
+
return reclaimed.length;
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
this.sweeping = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** 枚举本实例 baseUrl 下的通道记录。topic 索引行(值是 id 数组)不是通道,跳过。 */
|
|
119
|
+
async listOwnedChannels() {
|
|
120
|
+
const channels = new Map();
|
|
121
|
+
for await (const [, value] of this.channelIndex.entries()) {
|
|
122
|
+
if (!isNotificationChannel(value) || !value.id.startsWith(this.baseUrl)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
channels.set(value.id, value);
|
|
126
|
+
}
|
|
127
|
+
return channels;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.NotificationChannelSweeper = NotificationChannelSweeper;
|
|
131
|
+
//# sourceMappingURL=NotificationChannelSweeper.js.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@undefineds.co/xpod/^0.0.0/components/context.jsonld",
|
|
4
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^8.0.0/components/context.jsonld"
|
|
5
|
+
],
|
|
6
|
+
"@id": "npmd:@undefineds.co/xpod",
|
|
7
|
+
"components": [
|
|
8
|
+
{
|
|
9
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper",
|
|
10
|
+
"@type": "Class",
|
|
11
|
+
"requireElement": "NotificationChannelSweeper",
|
|
12
|
+
"extends": [
|
|
13
|
+
"css:dist/init/Initializer.jsonld#Initializer",
|
|
14
|
+
"css:dist/init/final/Finalizable.jsonld#Finalizable"
|
|
15
|
+
],
|
|
16
|
+
"comment": "回收没有活动 socket 的通知通道。 背景:CSS 的 `WebSocket2023Storer` 只在 socket 关闭时把它从内存 map 中移除,通道记录留在 `SubscriptionStorage` 里直到 `endAt` 过期(默认 2 周);客户端 DELETE 失败、页面崩溃、 进程被强杀等情况都会留下再也无人使用、也无人回收的通道。`ReclaimingWebSocket2023Storer` 覆盖了正常关闭的路径,本组件负责其余部分: 1. 启动时清扫一次:进程刚起来,内存 map 必然为空,任何持久化的通道都不可能还有活动 socket; 2. 之后每 {@link NOTIFICATION_CHANNEL_SWEEP_INTERVAL_MINUTES} 分钟清扫一次:无 socket 的通道 需要连续两次被判定为孤儿才删除,避免误删“刚 POST 出来、socket 还在握手”的通道。 只回收本实例 `baseUrl` 下的通道:通道 id 由本实例的订阅路由生成,Cloud 集群中共享 `internal_kv` 的其他节点(若存在)的通道由各自实例负责,这里不做跨实例删除。 与 socket 归属相关的限制(同一个 baseUrl 被多个 CSS 进程共享时无法判断通道是否在别的进程里存活) 见 `docs/COMPONENTS.md`。",
|
|
17
|
+
"parameters": [
|
|
18
|
+
{
|
|
19
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_baseUrl",
|
|
20
|
+
"range": "xsd:string"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_intervalMinutes",
|
|
24
|
+
"range": {
|
|
25
|
+
"@type": "ParameterRangeUnion",
|
|
26
|
+
"parameterRangeElements": [
|
|
27
|
+
"xsd:number",
|
|
28
|
+
{
|
|
29
|
+
"@type": "ParameterRangeUndefined"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_storage",
|
|
36
|
+
"range": "css:dist/server/notifications/NotificationChannelStorage.jsonld#NotificationChannelStorage"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_socketMap",
|
|
40
|
+
"range": "css:dist/server/notifications/WebSocketChannel2023/WebSocketMap.jsonld#WebSocketMap"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_channelIndex",
|
|
44
|
+
"range": {
|
|
45
|
+
"@type": "ParameterRangeGenericComponent",
|
|
46
|
+
"component": "css:dist/storage/keyvalue/KeyValueStorage.jsonld#KeyValueStorage",
|
|
47
|
+
"genericTypeInstances": [
|
|
48
|
+
"xsd:string",
|
|
49
|
+
{
|
|
50
|
+
"@type": "ParameterRangeWildcard"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"memberFields": [
|
|
57
|
+
{
|
|
58
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_logger",
|
|
59
|
+
"memberFieldName": "logger",
|
|
60
|
+
"range": {
|
|
61
|
+
"@type": "ParameterRangeWildcard"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_channelStorage",
|
|
66
|
+
"memberFieldName": "channelStorage"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_channelIndex",
|
|
70
|
+
"memberFieldName": "channelIndex"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_socketMap",
|
|
74
|
+
"memberFieldName": "socketMap"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_baseUrl",
|
|
78
|
+
"memberFieldName": "baseUrl"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_intervalMs",
|
|
82
|
+
"memberFieldName": "intervalMs"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_awaitingSecondLook",
|
|
86
|
+
"memberFieldName": "awaitingSecondLook"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_timer",
|
|
90
|
+
"memberFieldName": "timer"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_sweeping",
|
|
94
|
+
"memberFieldName": "sweeping"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_constructor",
|
|
98
|
+
"memberFieldName": "constructor"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_handle",
|
|
102
|
+
"memberFieldName": "handle"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_finalize",
|
|
106
|
+
"memberFieldName": "finalize"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_sweep",
|
|
110
|
+
"memberFieldName": "sweep"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper__member_listOwnedChannels",
|
|
114
|
+
"memberFieldName": "listOwnedChannels"
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"constructorArguments": [
|
|
118
|
+
{
|
|
119
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_storage"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_channelIndex"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_socketMap"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_baseUrl"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"@id": "undefineds:dist/notifications/NotificationChannelSweeper.jsonld#NotificationChannelSweeper_intervalMinutes"
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { NotificationChannelStorage, WebSocket2023HandlerInput, WebSocketMap } from '@solid/community-server';
|
|
2
|
+
import { WebSocket2023Storer } from '@solid/community-server';
|
|
3
|
+
/**
|
|
4
|
+
* WebSocket2023Storer 的等位替换:保留 CSS 原有行为(把 socket 存进 map、socket 关闭时从 map 移除、
|
|
5
|
+
* 定期关掉已过期通道的 socket),并补上缺失的一环——最后一个 socket 关闭或出错时回收通道记录。
|
|
6
|
+
*
|
|
7
|
+
* CSS 默认实现只在 `close`/`error` 时调用 `socketMap.deleteEntry(...)`,通道记录会一直留在
|
|
8
|
+
* `SubscriptionStorage` 里直到 `endAt` 过期(`NotificationSubscriber` 默认把它压到 2 周后),
|
|
9
|
+
* 因此每次页面刷新、HMR、崩溃都会留下一个再也不会被使用的通道。
|
|
10
|
+
*
|
|
11
|
+
* 只有当该通道名下的 socket 全部消失时才删除:同一个通道允许多个 socket(例如两个标签页共用一次订阅),
|
|
12
|
+
* 只要还有 socket 存活就必须保留通道,否则会静默掐断仍在监听的客户端。
|
|
13
|
+
*/
|
|
14
|
+
export declare class ReclaimingWebSocket2023Storer extends WebSocket2023Storer {
|
|
15
|
+
private readonly channelStorage;
|
|
16
|
+
private readonly liveSockets;
|
|
17
|
+
/**
|
|
18
|
+
* 一次 socket 终止可能先 `error` 再 `close`,这里保证同一个通道只回收一次。
|
|
19
|
+
* 通道 id 由 `randomUUID()` 生成且永不复用,因此不需要清理已回收的 id。
|
|
20
|
+
*/
|
|
21
|
+
private readonly reclaiming;
|
|
22
|
+
constructor(storage: NotificationChannelStorage, socketMap: WebSocketMap, cleanupTimer?: number);
|
|
23
|
+
handle(input: WebSocket2023HandlerInput): Promise<void>;
|
|
24
|
+
private reclaim;
|
|
25
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReclaimingWebSocket2023Storer = void 0;
|
|
4
|
+
const community_server_1 = require("@solid/community-server");
|
|
5
|
+
/**
|
|
6
|
+
* WebSocket2023Storer 的等位替换:保留 CSS 原有行为(把 socket 存进 map、socket 关闭时从 map 移除、
|
|
7
|
+
* 定期关掉已过期通道的 socket),并补上缺失的一环——最后一个 socket 关闭或出错时回收通道记录。
|
|
8
|
+
*
|
|
9
|
+
* CSS 默认实现只在 `close`/`error` 时调用 `socketMap.deleteEntry(...)`,通道记录会一直留在
|
|
10
|
+
* `SubscriptionStorage` 里直到 `endAt` 过期(`NotificationSubscriber` 默认把它压到 2 周后),
|
|
11
|
+
* 因此每次页面刷新、HMR、崩溃都会留下一个再也不会被使用的通道。
|
|
12
|
+
*
|
|
13
|
+
* 只有当该通道名下的 socket 全部消失时才删除:同一个通道允许多个 socket(例如两个标签页共用一次订阅),
|
|
14
|
+
* 只要还有 socket 存活就必须保留通道,否则会静默掐断仍在监听的客户端。
|
|
15
|
+
*/
|
|
16
|
+
class ReclaimingWebSocket2023Storer extends community_server_1.WebSocket2023Storer {
|
|
17
|
+
constructor(storage, socketMap, cleanupTimer) {
|
|
18
|
+
super(storage, socketMap, cleanupTimer);
|
|
19
|
+
/**
|
|
20
|
+
* 一次 socket 终止可能先 `error` 再 `close`,这里保证同一个通道只回收一次。
|
|
21
|
+
* 通道 id 由 `randomUUID()` 生成且永不复用,因此不需要清理已回收的 id。
|
|
22
|
+
*/
|
|
23
|
+
this.reclaiming = new Set();
|
|
24
|
+
this.channelStorage = storage;
|
|
25
|
+
this.liveSockets = socketMap;
|
|
26
|
+
}
|
|
27
|
+
async handle(input) {
|
|
28
|
+
await super.handle(input);
|
|
29
|
+
const { channel, webSocket } = input;
|
|
30
|
+
// 基类的监听器先注册,所以这里运行时 map 已经反映了本次关闭后的真实状态。
|
|
31
|
+
// socket 事件回调不能把 rejection 抛回事件循环:删除失败只记日志,交给清扫器和 endAt 兜底。
|
|
32
|
+
const reclaim = () => {
|
|
33
|
+
this.reclaim(channel.id).catch((error) => {
|
|
34
|
+
this.logger.error(`Failed to reclaim notification channel ${channel.id}: ${(0, community_server_1.createErrorMessage)(error)}`);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
webSocket.on('close', reclaim);
|
|
38
|
+
webSocket.on('error', reclaim);
|
|
39
|
+
}
|
|
40
|
+
async reclaim(id) {
|
|
41
|
+
if (this.liveSockets.has(id) || this.reclaiming.has(id)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
this.reclaiming.add(id);
|
|
45
|
+
try {
|
|
46
|
+
if (await this.channelStorage.delete(id)) {
|
|
47
|
+
this.logger.info(`Reclaimed notification channel ${id}: its last WebSocket closed`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
this.reclaiming.delete(id);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.ReclaimingWebSocket2023Storer = ReclaimingWebSocket2023Storer;
|
|
56
|
+
//# sourceMappingURL=ReclaimingWebSocket2023Storer.js.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@undefineds.co/xpod/^0.0.0/components/context.jsonld",
|
|
4
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^8.0.0/components/context.jsonld"
|
|
5
|
+
],
|
|
6
|
+
"@id": "npmd:@undefineds.co/xpod",
|
|
7
|
+
"components": [
|
|
8
|
+
{
|
|
9
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer",
|
|
10
|
+
"@type": "Class",
|
|
11
|
+
"requireElement": "ReclaimingWebSocket2023Storer",
|
|
12
|
+
"extends": [
|
|
13
|
+
"css:dist/server/notifications/WebSocketChannel2023/WebSocket2023Storer.jsonld#WebSocket2023Storer"
|
|
14
|
+
],
|
|
15
|
+
"comment": "WebSocket2023Storer 的等位替换:保留 CSS 原有行为(把 socket 存进 map、socket 关闭时从 map 移除、 定期关掉已过期通道的 socket),并补上缺失的一环——最后一个 socket 关闭或出错时回收通道记录。 CSS 默认实现只在 `close`/`error` 时调用 `socketMap.deleteEntry(...)`,通道记录会一直留在 `SubscriptionStorage` 里直到 `endAt` 过期(`NotificationSubscriber` 默认把它压到 2 周后), 因此每次页面刷新、HMR、崩溃都会留下一个再也不会被使用的通道。 只有当该通道名下的 socket 全部消失时才删除:同一个通道允许多个 socket(例如两个标签页共用一次订阅), 只要还有 socket 存活就必须保留通道,否则会静默掐断仍在监听的客户端。",
|
|
16
|
+
"parameters": [
|
|
17
|
+
{
|
|
18
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer_cleanupTimer",
|
|
19
|
+
"range": {
|
|
20
|
+
"@type": "ParameterRangeUnion",
|
|
21
|
+
"parameterRangeElements": [
|
|
22
|
+
"xsd:number",
|
|
23
|
+
{
|
|
24
|
+
"@type": "ParameterRangeUndefined"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer_storage",
|
|
31
|
+
"range": "css:dist/server/notifications/NotificationChannelStorage.jsonld#NotificationChannelStorage"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer_socketMap",
|
|
35
|
+
"range": "css:dist/server/notifications/WebSocketChannel2023/WebSocketMap.jsonld#WebSocketMap"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"memberFields": [
|
|
39
|
+
{
|
|
40
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer__member_channelStorage",
|
|
41
|
+
"memberFieldName": "channelStorage"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer__member_liveSockets",
|
|
45
|
+
"memberFieldName": "liveSockets"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer__member_reclaiming",
|
|
49
|
+
"memberFieldName": "reclaiming"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer__member_constructor",
|
|
53
|
+
"memberFieldName": "constructor"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer__member_handle",
|
|
57
|
+
"memberFieldName": "handle"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer__member_reclaim",
|
|
61
|
+
"memberFieldName": "reclaim"
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"constructorArguments": [
|
|
65
|
+
{
|
|
66
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer_storage"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer_socketMap"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"@id": "undefineds:dist/notifications/ReclaimingWebSocket2023Storer.jsonld#ReclaimingWebSocket2023Storer_cleanupTimer"
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
@@ -17,4 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./device-notification-protocol"), exports);
|
|
18
18
|
__exportStar(require("./DeviceNotificationHub"), exports);
|
|
19
19
|
__exportStar(require("./DeviceNotificationResourceListener"), exports);
|
|
20
|
+
__exportStar(require("./NotificationChannelSweeper"), exports);
|
|
21
|
+
__exportStar(require("./ReclaimingWebSocket2023Storer"), exports);
|
|
20
22
|
//# sourceMappingURL=index.js.map
|
package/dist/runtime/Proxy.d.ts
CHANGED
|
@@ -14,13 +14,44 @@ export declare class GatewayProxy {
|
|
|
14
14
|
private readonly baseUrl?;
|
|
15
15
|
private readonly internalAdminAuthSecret?;
|
|
16
16
|
private readonly clientRemoteAddressResolver?;
|
|
17
|
+
/**
|
|
18
|
+
* Upgrade relay for runtimes whose HTTP server cannot expose the raw upgraded
|
|
19
|
+
* socket (Bun). `undefined` keeps the byte-level `http-proxy` relay.
|
|
20
|
+
*/
|
|
21
|
+
private readonly nativeUpgradeRelay?;
|
|
22
|
+
/** Sockets created by `upgrade` events, dropped on shutdown. */
|
|
23
|
+
private readonly upgradeSockets;
|
|
17
24
|
constructor(port: number | undefined, supervisor: Supervisor, bindHost?: string, options?: GatewayProxyOptions);
|
|
25
|
+
/**
|
|
26
|
+
* Upgraded sockets outlive the HTTP request that created them; they are
|
|
27
|
+
* tracked so shutdown can drop them instead of waiting for a long lived
|
|
28
|
+
* notification channel to end on its own.
|
|
29
|
+
*/
|
|
30
|
+
private trackUpgradeSocket;
|
|
31
|
+
/**
|
|
32
|
+
* Picks the internal service that owns an upgrade path.
|
|
33
|
+
*
|
|
34
|
+
* `/ws/*` and the device notification multiplex live on the API server; every
|
|
35
|
+
* other upgrade (Solid notification channels, edge node tunnels) goes to CSS.
|
|
36
|
+
*/
|
|
37
|
+
private resolveUpgradeTarget;
|
|
38
|
+
private relayUpgradeWithHttpProxy;
|
|
18
39
|
setTargets(targets: {
|
|
19
40
|
css?: string | GatewayProxyTarget;
|
|
20
41
|
api?: string | GatewayProxyTarget;
|
|
21
42
|
}): void;
|
|
22
43
|
start(): Promise<void>;
|
|
23
44
|
stop(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Closes the listener with a bounded wait.
|
|
47
|
+
*
|
|
48
|
+
* The listening socket stops accepting as soon as `close()` is called, but
|
|
49
|
+
* the callback waits for every connection to end. Node keeps upgraded sockets
|
|
50
|
+
* counted until they are destroyed (done above); Bun additionally never calls
|
|
51
|
+
* back once a WebSocket was closed from the server side
|
|
52
|
+
* (oven-sh/bun#28396), so waiting forever would block gateway restarts.
|
|
53
|
+
*/
|
|
54
|
+
private closeServer;
|
|
24
55
|
private handleRequest;
|
|
25
56
|
private isApiWebProductPath;
|
|
26
57
|
private shouldRouteToApi;
|
|
@@ -65,4 +96,10 @@ export interface GatewayProxyOptions {
|
|
|
65
96
|
baseUrl?: string;
|
|
66
97
|
internalAdminAuthSecret?: string;
|
|
67
98
|
clientRemoteAddressResolver?: (req: http.IncomingMessage) => string | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Forces the native (message level) upgrade relay on or off.
|
|
101
|
+
* Defaults to `true` on Bun, where the `http-proxy` relay cannot reach the
|
|
102
|
+
* client socket at all.
|
|
103
|
+
*/
|
|
104
|
+
nativeUpgradeRelay?: boolean;
|
|
68
105
|
}
|