@undefineds.co/xpod 0.1.6 → 0.2.0-preview.2
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 +141 -2
- package/config/cli.json +9 -71
- package/config/cloud.json +34 -7
- package/config/local.json +6 -2
- package/config/resolver.json +11 -49
- package/config/runtime-open.json +22 -0
- package/config/xpod.base.json +32 -0
- package/config/xpod.cluster.json +2 -44
- package/config/xpod.json +5 -2
- package/dist/api/ApiServer.js +1 -1
- package/dist/api/ApiServer.js.map +1 -1
- package/dist/api/auth/AuthContext.d.ts +12 -1
- package/dist/api/auth/AuthContext.js +18 -1
- package/dist/api/auth/AuthContext.js.map +1 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
- package/dist/api/auth/ServiceTokenAuthenticator.d.ts +18 -0
- package/dist/api/auth/ServiceTokenAuthenticator.js +50 -0
- package/dist/api/auth/ServiceTokenAuthenticator.js.map +1 -0
- package/dist/api/auth/index.d.ts +1 -0
- package/dist/api/auth/index.js +1 -0
- package/dist/api/auth/index.js.map +1 -1
- package/dist/api/chatkit/ai-provider.d.ts +0 -10
- package/dist/api/chatkit/ai-provider.js +11 -120
- package/dist/api/chatkit/ai-provider.js.map +1 -1
- package/dist/api/chatkit/default-agent.js +11 -8
- package/dist/api/chatkit/default-agent.js.map +1 -1
- package/dist/api/chatkit/pod-store.js +19 -3
- package/dist/api/chatkit/pod-store.js.map +1 -1
- package/dist/api/chatkit/schema.d.ts +9 -3
- package/dist/api/chatkit/schema.js +14 -6
- package/dist/api/chatkit/schema.js.map +1 -1
- package/dist/api/container/business-token.d.ts +9 -0
- package/dist/api/container/business-token.js +32 -0
- package/dist/api/container/business-token.js.map +1 -0
- package/dist/api/container/cloud.js +36 -12
- package/dist/api/container/cloud.js.map +1 -1
- package/dist/api/container/common.js +12 -5
- package/dist/api/container/common.js.map +1 -1
- package/dist/api/container/index.js +94 -14
- package/dist/api/container/index.js.map +1 -1
- package/dist/api/container/local.js +2 -1
- package/dist/api/container/local.js.map +1 -1
- package/dist/api/container/routes.js +81 -15
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +8 -6
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/AdminHandler.js +9 -9
- package/dist/api/handlers/AdminHandler.js.map +1 -1
- package/dist/api/handlers/ApiKeyHandler.js +0 -6
- package/dist/api/handlers/ApiKeyHandler.js.map +1 -1
- package/dist/api/handlers/EdgeNodeSignalHandler.d.ts +17 -0
- package/dist/api/handlers/EdgeNodeSignalHandler.js +171 -0
- package/dist/api/handlers/EdgeNodeSignalHandler.js.map +1 -0
- package/dist/api/handlers/PodManagementHandler.d.ts +5 -4
- package/dist/api/handlers/PodManagementHandler.js +11 -10
- package/dist/api/handlers/PodManagementHandler.js.map +1 -1
- package/dist/api/handlers/ProvisionHandler.d.ts +42 -0
- package/dist/api/handlers/ProvisionHandler.js +161 -0
- package/dist/api/handlers/ProvisionHandler.js.map +1 -0
- package/dist/api/handlers/QuotaHandler.d.ts +7 -7
- package/dist/api/handlers/QuotaHandler.js +143 -73
- package/dist/api/handlers/QuotaHandler.js.map +1 -1
- package/dist/api/handlers/SubdomainClientHandler.js +2 -2
- package/dist/api/handlers/SubdomainClientHandler.js.map +1 -1
- package/dist/api/handlers/SubdomainHandler.js +13 -8
- package/dist/api/handlers/SubdomainHandler.js.map +1 -1
- package/dist/api/handlers/UsageHandler.d.ts +14 -0
- package/dist/api/handlers/UsageHandler.js +123 -0
- package/dist/api/handlers/UsageHandler.js.map +1 -0
- package/dist/api/handlers/index.d.ts +3 -1
- package/dist/api/handlers/index.js +3 -1
- package/dist/api/handlers/index.js.map +1 -1
- package/dist/api/main.js +18 -0
- package/dist/api/main.js.map +1 -1
- package/dist/api/middleware/OpenAuthMiddleware.d.ts +12 -0
- package/dist/api/middleware/OpenAuthMiddleware.js +27 -0
- package/dist/api/middleware/OpenAuthMiddleware.js.map +1 -0
- package/dist/api/runtime.d.ts +15 -0
- package/dist/api/runtime.js +104 -0
- package/dist/api/runtime.js.map +1 -0
- package/dist/api/service/VercelChatService.d.ts +16 -7
- package/dist/api/service/VercelChatService.js +98 -178
- package/dist/api/service/VercelChatService.js.map +1 -1
- package/dist/api/store/DrizzleClientCredentialsStore.d.ts +6 -11
- package/dist/api/store/DrizzleClientCredentialsStore.js +9 -39
- package/dist/api/store/DrizzleClientCredentialsStore.js.map +1 -1
- package/dist/authorization/AuthModeSelector.d.ts +10 -0
- package/dist/authorization/AuthModeSelector.js +27 -0
- package/dist/authorization/AuthModeSelector.js.map +1 -0
- package/dist/authorization/AuthModeSelector.jsonld +81 -0
- package/dist/cli/commands/account.d.ts +6 -0
- package/dist/cli/commands/account.js +119 -0
- package/dist/cli/commands/account.js.map +1 -0
- package/dist/cli/commands/auth.js +20 -29
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/backup.d.ts +15 -0
- package/dist/cli/commands/backup.js +286 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/config.d.ts +34 -3
- package/dist/cli/commands/config.js +195 -258
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.js +94 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/pod.d.ts +6 -0
- package/dist/cli/commands/pod.js +124 -0
- package/dist/cli/commands/pod.js.map +1 -0
- package/dist/cli/commands/start.js +28 -5
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/index.js +9 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/credentials-store.d.ts +17 -0
- package/dist/cli/lib/credentials-store.js +73 -0
- package/dist/cli/lib/credentials-store.js.map +1 -0
- package/dist/cli/lib/css-account.d.ts +17 -0
- package/dist/cli/lib/css-account.js +56 -0
- package/dist/cli/lib/css-account.js.map +1 -1
- package/dist/cli/lib/pod-thread-store.d.ts +57 -0
- package/dist/cli/lib/pod-thread-store.js +310 -0
- package/dist/cli/lib/pod-thread-store.js.map +1 -0
- package/dist/cli/lib/solid-auth.d.ts +20 -0
- package/dist/cli/lib/solid-auth.js +70 -0
- package/dist/cli/lib/solid-auth.js.map +1 -0
- package/dist/components/components.jsonld +5 -8
- package/dist/components/context.jsonld +114 -244
- package/dist/edge/EdgeNodeAgent.js +2 -2
- package/dist/edge/EdgeNodeAgent.js.map +1 -1
- package/dist/edge/EdgeNodeDnsCoordinator.d.ts +1 -7
- package/dist/edge/EdgeNodeDnsCoordinator.js +31 -41
- package/dist/edge/EdgeNodeDnsCoordinator.js.map +1 -1
- package/dist/edge/EdgeNodeDnsCoordinator.jsonld +1 -27
- package/dist/edge/EdgeNodeModeDetector.d.ts +1 -1
- package/dist/edge/EdgeNodeModeDetector.js +9 -11
- package/dist/edge/EdgeNodeModeDetector.js.map +1 -1
- package/dist/http/ClusterIngressRouter.js +3 -3
- package/dist/http/ClusterIngressRouter.js.map +1 -1
- package/dist/http/ClusterWebSocketConfigurator.js +2 -2
- package/dist/http/ClusterWebSocketConfigurator.js.map +1 -1
- package/dist/http/PodRoutingHttpHandler.js +2 -2
- package/dist/http/PodRoutingHttpHandler.js.map +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.d.ts +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.js +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.js.map +1 -1
- package/dist/identity/drizzle/EdgeNodeRepository.d.ts +37 -4
- package/dist/identity/drizzle/EdgeNodeRepository.js +120 -128
- package/dist/identity/drizzle/EdgeNodeRepository.js.map +1 -1
- package/dist/identity/drizzle/ServiceTokenRepository.d.ts +52 -0
- package/dist/identity/drizzle/ServiceTokenRepository.js +143 -0
- package/dist/identity/drizzle/ServiceTokenRepository.js.map +1 -0
- package/dist/identity/drizzle/db.d.ts +9 -0
- package/dist/identity/drizzle/db.js +208 -1
- package/dist/identity/drizzle/db.js.map +1 -1
- package/dist/identity/drizzle/schema.pg.d.ts +5 -0
- package/dist/identity/drizzle/schema.pg.js +49 -20
- package/dist/identity/drizzle/schema.pg.js.map +1 -1
- package/dist/identity/drizzle/schema.sqlite.d.ts +332 -57
- package/dist/identity/drizzle/schema.sqlite.js +48 -18
- package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +6 -4
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
- package/dist/index.d.ts +6 -9
- package/dist/index.js +12 -14
- package/dist/index.js.map +1 -1
- package/dist/main.js +25 -8
- package/dist/main.js.map +1 -1
- package/dist/provision/ProvisionCodeCodec.d.ts +39 -0
- package/dist/provision/ProvisionCodeCodec.js +65 -0
- package/dist/provision/ProvisionCodeCodec.js.map +1 -0
- package/dist/provision/ProvisionCodeCodec.jsonld +47 -0
- package/dist/provision/ProvisionPodCreator.d.ts +20 -0
- package/dist/provision/ProvisionPodCreator.js +84 -0
- package/dist/provision/ProvisionPodCreator.js.map +1 -0
- package/dist/provision/ProvisionPodCreator.jsonld +118 -0
- package/dist/quota/DrizzleQuotaService.d.ts +17 -3
- package/dist/quota/DrizzleQuotaService.js +108 -8
- package/dist/quota/DrizzleQuotaService.js.map +1 -1
- package/dist/quota/DrizzleQuotaService.jsonld +33 -22
- package/dist/quota/NoopQuotaService.d.ts +7 -1
- package/dist/quota/NoopQuotaService.js +12 -0
- package/dist/quota/NoopQuotaService.js.map +1 -1
- package/dist/quota/NoopQuotaService.jsonld +24 -0
- package/dist/quota/QuotaService.d.ts +17 -0
- package/dist/quota/QuotaService.js +5 -0
- package/dist/quota/QuotaService.js.map +1 -1
- package/dist/quota/QuotaService.jsonld +50 -0
- package/dist/runtime/Proxy.d.ts +22 -4
- package/dist/runtime/Proxy.js +154 -35
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/runtime/XpodRuntime.d.ts +49 -0
- package/dist/runtime/XpodRuntime.js +374 -0
- package/dist/runtime/XpodRuntime.js.map +1 -0
- package/dist/runtime/env-utils.d.ts +2 -0
- package/dist/runtime/env-utils.js +55 -0
- package/dist/runtime/env-utils.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +8 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/socket-fetch.d.ts +1 -0
- package/dist/runtime/socket-fetch.js +72 -0
- package/dist/runtime/socket-fetch.js.map +1 -0
- package/dist/runtime/socket-http.d.ts +1 -0
- package/dist/runtime/socket-http.js +142 -0
- package/dist/runtime/socket-http.js.map +1 -0
- package/dist/runtime/socket-utils.d.ts +2 -0
- package/dist/runtime/socket-utils.js +34 -0
- package/dist/runtime/socket-utils.js.map +1 -0
- package/dist/service/{EdgeNodeHeartbeatService.d.ts → EdgeNodeSignalClient.d.ts} +3 -3
- package/dist/service/{EdgeNodeHeartbeatService.js → EdgeNodeSignalClient.js} +4 -4
- package/dist/service/EdgeNodeSignalClient.js.map +1 -0
- package/dist/service/PodMigrationService.d.ts +1 -2
- package/dist/service/PodMigrationService.js +1 -2
- package/dist/service/PodMigrationService.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.d.ts +6 -0
- package/dist/storage/accessors/MinioDataAccessor.js +10 -0
- package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.jsonld +4 -0
- package/dist/storage/accessors/MixDataAccessor.d.ts +2 -1
- package/dist/storage/accessors/MixDataAccessor.js +12 -1
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +19 -0
- package/dist/storage/locking/UrlAwareRedisLocker.d.ts +18 -0
- package/dist/storage/locking/UrlAwareRedisLocker.js +60 -0
- package/dist/storage/locking/UrlAwareRedisLocker.js.map +1 -0
- package/dist/storage/locking/UrlAwareRedisLocker.jsonld +123 -0
- package/dist/storage/quota/UsageRepository.d.ts +41 -8
- package/dist/storage/quota/UsageRepository.js +252 -50
- package/dist/storage/quota/UsageRepository.js.map +1 -1
- package/dist/storage/sparql/ComunicaQuintEngine.d.ts +9 -0
- package/dist/storage/sparql/ComunicaQuintEngine.js +50 -9
- package/dist/storage/sparql/ComunicaQuintEngine.js.map +1 -1
- package/dist/storage/sparql/QueryOptimizer.js +13 -1
- package/dist/storage/sparql/QueryOptimizer.js.map +1 -1
- package/dist/storage/sparql/QuintQuerySource.d.ts +14 -0
- package/dist/storage/sparql/QuintQuerySource.js +152 -1
- package/dist/storage/sparql/QuintQuerySource.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -0
- package/dist/storage/sparql/SubgraphQueryEngine.js +6 -2
- package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.jsonld +4 -0
- package/dist/subdomain/SubdomainClient.d.ts +3 -3
- package/dist/subdomain/SubdomainClient.js +1 -1
- package/dist/subdomain/SubdomainClient.js.map +1 -1
- package/dist/subdomain/SubdomainService.d.ts +15 -16
- package/dist/subdomain/SubdomainService.js +80 -54
- package/dist/subdomain/SubdomainService.js.map +1 -1
- package/dist/subdomain/SubdomainService.jsonld +22 -26
- package/dist/supervisor/Supervisor.d.ts +7 -2
- package/dist/supervisor/Supervisor.js +33 -1
- package/dist/supervisor/Supervisor.js.map +1 -1
- package/dist/test-utils/index.d.ts +4 -0
- package/dist/test-utils/index.js +8 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/no-auth-xpod.d.ts +11 -0
- package/dist/test-utils/no-auth-xpod.js +25 -0
- package/dist/test-utils/no-auth-xpod.js.map +1 -0
- package/dist/test-utils/seed-pod.d.ts +5 -0
- package/dist/test-utils/seed-pod.js +61 -0
- package/dist/test-utils/seed-pod.js.map +1 -0
- package/package.json +23 -5
- package/templates/identity/account/create-pod.html.ejs +110 -0
- package/templates/main.html.ejs +10 -0
- package/dist/api/handlers/DevHandler.d.ts +0 -18
- package/dist/api/handlers/DevHandler.js +0 -276
- package/dist/api/handlers/DevHandler.js.map +0 -1
- package/dist/api/handlers/SignalHandler.d.ts +0 -13
- package/dist/api/handlers/SignalHandler.js +0 -122
- package/dist/api/handlers/SignalHandler.js.map +0 -1
- package/dist/gateway/Proxy.d.ts +0 -24
- package/dist/gateway/Proxy.js +0 -209
- package/dist/gateway/Proxy.js.map +0 -1
- package/dist/gateway/Supervisor.d.ts +0 -2
- package/dist/gateway/Supervisor.js +0 -7
- package/dist/gateway/Supervisor.js.map +0 -1
- package/dist/gateway/port-finder.d.ts +0 -4
- package/dist/gateway/port-finder.js +0 -15
- package/dist/gateway/port-finder.js.map +0 -1
- package/dist/gateway/types.d.ts +0 -1
- package/dist/gateway/types.js +0 -3
- package/dist/gateway/types.js.map +0 -1
- package/dist/http/SignalInterceptHttpHandler.d.ts +0 -24
- package/dist/http/SignalInterceptHttpHandler.js +0 -47
- package/dist/http/SignalInterceptHttpHandler.js.map +0 -1
- package/dist/http/SignalInterceptHttpHandler.jsonld +0 -103
- package/dist/http/admin/EdgeNodeSignalHttpHandler.d.ts +0 -71
- package/dist/http/admin/EdgeNodeSignalHttpHandler.js +0 -674
- package/dist/http/admin/EdgeNodeSignalHttpHandler.js.map +0 -1
- package/dist/http/admin/EdgeNodeSignalHttpHandler.jsonld +0 -406
- package/dist/http/cluster/PodMigrationHttpHandler.jsonld +0 -169
- package/dist/quota/DefaultQuotaService.d.ts +0 -16
- package/dist/quota/DefaultQuotaService.js +0 -37
- package/dist/quota/DefaultQuotaService.js.map +0 -1
- package/dist/quota/DefaultQuotaService.jsonld +0 -85
- package/dist/service/EdgeNodeHeartbeatService.js.map +0 -1
- package/dist/service/PodMigrationService.jsonld +0 -76
- package/dist/storage/MigratableDataAccessor.d.ts +0 -63
- package/dist/storage/MigratableDataAccessor.js +0 -11
- package/dist/storage/MigratableDataAccessor.js.map +0 -1
- package/dist/storage/MigratableDataAccessor.jsonld +0 -60
- package/dist/storage/accessors/TieredMinioDataAccessor.d.ts +0 -150
- package/dist/storage/accessors/TieredMinioDataAccessor.js +0 -582
- package/dist/storage/accessors/TieredMinioDataAccessor.js.map +0 -1
- package/dist/storage/accessors/TieredMinioDataAccessor.jsonld +0 -333
- package/static/app/assets/index.css +0 -1
- package/static/app/assets/main.js +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubdomainClientHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/SubdomainClientHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SubdomainClientHandler - Local 模式子域名 API\n * \n * 代理请求到 Cloud API,供本地 UI 调用\n */\n\nimport type { ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { ApiServer } from '../ApiServer';\nimport type { SubdomainClient } from '../../subdomain/SubdomainClient';\n\nexport interface SubdomainClientHandlerOptions {\n subdomainClient: SubdomainClient;\n}\n\n/**\n * 注册 Local 模式子域名路由\n * \n * 这些路由是本地 UI 调用的入口,内部通过 SubdomainClient 转发到 Cloud\n * \n * GET /v1/subdomain/check?name=xxx - 检查子域名可用性\n * GET /v1/subdomain - 列出子域名\n * GET /v1/subdomain/:name - 获取子域名详情\n * POST /v1/subdomain/register - 注册子域名\n * DELETE /v1/subdomain/:name - 释放子域名\n * POST /v1/subdomain/:name/start - 启动隧道\n * POST /v1/subdomain/:name/stop - 停止隧道\n */\nexport function registerSubdomainClientRoutes(\n server: ApiServer,\n options: SubdomainClientHandlerOptions,\n): void {\n const logger = getLoggerFor('SubdomainClientHandler');\n const client = options.subdomainClient;\n\n // GET /v1/subdomain/check?name=xxx - 检查可用性 (public)\n server.get('/v1/subdomain/check', async (request, response, _params) => {\n const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);\n const name = url.searchParams.get('name');\n\n if (!name) {\n sendJson(response, 400, { error: 'Missing \"name\" query parameter' });\n return;\n }\n\n try {\n const result = await client.checkAvailability(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to check availability: ${error}`);\n sendErrorJson(response, error);\n }\n }, { public: true });\n\n // GET /v1/subdomain - 列出子域名\n server.get('/v1/subdomain', async (_request, response, _params) => {\n try {\n const result = await client.list();\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to list subdomains: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // GET /v1/subdomain/:name - 获取子域名详情\n server.get('/v1/subdomain/:name', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.getInfo(name);\n if (!result) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to get subdomain info: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // POST /v1/subdomain/register - 注册子域名\n server.post('/v1/subdomain/register', async (request, response, _params) => {\n const body = await readJsonBody(request);\n \n if (!body || typeof body !== 'object') {\n sendJson(response, 400, { error: 'Invalid request body' });\n return;\n }\n\n const { subdomain, localPort, publicIp } = body as Record<string, unknown>;\n\n if (!subdomain || typeof subdomain !== 'string') {\n sendJson(response, 400, { error: 'Missing \"subdomain\" field' });\n return;\n }\n\n if (!localPort || typeof localPort !== 'number') {\n sendJson(response, 400, { error: 'Missing or invalid \"localPort\" field' });\n return;\n }\n\n try {\n const result = await client.register({\n subdomain,\n localPort,\n publicIp: typeof publicIp === 'string' ? publicIp : undefined,\n });\n sendJson(response, 201, result);\n } catch (error) {\n logger.error(`Failed to register subdomain: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // DELETE /v1/subdomain/:name - 释放子域名\n server.delete('/v1/subdomain/:name', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.release(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to release subdomain: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // POST /v1/subdomain/:name/start - 启动隧道\n server.post('/v1/subdomain/:name/start', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.startTunnel(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to start tunnel: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // POST /v1/subdomain/:name/stop - 停止隧道\n server.post('/v1/subdomain/:name/stop', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.stopTunnel(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to stop tunnel: ${error}`);\n sendErrorJson(response, error);\n }\n });\n}\n\n// ============ Helper Functions ============\n\nasync function readJsonBody(request: AuthenticatedRequest): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n request.setEncoding('utf8');\n request.on('data', (chunk: string) => {\n data += chunk;\n });\n request.on('end', () => {\n if (!data) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(undefined);\n }\n });\n request.on('error', reject);\n });\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction sendErrorJson(response: ServerResponse, error: unknown): void {\n const status = (error as any)?.status ?? 500;\n const message = error instanceof Error ? error.message : 'Unknown error';\n sendJson(response, status, { error: message });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SubdomainClientHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/SubdomainClientHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SubdomainClientHandler - Local 模式子域名 API\n * \n * 代理请求到 Cloud API,供本地 UI 调用\n */\n\nimport type { ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { ApiServer } from '../ApiServer';\nimport type { SubdomainClient } from '../../subdomain/SubdomainClient';\n\nexport interface SubdomainClientHandlerOptions {\n subdomainClient: SubdomainClient;\n}\n\n/**\n * 注册 Local 模式子域名路由\n * \n * 这些路由是本地 UI 调用的入口,内部通过 SubdomainClient 转发到 Cloud\n * \n * GET /v1/subdomain/check?name=xxx - 检查子域名可用性\n * GET /v1/subdomain - 列出子域名\n * GET /v1/subdomain/:name - 获取子域名详情\n * POST /v1/subdomain/register - 注册子域名\n * DELETE /v1/subdomain/:name - 释放子域名\n * POST /v1/subdomain/:name/start - 启动隧道\n * POST /v1/subdomain/:name/stop - 停止隧道\n */\nexport function registerSubdomainClientRoutes(\n server: ApiServer,\n options: SubdomainClientHandlerOptions,\n): void {\n const logger = getLoggerFor('SubdomainClientHandler');\n const client = options.subdomainClient;\n\n // GET /v1/subdomain/check?name=xxx - 检查可用性 (public)\n server.get('/v1/subdomain/check', async (request, response, _params) => {\n const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);\n const name = url.searchParams.get('name');\n\n if (!name) {\n sendJson(response, 400, { error: 'Missing \"name\" query parameter' });\n return;\n }\n\n try {\n const result = await client.checkAvailability(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to check availability: ${error}`);\n sendErrorJson(response, error);\n }\n }, { public: true });\n\n // GET /v1/subdomain - 列出子域名\n server.get('/v1/subdomain', async (_request, response, _params) => {\n try {\n const result = await client.list();\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to list subdomains: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // GET /v1/subdomain/:name - 获取子域名详情\n server.get('/v1/subdomain/:name', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.getInfo(name);\n if (!result) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to get subdomain info: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // POST /v1/subdomain/register - 注册子域名\n server.post('/v1/subdomain/register', async (request, response, _params) => {\n const body = await readJsonBody(request);\n \n if (!body || typeof body !== 'object') {\n sendJson(response, 400, { error: 'Invalid request body' });\n return;\n }\n\n const { subdomain, localPort, ipv4 } = body as Record<string, unknown>;\n\n if (!subdomain || typeof subdomain !== 'string') {\n sendJson(response, 400, { error: 'Missing \"subdomain\" field' });\n return;\n }\n\n if (!localPort || typeof localPort !== 'number') {\n sendJson(response, 400, { error: 'Missing or invalid \"localPort\" field' });\n return;\n }\n\n try {\n const result = await client.register({\n subdomain,\n localPort,\n ipv4: typeof ipv4 === 'string' ? ipv4 : undefined,\n });\n sendJson(response, 201, result);\n } catch (error) {\n logger.error(`Failed to register subdomain: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // DELETE /v1/subdomain/:name - 释放子域名\n server.delete('/v1/subdomain/:name', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.release(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to release subdomain: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // POST /v1/subdomain/:name/start - 启动隧道\n server.post('/v1/subdomain/:name/start', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.startTunnel(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to start tunnel: ${error}`);\n sendErrorJson(response, error);\n }\n });\n\n // POST /v1/subdomain/:name/stop - 停止隧道\n server.post('/v1/subdomain/:name/stop', async (_request, response, params) => {\n const name = decodeURIComponent(params.name);\n\n try {\n const result = await client.stopTunnel(name);\n sendJson(response, 200, result);\n } catch (error) {\n logger.error(`Failed to stop tunnel: ${error}`);\n sendErrorJson(response, error);\n }\n });\n}\n\n// ============ Helper Functions ============\n\nasync function readJsonBody(request: AuthenticatedRequest): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n request.setEncoding('utf8');\n request.on('data', (chunk: string) => {\n data += chunk;\n });\n request.on('end', () => {\n if (!data) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(undefined);\n }\n });\n request.on('error', reject);\n });\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction sendErrorJson(response: ServerResponse, error: unknown): void {\n const status = (error as any)?.status ?? 500;\n const message = error instanceof Error ? error.message : 'Unknown error';\n sendJson(response, status, { error: message });\n}\n"]}
|
|
@@ -60,7 +60,7 @@ function registerSubdomainRoutes(server, options) {
|
|
|
60
60
|
}
|
|
61
61
|
try {
|
|
62
62
|
// Filter registrations by owner
|
|
63
|
-
const allRegistrations = service.getAllRegistrations();
|
|
63
|
+
const allRegistrations = await service.getAllRegistrations();
|
|
64
64
|
const userRegistrations = allRegistrations.filter(r => r.ownerId === webId);
|
|
65
65
|
sendJson(response, 200, {
|
|
66
66
|
registrations: userRegistrations.map(formatRegistration),
|
|
@@ -86,7 +86,7 @@ function registerSubdomainRoutes(server, options) {
|
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
88
|
try {
|
|
89
|
-
const registration = service.getRegistration(name);
|
|
89
|
+
const registration = await service.getRegistration(name);
|
|
90
90
|
if (!registration) {
|
|
91
91
|
sendJson(response, 404, { error: 'Subdomain not found' });
|
|
92
92
|
return;
|
|
@@ -122,11 +122,15 @@ function registerSubdomainRoutes(server, options) {
|
|
|
122
122
|
sendJson(response, 400, { error: 'Invalid request body' });
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
|
-
const { subdomain, localPort,
|
|
125
|
+
const { subdomain, nodeId, localPort, ipv4 } = body;
|
|
126
126
|
if (!subdomain || typeof subdomain !== 'string') {
|
|
127
127
|
sendJson(response, 400, { error: 'Missing "subdomain" field' });
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
|
+
if (!nodeId || typeof nodeId !== 'string') {
|
|
131
|
+
sendJson(response, 400, { error: 'Missing "nodeId" field' });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
130
134
|
if (!localPort || typeof localPort !== 'number') {
|
|
131
135
|
sendJson(response, 400, { error: 'Missing or invalid "localPort" field' });
|
|
132
136
|
return;
|
|
@@ -134,8 +138,9 @@ function registerSubdomainRoutes(server, options) {
|
|
|
134
138
|
try {
|
|
135
139
|
const registration = await service.register({
|
|
136
140
|
subdomain,
|
|
141
|
+
nodeId,
|
|
137
142
|
localPort,
|
|
138
|
-
|
|
143
|
+
ipv4: typeof ipv4 === 'string' ? ipv4 : undefined,
|
|
139
144
|
ownerId: webId,
|
|
140
145
|
});
|
|
141
146
|
logger.info(`Registered subdomain: ${registration.fullDomain} for ${webId} (mode: ${registration.mode})`);
|
|
@@ -168,7 +173,7 @@ function registerSubdomainRoutes(server, options) {
|
|
|
168
173
|
return;
|
|
169
174
|
}
|
|
170
175
|
try {
|
|
171
|
-
const registration = service.getRegistration(name);
|
|
176
|
+
const registration = await service.getRegistration(name);
|
|
172
177
|
if (!registration) {
|
|
173
178
|
sendJson(response, 404, { error: 'Subdomain not found' });
|
|
174
179
|
return;
|
|
@@ -205,7 +210,7 @@ function registerSubdomainRoutes(server, options) {
|
|
|
205
210
|
return;
|
|
206
211
|
}
|
|
207
212
|
try {
|
|
208
|
-
const registration = service.getRegistration(name);
|
|
213
|
+
const registration = await service.getRegistration(name);
|
|
209
214
|
if (!registration) {
|
|
210
215
|
sendJson(response, 404, { error: 'Subdomain not found' });
|
|
211
216
|
return;
|
|
@@ -246,7 +251,7 @@ function registerSubdomainRoutes(server, options) {
|
|
|
246
251
|
return;
|
|
247
252
|
}
|
|
248
253
|
try {
|
|
249
|
-
const registration = service.getRegistration(name);
|
|
254
|
+
const registration = await service.getRegistration(name);
|
|
250
255
|
if (!registration) {
|
|
251
256
|
sendJson(response, 404, { error: 'Subdomain not found' });
|
|
252
257
|
return;
|
|
@@ -275,7 +280,7 @@ function formatRegistration(reg) {
|
|
|
275
280
|
subdomain: reg.subdomain,
|
|
276
281
|
fullDomain: reg.fullDomain,
|
|
277
282
|
mode: reg.mode,
|
|
278
|
-
|
|
283
|
+
ipv4: reg.ipv4,
|
|
279
284
|
tunnelProvider: reg.tunnelConfig?.provider,
|
|
280
285
|
tunnelEndpoint: reg.tunnelConfig?.endpoint,
|
|
281
286
|
registeredAt: reg.registeredAt.toISOString(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubdomainHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/SubdomainHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { ApiServer } from '../ApiServer';\nimport type { SubdomainService, SubdomainRegistration } from '../../subdomain/SubdomainService';\nimport { getWebId, isSolidAuth } from '../auth/AuthContext';\n\nexport interface SubdomainHandlerOptions {\n subdomainService: SubdomainService;\n}\n\n/**\n * Handler for subdomain management API\n *\n * GET /v1/subdomain/check?name=xxx - Check subdomain availability (public)\n * GET /v1/subdomain - List user's subdomain registrations\n * GET /v1/subdomain/:name - Get subdomain info\n * POST /v1/subdomain/register - Register a new subdomain\n * DELETE /v1/subdomain/:name - Release a subdomain\n * POST /v1/subdomain/:name/start - Start tunnel\n * POST /v1/subdomain/:name/stop - Stop tunnel\n */\nexport function registerSubdomainRoutes(server: ApiServer, options: SubdomainHandlerOptions): void {\n const logger = getLoggerFor('SubdomainHandler');\n const service = options.subdomainService;\n\n const rejectApiKey = (request: AuthenticatedRequest, response: ServerResponse): boolean => {\n const auth = request.auth;\n if (auth && isSolidAuth(auth) && auth.viaApiKey) {\n sendJson(response, 403, { error: 'API key is not allowed for this endpoint' });\n return true;\n }\n return false;\n };\n\n // GET /v1/subdomain/check?name=xxx - Check availability (public)\n server.get('/v1/subdomain/check', async (request, response, _params) => {\n const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);\n const name = url.searchParams.get('name');\n\n if (!name) {\n sendJson(response, 400, { error: 'Missing \"name\" query parameter' });\n return;\n }\n\n try {\n const result = await service.checkAvailability(name);\n sendJson(response, 200, {\n subdomain: name,\n available: result.available,\n reason: result.reason,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to check availability: ${error}`);\n sendJson(response, 500, { error: 'Failed to check availability' });\n }\n }, { public: true });\n\n // GET /v1/subdomain - List user's registrations\n server.get('/v1/subdomain', async (request, response, _params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n // Filter registrations by owner\n const allRegistrations = service.getAllRegistrations();\n const userRegistrations = allRegistrations.filter(r => r.ownerId === webId);\n\n sendJson(response, 200, {\n registrations: userRegistrations.map(formatRegistration),\n total: userRegistrations.length,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to list registrations: ${error}`);\n sendJson(response, 500, { error: 'Failed to list registrations' });\n }\n });\n\n // GET /v1/subdomain/:name - Get subdomain info\n server.get('/v1/subdomain/:name', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = service.getRegistration(name);\n \n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n // Check ownership\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n sendJson(response, 200, {\n ...formatRegistration(registration),\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to get registration: ${error}`);\n sendJson(response, 500, { error: 'Failed to get registration' });\n }\n });\n\n // POST /v1/subdomain/register - Register a new subdomain\n server.post('/v1/subdomain/register', async (request, response, _params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n const body = await readJsonBody(request);\n if (!body || typeof body !== 'object') {\n sendJson(response, 400, { error: 'Invalid request body' });\n return;\n }\n\n const { subdomain, localPort, publicIp } = body as Record<string, unknown>;\n\n if (!subdomain || typeof subdomain !== 'string') {\n sendJson(response, 400, { error: 'Missing \"subdomain\" field' });\n return;\n }\n\n if (!localPort || typeof localPort !== 'number') {\n sendJson(response, 400, { error: 'Missing or invalid \"localPort\" field' });\n return;\n }\n\n try {\n const registration = await service.register({\n subdomain,\n localPort,\n publicIp: typeof publicIp === 'string' ? publicIp : undefined,\n ownerId: webId,\n });\n\n logger.info(`Registered subdomain: ${registration.fullDomain} for ${webId} (mode: ${registration.mode})`);\n\n sendJson(response, 201, {\n success: true,\n ...formatRegistration(registration),\n message: `Subdomain registered successfully in ${registration.mode} mode.`,\n });\n } catch (error) {\n logger.error(`Failed to register subdomain: ${error}`);\n if (error instanceof Error) {\n sendJson(response, 400, { error: error.message });\n } else {\n sendJson(response, 500, { error: 'Failed to register subdomain' });\n }\n }\n });\n\n // DELETE /v1/subdomain/:name - Release a subdomain\n server.delete('/v1/subdomain/:name', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = service.getRegistration(name);\n \n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n // Check ownership\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n await service.release(name);\n\n logger.info(`Released subdomain: ${name} by ${webId}`);\n sendJson(response, 200, {\n success: true,\n subdomain: name,\n message: 'Subdomain released successfully.',\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to release subdomain: ${error}`);\n sendJson(response, 500, { error: 'Failed to release subdomain' });\n }\n });\n\n // POST /v1/subdomain/:name/start - Start tunnel\n server.post('/v1/subdomain/:name/start', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = service.getRegistration(name);\n \n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n await service.startTunnel(name);\n\n logger.info(`Started tunnel for subdomain: ${name}`);\n sendJson(response, 200, {\n success: true,\n subdomain: name,\n message: 'Tunnel started successfully.',\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to start tunnel: ${error}`);\n if (error instanceof Error) {\n sendJson(response, 400, { error: error.message });\n } else {\n sendJson(response, 500, { error: 'Failed to start tunnel' });\n }\n }\n });\n\n // POST /v1/subdomain/:name/stop - Stop tunnel\n server.post('/v1/subdomain/:name/stop', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = service.getRegistration(name);\n \n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n await service.stopTunnel();\n\n logger.info(`Stopped tunnel for subdomain: ${name}`);\n sendJson(response, 200, {\n success: true,\n subdomain: name,\n message: 'Tunnel stopped successfully.',\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to stop tunnel: ${error}`);\n sendJson(response, 500, { error: 'Failed to stop tunnel' });\n }\n });\n}\n\nfunction formatRegistration(reg: SubdomainRegistration): Record<string, unknown> {\n return {\n subdomain: reg.subdomain,\n fullDomain: reg.fullDomain,\n mode: reg.mode,\n publicIp: reg.publicIp,\n tunnelProvider: reg.tunnelConfig?.provider,\n tunnelEndpoint: reg.tunnelConfig?.endpoint,\n registeredAt: reg.registeredAt.toISOString(),\n ownerId: reg.ownerId,\n };\n}\n\nasync function readJsonBody(request: AuthenticatedRequest): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n request.setEncoding('utf8');\n request.on('data', (chunk: string) => {\n data += chunk;\n });\n request.on('end', () => {\n if (!data) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(undefined);\n }\n });\n request.on('error', reject);\n });\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SubdomainHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/SubdomainHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { ApiServer } from '../ApiServer';\nimport type { SubdomainService, SubdomainRegistration } from '../../subdomain/SubdomainService';\nimport { getWebId, isSolidAuth } from '../auth/AuthContext';\n\nexport interface SubdomainHandlerOptions {\n subdomainService: SubdomainService;\n}\n\n/**\n * Handler for subdomain management API\n *\n * GET /v1/subdomain/check?name=xxx - Check subdomain availability (public)\n * GET /v1/subdomain - List user's subdomain registrations\n * GET /v1/subdomain/:name - Get subdomain info\n * POST /v1/subdomain/register - Register a new subdomain\n * DELETE /v1/subdomain/:name - Release a subdomain\n * POST /v1/subdomain/:name/start - Start tunnel\n * POST /v1/subdomain/:name/stop - Stop tunnel\n */\nexport function registerSubdomainRoutes(server: ApiServer, options: SubdomainHandlerOptions): void {\n const logger = getLoggerFor('SubdomainHandler');\n const service = options.subdomainService;\n\n const rejectApiKey = (request: AuthenticatedRequest, response: ServerResponse): boolean => {\n const auth = request.auth;\n if (auth && isSolidAuth(auth) && auth.viaApiKey) {\n sendJson(response, 403, { error: 'API key is not allowed for this endpoint' });\n return true;\n }\n return false;\n };\n\n // GET /v1/subdomain/check?name=xxx - Check availability (public)\n server.get('/v1/subdomain/check', async (request, response, _params) => {\n const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);\n const name = url.searchParams.get('name');\n\n if (!name) {\n sendJson(response, 400, { error: 'Missing \"name\" query parameter' });\n return;\n }\n\n try {\n const result = await service.checkAvailability(name);\n sendJson(response, 200, {\n subdomain: name,\n available: result.available,\n reason: result.reason,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to check availability: ${error}`);\n sendJson(response, 500, { error: 'Failed to check availability' });\n }\n }, { public: true });\n\n // GET /v1/subdomain - List user's registrations\n server.get('/v1/subdomain', async (request, response, _params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n // Filter registrations by owner\n const allRegistrations = await service.getAllRegistrations();\n const userRegistrations = allRegistrations.filter(r => r.ownerId === webId);\n\n sendJson(response, 200, {\n registrations: userRegistrations.map(formatRegistration),\n total: userRegistrations.length,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to list registrations: ${error}`);\n sendJson(response, 500, { error: 'Failed to list registrations' });\n }\n });\n\n // GET /v1/subdomain/:name - Get subdomain info\n server.get('/v1/subdomain/:name', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = await service.getRegistration(name);\n\n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n // Check ownership\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n sendJson(response, 200, {\n ...formatRegistration(registration),\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to get registration: ${error}`);\n sendJson(response, 500, { error: 'Failed to get registration' });\n }\n });\n\n // POST /v1/subdomain/register - Register a new subdomain\n server.post('/v1/subdomain/register', async (request, response, _params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n const body = await readJsonBody(request);\n if (!body || typeof body !== 'object') {\n sendJson(response, 400, { error: 'Invalid request body' });\n return;\n }\n\n const { subdomain, nodeId, localPort, ipv4 } = body as Record<string, unknown>;\n\n if (!subdomain || typeof subdomain !== 'string') {\n sendJson(response, 400, { error: 'Missing \"subdomain\" field' });\n return;\n }\n\n if (!nodeId || typeof nodeId !== 'string') {\n sendJson(response, 400, { error: 'Missing \"nodeId\" field' });\n return;\n }\n\n if (!localPort || typeof localPort !== 'number') {\n sendJson(response, 400, { error: 'Missing or invalid \"localPort\" field' });\n return;\n }\n\n try {\n const registration = await service.register({\n subdomain,\n nodeId,\n localPort,\n ipv4: typeof ipv4 === 'string' ? ipv4 : undefined,\n ownerId: webId,\n });\n\n logger.info(`Registered subdomain: ${registration.fullDomain} for ${webId} (mode: ${registration.mode})`);\n\n sendJson(response, 201, {\n success: true,\n ...formatRegistration(registration),\n message: `Subdomain registered successfully in ${registration.mode} mode.`,\n });\n } catch (error) {\n logger.error(`Failed to register subdomain: ${error}`);\n if (error instanceof Error) {\n sendJson(response, 400, { error: error.message });\n } else {\n sendJson(response, 500, { error: 'Failed to register subdomain' });\n }\n }\n });\n\n // DELETE /v1/subdomain/:name - Release a subdomain\n server.delete('/v1/subdomain/:name', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = await service.getRegistration(name);\n\n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n // Check ownership\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n await service.release(name);\n\n logger.info(`Released subdomain: ${name} by ${webId}`);\n sendJson(response, 200, {\n success: true,\n subdomain: name,\n message: 'Subdomain released successfully.',\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to release subdomain: ${error}`);\n sendJson(response, 500, { error: 'Failed to release subdomain' });\n }\n });\n\n // POST /v1/subdomain/:name/start - Start tunnel\n server.post('/v1/subdomain/:name/start', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = await service.getRegistration(name);\n\n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n await service.startTunnel(name);\n\n logger.info(`Started tunnel for subdomain: ${name}`);\n sendJson(response, 200, {\n success: true,\n subdomain: name,\n message: 'Tunnel started successfully.',\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to start tunnel: ${error}`);\n if (error instanceof Error) {\n sendJson(response, 400, { error: error.message });\n } else {\n sendJson(response, 500, { error: 'Failed to start tunnel' });\n }\n }\n });\n\n // POST /v1/subdomain/:name/stop - Stop tunnel\n server.post('/v1/subdomain/:name/stop', async (request, response, params) => {\n if (rejectApiKey(request, response)) {\n return;\n }\n const auth = request.auth!;\n const webId = getWebId(auth);\n const name = decodeURIComponent(params.name);\n\n if (!webId) {\n sendJson(response, 400, { error: 'Cannot determine user' });\n return;\n }\n\n try {\n const registration = await service.getRegistration(name);\n\n if (!registration) {\n sendJson(response, 404, { error: 'Subdomain not found' });\n return;\n }\n\n if (registration.ownerId !== webId) {\n sendJson(response, 403, { error: 'Access denied' });\n return;\n }\n\n await service.stopTunnel();\n\n logger.info(`Stopped tunnel for subdomain: ${name}`);\n sendJson(response, 200, {\n success: true,\n subdomain: name,\n message: 'Tunnel stopped successfully.',\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to stop tunnel: ${error}`);\n sendJson(response, 500, { error: 'Failed to stop tunnel' });\n }\n });\n}\n\nfunction formatRegistration(reg: SubdomainRegistration): Record<string, unknown> {\n return {\n subdomain: reg.subdomain,\n fullDomain: reg.fullDomain,\n mode: reg.mode,\n ipv4: reg.ipv4,\n tunnelProvider: reg.tunnelConfig?.provider,\n tunnelEndpoint: reg.tunnelConfig?.endpoint,\n registeredAt: reg.registeredAt.toISOString(),\n ownerId: reg.ownerId,\n };\n}\n\nasync function readJsonBody(request: AuthenticatedRequest): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n request.setEncoding('utf8');\n request.on('data', (chunk: string) => {\n data += chunk;\n });\n request.on('end', () => {\n if (!data) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(undefined);\n }\n });\n request.on('error', reject);\n });\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ApiServer } from '../ApiServer';
|
|
2
|
+
import type { UsageRepository } from '../../storage/quota/UsageRepository';
|
|
3
|
+
export interface UsageHandlerOptions {
|
|
4
|
+
usageRepo: UsageRepository;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Handler for usage query API
|
|
8
|
+
*
|
|
9
|
+
* Requires ServiceAuthContext with 'usage:read' scope.
|
|
10
|
+
*
|
|
11
|
+
* GET /v1/usage/accounts/:accountId - Get account usage details
|
|
12
|
+
* GET /v1/usage/pods/:podId - Get pod usage details
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerUsageRoutes(server: ApiServer, options: UsageHandlerOptions): void;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerUsageRoutes = registerUsageRoutes;
|
|
4
|
+
const global_logger_factory_1 = require("global-logger-factory");
|
|
5
|
+
const AuthContext_1 = require("../auth/AuthContext");
|
|
6
|
+
/**
|
|
7
|
+
* Handler for usage query API
|
|
8
|
+
*
|
|
9
|
+
* Requires ServiceAuthContext with 'usage:read' scope.
|
|
10
|
+
*
|
|
11
|
+
* GET /v1/usage/accounts/:accountId - Get account usage details
|
|
12
|
+
* GET /v1/usage/pods/:podId - Get pod usage details
|
|
13
|
+
*/
|
|
14
|
+
function registerUsageRoutes(server, options) {
|
|
15
|
+
const logger = (0, global_logger_factory_1.getLoggerFor)('UsageHandler');
|
|
16
|
+
const { usageRepo } = options;
|
|
17
|
+
// GET /v1/usage/accounts/:accountId
|
|
18
|
+
server.get('/v1/usage/accounts/:accountId', async (request, response, params) => {
|
|
19
|
+
if (!requireUsageRead(request, response)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const accountId = decodeURIComponent(params.accountId);
|
|
23
|
+
try {
|
|
24
|
+
const usage = await usageRepo.getAccountUsage(accountId);
|
|
25
|
+
if (!usage) {
|
|
26
|
+
sendJson(response, 200, {
|
|
27
|
+
accountId,
|
|
28
|
+
usage: {
|
|
29
|
+
storageBytes: 0,
|
|
30
|
+
ingressBytes: 0,
|
|
31
|
+
egressBytes: 0,
|
|
32
|
+
computeSeconds: 0,
|
|
33
|
+
tokensUsed: 0,
|
|
34
|
+
periodStart: null,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
sendJson(response, 200, {
|
|
40
|
+
accountId,
|
|
41
|
+
usage: {
|
|
42
|
+
storageBytes: usage.storageBytes,
|
|
43
|
+
ingressBytes: usage.ingressBytes,
|
|
44
|
+
egressBytes: usage.egressBytes,
|
|
45
|
+
computeSeconds: usage.computeSeconds,
|
|
46
|
+
tokensUsed: usage.tokensUsed,
|
|
47
|
+
periodStart: usage.periodStart ? new Date(usage.periodStart * 1000).toISOString() : null,
|
|
48
|
+
},
|
|
49
|
+
limits: {
|
|
50
|
+
storageLimitBytes: usage.storageLimitBytes ?? null,
|
|
51
|
+
bandwidthLimitBps: usage.bandwidthLimitBps ?? null,
|
|
52
|
+
computeLimitSeconds: usage.computeLimitSeconds ?? null,
|
|
53
|
+
tokenLimitMonthly: usage.tokenLimitMonthly ?? null,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
logger.error(`Failed to get account usage: ${error}`);
|
|
59
|
+
sendJson(response, 500, { error: 'Failed to get usage' });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// GET /v1/usage/pods/:podId
|
|
63
|
+
server.get('/v1/usage/pods/:podId', async (request, response, params) => {
|
|
64
|
+
if (!requireUsageRead(request, response)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const podId = decodeURIComponent(params.podId);
|
|
68
|
+
try {
|
|
69
|
+
const usage = await usageRepo.getPodUsage(podId);
|
|
70
|
+
if (!usage) {
|
|
71
|
+
sendJson(response, 404, { error: 'Pod usage not found' });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
sendJson(response, 200, {
|
|
75
|
+
podId,
|
|
76
|
+
accountId: usage.accountId,
|
|
77
|
+
usage: {
|
|
78
|
+
storageBytes: usage.storageBytes,
|
|
79
|
+
ingressBytes: usage.ingressBytes,
|
|
80
|
+
egressBytes: usage.egressBytes,
|
|
81
|
+
computeSeconds: usage.computeSeconds,
|
|
82
|
+
tokensUsed: usage.tokensUsed,
|
|
83
|
+
periodStart: usage.periodStart ? new Date(usage.periodStart * 1000).toISOString() : null,
|
|
84
|
+
},
|
|
85
|
+
limits: {
|
|
86
|
+
storageLimitBytes: usage.storageLimitBytes ?? null,
|
|
87
|
+
bandwidthLimitBps: usage.bandwidthLimitBps ?? null,
|
|
88
|
+
computeLimitSeconds: usage.computeLimitSeconds ?? null,
|
|
89
|
+
tokenLimitMonthly: usage.tokenLimitMonthly ?? null,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
logger.error(`Failed to get pod usage: ${error}`);
|
|
95
|
+
sendJson(response, 500, { error: 'Failed to get usage' });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function requireUsageRead(request, response) {
|
|
100
|
+
if (!request.auth) {
|
|
101
|
+
sendJson(response, 401, { error: 'Authentication required' });
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (request.auth.type === 'service') {
|
|
105
|
+
if (!(0, AuthContext_1.hasScope)(request.auth, 'usage:read')) {
|
|
106
|
+
sendJson(response, 403, { error: 'Missing required scope: usage:read' });
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
// Allow Solid auth (for admin/user self-query)
|
|
112
|
+
if (request.auth.type === 'solid') {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
sendJson(response, 403, { error: 'Insufficient permissions' });
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
function sendJson(response, status, data) {
|
|
119
|
+
response.statusCode = status;
|
|
120
|
+
response.setHeader('Content-Type', 'application/json');
|
|
121
|
+
response.end(JSON.stringify(data));
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=UsageHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UsageHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/UsageHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { ApiServer } from '../ApiServer';\nimport type { UsageRepository } from '../../storage/quota/UsageRepository';\nimport { hasScope } from '../auth/AuthContext';\n\nexport interface UsageHandlerOptions {\n usageRepo: UsageRepository;\n}\n\n/**\n * Handler for usage query API\n *\n * Requires ServiceAuthContext with 'usage:read' scope.\n *\n * GET /v1/usage/accounts/:accountId - Get account usage details\n * GET /v1/usage/pods/:podId - Get pod usage details\n */\nexport function registerUsageRoutes(server: ApiServer, options: UsageHandlerOptions): void {\n const logger = getLoggerFor('UsageHandler');\n const { usageRepo } = options;\n\n // GET /v1/usage/accounts/:accountId\n server.get('/v1/usage/accounts/:accountId', async (request, response, params) => {\n if (!requireUsageRead(request, response)) {\n return;\n }\n\n const accountId = decodeURIComponent(params.accountId);\n\n try {\n const usage = await usageRepo.getAccountUsage(accountId);\n if (!usage) {\n sendJson(response, 200, {\n accountId,\n usage: {\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n computeSeconds: 0,\n tokensUsed: 0,\n periodStart: null,\n },\n });\n return;\n }\n\n sendJson(response, 200, {\n accountId,\n usage: {\n storageBytes: usage.storageBytes,\n ingressBytes: usage.ingressBytes,\n egressBytes: usage.egressBytes,\n computeSeconds: usage.computeSeconds,\n tokensUsed: usage.tokensUsed,\n periodStart: usage.periodStart ? new Date(usage.periodStart * 1000).toISOString() : null,\n },\n limits: {\n storageLimitBytes: usage.storageLimitBytes ?? null,\n bandwidthLimitBps: usage.bandwidthLimitBps ?? null,\n computeLimitSeconds: usage.computeLimitSeconds ?? null,\n tokenLimitMonthly: usage.tokenLimitMonthly ?? null,\n },\n });\n } catch (error) {\n logger.error(`Failed to get account usage: ${error}`);\n sendJson(response, 500, { error: 'Failed to get usage' });\n }\n });\n\n // GET /v1/usage/pods/:podId\n server.get('/v1/usage/pods/:podId', async (request, response, params) => {\n if (!requireUsageRead(request, response)) {\n return;\n }\n\n const podId = decodeURIComponent(params.podId);\n\n try {\n const usage = await usageRepo.getPodUsage(podId);\n if (!usage) {\n sendJson(response, 404, { error: 'Pod usage not found' });\n return;\n }\n\n sendJson(response, 200, {\n podId,\n accountId: usage.accountId,\n usage: {\n storageBytes: usage.storageBytes,\n ingressBytes: usage.ingressBytes,\n egressBytes: usage.egressBytes,\n computeSeconds: usage.computeSeconds,\n tokensUsed: usage.tokensUsed,\n periodStart: usage.periodStart ? new Date(usage.periodStart * 1000).toISOString() : null,\n },\n limits: {\n storageLimitBytes: usage.storageLimitBytes ?? null,\n bandwidthLimitBps: usage.bandwidthLimitBps ?? null,\n computeLimitSeconds: usage.computeLimitSeconds ?? null,\n tokenLimitMonthly: usage.tokenLimitMonthly ?? null,\n },\n });\n } catch (error) {\n logger.error(`Failed to get pod usage: ${error}`);\n sendJson(response, 500, { error: 'Failed to get usage' });\n }\n });\n}\n\nfunction requireUsageRead(request: AuthenticatedRequest, response: ServerResponse): boolean {\n if (!request.auth) {\n sendJson(response, 401, { error: 'Authentication required' });\n return false;\n }\n if (request.auth.type === 'service') {\n if (!hasScope(request.auth, 'usage:read')) {\n sendJson(response, 403, { error: 'Missing required scope: usage:read' });\n return false;\n }\n return true;\n }\n // Allow Solid auth (for admin/user self-query)\n if (request.auth.type === 'solid') {\n return true;\n }\n sendJson(response, 403, { error: 'Insufficient permissions' });\n return false;\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './EdgeNodeSignalHandler';
|
|
2
2
|
export * from './QuotaHandler';
|
|
3
3
|
export * from './NodeHandler';
|
|
4
4
|
export * from './ChatHandler';
|
|
@@ -9,3 +9,5 @@ export * from './ApiKeyHandler';
|
|
|
9
9
|
export * from './SubdomainHandler';
|
|
10
10
|
export * from './SubdomainClientHandler';
|
|
11
11
|
export * from './ChatKitHandler';
|
|
12
|
+
export * from './ProvisionHandler';
|
|
13
|
+
export * from './PodManagementHandler';
|
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./
|
|
17
|
+
__exportStar(require("./EdgeNodeSignalHandler"), exports);
|
|
18
18
|
__exportStar(require("./QuotaHandler"), exports);
|
|
19
19
|
__exportStar(require("./NodeHandler"), exports);
|
|
20
20
|
__exportStar(require("./ChatHandler"), exports);
|
|
@@ -25,4 +25,6 @@ __exportStar(require("./ApiKeyHandler"), exports);
|
|
|
25
25
|
__exportStar(require("./SubdomainHandler"), exports);
|
|
26
26
|
__exportStar(require("./SubdomainClientHandler"), exports);
|
|
27
27
|
__exportStar(require("./ChatKitHandler"), exports);
|
|
28
|
+
__exportStar(require("./ProvisionHandler"), exports);
|
|
29
|
+
__exportStar(require("./PodManagementHandler"), exports);
|
|
28
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/handlers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/handlers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAwC;AACxC,iDAA+B;AAC/B,gDAA8B;AAC9B,gDAA8B;AAC9B,kDAAgC;AAChC,uDAAqC;AACrC,8DAA4C;AAC5C,kDAAgC;AAChC,qDAAmC;AACnC,2DAAyC;AACzC,mDAAiC;AACjC,qDAAmC;AACnC,yDAAuC","sourcesContent":["export * from './EdgeNodeSignalHandler';\nexport * from './QuotaHandler';\nexport * from './NodeHandler';\nexport * from './ChatHandler';\nexport * from './VectorHandler';\nexport * from './VectorStoreHandler';\nexport * from './VectorStoreWebhookHandler';\nexport * from './ApiKeyHandler';\nexport * from './SubdomainHandler';\nexport * from './SubdomainClientHandler';\nexport * from './ChatKitHandler';\nexport * from './ProvisionHandler';\nexport * from './PodManagementHandler';\n"]}
|
package/dist/api/main.js
CHANGED
|
@@ -36,6 +36,24 @@ async function main() {
|
|
|
36
36
|
const container = (0, container_1.createApiContainer)(config);
|
|
37
37
|
// 注册路由
|
|
38
38
|
(0, routes_1.registerRoutes)(container);
|
|
39
|
+
// 自动注册 service token(如果配置了 XPOD_SERVICE_TOKEN)
|
|
40
|
+
try {
|
|
41
|
+
const serviceToken = process.env.XPOD_SERVICE_TOKEN;
|
|
42
|
+
if (serviceToken) {
|
|
43
|
+
const serviceTokenRepo = container.resolve('serviceTokenRepo');
|
|
44
|
+
const serviceType = config.edition === 'cloud' ? 'cloud' : 'local';
|
|
45
|
+
const serviceId = process.env.XPOD_NODE_ID || (config.edition === 'cloud' ? 'cloud-1' : 'local-1');
|
|
46
|
+
await serviceTokenRepo.registerToken(serviceToken, {
|
|
47
|
+
serviceType,
|
|
48
|
+
serviceId,
|
|
49
|
+
scopes: ['quota:write', 'usage:read', 'account:manage'],
|
|
50
|
+
});
|
|
51
|
+
logger.info(`Registered service token for ${serviceType}:${serviceId}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
logger.error(`Failed to register service token: ${error}`);
|
|
56
|
+
}
|
|
39
57
|
// Start background maintenance (IPv6 DDNS / Tunnel Control)
|
|
40
58
|
try {
|
|
41
59
|
const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });
|
package/dist/api/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/api/main.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * API Service Entry Point\n *\n * 使用 Awilix 依赖注入,根据 XPOD_EDITION 环境变量切换 cloud/local 模式\n *\n * - cloud: 持有 DNS/Tunnel 密钥,直接操作子域名,提供身份服务\n * - local: 连接 Cloud 获取身份服务和 DDNS,或独立运行\n *\n * Authentication:\n * - Solid DPoP Token: for browser/frontend users\n * - Client Credentials (Basic Auth with client_id:client_secret): for edge nodes and third-party backends\n */\n\nimport { createApiContainer, loadConfigFromEnv } from './container';\nimport { registerRoutes } from './container/routes';\nimport { setGlobalLoggerFactory, getLoggerFor } from 'global-logger-factory';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\n\nasync function main(): Promise<void> {\n // 从环境变量加载配置\n const config = loadConfigFromEnv();\n\n // 初始化全局统一日志工厂\n const loggerFactory = new ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {\n fileName: './logs/xpod-%DATE%.log',\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n\n const logger = getLoggerFor('Main');\n\n if (!config.databaseUrl) {\n logger.error('CSS_IDENTITY_DB_URL or DATABASE_URL environment variable is required');\n process.exit(1);\n }\n\n logger.info(`Starting API Service (edition: ${config.edition})...`);\n\n // 创建 DI 容器\n const container = createApiContainer(config);\n\n // 注册路由\n registerRoutes(container);\n\n // Start background maintenance (IPv6 DDNS / Tunnel Control)\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true }) as any;\n if (localNetworkManager) {\n localNetworkManager.start();\n }\n } catch (error) {\n logger.error(`Failed to initialize LocalNetworkManager: ${error}`);\n }\n\n // Start DDNS Manager (托管式 Local 模式)\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n if (ddnsManager) {\n await ddnsManager.start();\n logger.info('DDNS Manager started');\n }\n } catch (error) {\n logger.error(`Failed to initialize DdnsManager: ${error}`);\n }\n\n // Start Cloudflare Tunnel (独立式 Local 模式,没有 LocalNetworkManager 时直接启动)\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n\n // 只有当没有 LocalNetworkManager(它会自动管理 Tunnel)且有 Tunnel Provider 时才手动启动\n if (!localNetworkManager && localTunnelProvider) {\n logger.info('Starting Cloudflare Tunnel (standalone mode)...');\n await localTunnelProvider.start();\n logger.info('Cloudflare Tunnel started');\n }\n } catch (error) {\n logger.error(`Failed to start Cloudflare Tunnel: ${error}`);\n }\n\n // Start the HTTP server\n const server = container.resolve('apiServer') as any;\n await server.start();\n logger.info(`API Service active on ${config.host}:${config.port}`);\n\n // Graceful shutdown\n const shutdown = async (signal: string): Promise<void> => {\n logger.info(`Stopping API Service (${signal})...`);\n\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n ddnsManager?.stop();\n } catch {}\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n await localNetworkManager?.stop();\n } catch {}\n\n try {\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n await localTunnelProvider?.stop();\n } catch {}\n\n await server.stop();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n}\n\nmain().catch((error) => {\n console.error(`Failed to start API Service: ${error}`);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/api/main.ts"],"names":[],"mappings":";;AACA;;;;;;;;;;;GAWG;;AAEH,2CAAoE;AACpE,+CAAoD;AACpD,iEAA6E;AAC7E,oFAAiF;AAEjF,KAAK,UAAU,IAAI;IACjB,YAAY;IACZ,MAAM,MAAM,GAAG,IAAA,6BAAiB,GAAE,CAAC;IAEnC,cAAc;IACd,MAAM,aAAa,GAAG,IAAI,qDAAyB,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,MAAM,EAAE;QAC3F,QAAQ,EAAE,wBAAwB;QAClC,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IACH,IAAA,8CAAsB,EAAC,aAAa,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,IAAA,oCAAY,EAAC,MAAM,CAAC,CAAC;IAEpC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,kCAAkC,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC;IAEpE,WAAW;IACX,MAAM,SAAS,GAAG,IAAA,8BAAkB,EAAC,MAAM,CAAC,CAAC;IAE7C,OAAO;IACP,IAAA,uBAAc,EAAC,SAAS,CAAC,CAAC;IAE1B,+CAA+C;IAC/C,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACpD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAQ,CAAC;YACtE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YACnE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAEnG,MAAM,gBAAgB,CAAC,aAAa,CAAC,YAAY,EAAE;gBACjD,WAAW;gBACX,SAAS;gBACT,MAAM,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,gBAAgB,CAAC;aACxD,CAAC,CAAC;YAEH,MAAM,CAAC,IAAI,CAAC,gCAAgC,WAAW,IAAI,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,4DAA4D;IAC5D,IAAI,CAAC;QACH,MAAM,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAQ,CAAC;QACzG,IAAI,mBAAmB,EAAE,CAAC;YACxB,mBAAmB,CAAC,KAAK,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,6CAA6C,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,oCAAoC;IACpC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAQ,CAAC;QACzF,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC;QACH,MAAM,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;QAClG,MAAM,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAQ,CAAC;QAEzG,oEAAoE;QACpE,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC/D,MAAM,mBAAmB,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,wBAAwB;IACxB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAQ,CAAC;IACrD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,MAAM,CAAC,IAAI,CAAC,yBAAyB,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAEnE,oBAAoB;IACpB,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAiB,EAAE;QACvD,MAAM,CAAC,IAAI,CAAC,yBAAyB,MAAM,MAAM,CAAC,CAAC;QAEnD,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAQ,CAAC;YACzF,WAAW,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,IAAI,CAAC;YACH,MAAM,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;YAClG,MAAM,mBAAmB,EAAE,IAAI,EAAE,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,IAAI,CAAC;YACH,MAAM,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAQ,CAAC;YACzG,MAAM,mBAAmB,EAAE,IAAI,EAAE,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * API Service Entry Point\n *\n * 使用 Awilix 依赖注入,根据 XPOD_EDITION 环境变量切换 cloud/local 模式\n *\n * - cloud: 持有 DNS/Tunnel 密钥,直接操作子域名,提供身份服务\n * - local: 连接 Cloud 获取身份服务和 DDNS,或独立运行\n *\n * Authentication:\n * - Solid DPoP Token: for browser/frontend users\n * - Client Credentials (Basic Auth with client_id:client_secret): for edge nodes and third-party backends\n */\n\nimport { createApiContainer, loadConfigFromEnv } from './container';\nimport { registerRoutes } from './container/routes';\nimport { setGlobalLoggerFactory, getLoggerFor } from 'global-logger-factory';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\n\nasync function main(): Promise<void> {\n // 从环境变量加载配置\n const config = loadConfigFromEnv();\n\n // 初始化全局统一日志工厂\n const loggerFactory = new ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {\n fileName: './logs/xpod-%DATE%.log',\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n\n const logger = getLoggerFor('Main');\n\n if (!config.databaseUrl) {\n logger.error('CSS_IDENTITY_DB_URL or DATABASE_URL environment variable is required');\n process.exit(1);\n }\n\n logger.info(`Starting API Service (edition: ${config.edition})...`);\n\n // 创建 DI 容器\n const container = createApiContainer(config);\n\n // 注册路由\n registerRoutes(container);\n\n // 自动注册 service token(如果配置了 XPOD_SERVICE_TOKEN)\n try {\n const serviceToken = process.env.XPOD_SERVICE_TOKEN;\n if (serviceToken) {\n const serviceTokenRepo = container.resolve('serviceTokenRepo') as any;\n const serviceType = config.edition === 'cloud' ? 'cloud' : 'local';\n const serviceId = process.env.XPOD_NODE_ID || (config.edition === 'cloud' ? 'cloud-1' : 'local-1');\n\n await serviceTokenRepo.registerToken(serviceToken, {\n serviceType,\n serviceId,\n scopes: ['quota:write', 'usage:read', 'account:manage'],\n });\n\n logger.info(`Registered service token for ${serviceType}:${serviceId}`);\n }\n } catch (error) {\n logger.error(`Failed to register service token: ${error}`);\n }\n\n // Start background maintenance (IPv6 DDNS / Tunnel Control)\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true }) as any;\n if (localNetworkManager) {\n localNetworkManager.start();\n }\n } catch (error) {\n logger.error(`Failed to initialize LocalNetworkManager: ${error}`);\n }\n\n // Start DDNS Manager (托管式 Local 模式)\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n if (ddnsManager) {\n await ddnsManager.start();\n logger.info('DDNS Manager started');\n }\n } catch (error) {\n logger.error(`Failed to initialize DdnsManager: ${error}`);\n }\n\n // Start Cloudflare Tunnel (独立式 Local 模式,没有 LocalNetworkManager 时直接启动)\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n\n // 只有当没有 LocalNetworkManager(它会自动管理 Tunnel)且有 Tunnel Provider 时才手动启动\n if (!localNetworkManager && localTunnelProvider) {\n logger.info('Starting Cloudflare Tunnel (standalone mode)...');\n await localTunnelProvider.start();\n logger.info('Cloudflare Tunnel started');\n }\n } catch (error) {\n logger.error(`Failed to start Cloudflare Tunnel: ${error}`);\n }\n\n // Start the HTTP server\n const server = container.resolve('apiServer') as any;\n await server.start();\n logger.info(`API Service active on ${config.host}:${config.port}`);\n\n // Graceful shutdown\n const shutdown = async (signal: string): Promise<void> => {\n logger.info(`Stopping API Service (${signal})...`);\n\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n ddnsManager?.stop();\n } catch {}\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n await localNetworkManager?.stop();\n } catch {}\n\n try {\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n await localTunnelProvider?.stop();\n } catch {}\n\n await server.stop();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n}\n\nmain().catch((error) => {\n console.error(`Failed to start API Service: ${error}`);\n process.exit(1);\n});\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ServerResponse } from 'node:http';
|
|
2
|
+
import type { AuthContext } from '../auth/AuthContext';
|
|
3
|
+
import type { AuthenticatedRequest } from './AuthMiddleware';
|
|
4
|
+
import { AuthMiddleware } from './AuthMiddleware';
|
|
5
|
+
export interface OpenAuthMiddlewareOptions {
|
|
6
|
+
context?: AuthContext;
|
|
7
|
+
}
|
|
8
|
+
export declare class OpenAuthMiddleware extends AuthMiddleware {
|
|
9
|
+
private readonly context;
|
|
10
|
+
constructor(options?: OpenAuthMiddlewareOptions);
|
|
11
|
+
process(request: AuthenticatedRequest, _response: ServerResponse): Promise<boolean>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenAuthMiddleware = void 0;
|
|
4
|
+
const AuthMiddleware_1 = require("./AuthMiddleware");
|
|
5
|
+
const DEFAULT_OPEN_AUTH_CONTEXT = {
|
|
6
|
+
type: 'solid',
|
|
7
|
+
webId: 'http://xpod.test/test/profile/card#me',
|
|
8
|
+
accountId: 'xpod-open-account',
|
|
9
|
+
displayName: 'Xpod Open Mode',
|
|
10
|
+
};
|
|
11
|
+
class OpenAuthMiddleware extends AuthMiddleware_1.AuthMiddleware {
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
super({
|
|
14
|
+
authenticator: {
|
|
15
|
+
canAuthenticate: () => true,
|
|
16
|
+
authenticate: async () => ({ success: true, context: options.context ?? DEFAULT_OPEN_AUTH_CONTEXT }),
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
this.context = options.context ?? DEFAULT_OPEN_AUTH_CONTEXT;
|
|
20
|
+
}
|
|
21
|
+
async process(request, _response) {
|
|
22
|
+
request.auth = this.context;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.OpenAuthMiddleware = OpenAuthMiddleware;
|
|
27
|
+
//# sourceMappingURL=OpenAuthMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenAuthMiddleware.js","sourceRoot":"","sources":["../../../src/api/middleware/OpenAuthMiddleware.ts"],"names":[],"mappings":";;;AAGA,qDAAkD;AAElD,MAAM,yBAAyB,GAAgB;IAC7C,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,uCAAuC;IAC9C,SAAS,EAAE,mBAAmB;IAC9B,WAAW,EAAE,gBAAgB;CAC9B,CAAC;AAMF,MAAa,kBAAmB,SAAQ,+BAAc;IAGpD,YAAmB,UAAqC,EAAE;QACxD,KAAK,CAAC;YACJ,aAAa,EAAE;gBACb,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI;gBAC3B,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,yBAAyB,EAAE,CAAC;aACrG;SACF,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,yBAAyB,CAAC;IAC9D,CAAC;IAEe,KAAK,CAAC,OAAO,CAAC,OAA6B,EAAE,SAAyB;QACpF,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAjBD,gDAiBC","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport type { AuthContext } from '../auth/AuthContext';\nimport type { AuthenticatedRequest } from './AuthMiddleware';\nimport { AuthMiddleware } from './AuthMiddleware';\n\nconst DEFAULT_OPEN_AUTH_CONTEXT: AuthContext = {\n type: 'solid',\n webId: 'http://xpod.test/test/profile/card#me',\n accountId: 'xpod-open-account',\n displayName: 'Xpod Open Mode',\n};\n\nexport interface OpenAuthMiddlewareOptions {\n context?: AuthContext;\n}\n\nexport class OpenAuthMiddleware extends AuthMiddleware {\n private readonly context: AuthContext;\n\n public constructor(options: OpenAuthMiddlewareOptions = {}) {\n super({\n authenticator: {\n canAuthenticate: () => true,\n authenticate: async () => ({ success: true, context: options.context ?? DEFAULT_OPEN_AUTH_CONTEXT }),\n },\n });\n this.context = options.context ?? DEFAULT_OPEN_AUTH_CONTEXT;\n }\n\n public override async process(request: AuthenticatedRequest, _response: ServerResponse): Promise<boolean> {\n request.auth = this.context;\n return true;\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type AwilixContainer } from 'awilix';
|
|
2
|
+
import { type ApiContainerConfig, type ApiContainerCradle } from './container';
|
|
3
|
+
import type { AuthContext } from './auth/AuthContext';
|
|
4
|
+
export interface StartApiServiceOptions {
|
|
5
|
+
config?: ApiContainerConfig;
|
|
6
|
+
open?: boolean;
|
|
7
|
+
authContext?: AuthContext;
|
|
8
|
+
initializeLogger?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ApiServiceHandle {
|
|
11
|
+
config: ApiContainerConfig;
|
|
12
|
+
container: AwilixContainer<ApiContainerCradle>;
|
|
13
|
+
stop: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function startApiService(options?: StartApiServiceOptions): Promise<ApiServiceHandle>;
|