@undefineds.co/xpod 0.2.1 → 0.2.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.
@@ -23,5 +23,5 @@ export interface RuntimeBootstrapState {
23
23
  export declare function resolveRuntimeBootstrap(id: string, options: XpodRuntimeOptions, host: RuntimeHost, platform?: RuntimePlatform): Promise<RuntimeBootstrapState>;
24
24
  export declare function buildRuntimeEnv(state: RuntimeBootstrapState, options: XpodRuntimeOptions, envFromFile?: Record<string, string | undefined>): Record<string, string | undefined>;
25
25
  export declare function buildRuntimeShorthand(runtimeEnv: Record<string, string | undefined>, options: XpodRuntimeOptions, state: RuntimeBootstrapState, baseEnv?: Record<string, string | undefined>): Record<string, string | number | boolean>;
26
- export declare function createCssRuntimeConfig(state: RuntimeBootstrapState, open: boolean, platform?: Pick<RuntimePlatform, 'joinPath' | 'writeTextFile'>): string;
26
+ export declare function createCssRuntimeConfig(state: RuntimeBootstrapState, open: boolean, platform?: Pick<RuntimePlatform, 'dirname' | 'ensureDir' | 'joinPath' | 'writeTextFile'>): string;
27
27
  export declare function initRuntimeLogger(level: string, platform?: Pick<RuntimePlatform, 'cwd' | 'joinPath'>): void;
@@ -16,10 +16,36 @@ const NodeRuntimePlatform_1 = require("./platform/node/NodeRuntimePlatform");
16
16
  function ensureTrailingSlash(url) {
17
17
  return url.endsWith('/') ? url : `${url}/`;
18
18
  }
19
+ function normalizeWindowsAbsolutePath(filePath) {
20
+ return filePath.replace(/^[\\/]+(?=[A-Za-z]:[\\/])/, '');
21
+ }
22
+ function isWindowsAbsolutePath(filePath) {
23
+ return /^[A-Za-z]:[\\/]/.test(normalizeWindowsAbsolutePath(filePath));
24
+ }
25
+ function getWindowsDriveRoot(filePath) {
26
+ const normalizedPath = normalizeWindowsAbsolutePath(filePath);
27
+ return isWindowsAbsolutePath(normalizedPath) ? node_path_1.default.win32.parse(normalizedPath).root.toLowerCase() : undefined;
28
+ }
29
+ function arePathsOnDifferentWindowsDrives(firstPath, secondPath) {
30
+ const firstRoot = getWindowsDriveRoot(firstPath);
31
+ const secondRoot = getWindowsDriveRoot(secondPath);
32
+ return Boolean(firstRoot && secondRoot && firstRoot !== secondRoot);
33
+ }
34
+ function toWindowsFileUrl(filePath) {
35
+ const normalizedPath = normalizeWindowsAbsolutePath(filePath).replace(/\\/g, '/');
36
+ return new URL(`file:///${normalizedPath}`).href;
37
+ }
19
38
  function toConfigImportSpecifier(fromFilePath, toFilePath) {
20
- const useWindowsPaths = /^[A-Za-z]:[\\/]/.test(fromFilePath) || /^[A-Za-z]:[\\/]/.test(toFilePath);
39
+ const normalizedFromPath = normalizeWindowsAbsolutePath(fromFilePath);
40
+ const normalizedToPath = normalizeWindowsAbsolutePath(toFilePath);
41
+ const useWindowsPaths = isWindowsAbsolutePath(normalizedFromPath) || isWindowsAbsolutePath(normalizedToPath);
21
42
  const pathApi = useWindowsPaths ? node_path_1.default.win32 : node_path_1.default.posix;
22
- const relativePath = pathApi.relative(pathApi.dirname(fromFilePath), toFilePath).replace(/\\/g, '/');
43
+ const fromDirectoryPath = pathApi.dirname(useWindowsPaths ? normalizedFromPath : fromFilePath);
44
+ const targetPath = useWindowsPaths ? normalizedToPath : toFilePath;
45
+ if (useWindowsPaths && arePathsOnDifferentWindowsDrives(fromDirectoryPath, targetPath)) {
46
+ return toWindowsFileUrl(targetPath);
47
+ }
48
+ const relativePath = pathApi.relative(fromDirectoryPath, targetPath).replace(/\\/g, '/');
23
49
  if (relativePath.startsWith('./') || relativePath.startsWith('../')) {
24
50
  return relativePath;
25
51
  }
@@ -154,12 +180,19 @@ function buildRuntimeShorthand(runtimeEnv, options, state, baseEnv = NodeRuntime
154
180
  };
155
181
  }
156
182
  function createCssRuntimeConfig(state, open, platform = NodeRuntimePlatform_1.nodeRuntimePlatform) {
157
- const configPath = platform.joinPath(package_root_1.PACKAGE_ROOT, `config/${state.mode}.json`);
183
+ const configPath = normalizeWindowsAbsolutePath(platform.joinPath(package_root_1.PACKAGE_ROOT, `config/${state.mode}.json`));
158
184
  if (!open) {
159
185
  return configPath;
160
186
  }
161
- const runtimeConfigPath = platform.joinPath(state.runtimeRoot, 'css-runtime.config.json');
162
- const openConfigPath = platform.joinPath(package_root_1.PACKAGE_ROOT, 'config/runtime-open.json');
187
+ const runtimeRoot = normalizeWindowsAbsolutePath(state.runtimeRoot);
188
+ const runtimeConfigPath = arePathsOnDifferentWindowsDrives(runtimeRoot, configPath)
189
+ ? (() => {
190
+ const runtimeConfigDir = normalizeWindowsAbsolutePath(platform.joinPath(platform.dirname(configPath), '..', '.xpod-runtime', state.id));
191
+ platform.ensureDir(runtimeConfigDir);
192
+ return normalizeWindowsAbsolutePath(platform.joinPath(runtimeConfigDir, 'css-runtime.config.json'));
193
+ })()
194
+ : normalizeWindowsAbsolutePath(platform.joinPath(runtimeRoot, 'css-runtime.config.json'));
195
+ const openConfigPath = normalizeWindowsAbsolutePath(platform.joinPath(package_root_1.PACKAGE_ROOT, 'config/runtime-open.json'));
163
196
  platform.writeTextFile(runtimeConfigPath, JSON.stringify({
164
197
  '@context': [
165
198
  'https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^8.0.0/components/context.jsonld',
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/runtime/bootstrap.ts"],"names":[],"mappings":"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","sourcesContent":["import { setGlobalLoggerFactory } from 'global-logger-factory';\nimport path from 'node:path';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\nimport { PACKAGE_ROOT } from './package-root';\nimport type { RuntimeHost } from './host/types';\nimport { nodeRuntimePlatform } from './platform/node/NodeRuntimePlatform';\nimport type { RuntimePlatform } from './platform/types';\nimport type { XpodRuntimeOptions, XpodRuntimePorts, XpodRuntimeSockets } from './runtime-types';\n\nexport interface RuntimeBootstrapState {\n id: string;\n host: RuntimeHost;\n mode: 'local' | 'cloud';\n transport: 'socket' | 'port';\n bindHost: string;\n runtimeRoot: string;\n rootFilePath: string;\n sparqlEndpoint: string;\n identityDbUrl: string;\n usageDbUrl: string;\n cssAuthMode: 'acp' | 'acl' | 'allow-all';\n apiOpen: boolean;\n logLevel: string;\n baseUrl: string;\n envFilePath?: string;\n ports: XpodRuntimePorts;\n sockets: XpodRuntimeSockets;\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\nfunction toConfigImportSpecifier(fromFilePath: string, toFilePath: string): string {\n const useWindowsPaths = /^[A-Za-z]:[\\\\/]/.test(fromFilePath) || /^[A-Za-z]:[\\\\/]/.test(toFilePath);\n const pathApi = useWindowsPaths ? path.win32 : path.posix;\n const relativePath = pathApi.relative(pathApi.dirname(fromFilePath), toFilePath).replace(/\\\\/g, '/');\n if (relativePath.startsWith('./') || relativePath.startsWith('../')) {\n return relativePath;\n }\n return `./${relativePath}`;\n}\n\nfunction withDefinedEntries(entries: Array<[string, string | number | boolean | undefined]>): Record<string, string | number | boolean> {\n const result: Record<string, string | number | boolean> = {};\n for (const [key, value] of entries) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction normalizeDatabaseUrl(\n value: string,\n platform: Pick<RuntimePlatform, 'resolvePath'> = nodeRuntimePlatform,\n): string {\n if (\n value.startsWith('sqlite:') ||\n value.startsWith('postgres://') ||\n value.startsWith('postgresql://') ||\n value.startsWith('mysql://')\n ) {\n return value;\n }\n return `sqlite:${platform.resolvePath(value)}`;\n}\n\nexport async function resolveRuntimeBootstrap(\n id: string,\n options: XpodRuntimeOptions,\n host: RuntimeHost,\n platform: RuntimePlatform = nodeRuntimePlatform,\n): Promise<RuntimeBootstrapState> {\n const mode = options.mode ?? 'local';\n const transport = host.resolveTransport(options.transport);\n const bindHost = options.bindHost ?? '127.0.0.1';\n const runtimeRoot = platform.resolvePath(options.runtimeRoot ?? platform.joinPath(platform.cwd(), '.test-data', 'xpod-runtime', id));\n const rootFilePath = platform.resolvePath(options.rootFilePath ?? platform.joinPath(runtimeRoot, 'data'));\n const sparqlEndpoint = normalizeDatabaseUrl(options.sparqlEndpoint ?? platform.joinPath(runtimeRoot, 'quadstore.sqlite'), platform);\n const identityDbUrl = normalizeDatabaseUrl(options.identityDbUrl ?? platform.joinPath(runtimeRoot, 'identity.sqlite'), platform);\n const usageDbUrl = normalizeDatabaseUrl(options.usageDbUrl ?? platform.joinPath(runtimeRoot, 'usage.sqlite'), platform);\n const cssAuthMode = options.authMode ?? (options.open ? 'allow-all' : 'acp');\n const apiOpen = options.apiOpen ?? options.open ?? false;\n const logLevel = options.logLevel ?? platform.getEnv('CSS_LOGGING_LEVEL') ?? 'warn';\n\n platform.ensureDir(runtimeRoot);\n platform.ensureDir(rootFilePath);\n\n const socketsRoot = platform.joinPath(runtimeRoot, 'sockets');\n if (transport === 'socket') {\n platform.ensureDir(socketsRoot);\n }\n const ports: XpodRuntimePorts = transport === 'port'\n ? await host.allocatePorts({\n gatewayPort: options.gatewayPort,\n cssPort: options.cssPort,\n apiPort: options.apiPort,\n basePort: 5600,\n })\n : {};\n const sockets: XpodRuntimeSockets = {};\n\n if (transport === 'socket') {\n sockets.gateway = platform.resolvePath(options.gatewaySocketPath ?? platform.joinPath(socketsRoot, 'gateway.sock'));\n sockets.css = platform.resolvePath(options.cssSocketPath ?? platform.joinPath(socketsRoot, 'css.sock'));\n sockets.api = platform.resolvePath(options.apiSocketPath ?? platform.joinPath(socketsRoot, 'api.sock'));\n }\n\n const baseUrl = ensureTrailingSlash(\n options.baseUrl ?? (transport === 'socket'\n ? 'http://localhost'\n : `http://${bindHost}:${ports.gateway}`),\n );\n\n return {\n id,\n host,\n mode,\n transport,\n bindHost,\n runtimeRoot,\n rootFilePath,\n sparqlEndpoint,\n identityDbUrl,\n usageDbUrl,\n cssAuthMode,\n apiOpen,\n logLevel,\n baseUrl,\n envFilePath: options.envFile ? platform.resolvePath(options.envFile) : undefined,\n ports,\n sockets,\n };\n}\n\nexport function buildRuntimeEnv(\n state: RuntimeBootstrapState,\n options: XpodRuntimeOptions,\n envFromFile: Record<string, string | undefined> = {},\n): Record<string, string | undefined> {\n return {\n ...envFromFile,\n ...options.env,\n XPOD_ENV_PATH: state.envFilePath,\n XPOD_EDITION: state.mode,\n CSS_BASE_URL: state.baseUrl,\n CSS_TOKEN_ENDPOINT: `${state.baseUrl}.oidc/token`,\n CSS_ROOT_FILE_PATH: state.rootFilePath,\n CSS_IDENTITY_DB_URL: state.identityDbUrl,\n DATABASE_URL: state.identityDbUrl,\n CSS_PORT: state.ports.css !== undefined ? String(state.ports.css) : undefined,\n API_PORT: state.ports.api !== undefined ? String(state.ports.api) : undefined,\n API_HOST: state.bindHost,\n API_SOCKET_PATH: state.sockets.api,\n XPOD_MAIN_PORT: state.ports.gateway !== undefined ? String(state.ports.gateway) : undefined,\n CORS_ORIGINS: new URL(state.baseUrl).origin,\n CSS_LOGGING_LEVEL: state.logLevel,\n };\n}\n\nexport function buildRuntimeShorthand(\n runtimeEnv: Record<string, string | undefined>,\n options: XpodRuntimeOptions,\n state: RuntimeBootstrapState,\n baseEnv: Record<string, string | undefined> = nodeRuntimePlatform.baseEnv,\n): Record<string, string | number | boolean> {\n const envValue = (key: string): string | undefined => runtimeEnv[key] ?? baseEnv[key];\n\n return {\n ...withDefinedEntries([\n ['baseStorageDomain', envValue('CSS_BASE_STORAGE_DOMAIN')],\n ['minioAccessKey', envValue('CSS_MINIO_ACCESS_KEY')],\n ['minioSecretKey', envValue('CSS_MINIO_SECRET_KEY')],\n ['minioEndpoint', envValue('CSS_MINIO_ENDPOINT')],\n ['minioBucketName', envValue('CSS_MINIO_BUCKET_NAME')],\n ['redisClient', envValue('CSS_REDIS_CLIENT')],\n ['redisUsername', envValue('CSS_REDIS_USERNAME')],\n ['redisPassword', envValue('CSS_REDIS_PASSWORD')],\n ['emailConfigHost', envValue('CSS_EMAIL_CONFIG_HOST')],\n ['emailConfigPort', envValue('CSS_EMAIL_CONFIG_PORT')],\n ['emailConfigAuthUser', envValue('CSS_EMAIL_CONFIG_AUTH_USER')],\n ['emailConfigAuthPass', envValue('CSS_EMAIL_CONFIG_AUTH_PASS')],\n ['idpUrl', envValue('CSS_IDP_URL') ?? envValue('XPOD_CLOUD_API_ENDPOINT')],\n ['allowedHosts', envValue('CSS_ALLOWED_HOSTS')],\n ['nodeId', envValue('XPOD_NODE_ID')],\n ['nodeToken', envValue('XPOD_NODE_TOKEN')],\n ['serviceToken', envValue('XPOD_SERVICE_TOKEN')],\n ]),\n baseUrl: state.baseUrl,\n rootFilePath: state.rootFilePath,\n sparqlEndpoint: state.sparqlEndpoint,\n identityDbUrl: state.identityDbUrl,\n usageDbUrl: state.usageDbUrl,\n logLevel: state.logLevel,\n authMode: state.cssAuthMode,\n edition: state.mode === 'cloud' ? 'server' : 'local',\n edgeNodesEnabled: options.edgeNodesEnabled ?? false,\n centerRegistrationEnabled: options.centerRegistrationEnabled ?? false,\n ...(options.shorthand ?? {}),\n };\n}\n\nexport function createCssRuntimeConfig(\n state: RuntimeBootstrapState,\n open: boolean,\n platform: Pick<RuntimePlatform, 'joinPath' | 'writeTextFile'> = nodeRuntimePlatform,\n): string {\n const configPath = platform.joinPath(PACKAGE_ROOT, `config/${state.mode}.json`);\n if (!open) {\n return configPath;\n }\n\n const runtimeConfigPath = platform.joinPath(state.runtimeRoot, 'css-runtime.config.json');\n const openConfigPath = platform.joinPath(PACKAGE_ROOT, 'config/runtime-open.json');\n platform.writeTextFile(runtimeConfigPath, JSON.stringify({\n '@context': [\n 'https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^8.0.0/components/context.jsonld',\n 'https://linkedsoftwaredependencies.org/bundles/npm/asynchronous-handlers/^1.0.0/components/context.jsonld',\n ],\n import: [\n toConfigImportSpecifier(runtimeConfigPath, configPath),\n toConfigImportSpecifier(runtimeConfigPath, openConfigPath),\n ],\n }, null, 2));\n\n return runtimeConfigPath;\n}\n\nexport function initRuntimeLogger(\n level: string,\n platform: Pick<RuntimePlatform, 'cwd' | 'joinPath'> = nodeRuntimePlatform,\n): void {\n const loggerFactory = new ConfigurableLoggerFactory(level, {\n fileName: platform.joinPath(platform.cwd(), 'logs/xpod-%DATE%.log'),\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n}\n"]}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/runtime/bootstrap.ts"],"names":[],"mappings":"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","sourcesContent":["import { setGlobalLoggerFactory } from 'global-logger-factory';\nimport path from 'node:path';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\nimport { PACKAGE_ROOT } from './package-root';\nimport type { RuntimeHost } from './host/types';\nimport { nodeRuntimePlatform } from './platform/node/NodeRuntimePlatform';\nimport type { RuntimePlatform } from './platform/types';\nimport type { XpodRuntimeOptions, XpodRuntimePorts, XpodRuntimeSockets } from './runtime-types';\n\nexport interface RuntimeBootstrapState {\n id: string;\n host: RuntimeHost;\n mode: 'local' | 'cloud';\n transport: 'socket' | 'port';\n bindHost: string;\n runtimeRoot: string;\n rootFilePath: string;\n sparqlEndpoint: string;\n identityDbUrl: string;\n usageDbUrl: string;\n cssAuthMode: 'acp' | 'acl' | 'allow-all';\n apiOpen: boolean;\n logLevel: string;\n baseUrl: string;\n envFilePath?: string;\n ports: XpodRuntimePorts;\n sockets: XpodRuntimeSockets;\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\nfunction normalizeWindowsAbsolutePath(filePath: string): string {\n return filePath.replace(/^[\\\\/]+(?=[A-Za-z]:[\\\\/])/, '');\n}\n\nfunction isWindowsAbsolutePath(filePath: string): boolean {\n return /^[A-Za-z]:[\\\\/]/.test(normalizeWindowsAbsolutePath(filePath));\n}\n\nfunction getWindowsDriveRoot(filePath: string): string | undefined {\n const normalizedPath = normalizeWindowsAbsolutePath(filePath);\n return isWindowsAbsolutePath(normalizedPath) ? path.win32.parse(normalizedPath).root.toLowerCase() : undefined;\n}\n\nfunction arePathsOnDifferentWindowsDrives(firstPath: string, secondPath: string): boolean {\n const firstRoot = getWindowsDriveRoot(firstPath);\n const secondRoot = getWindowsDriveRoot(secondPath);\n return Boolean(firstRoot && secondRoot && firstRoot !== secondRoot);\n}\n\nfunction toWindowsFileUrl(filePath: string): string {\n const normalizedPath = normalizeWindowsAbsolutePath(filePath).replace(/\\\\/g, '/');\n return new URL(`file:///${normalizedPath}`).href;\n}\n\nfunction toConfigImportSpecifier(fromFilePath: string, toFilePath: string): string {\n const normalizedFromPath = normalizeWindowsAbsolutePath(fromFilePath);\n const normalizedToPath = normalizeWindowsAbsolutePath(toFilePath);\n const useWindowsPaths = isWindowsAbsolutePath(normalizedFromPath) || isWindowsAbsolutePath(normalizedToPath);\n const pathApi = useWindowsPaths ? path.win32 : path.posix;\n const fromDirectoryPath = pathApi.dirname(useWindowsPaths ? normalizedFromPath : fromFilePath);\n const targetPath = useWindowsPaths ? normalizedToPath : toFilePath;\n\n if (useWindowsPaths && arePathsOnDifferentWindowsDrives(fromDirectoryPath, targetPath)) {\n return toWindowsFileUrl(targetPath);\n }\n\n const relativePath = pathApi.relative(fromDirectoryPath, targetPath).replace(/\\\\/g, '/');\n if (relativePath.startsWith('./') || relativePath.startsWith('../')) {\n return relativePath;\n }\n return `./${relativePath}`;\n}\n\nfunction withDefinedEntries(entries: Array<[string, string | number | boolean | undefined]>): Record<string, string | number | boolean> {\n const result: Record<string, string | number | boolean> = {};\n for (const [key, value] of entries) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction normalizeDatabaseUrl(\n value: string,\n platform: Pick<RuntimePlatform, 'resolvePath'> = nodeRuntimePlatform,\n): string {\n if (\n value.startsWith('sqlite:') ||\n value.startsWith('postgres://') ||\n value.startsWith('postgresql://') ||\n value.startsWith('mysql://')\n ) {\n return value;\n }\n return `sqlite:${platform.resolvePath(value)}`;\n}\n\nexport async function resolveRuntimeBootstrap(\n id: string,\n options: XpodRuntimeOptions,\n host: RuntimeHost,\n platform: RuntimePlatform = nodeRuntimePlatform,\n): Promise<RuntimeBootstrapState> {\n const mode = options.mode ?? 'local';\n const transport = host.resolveTransport(options.transport);\n const bindHost = options.bindHost ?? '127.0.0.1';\n const runtimeRoot = platform.resolvePath(options.runtimeRoot ?? platform.joinPath(platform.cwd(), '.test-data', 'xpod-runtime', id));\n const rootFilePath = platform.resolvePath(options.rootFilePath ?? platform.joinPath(runtimeRoot, 'data'));\n const sparqlEndpoint = normalizeDatabaseUrl(options.sparqlEndpoint ?? platform.joinPath(runtimeRoot, 'quadstore.sqlite'), platform);\n const identityDbUrl = normalizeDatabaseUrl(options.identityDbUrl ?? platform.joinPath(runtimeRoot, 'identity.sqlite'), platform);\n const usageDbUrl = normalizeDatabaseUrl(options.usageDbUrl ?? platform.joinPath(runtimeRoot, 'usage.sqlite'), platform);\n const cssAuthMode = options.authMode ?? (options.open ? 'allow-all' : 'acp');\n const apiOpen = options.apiOpen ?? options.open ?? false;\n const logLevel = options.logLevel ?? platform.getEnv('CSS_LOGGING_LEVEL') ?? 'warn';\n\n platform.ensureDir(runtimeRoot);\n platform.ensureDir(rootFilePath);\n\n const socketsRoot = platform.joinPath(runtimeRoot, 'sockets');\n if (transport === 'socket') {\n platform.ensureDir(socketsRoot);\n }\n const ports: XpodRuntimePorts = transport === 'port'\n ? await host.allocatePorts({\n gatewayPort: options.gatewayPort,\n cssPort: options.cssPort,\n apiPort: options.apiPort,\n basePort: 5600,\n })\n : {};\n const sockets: XpodRuntimeSockets = {};\n\n if (transport === 'socket') {\n sockets.gateway = platform.resolvePath(options.gatewaySocketPath ?? platform.joinPath(socketsRoot, 'gateway.sock'));\n sockets.css = platform.resolvePath(options.cssSocketPath ?? platform.joinPath(socketsRoot, 'css.sock'));\n sockets.api = platform.resolvePath(options.apiSocketPath ?? platform.joinPath(socketsRoot, 'api.sock'));\n }\n\n const baseUrl = ensureTrailingSlash(\n options.baseUrl ?? (transport === 'socket'\n ? 'http://localhost'\n : `http://${bindHost}:${ports.gateway}`),\n );\n\n return {\n id,\n host,\n mode,\n transport,\n bindHost,\n runtimeRoot,\n rootFilePath,\n sparqlEndpoint,\n identityDbUrl,\n usageDbUrl,\n cssAuthMode,\n apiOpen,\n logLevel,\n baseUrl,\n envFilePath: options.envFile ? platform.resolvePath(options.envFile) : undefined,\n ports,\n sockets,\n };\n}\n\nexport function buildRuntimeEnv(\n state: RuntimeBootstrapState,\n options: XpodRuntimeOptions,\n envFromFile: Record<string, string | undefined> = {},\n): Record<string, string | undefined> {\n return {\n ...envFromFile,\n ...options.env,\n XPOD_ENV_PATH: state.envFilePath,\n XPOD_EDITION: state.mode,\n CSS_BASE_URL: state.baseUrl,\n CSS_TOKEN_ENDPOINT: `${state.baseUrl}.oidc/token`,\n CSS_ROOT_FILE_PATH: state.rootFilePath,\n CSS_IDENTITY_DB_URL: state.identityDbUrl,\n DATABASE_URL: state.identityDbUrl,\n CSS_PORT: state.ports.css !== undefined ? String(state.ports.css) : undefined,\n API_PORT: state.ports.api !== undefined ? String(state.ports.api) : undefined,\n API_HOST: state.bindHost,\n API_SOCKET_PATH: state.sockets.api,\n XPOD_MAIN_PORT: state.ports.gateway !== undefined ? String(state.ports.gateway) : undefined,\n CORS_ORIGINS: new URL(state.baseUrl).origin,\n CSS_LOGGING_LEVEL: state.logLevel,\n };\n}\n\nexport function buildRuntimeShorthand(\n runtimeEnv: Record<string, string | undefined>,\n options: XpodRuntimeOptions,\n state: RuntimeBootstrapState,\n baseEnv: Record<string, string | undefined> = nodeRuntimePlatform.baseEnv,\n): Record<string, string | number | boolean> {\n const envValue = (key: string): string | undefined => runtimeEnv[key] ?? baseEnv[key];\n\n return {\n ...withDefinedEntries([\n ['baseStorageDomain', envValue('CSS_BASE_STORAGE_DOMAIN')],\n ['minioAccessKey', envValue('CSS_MINIO_ACCESS_KEY')],\n ['minioSecretKey', envValue('CSS_MINIO_SECRET_KEY')],\n ['minioEndpoint', envValue('CSS_MINIO_ENDPOINT')],\n ['minioBucketName', envValue('CSS_MINIO_BUCKET_NAME')],\n ['redisClient', envValue('CSS_REDIS_CLIENT')],\n ['redisUsername', envValue('CSS_REDIS_USERNAME')],\n ['redisPassword', envValue('CSS_REDIS_PASSWORD')],\n ['emailConfigHost', envValue('CSS_EMAIL_CONFIG_HOST')],\n ['emailConfigPort', envValue('CSS_EMAIL_CONFIG_PORT')],\n ['emailConfigAuthUser', envValue('CSS_EMAIL_CONFIG_AUTH_USER')],\n ['emailConfigAuthPass', envValue('CSS_EMAIL_CONFIG_AUTH_PASS')],\n ['idpUrl', envValue('CSS_IDP_URL') ?? envValue('XPOD_CLOUD_API_ENDPOINT')],\n ['allowedHosts', envValue('CSS_ALLOWED_HOSTS')],\n ['nodeId', envValue('XPOD_NODE_ID')],\n ['nodeToken', envValue('XPOD_NODE_TOKEN')],\n ['serviceToken', envValue('XPOD_SERVICE_TOKEN')],\n ]),\n baseUrl: state.baseUrl,\n rootFilePath: state.rootFilePath,\n sparqlEndpoint: state.sparqlEndpoint,\n identityDbUrl: state.identityDbUrl,\n usageDbUrl: state.usageDbUrl,\n logLevel: state.logLevel,\n authMode: state.cssAuthMode,\n edition: state.mode === 'cloud' ? 'server' : 'local',\n edgeNodesEnabled: options.edgeNodesEnabled ?? false,\n centerRegistrationEnabled: options.centerRegistrationEnabled ?? false,\n ...(options.shorthand ?? {}),\n };\n}\n\nexport function createCssRuntimeConfig(\n state: RuntimeBootstrapState,\n open: boolean,\n platform: Pick<RuntimePlatform, 'dirname' | 'ensureDir' | 'joinPath' | 'writeTextFile'> = nodeRuntimePlatform,\n): string {\n const configPath = normalizeWindowsAbsolutePath(platform.joinPath(PACKAGE_ROOT, `config/${state.mode}.json`));\n if (!open) {\n return configPath;\n }\n\n const runtimeRoot = normalizeWindowsAbsolutePath(state.runtimeRoot);\n const runtimeConfigPath = arePathsOnDifferentWindowsDrives(runtimeRoot, configPath)\n ? (() => {\n const runtimeConfigDir = normalizeWindowsAbsolutePath(platform.joinPath(\n platform.dirname(configPath),\n '..',\n '.xpod-runtime',\n state.id,\n ));\n platform.ensureDir(runtimeConfigDir);\n return normalizeWindowsAbsolutePath(platform.joinPath(runtimeConfigDir, 'css-runtime.config.json'));\n })()\n : normalizeWindowsAbsolutePath(platform.joinPath(runtimeRoot, 'css-runtime.config.json'));\n const openConfigPath = normalizeWindowsAbsolutePath(platform.joinPath(PACKAGE_ROOT, 'config/runtime-open.json'));\n platform.writeTextFile(runtimeConfigPath, JSON.stringify({\n '@context': [\n 'https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^8.0.0/components/context.jsonld',\n 'https://linkedsoftwaredependencies.org/bundles/npm/asynchronous-handlers/^1.0.0/components/context.jsonld',\n ],\n import: [\n toConfigImportSpecifier(runtimeConfigPath, configPath),\n toConfigImportSpecifier(runtimeConfigPath, openConfigPath),\n ],\n }, null, 2));\n\n return runtimeConfigPath;\n}\n\nexport function initRuntimeLogger(\n level: string,\n platform: Pick<RuntimePlatform, 'cwd' | 'joinPath'> = nodeRuntimePlatform,\n): void {\n const loggerFactory = new ConfigurableLoggerFactory(level, {\n fileName: platform.joinPath(platform.cwd(), 'logs/xpod-%DATE%.log'),\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n}\n"]}
@@ -21,6 +21,7 @@ export declare class SqliteVectorStore extends VectorStore implements Initializa
21
21
  close(): Promise<void>;
22
22
  private ensureOpen;
23
23
  private getTableName;
24
+ private getCountTableCandidates;
24
25
  private getDimension;
25
26
  ensureVectorTable(modelId: string): Promise<void>;
26
27
  dropVectorTable(modelId: string): Promise<void>;
@@ -83,6 +83,14 @@ class SqliteVectorStore extends VectorStore_1.VectorStore {
83
83
  getTableName(modelId) {
84
84
  return `vec_${(0, VectorStore_1.hashModelId)(modelId)}`;
85
85
  }
86
+ getCountTableCandidates(modelIdOrTableName) {
87
+ const candidates = [];
88
+ if (modelIdOrTableName.startsWith('vec_')) {
89
+ candidates.push(modelIdOrTableName);
90
+ }
91
+ candidates.push(this.getTableName(modelIdOrTableName));
92
+ return [...new Set(candidates)];
93
+ }
86
94
  getDimension() {
87
95
  return this.defaultDimension;
88
96
  }
@@ -122,7 +130,13 @@ class SqliteVectorStore extends VectorStore_1.VectorStore {
122
130
  const db = this.ensureOpen();
123
131
  try {
124
132
  const rows = db
125
- .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'vec_%'`)
133
+ .prepare(`
134
+ SELECT name
135
+ FROM sqlite_master
136
+ WHERE type = 'table'
137
+ AND name LIKE 'vec_%'
138
+ AND sql LIKE '%USING vec0%'
139
+ `)
126
140
  .all();
127
141
  return rows.map((r) => r.name);
128
142
  }
@@ -226,14 +240,16 @@ class SqliteVectorStore extends VectorStore_1.VectorStore {
226
240
  // ============================================
227
241
  async countVectors(modelId) {
228
242
  const db = this.ensureOpen();
229
- const tableName = this.getTableName(modelId);
230
- try {
231
- const row = db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).get();
232
- return row?.count ?? 0;
233
- }
234
- catch {
235
- return 0;
243
+ for (const tableName of this.getCountTableCandidates(modelId)) {
244
+ try {
245
+ const row = db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).get();
246
+ return row?.count ?? 0;
247
+ }
248
+ catch {
249
+ continue;
250
+ }
236
251
  }
252
+ return 0;
237
253
  }
238
254
  // ============================================
239
255
  // 迁移支持
@@ -1 +1 @@
1
- {"version":3,"file":"SqliteVectorStore.js","sourceRoot":"","sources":["../../../src/storage/vector/SqliteVectorStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SqliteVectorStore - SQLite 向量存储实现(使用 sqlite-vec 扩展)\n *\n * 设计思路:\n * - sqlite-vec 的 vec0 表使用 rowid 作为主键\n * - rowid 直接与 quints 表的 rowid 对应,无需额外映射\n * - 通过 rowid JOIN quints 表即可关联业务数据\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport type { Finalizable, Initializable } from '@solid/community-server';\nimport { VectorStore, hashModelId } from './VectorStore';\nimport type { VectorRecord, VectorSearchOptions, VectorSearchResult, VectorStoreOptions } from './types';\nimport { getSqliteRuntime, type SqliteDatabase } from '../SqliteRuntime';\nimport { loadSqliteVecExtension } from './SqliteVecExtension';\n\nexport class SqliteVectorStore extends VectorStore implements Initializable, Finalizable {\n /** @ignored */\n private db: SqliteDatabase | null = null;\n private readonly filename: string;\n private readonly sqliteRuntime = getSqliteRuntime();\n\n public constructor(options: VectorStoreOptions) {\n super();\n let connStr = options.connectionString;\n if (connStr.startsWith('sqlite:')) {\n connStr = connStr.slice(7);\n }\n this.filename = connStr;\n }\n\n // ============================================\n // Lifecycle (Initializable / Finalizable)\n // ============================================\n\n public async initialize(): Promise<void> {\n await this.open();\n }\n\n public async finalize(): Promise<void> {\n await this.close();\n }\n\n public override async open(): Promise<void> {\n if (this.db) return;\n\n // 确保目录存在\n if (this.filename !== ':memory:') {\n const dir = path.dirname(this.filename);\n if (dir && dir !== '.' && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n }\n\n this.db = this.sqliteRuntime.openDatabase(this.filename);\n loadSqliteVecExtension(this.db);\n\n if (this.filename !== ':memory:') {\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('busy_timeout = 5000');\n }\n }\n\n public override async close(): Promise<void> {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n\n private ensureOpen(): SqliteDatabase {\n if (!this.db) {\n // 懒初始化:如果尚未打开,则自动打开\n // 确保目录存在\n if (this.filename !== ':memory:') {\n const dir = path.dirname(this.filename);\n if (dir && dir !== '.' && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n }\n\n this.db = this.sqliteRuntime.openDatabase(this.filename);\n loadSqliteVecExtension(this.db);\n\n if (this.filename !== ':memory:') {\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('busy_timeout = 5000');\n }\n }\n return this.db;\n }\n\n private getTableName(modelId: string): string {\n return `vec_${hashModelId(modelId)}`;\n }\n\n private getDimension(): number {\n return this.defaultDimension;\n }\n\n // ============================================\n // 向量表管理\n // ============================================\n\n public override async ensureVectorTable(modelId: string): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n // 使用 sqlite-vec 的 vec0 虚拟表\n // rowid 作为主键,与 quints 表的 rowid 对应\n db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS ${tableName} USING vec0(\n embedding float[${this.getDimension()}]\n )\n `);\n }\n\n public override async dropVectorTable(modelId: string): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n db.exec(`DROP TABLE IF EXISTS ${tableName}`);\n }\n\n public override async hasVectorTable(modelId: string): Promise<boolean> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n try {\n const row = db\n .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n .get(tableName) as { name: string } | undefined;\n return !!row;\n } catch {\n return false;\n }\n }\n\n public override async listVectorTables(): Promise<string[]> {\n const db = this.ensureOpen();\n\n try {\n const rows = db\n .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'vec_%'`)\n .all() as { name: string }[];\n return rows.map((r) => r.name);\n } catch {\n return [];\n }\n }\n\n // ============================================\n // 向量操作\n // ============================================\n\n public override async upsertVector(modelId: string, id: number, embedding: number[]): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n // 转换为 BigInt 以确保 sqlite-vec 识别为整数\n const bigId = BigInt(Math.floor(id));\n\n // sqlite-vec 不支持 UPDATE,需要先删除再插入\n db.prepare(`DELETE FROM ${tableName} WHERE rowid = ?`).run(bigId);\n\n // 使用 rowid 作为主键插入向量\n db.prepare(\n `INSERT INTO ${tableName} (rowid, embedding) VALUES (?, ?)`\n ).run(bigId, JSON.stringify(embedding));\n }\n\n public override async batchUpsertVectors(modelId: string, records: { id: number; embedding: number[] }[]): Promise<void> {\n if (records.length === 0) return;\n\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n const transaction = db.transaction((recs: typeof records) => {\n for (const rec of recs) {\n // 转换为 BigInt 以确保 sqlite-vec 识别为整数\n const bigId = BigInt(Math.floor(rec.id));\n\n // sqlite-vec 不支持 UPDATE,需要先删除再插入\n db.prepare(`DELETE FROM ${tableName} WHERE rowid = ?`).run(bigId);\n db.prepare(\n `INSERT INTO ${tableName} (rowid, embedding) VALUES (?, ?)`\n ).run(bigId, JSON.stringify(rec.embedding));\n }\n });\n\n transaction(records);\n }\n\n public override async getVector(modelId: string, id: number): Promise<VectorRecord | null> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n try {\n const row = db.prepare(`SELECT rowid, embedding FROM ${tableName} WHERE rowid = ?`).get(id) as any;\n return row ? this.rowToVector(row) : null;\n } catch {\n return null;\n }\n }\n\n public override async deleteVector(modelId: string, id: number): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n db.prepare(`DELETE FROM ${tableName} WHERE rowid = ?`).run(id);\n }\n\n public override async batchDeleteVectors(modelId: string, ids: number[]): Promise<void> {\n if (ids.length === 0) return;\n\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n const placeholders = ids.map(() => '?').join(',');\n db.prepare(`DELETE FROM ${tableName} WHERE rowid IN (${placeholders})`).run(...ids);\n }\n\n public override async search(modelId: string, queryEmbedding: number[], options: VectorSearchOptions = {}): Promise<VectorSearchResult[]> {\n const db = this.ensureOpen();\n\n const { limit = 10, threshold, excludeIds } = options;\n const tableName = this.getTableName(modelId);\n\n try {\n // 使用 sqlite-vec 的近似最近邻搜索\n // 注意:sqlite-vec 要求在 MATCH 中使用 k=? 参数\n const sql = `\n SELECT\n rowid as id,\n distance\n FROM ${tableName}\n WHERE embedding MATCH ?\n AND k = ?\n ORDER BY distance\n `;\n\n const rows = db.prepare(sql).all(JSON.stringify(queryEmbedding), limit * 2) as { id: number; distance: number }[];\n\n const results: VectorSearchResult[] = [];\n\n for (const row of rows) {\n if (excludeIds?.has(row.id)) continue;\n\n const distance = row.distance;\n // sqlite-vec 使用 L2 距离,对于归一化向量,转换为余弦相似度:\n // L2² = 2 * (1 - cosine_similarity)\n // cosine_similarity = 1 - L2² / 2\n // score 限制在 [0, 1] 范围内\n const score = Math.max(0, Math.min(1, 1 - (distance * distance) / 2));\n\n if (threshold !== undefined && score < threshold) continue;\n\n results.push({ id: row.id, distance, score });\n }\n\n return results.slice(0, limit);\n } catch (e) {\n // sqlite-vec 扩展不可用时抛出错误\n throw new Error(`sqlite-vec search failed: ${e}`);\n }\n }\n\n // ============================================\n // 统计\n // ============================================\n\n public override async countVectors(modelId: string): Promise<number> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n try {\n const row = db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).get() as any;\n return row?.count ?? 0;\n } catch {\n return 0;\n }\n }\n\n // ============================================\n // 迁移支持\n // ============================================\n\n public override async getVectorIds(modelId: string, options: { limit?: number; afterId?: number } = {}): Promise<number[]> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n const { limit = 1000, afterId } = options;\n\n try {\n const sql = afterId !== undefined\n ? `SELECT rowid FROM ${tableName} WHERE rowid > ? ORDER BY rowid LIMIT ?`\n : `SELECT rowid FROM ${tableName} ORDER BY rowid LIMIT ?`;\n const params = afterId !== undefined ? [afterId, limit] : [limit];\n const rows = db.prepare(sql).all(...params) as any[];\n return rows.map((r) => r.rowid);\n } catch {\n return [];\n }\n }\n\n // ============================================\n // 行转换\n // ============================================\n\n private rowToVector(row: any): VectorRecord {\n return {\n id: row.rowid,\n embedding: this.deserializeEmbedding(row.embedding),\n createdAt: Math.floor(Date.now() / 1000),\n };\n }\n\n private deserializeEmbedding(blob: Buffer | Uint8Array): number[] {\n // sqlite-vec 返回的是 float32 buffer\n const buffer = Buffer.isBuffer(blob) ? blob : Buffer.from(blob);\n const embedding: number[] = [];\n for (let i = 0; i < buffer.length; i += 4) {\n embedding.push(buffer.readFloatLE(i));\n }\n return embedding;\n }\n}\n"]}
1
+ {"version":3,"file":"SqliteVectorStore.js","sourceRoot":"","sources":["../../../src/storage/vector/SqliteVectorStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SqliteVectorStore - SQLite 向量存储实现(使用 sqlite-vec 扩展)\n *\n * 设计思路:\n * - sqlite-vec 的 vec0 表使用 rowid 作为主键\n * - rowid 直接与 quints 表的 rowid 对应,无需额外映射\n * - 通过 rowid JOIN quints 表即可关联业务数据\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport type { Finalizable, Initializable } from '@solid/community-server';\nimport { VectorStore, hashModelId } from './VectorStore';\nimport type { VectorRecord, VectorSearchOptions, VectorSearchResult, VectorStoreOptions } from './types';\nimport { getSqliteRuntime, type SqliteDatabase } from '../SqliteRuntime';\nimport { loadSqliteVecExtension } from './SqliteVecExtension';\n\nexport class SqliteVectorStore extends VectorStore implements Initializable, Finalizable {\n /** @ignored */\n private db: SqliteDatabase | null = null;\n private readonly filename: string;\n private readonly sqliteRuntime = getSqliteRuntime();\n\n public constructor(options: VectorStoreOptions) {\n super();\n let connStr = options.connectionString;\n if (connStr.startsWith('sqlite:')) {\n connStr = connStr.slice(7);\n }\n this.filename = connStr;\n }\n\n // ============================================\n // Lifecycle (Initializable / Finalizable)\n // ============================================\n\n public async initialize(): Promise<void> {\n await this.open();\n }\n\n public async finalize(): Promise<void> {\n await this.close();\n }\n\n public override async open(): Promise<void> {\n if (this.db) return;\n\n // 确保目录存在\n if (this.filename !== ':memory:') {\n const dir = path.dirname(this.filename);\n if (dir && dir !== '.' && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n }\n\n this.db = this.sqliteRuntime.openDatabase(this.filename);\n loadSqliteVecExtension(this.db);\n\n if (this.filename !== ':memory:') {\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('busy_timeout = 5000');\n }\n }\n\n public override async close(): Promise<void> {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n\n private ensureOpen(): SqliteDatabase {\n if (!this.db) {\n // 懒初始化:如果尚未打开,则自动打开\n // 确保目录存在\n if (this.filename !== ':memory:') {\n const dir = path.dirname(this.filename);\n if (dir && dir !== '.' && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n }\n\n this.db = this.sqliteRuntime.openDatabase(this.filename);\n loadSqliteVecExtension(this.db);\n\n if (this.filename !== ':memory:') {\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('busy_timeout = 5000');\n }\n }\n return this.db;\n }\n\n private getTableName(modelId: string): string {\n return `vec_${hashModelId(modelId)}`;\n }\n\n private getCountTableCandidates(modelIdOrTableName: string): string[] {\n const candidates: string[] = [];\n if (modelIdOrTableName.startsWith('vec_')) {\n candidates.push(modelIdOrTableName);\n }\n candidates.push(this.getTableName(modelIdOrTableName));\n return [...new Set(candidates)];\n }\n\n private getDimension(): number {\n return this.defaultDimension;\n }\n\n // ============================================\n // 向量表管理\n // ============================================\n\n public override async ensureVectorTable(modelId: string): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n // 使用 sqlite-vec 的 vec0 虚拟表\n // rowid 作为主键,与 quints 表的 rowid 对应\n db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS ${tableName} USING vec0(\n embedding float[${this.getDimension()}]\n )\n `);\n }\n\n public override async dropVectorTable(modelId: string): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n db.exec(`DROP TABLE IF EXISTS ${tableName}`);\n }\n\n public override async hasVectorTable(modelId: string): Promise<boolean> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n try {\n const row = db\n .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n .get(tableName) as { name: string } | undefined;\n return !!row;\n } catch {\n return false;\n }\n }\n\n public override async listVectorTables(): Promise<string[]> {\n const db = this.ensureOpen();\n\n try {\n const rows = db\n .prepare(`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name LIKE 'vec_%'\n AND sql LIKE '%USING vec0%'\n `)\n .all() as { name: string }[];\n return rows.map((r) => r.name);\n } catch {\n return [];\n }\n }\n\n // ============================================\n // 向量操作\n // ============================================\n\n public override async upsertVector(modelId: string, id: number, embedding: number[]): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n // 转换为 BigInt 以确保 sqlite-vec 识别为整数\n const bigId = BigInt(Math.floor(id));\n\n // sqlite-vec 不支持 UPDATE,需要先删除再插入\n db.prepare(`DELETE FROM ${tableName} WHERE rowid = ?`).run(bigId);\n\n // 使用 rowid 作为主键插入向量\n db.prepare(\n `INSERT INTO ${tableName} (rowid, embedding) VALUES (?, ?)`\n ).run(bigId, JSON.stringify(embedding));\n }\n\n public override async batchUpsertVectors(modelId: string, records: { id: number; embedding: number[] }[]): Promise<void> {\n if (records.length === 0) return;\n\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n const transaction = db.transaction((recs: typeof records) => {\n for (const rec of recs) {\n // 转换为 BigInt 以确保 sqlite-vec 识别为整数\n const bigId = BigInt(Math.floor(rec.id));\n\n // sqlite-vec 不支持 UPDATE,需要先删除再插入\n db.prepare(`DELETE FROM ${tableName} WHERE rowid = ?`).run(bigId);\n db.prepare(\n `INSERT INTO ${tableName} (rowid, embedding) VALUES (?, ?)`\n ).run(bigId, JSON.stringify(rec.embedding));\n }\n });\n\n transaction(records);\n }\n\n public override async getVector(modelId: string, id: number): Promise<VectorRecord | null> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n try {\n const row = db.prepare(`SELECT rowid, embedding FROM ${tableName} WHERE rowid = ?`).get(id) as any;\n return row ? this.rowToVector(row) : null;\n } catch {\n return null;\n }\n }\n\n public override async deleteVector(modelId: string, id: number): Promise<void> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n db.prepare(`DELETE FROM ${tableName} WHERE rowid = ?`).run(id);\n }\n\n public override async batchDeleteVectors(modelId: string, ids: number[]): Promise<void> {\n if (ids.length === 0) return;\n\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n\n const placeholders = ids.map(() => '?').join(',');\n db.prepare(`DELETE FROM ${tableName} WHERE rowid IN (${placeholders})`).run(...ids);\n }\n\n public override async search(modelId: string, queryEmbedding: number[], options: VectorSearchOptions = {}): Promise<VectorSearchResult[]> {\n const db = this.ensureOpen();\n\n const { limit = 10, threshold, excludeIds } = options;\n const tableName = this.getTableName(modelId);\n\n try {\n // 使用 sqlite-vec 的近似最近邻搜索\n // 注意:sqlite-vec 要求在 MATCH 中使用 k=? 参数\n const sql = `\n SELECT\n rowid as id,\n distance\n FROM ${tableName}\n WHERE embedding MATCH ?\n AND k = ?\n ORDER BY distance\n `;\n\n const rows = db.prepare(sql).all(JSON.stringify(queryEmbedding), limit * 2) as { id: number; distance: number }[];\n\n const results: VectorSearchResult[] = [];\n\n for (const row of rows) {\n if (excludeIds?.has(row.id)) continue;\n\n const distance = row.distance;\n // sqlite-vec 使用 L2 距离,对于归一化向量,转换为余弦相似度:\n // L2² = 2 * (1 - cosine_similarity)\n // cosine_similarity = 1 - L2² / 2\n // score 限制在 [0, 1] 范围内\n const score = Math.max(0, Math.min(1, 1 - (distance * distance) / 2));\n\n if (threshold !== undefined && score < threshold) continue;\n\n results.push({ id: row.id, distance, score });\n }\n\n return results.slice(0, limit);\n } catch (e) {\n // sqlite-vec 扩展不可用时抛出错误\n throw new Error(`sqlite-vec search failed: ${e}`);\n }\n }\n\n // ============================================\n // 统计\n // ============================================\n\n public override async countVectors(modelId: string): Promise<number> {\n const db = this.ensureOpen();\n\n for (const tableName of this.getCountTableCandidates(modelId)) {\n try {\n const row = db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).get() as any;\n return row?.count ?? 0;\n } catch {\n continue;\n }\n }\n\n return 0;\n }\n\n // ============================================\n // 迁移支持\n // ============================================\n\n public override async getVectorIds(modelId: string, options: { limit?: number; afterId?: number } = {}): Promise<number[]> {\n const db = this.ensureOpen();\n const tableName = this.getTableName(modelId);\n const { limit = 1000, afterId } = options;\n\n try {\n const sql = afterId !== undefined\n ? `SELECT rowid FROM ${tableName} WHERE rowid > ? ORDER BY rowid LIMIT ?`\n : `SELECT rowid FROM ${tableName} ORDER BY rowid LIMIT ?`;\n const params = afterId !== undefined ? [afterId, limit] : [limit];\n const rows = db.prepare(sql).all(...params) as any[];\n return rows.map((r) => r.rowid);\n } catch {\n return [];\n }\n }\n\n // ============================================\n // 行转换\n // ============================================\n\n private rowToVector(row: any): VectorRecord {\n return {\n id: row.rowid,\n embedding: this.deserializeEmbedding(row.embedding),\n createdAt: Math.floor(Date.now() / 1000),\n };\n }\n\n private deserializeEmbedding(blob: Buffer | Uint8Array): number[] {\n // sqlite-vec 返回的是 float32 buffer\n const buffer = Buffer.isBuffer(blob) ? blob : Buffer.from(blob);\n const embedding: number[] = [];\n for (let i = 0; i < buffer.length; i += 4) {\n embedding.push(buffer.readFloatLE(i));\n }\n return embedding;\n }\n}\n"]}
@@ -62,6 +62,10 @@
62
62
  "@id": "undefineds:dist/storage/vector/SqliteVectorStore.jsonld#SqliteVectorStore__member_getTableName",
63
63
  "memberFieldName": "getTableName"
64
64
  },
65
+ {
66
+ "@id": "undefineds:dist/storage/vector/SqliteVectorStore.jsonld#SqliteVectorStore__member_getCountTableCandidates",
67
+ "memberFieldName": "getCountTableCandidates"
68
+ },
65
69
  {
66
70
  "@id": "undefineds:dist/storage/vector/SqliteVectorStore.jsonld#SqliteVectorStore__member_getDimension",
67
71
  "memberFieldName": "getDimension"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@undefineds.co/xpod",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Xpod is an extended Community Solid Server, offering rich-feature, production-level Solid Pod and identity management.",
5
5
  "repository": "https://github.com/undefinedsco/xpod",
6
6
  "author": "developer@undefineds.co",
@@ -94,7 +94,7 @@
94
94
  "test:integration:lite": "bun scripts/run-integration-lite-local.ts",
95
95
  "test:integration:full": "bun scripts/run-integration-full.ts",
96
96
  "test:integration:all": "bun run test:integration:lite && bun run test:integration:full",
97
- "test:bun:runtime": "bun run build:ts && XPOD_TEST_TRANSPORT=port bun scripts/run-bun-runtime-smoke.ts",
97
+ "test:bun:runtime": "bun run build:ts && bun run build:components && XPOD_TEST_TRANSPORT=port bun scripts/run-bun-runtime-smoke.ts",
98
98
  "test:integration:lite:up": "docker compose -f docker-compose.standalone.yml up -d --build",
99
99
  "test:integration:lite:down": "docker compose -f docker-compose.standalone.yml down",
100
100
  "build:single": "node scripts/build-single-file.js",