@undefineds.co/xpod 0.2.42 → 0.2.44
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/dist/api/handlers/WebIdProfileHandler.js +9 -1
- package/dist/api/handlers/WebIdProfileHandler.js.map +1 -1
- package/dist/components/context.jsonld +45 -0
- package/dist/storage/quint/BaseQuintStore.jsonld +82 -0
- package/dist/storage/quint/PgQuintStore.d.ts +43 -3
- package/dist/storage/quint/PgQuintStore.js +596 -28
- package/dist/storage/quint/PgQuintStore.js.map +1 -1
- package/dist/storage/quint/PgQuintStore.jsonld +202 -0
- package/dist/storage/quint/SqliteQuintStore.jsonld +82 -0
- package/dist/storage/quint/index.d.ts +1 -0
- package/dist/storage/quint/index.js +1 -0
- package/dist/storage/quint/index.js.map +1 -1
- package/dist/storage/quint/types.d.ts +13 -0
- package/dist/storage/quint/types.js.map +1 -1
- package/dist/storage/quint/value-types.d.ts +32 -0
- package/dist/storage/quint/value-types.js +100 -0
- package/dist/storage/quint/value-types.js.map +1 -0
- package/package.json +1 -1
- package/static/app/assets/main.js +22 -22
|
@@ -357,7 +357,7 @@ async function probeHostedStorageRoot(storageUrl, username) {
|
|
|
357
357
|
method: 'HEAD',
|
|
358
358
|
signal: controller.signal,
|
|
359
359
|
});
|
|
360
|
-
if ((response
|
|
360
|
+
if (isHostedStorageRootResponse(response)) {
|
|
361
361
|
logger.info(`Resolved hosted WebID profile for ${username} from existing storage root: ${storageUrl}`);
|
|
362
362
|
return true;
|
|
363
363
|
}
|
|
@@ -371,6 +371,14 @@ async function probeHostedStorageRoot(storageUrl, username) {
|
|
|
371
371
|
clearTimeout(timer);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
+
function isHostedStorageRootResponse(response) {
|
|
375
|
+
if (response.status < 200 || response.status >= 400) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
const link = response.headers.get('link') ?? '';
|
|
379
|
+
return /<http:\/\/www\.w3\.org\/ns\/pim\/space#Storage>;\s*rel="?type"?/iu.test(link) ||
|
|
380
|
+
/<http:\/\/www\.w3\.org\/ns\/ldp#(?:Basic)?Container>;\s*rel="?type"?/iu.test(link);
|
|
381
|
+
}
|
|
374
382
|
function ensureTrailingSlash(url) {
|
|
375
383
|
return url.replace(/\/+$/, '') + '/';
|
|
376
384
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebIdProfileHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/WebIdProfileHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WebID Profile API Handler\n *\n * 提供 WebID Profile 托管服务的 HTTP API\n *\n * GET /{username}/profile/card - 获取 WebID Profile (Turtle 格式)\n * POST /api/v1/identity/{username}/storage - 更新 storage 指针 (需认证)\n */\n\nimport type { ServerResponse, IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\n\nconst logger = getLoggerFor('WebIdProfileHandler');\n\nexport interface WebIdProfileHandlerOptions {\n profileRepo: WebIdProfileRepository;\n podLookupRepo?: PodLookupRepository;\n}\n\ninterface IdentityProfileResponse {\n username: string;\n webidUrl: string;\n storageUrl?: string;\n storageMode: 'cloud' | 'local' | 'custom';\n oidcIssuer?: string;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nexport function registerWebIdProfileRoutes(\n server: ApiServer,\n options: WebIdProfileHandlerOptions,\n): void {\n const { profileRepo } = options;\n\n /**\n * GET /{username}/profile/card\n *\n * 获取 WebID Profile (Turtle 格式)\n * 这是 Solid 标准的 WebID 端点\n */\n server.get('/:username/profile/card', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveIdentityLookup(username, options, request);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n // 返回 Turtle 格式\n const turtle = profileRepo.generateProfileTurtle(profile);\n\n response.statusCode = 200;\n response.setHeader('Content-Type', 'text/turtle');\n response.setHeader('Link', `<${profile.webidUrl}>; rel=\"describedby\"`);\n response.end(turtle);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity/{username}/storage\n *\n * 更新 storage 指针\n * 用于 Local 节点更新其 storage URL\n *\n * Request body:\n * {\n * \"storageUrl\": \"https://alice.undefineds.xyz/\"\n * }\n */\n server.post('/api/v1/identity/:username/storage', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const body = await readJsonBody(request);\n const payload = body as { storageUrl?: string; storageMode?: string } | undefined;\n\n if (!payload?.storageUrl) {\n sendError(response, 400, 'storageUrl is required');\n return;\n }\n\n // 验证 URL 格式\n try {\n new URL(payload.storageUrl);\n } catch {\n sendError(response, 400, 'Invalid storageUrl format');\n return;\n }\n\n const profile = await profileRepo.updateStorage(username, {\n storageUrl: payload.storageUrl,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n });\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n logger.info(`Updated storage for ${username}: ${payload.storageUrl}`);\n\n sendJson(response, 200, {\n success: true,\n username,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n updatedAt: profile.updatedAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to update storage for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n /**\n * GET /api/v1/identity/{username}\n *\n * 获取 WebID Profile 信息 (JSON 格式)\n */\n server.get('/api/v1/identity/:username', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveIdentityLookup(username, options, request);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n const body: Record<string, unknown> = {\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n oidcIssuer: profile.oidcIssuer,\n };\n if (profile.createdAt) {\n body.createdAt = profile.createdAt.toISOString();\n }\n if (profile.updatedAt) {\n body.updatedAt = profile.updatedAt.toISOString();\n }\n sendJson(response, 200, body);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity\n *\n * 创建 WebID Profile\n *\n * Request body:\n * {\n * \"username\": \"alice\",\n * \"storageMode\": \"local\", // optional, default: \"cloud\"\n * \"storageUrl\": \"https://alice.undefineds.xyz/\" // optional\n * }\n */\n server.post('/api/v1/identity', async (request, response, _params) => {\n try {\n const body = await readJsonBody(request);\n const payload = body as {\n username?: string;\n storageMode?: string;\n storageUrl?: string;\n accountId?: string;\n } | undefined;\n\n if (!payload?.username) {\n sendError(response, 400, 'username is required');\n return;\n }\n\n // 验证用户名格式\n if (!/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(payload.username)) {\n sendError(response, 400, 'Invalid username format');\n return;\n }\n\n // 检查是否已存在\n const existing = await profileRepo.get(payload.username);\n if (existing) {\n sendError(response, 409, 'Username already taken');\n return;\n }\n\n const profile = await profileRepo.create({\n username: payload.username,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n storageUrl: payload.storageUrl,\n accountId: payload.accountId,\n });\n\n logger.info(`Created profile for ${payload.username}`);\n\n sendJson(response, 201, {\n success: true,\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n createdAt: profile.createdAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to create profile: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n logger.info('WebID Profile routes registered');\n}\n\nasync function resolveIdentityLookup(\n username: string,\n options: WebIdProfileHandlerOptions,\n request?: IncomingMessage,\n): Promise<IdentityProfileResponse | null> {\n try {\n const profile = await resolveProfileWithStorageBackfill(username, options);\n if (profile) {\n return profile;\n }\n } catch (error) {\n logger.warn(`Profile lookup unavailable for ${username}, falling back to Pod index: ${error}`);\n }\n\n return resolveProfileFromPods(username, options, request);\n}\n\nasync function resolveProfileFromPods(\n username: string,\n options: WebIdProfileHandlerOptions,\n request?: IncomingMessage,\n): Promise<IdentityProfileResponse | null> {\n const { podLookupRepo } = options;\n const identityBaseUrl = getHostedIdentityBaseUrl(request);\n\n if (podLookupRepo) {\n const webidUrl = buildHostedWebIdUrl(username, identityBaseUrl);\n const webIdMatch = await tryFindPodByWebId(podLookupRepo, webidUrl, username);\n if (webIdMatch) {\n return profileFromPod(username, webidUrl, webIdMatch);\n }\n\n const match = await tryFindPodByStorageSlug(podLookupRepo, username);\n if (match) {\n return profileFromPod(username, buildStorageWebIdUrl(match.baseUrl), match);\n }\n }\n\n const hostedStorageUrl = new URL(`${encodeURIComponent(username)}/`, identityBaseUrl).toString();\n if (await probeHostedStorageRoot(hostedStorageUrl, username)) {\n return {\n username,\n webidUrl: buildHostedWebIdUrl(username, identityBaseUrl),\n storageUrl: hostedStorageUrl,\n storageMode: 'cloud',\n oidcIssuer: deriveOrigin(identityBaseUrl),\n };\n }\n\n return null;\n}\n\nasync function resolveProfileWithStorageBackfill(\n username: string,\n options: WebIdProfileHandlerOptions,\n) {\n const { profileRepo, podLookupRepo } = options;\n const profile = await profileRepo.get(username);\n if (!profile) {\n return null;\n }\n\n if (profile.storageUrl || !profile.accountId || !podLookupRepo) {\n return profile;\n }\n\n let pods: PodLookupResult[];\n try {\n pods = await podLookupRepo.listByAccountId(profile.accountId);\n } catch (error) {\n logger.warn(`Skipped storage backfill for ${username}: pod index unavailable for account ${profile.accountId}: ${error}`);\n return profile;\n }\n const storageUrl = selectStorageBackfillCandidate(username, pods);\n if (!storageUrl) {\n logger.warn(`Skipped storage backfill for ${username}: no unambiguous pod found for account ${profile.accountId}`);\n return profile;\n }\n\n try {\n const updated = await profileRepo.updateStorage(username, {\n storageUrl,\n storageMode: profile.storageMode,\n });\n if (updated) {\n logger.info(`Backfilled storage for ${username}: ${storageUrl}`);\n return updated;\n }\n } catch (error) {\n logger.warn(`Failed to backfill storage for ${username}: ${error}`);\n }\n\n return profile;\n}\n\nfunction selectStorageBackfillCandidate(\n username: string,\n pods: PodLookupResult[],\n): string | null {\n if (pods.length === 0) {\n return null;\n }\n\n const exactMatches = pods.filter((pod) => derivePodSlug(pod.baseUrl) === username);\n if (exactMatches.length === 1) {\n return ensureTrailingSlash(exactMatches[0].baseUrl);\n }\n\n if (exactMatches.length > 1) {\n return null;\n }\n\n if (pods.length === 1) {\n return ensureTrailingSlash(pods[0].baseUrl);\n }\n\n return null;\n}\n\nfunction derivePodSlug(baseUrl: string): string | null {\n try {\n const parsed = new URL(baseUrl);\n const [slug] = parsed.pathname.split('/').filter(Boolean);\n return slug || null;\n } catch {\n return null;\n }\n}\n\nasync function tryFindPodByWebId(\n podLookupRepo: PodLookupRepository,\n webidUrl: string,\n username: string,\n): Promise<PodLookupResult | undefined> {\n try {\n if (typeof podLookupRepo.findByWebId === 'function') {\n return await podLookupRepo.findByWebId(webidUrl);\n }\n } catch (error) {\n logger.warn(`WebID index lookup unavailable for ${username}: ${error}`);\n }\n return undefined;\n}\n\nasync function tryFindPodByStorageSlug(\n podLookupRepo: PodLookupRepository,\n username: string,\n): Promise<PodLookupResult | undefined> {\n try {\n const pods = await podLookupRepo.listAllPods();\n return pods.find((pod) => derivePodSlug(pod.baseUrl) === username);\n } catch (error) {\n logger.warn(`Pod index lookup unavailable for ${username}: ${error}`);\n return undefined;\n }\n}\n\nfunction profileFromPod(\n username: string,\n webidUrl: string,\n pod: PodLookupResult,\n): IdentityProfileResponse {\n const storageUrl = ensureTrailingSlash(pod.baseUrl);\n return {\n username,\n webidUrl,\n storageUrl,\n storageMode: 'cloud',\n oidcIssuer: deriveOrigin(webidUrl),\n };\n}\n\nfunction buildHostedWebIdUrl(username: string, identityBaseUrl = getHostedIdentityBaseUrl()): string {\n return new URL(`${encodeURIComponent(username)}/profile/card#me`, identityBaseUrl).toString();\n}\n\nfunction buildStorageWebIdUrl(storageUrl: string): string {\n return new URL('profile/card#me', ensureTrailingSlash(storageUrl)).toString();\n}\n\nfunction getHostedIdentityBaseUrl(request?: IncomingMessage): string {\n return ensureTrailingSlash(\n requestOrigin(request) ??\n absoluteHttpUrl(process.env.CSS_BASE_URL) ??\n absoluteHttpUrl(process.env.BASE_URL) ??\n 'http://localhost:3000/',\n );\n}\n\nfunction absoluteHttpUrl(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:' ? url.toString() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction requestOrigin(request: IncomingMessage | undefined): string | undefined {\n if (!request?.headers) {\n return undefined;\n }\n const host = firstHeader(request.headers['x-forwarded-host']) ?? firstHeader(request.headers.host);\n if (!host) {\n return undefined;\n }\n const proto = firstHeader(request.headers['x-forwarded-proto']) ?? 'https';\n return absoluteHttpUrl(`${proto}://${host}`);\n}\n\nfunction firstHeader(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n}\n\nasync function probeHostedStorageRoot(storageUrl: string, username: string): Promise<boolean> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 2_000);\n try {\n const response = await fetch(storageUrl, {\n method: 'HEAD',\n signal: controller.signal,\n });\n if ((response.status >= 200 && response.status < 400) || response.status === 401 || response.status === 403) {\n logger.info(`Resolved hosted WebID profile for ${username} from existing storage root: ${storageUrl}`);\n return true;\n }\n return false;\n } catch (error) {\n logger.warn(`Hosted storage root probe unavailable for ${username}: ${error}`);\n return false;\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, '') + '/';\n}\n\nfunction deriveOrigin(url: string): string | undefined {\n try {\n return ensureTrailingSlash(new URL(url).origin);\n } catch {\n return undefined;\n }\n}\n\nasync function readJsonBody(request: IncomingMessage): 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 sendError(response: ServerResponse, status: number, message: string): void {\n sendJson(response, status, { error: message });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"WebIdProfileHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/WebIdProfileHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WebID Profile API Handler\n *\n * 提供 WebID Profile 托管服务的 HTTP API\n *\n * GET /{username}/profile/card - 获取 WebID Profile (Turtle 格式)\n * POST /api/v1/identity/{username}/storage - 更新 storage 指针 (需认证)\n */\n\nimport type { ServerResponse, IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\n\nconst logger = getLoggerFor('WebIdProfileHandler');\n\nexport interface WebIdProfileHandlerOptions {\n profileRepo: WebIdProfileRepository;\n podLookupRepo?: PodLookupRepository;\n}\n\ninterface IdentityProfileResponse {\n username: string;\n webidUrl: string;\n storageUrl?: string;\n storageMode: 'cloud' | 'local' | 'custom';\n oidcIssuer?: string;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nexport function registerWebIdProfileRoutes(\n server: ApiServer,\n options: WebIdProfileHandlerOptions,\n): void {\n const { profileRepo } = options;\n\n /**\n * GET /{username}/profile/card\n *\n * 获取 WebID Profile (Turtle 格式)\n * 这是 Solid 标准的 WebID 端点\n */\n server.get('/:username/profile/card', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveIdentityLookup(username, options, request);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n // 返回 Turtle 格式\n const turtle = profileRepo.generateProfileTurtle(profile);\n\n response.statusCode = 200;\n response.setHeader('Content-Type', 'text/turtle');\n response.setHeader('Link', `<${profile.webidUrl}>; rel=\"describedby\"`);\n response.end(turtle);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity/{username}/storage\n *\n * 更新 storage 指针\n * 用于 Local 节点更新其 storage URL\n *\n * Request body:\n * {\n * \"storageUrl\": \"https://alice.undefineds.xyz/\"\n * }\n */\n server.post('/api/v1/identity/:username/storage', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const body = await readJsonBody(request);\n const payload = body as { storageUrl?: string; storageMode?: string } | undefined;\n\n if (!payload?.storageUrl) {\n sendError(response, 400, 'storageUrl is required');\n return;\n }\n\n // 验证 URL 格式\n try {\n new URL(payload.storageUrl);\n } catch {\n sendError(response, 400, 'Invalid storageUrl format');\n return;\n }\n\n const profile = await profileRepo.updateStorage(username, {\n storageUrl: payload.storageUrl,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n });\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n logger.info(`Updated storage for ${username}: ${payload.storageUrl}`);\n\n sendJson(response, 200, {\n success: true,\n username,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n updatedAt: profile.updatedAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to update storage for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n /**\n * GET /api/v1/identity/{username}\n *\n * 获取 WebID Profile 信息 (JSON 格式)\n */\n server.get('/api/v1/identity/:username', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveIdentityLookup(username, options, request);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n const body: Record<string, unknown> = {\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n oidcIssuer: profile.oidcIssuer,\n };\n if (profile.createdAt) {\n body.createdAt = profile.createdAt.toISOString();\n }\n if (profile.updatedAt) {\n body.updatedAt = profile.updatedAt.toISOString();\n }\n sendJson(response, 200, body);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity\n *\n * 创建 WebID Profile\n *\n * Request body:\n * {\n * \"username\": \"alice\",\n * \"storageMode\": \"local\", // optional, default: \"cloud\"\n * \"storageUrl\": \"https://alice.undefineds.xyz/\" // optional\n * }\n */\n server.post('/api/v1/identity', async (request, response, _params) => {\n try {\n const body = await readJsonBody(request);\n const payload = body as {\n username?: string;\n storageMode?: string;\n storageUrl?: string;\n accountId?: string;\n } | undefined;\n\n if (!payload?.username) {\n sendError(response, 400, 'username is required');\n return;\n }\n\n // 验证用户名格式\n if (!/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(payload.username)) {\n sendError(response, 400, 'Invalid username format');\n return;\n }\n\n // 检查是否已存在\n const existing = await profileRepo.get(payload.username);\n if (existing) {\n sendError(response, 409, 'Username already taken');\n return;\n }\n\n const profile = await profileRepo.create({\n username: payload.username,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n storageUrl: payload.storageUrl,\n accountId: payload.accountId,\n });\n\n logger.info(`Created profile for ${payload.username}`);\n\n sendJson(response, 201, {\n success: true,\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n createdAt: profile.createdAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to create profile: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n logger.info('WebID Profile routes registered');\n}\n\nasync function resolveIdentityLookup(\n username: string,\n options: WebIdProfileHandlerOptions,\n request?: IncomingMessage,\n): Promise<IdentityProfileResponse | null> {\n try {\n const profile = await resolveProfileWithStorageBackfill(username, options);\n if (profile) {\n return profile;\n }\n } catch (error) {\n logger.warn(`Profile lookup unavailable for ${username}, falling back to Pod index: ${error}`);\n }\n\n return resolveProfileFromPods(username, options, request);\n}\n\nasync function resolveProfileFromPods(\n username: string,\n options: WebIdProfileHandlerOptions,\n request?: IncomingMessage,\n): Promise<IdentityProfileResponse | null> {\n const { podLookupRepo } = options;\n const identityBaseUrl = getHostedIdentityBaseUrl(request);\n\n if (podLookupRepo) {\n const webidUrl = buildHostedWebIdUrl(username, identityBaseUrl);\n const webIdMatch = await tryFindPodByWebId(podLookupRepo, webidUrl, username);\n if (webIdMatch) {\n return profileFromPod(username, webidUrl, webIdMatch);\n }\n\n const match = await tryFindPodByStorageSlug(podLookupRepo, username);\n if (match) {\n return profileFromPod(username, buildStorageWebIdUrl(match.baseUrl), match);\n }\n }\n\n const hostedStorageUrl = new URL(`${encodeURIComponent(username)}/`, identityBaseUrl).toString();\n if (await probeHostedStorageRoot(hostedStorageUrl, username)) {\n return {\n username,\n webidUrl: buildHostedWebIdUrl(username, identityBaseUrl),\n storageUrl: hostedStorageUrl,\n storageMode: 'cloud',\n oidcIssuer: deriveOrigin(identityBaseUrl),\n };\n }\n\n return null;\n}\n\nasync function resolveProfileWithStorageBackfill(\n username: string,\n options: WebIdProfileHandlerOptions,\n) {\n const { profileRepo, podLookupRepo } = options;\n const profile = await profileRepo.get(username);\n if (!profile) {\n return null;\n }\n\n if (profile.storageUrl || !profile.accountId || !podLookupRepo) {\n return profile;\n }\n\n let pods: PodLookupResult[];\n try {\n pods = await podLookupRepo.listByAccountId(profile.accountId);\n } catch (error) {\n logger.warn(`Skipped storage backfill for ${username}: pod index unavailable for account ${profile.accountId}: ${error}`);\n return profile;\n }\n const storageUrl = selectStorageBackfillCandidate(username, pods);\n if (!storageUrl) {\n logger.warn(`Skipped storage backfill for ${username}: no unambiguous pod found for account ${profile.accountId}`);\n return profile;\n }\n\n try {\n const updated = await profileRepo.updateStorage(username, {\n storageUrl,\n storageMode: profile.storageMode,\n });\n if (updated) {\n logger.info(`Backfilled storage for ${username}: ${storageUrl}`);\n return updated;\n }\n } catch (error) {\n logger.warn(`Failed to backfill storage for ${username}: ${error}`);\n }\n\n return profile;\n}\n\nfunction selectStorageBackfillCandidate(\n username: string,\n pods: PodLookupResult[],\n): string | null {\n if (pods.length === 0) {\n return null;\n }\n\n const exactMatches = pods.filter((pod) => derivePodSlug(pod.baseUrl) === username);\n if (exactMatches.length === 1) {\n return ensureTrailingSlash(exactMatches[0].baseUrl);\n }\n\n if (exactMatches.length > 1) {\n return null;\n }\n\n if (pods.length === 1) {\n return ensureTrailingSlash(pods[0].baseUrl);\n }\n\n return null;\n}\n\nfunction derivePodSlug(baseUrl: string): string | null {\n try {\n const parsed = new URL(baseUrl);\n const [slug] = parsed.pathname.split('/').filter(Boolean);\n return slug || null;\n } catch {\n return null;\n }\n}\n\nasync function tryFindPodByWebId(\n podLookupRepo: PodLookupRepository,\n webidUrl: string,\n username: string,\n): Promise<PodLookupResult | undefined> {\n try {\n if (typeof podLookupRepo.findByWebId === 'function') {\n return await podLookupRepo.findByWebId(webidUrl);\n }\n } catch (error) {\n logger.warn(`WebID index lookup unavailable for ${username}: ${error}`);\n }\n return undefined;\n}\n\nasync function tryFindPodByStorageSlug(\n podLookupRepo: PodLookupRepository,\n username: string,\n): Promise<PodLookupResult | undefined> {\n try {\n const pods = await podLookupRepo.listAllPods();\n return pods.find((pod) => derivePodSlug(pod.baseUrl) === username);\n } catch (error) {\n logger.warn(`Pod index lookup unavailable for ${username}: ${error}`);\n return undefined;\n }\n}\n\nfunction profileFromPod(\n username: string,\n webidUrl: string,\n pod: PodLookupResult,\n): IdentityProfileResponse {\n const storageUrl = ensureTrailingSlash(pod.baseUrl);\n return {\n username,\n webidUrl,\n storageUrl,\n storageMode: 'cloud',\n oidcIssuer: deriveOrigin(webidUrl),\n };\n}\n\nfunction buildHostedWebIdUrl(username: string, identityBaseUrl = getHostedIdentityBaseUrl()): string {\n return new URL(`${encodeURIComponent(username)}/profile/card#me`, identityBaseUrl).toString();\n}\n\nfunction buildStorageWebIdUrl(storageUrl: string): string {\n return new URL('profile/card#me', ensureTrailingSlash(storageUrl)).toString();\n}\n\nfunction getHostedIdentityBaseUrl(request?: IncomingMessage): string {\n return ensureTrailingSlash(\n requestOrigin(request) ??\n absoluteHttpUrl(process.env.CSS_BASE_URL) ??\n absoluteHttpUrl(process.env.BASE_URL) ??\n 'http://localhost:3000/',\n );\n}\n\nfunction absoluteHttpUrl(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:' ? url.toString() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction requestOrigin(request: IncomingMessage | undefined): string | undefined {\n if (!request?.headers) {\n return undefined;\n }\n const host = firstHeader(request.headers['x-forwarded-host']) ?? firstHeader(request.headers.host);\n if (!host) {\n return undefined;\n }\n const proto = firstHeader(request.headers['x-forwarded-proto']) ?? 'https';\n return absoluteHttpUrl(`${proto}://${host}`);\n}\n\nfunction firstHeader(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n}\n\nasync function probeHostedStorageRoot(storageUrl: string, username: string): Promise<boolean> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 2_000);\n try {\n const response = await fetch(storageUrl, {\n method: 'HEAD',\n signal: controller.signal,\n });\n if (isHostedStorageRootResponse(response)) {\n logger.info(`Resolved hosted WebID profile for ${username} from existing storage root: ${storageUrl}`);\n return true;\n }\n return false;\n } catch (error) {\n logger.warn(`Hosted storage root probe unavailable for ${username}: ${error}`);\n return false;\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction isHostedStorageRootResponse(response: Response): boolean {\n if (response.status < 200 || response.status >= 400) {\n return false;\n }\n\n const link = response.headers.get('link') ?? '';\n return /<http:\\/\\/www\\.w3\\.org\\/ns\\/pim\\/space#Storage>;\\s*rel=\"?type\"?/iu.test(link) ||\n /<http:\\/\\/www\\.w3\\.org\\/ns\\/ldp#(?:Basic)?Container>;\\s*rel=\"?type\"?/iu.test(link);\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, '') + '/';\n}\n\nfunction deriveOrigin(url: string): string | undefined {\n try {\n return ensureTrailingSlash(new URL(url).origin);\n } catch {\n return undefined;\n }\n}\n\nasync function readJsonBody(request: IncomingMessage): 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 sendError(response: ServerResponse, status: number, message: string): void {\n sendJson(response, status, { error: message });\n}\n"]}
|
|
@@ -1497,11 +1497,25 @@
|
|
|
1497
1497
|
"options_debug": {
|
|
1498
1498
|
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_debug"
|
|
1499
1499
|
},
|
|
1500
|
+
"options_predicateObjectDataTypes": {
|
|
1501
|
+
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_predicateObjectDataTypes",
|
|
1502
|
+
"@container": "@list"
|
|
1503
|
+
},
|
|
1504
|
+
"options_textMaxBytes": {
|
|
1505
|
+
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_textMaxBytes"
|
|
1506
|
+
},
|
|
1500
1507
|
"path": {
|
|
1501
1508
|
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_path"
|
|
1502
1509
|
},
|
|
1503
1510
|
"debug": {
|
|
1504
1511
|
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_debug"
|
|
1512
|
+
},
|
|
1513
|
+
"predicateObjectDataTypes": {
|
|
1514
|
+
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_predicateObjectDataTypes",
|
|
1515
|
+
"@container": "@list"
|
|
1516
|
+
},
|
|
1517
|
+
"textMaxBytes": {
|
|
1518
|
+
"@id": "undefineds:dist/storage/quint/SqliteQuintStore.jsonld#SqliteQuintStore_options_textMaxBytes"
|
|
1505
1519
|
}
|
|
1506
1520
|
}
|
|
1507
1521
|
},
|
|
@@ -1539,6 +1553,13 @@
|
|
|
1539
1553
|
"options_debug": {
|
|
1540
1554
|
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_debug"
|
|
1541
1555
|
},
|
|
1556
|
+
"options_predicateObjectDataTypes": {
|
|
1557
|
+
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_predicateObjectDataTypes",
|
|
1558
|
+
"@container": "@list"
|
|
1559
|
+
},
|
|
1560
|
+
"options_textMaxBytes": {
|
|
1561
|
+
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_textMaxBytes"
|
|
1562
|
+
},
|
|
1542
1563
|
"driver": {
|
|
1543
1564
|
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_driver"
|
|
1544
1565
|
},
|
|
@@ -1568,6 +1589,13 @@
|
|
|
1568
1589
|
},
|
|
1569
1590
|
"debug": {
|
|
1570
1591
|
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_debug"
|
|
1592
|
+
},
|
|
1593
|
+
"predicateObjectDataTypes": {
|
|
1594
|
+
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_predicateObjectDataTypes",
|
|
1595
|
+
"@container": "@list"
|
|
1596
|
+
},
|
|
1597
|
+
"textMaxBytes": {
|
|
1598
|
+
"@id": "undefineds:dist/storage/quint/PgQuintStore.jsonld#PgQuintStore_options_textMaxBytes"
|
|
1571
1599
|
}
|
|
1572
1600
|
}
|
|
1573
1601
|
},
|
|
@@ -1577,6 +1605,23 @@
|
|
|
1577
1605
|
"@context": {
|
|
1578
1606
|
"options_debug": {
|
|
1579
1607
|
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_debug"
|
|
1608
|
+
},
|
|
1609
|
+
"options_predicateObjectDataTypes": {
|
|
1610
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes",
|
|
1611
|
+
"@container": "@list"
|
|
1612
|
+
},
|
|
1613
|
+
"options_textMaxBytes": {
|
|
1614
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_textMaxBytes"
|
|
1615
|
+
},
|
|
1616
|
+
"debug": {
|
|
1617
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_debug"
|
|
1618
|
+
},
|
|
1619
|
+
"predicateObjectDataTypes": {
|
|
1620
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes",
|
|
1621
|
+
"@container": "@list"
|
|
1622
|
+
},
|
|
1623
|
+
"textMaxBytes": {
|
|
1624
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_textMaxBytes"
|
|
1580
1625
|
}
|
|
1581
1626
|
}
|
|
1582
1627
|
},
|
|
@@ -23,6 +23,67 @@
|
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes",
|
|
29
|
+
"range": {
|
|
30
|
+
"@type": "ParameterRangeCollectEntries",
|
|
31
|
+
"parameterRangeCollectEntriesParameters": [
|
|
32
|
+
{
|
|
33
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes_key"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes_value",
|
|
37
|
+
"range": {
|
|
38
|
+
"@type": "ParameterRangeUnion",
|
|
39
|
+
"parameterRangeElements": [
|
|
40
|
+
{
|
|
41
|
+
"@type": "ParameterRangeLiteral",
|
|
42
|
+
"parameterRangeValueLiteral": "iri"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"@type": "ParameterRangeLiteral",
|
|
46
|
+
"parameterRangeValueLiteral": "blankNode"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"@type": "ParameterRangeLiteral",
|
|
50
|
+
"parameterRangeValueLiteral": "text"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"@type": "ParameterRangeLiteral",
|
|
54
|
+
"parameterRangeValueLiteral": "longText"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"@type": "ParameterRangeLiteral",
|
|
58
|
+
"parameterRangeValueLiteral": "numeric"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"@type": "ParameterRangeLiteral",
|
|
62
|
+
"parameterRangeValueLiteral": "dateTime"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"@type": "ParameterRangeLiteral",
|
|
66
|
+
"parameterRangeValueLiteral": "literal"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"comment": "Predicate-level RDF object data declarations. This declares schema value types, not query modes. The store derives whether exact/range/prefix/search can be pushed down from the data type."
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_textMaxBytes",
|
|
77
|
+
"range": {
|
|
78
|
+
"@type": "ParameterRangeUnion",
|
|
79
|
+
"parameterRangeElements": [
|
|
80
|
+
"xsd:number",
|
|
81
|
+
{
|
|
82
|
+
"@type": "ParameterRangeUndefined"
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
"comment": "Maximum serialized byte length that can be indexed as text. Longer undeclared text literals are stored as longText."
|
|
26
87
|
}
|
|
27
88
|
],
|
|
28
89
|
"memberFields": [
|
|
@@ -166,6 +227,27 @@
|
|
|
166
227
|
"value": {
|
|
167
228
|
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_debug"
|
|
168
229
|
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"keyRaw": "predicateObjectDataTypes",
|
|
233
|
+
"value": {
|
|
234
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes__constructorArgument",
|
|
235
|
+
"fields": [
|
|
236
|
+
{
|
|
237
|
+
"collectEntries": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes",
|
|
238
|
+
"key": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes_key",
|
|
239
|
+
"value": {
|
|
240
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_predicateObjectDataTypes_value"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"keyRaw": "textMaxBytes",
|
|
248
|
+
"value": {
|
|
249
|
+
"@id": "undefineds:dist/storage/quint/BaseQuintStore.jsonld#BaseQuintStore_options_textMaxBytes"
|
|
250
|
+
}
|
|
169
251
|
}
|
|
170
252
|
]
|
|
171
253
|
}
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* PostgreSQL 不支持 TEXT 字段中的 \0 (null) 字符,
|
|
9
9
|
* 所以我们需要对序列化的字符串进行转换。
|
|
10
10
|
*/
|
|
11
|
+
import type { Term } from '@rdfjs/types';
|
|
11
12
|
import { BaseQuintStore, type SqlExecutor } from './BaseQuintStore';
|
|
12
|
-
import type { QuintStoreOptions, Quint } from './types';
|
|
13
|
+
import type { AttributeMap, CompoundPattern, QuintStoreOptions, Quint, QuintPattern, QueryOptions } from './types';
|
|
13
14
|
/**
|
|
14
15
|
* PostgreSQL 连接配置
|
|
15
16
|
*/
|
|
@@ -51,11 +52,50 @@ export declare class PgQuintStore extends BaseQuintStore {
|
|
|
51
52
|
*/
|
|
52
53
|
open(): Promise<void>;
|
|
53
54
|
/**
|
|
54
|
-
* 重写 put
|
|
55
|
+
* 重写 put 方法,避免长文本对象进入 PostgreSQL btree 唯一键
|
|
55
56
|
*/
|
|
56
57
|
put(quint: Quint): Promise<void>;
|
|
57
58
|
/**
|
|
58
|
-
* 重写 multiPut
|
|
59
|
+
* 重写 multiPut 方法,使用同一事务保持批量写入幂等
|
|
59
60
|
*/
|
|
60
61
|
multiPut(quintList: Quint[]): Promise<void>;
|
|
62
|
+
multiDel(quintList: Quint[]): Promise<void>;
|
|
63
|
+
getAttributes(subjects: string[], predicates: string[], graph?: Term): Promise<AttributeMap>;
|
|
64
|
+
protected buildWhereClause(pattern: QuintPattern): {
|
|
65
|
+
whereClause: string;
|
|
66
|
+
params: any[];
|
|
67
|
+
};
|
|
68
|
+
private addPgCondition;
|
|
69
|
+
protected addAliasedConditions(conditions: string[], params: any[], alias: string, pattern: any): void;
|
|
70
|
+
protected buildCompoundQuery(compound: CompoundPattern, options?: QueryOptions): {
|
|
71
|
+
sql: string;
|
|
72
|
+
params: any[];
|
|
73
|
+
};
|
|
74
|
+
protected buildSelectQuery(pattern: QuintPattern, options?: QueryOptions): {
|
|
75
|
+
sql: string;
|
|
76
|
+
params: any[];
|
|
77
|
+
};
|
|
78
|
+
private ensureTypedObjectSchema;
|
|
79
|
+
private backfillMissingObjectIndexFields;
|
|
80
|
+
private quintToPgRow;
|
|
81
|
+
private objectIndexForTerm;
|
|
82
|
+
private objectIndexForSerialized;
|
|
83
|
+
private objectDigestForIndex;
|
|
84
|
+
private writeStatementsForRow;
|
|
85
|
+
private addObjectConditions;
|
|
86
|
+
private addObjectExactCondition;
|
|
87
|
+
private addObjectExactValueCondition;
|
|
88
|
+
private addObjectExactSerializedCondition;
|
|
89
|
+
private addObjectComparableCondition;
|
|
90
|
+
private addObjectTextCondition;
|
|
91
|
+
private objectPredicateForOperatorValue;
|
|
92
|
+
private objectFieldsForTerm;
|
|
93
|
+
private objectFieldsForSerialized;
|
|
94
|
+
private objectFieldsForPrefix;
|
|
95
|
+
private assertComparableObject;
|
|
96
|
+
private addAliasedObjectConditions;
|
|
97
|
+
private extractExactPredicate;
|
|
98
|
+
private resolveObjectDataTypeForPattern;
|
|
99
|
+
private addAliasedPgCondition;
|
|
100
|
+
private addFallbackAliasedCondition;
|
|
61
101
|
}
|