@undefineds.co/xpod 0.2.6 → 0.2.8

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.
Files changed (53) hide show
  1. package/config/cloud.json +1 -1
  2. package/dist/api/chatkit/ai-provider.js +4 -3
  3. package/dist/api/chatkit/ai-provider.js.map +1 -1
  4. package/dist/api/chatkit/default-agent.js +8 -7
  5. package/dist/api/chatkit/default-agent.js.map +1 -1
  6. package/dist/api/chatkit/runtime/PtyThreadRuntime.js +2 -1
  7. package/dist/api/chatkit/runtime/PtyThreadRuntime.js.map +1 -1
  8. package/dist/api/handlers/AdminHandler.js +1 -1
  9. package/dist/api/handlers/AdminHandler.js.map +1 -1
  10. package/dist/api/service/VercelChatService.js +23 -23
  11. package/dist/api/service/VercelChatService.js.map +1 -1
  12. package/dist/api/service/platform-ai-config.d.ts +8 -0
  13. package/dist/api/service/platform-ai-config.js +64 -0
  14. package/dist/api/service/platform-ai-config.js.map +1 -0
  15. package/dist/cli/commands/start.js +1 -2
  16. package/dist/cli/commands/start.js.map +1 -1
  17. package/dist/components/context.jsonld +3 -0
  18. package/dist/http/TracingHandler.js +2 -0
  19. package/dist/http/TracingHandler.js.map +1 -1
  20. package/dist/identity/drizzle/DrizzleIndexedStorage.d.ts +10 -1
  21. package/dist/identity/drizzle/DrizzleIndexedStorage.js +99 -6
  22. package/dist/identity/drizzle/DrizzleIndexedStorage.js.map +1 -1
  23. package/dist/identity/drizzle/DrizzleIndexedStorage.jsonld +36 -0
  24. package/dist/main.js +1 -2
  25. package/dist/main.js.map +1 -1
  26. package/dist/provision/ProvisionPodCreator.d.ts +1 -0
  27. package/dist/provision/ProvisionPodCreator.js +33 -2
  28. package/dist/provision/ProvisionPodCreator.js.map +1 -1
  29. package/dist/provision/ProvisionPodCreator.jsonld +4 -0
  30. package/dist/runtime/bootstrap.js +4 -4
  31. package/dist/runtime/bootstrap.js.map +1 -1
  32. package/dist/storage/MetadataRequestContext.d.ts +13 -0
  33. package/dist/storage/MetadataRequestContext.js +6 -0
  34. package/dist/storage/MetadataRequestContext.js.map +1 -0
  35. package/dist/storage/NodeSqliteDrizzle.js +19 -5
  36. package/dist/storage/NodeSqliteDrizzle.js.map +1 -1
  37. package/dist/storage/accessors/MinioDataAccessor.d.ts +1 -0
  38. package/dist/storage/accessors/MinioDataAccessor.js +25 -2
  39. package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
  40. package/dist/storage/accessors/MinioDataAccessor.jsonld +4 -0
  41. package/dist/storage/accessors/MixDataAccessor.d.ts +3 -1
  42. package/dist/storage/accessors/MixDataAccessor.js +61 -23
  43. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  44. package/dist/storage/accessors/MixDataAccessor.jsonld +23 -0
  45. package/dist/supervisor/Supervisor.js +1 -1
  46. package/dist/supervisor/Supervisor.js.map +1 -1
  47. package/package.json +1 -1
  48. package/static/app/assets/index.css +1 -1
  49. package/static/app/assets/main.js +50 -10
  50. package/static/dashboard/assets/{dashboard-BfmT5Vc8.js → dashboard-CTk9cn1-.js} +8 -8
  51. package/static/dashboard/assets/dashboard-VQRsvXx9.css +1 -0
  52. package/static/dashboard/dashboard.html +2 -2
  53. package/static/dashboard/assets/dashboard-DkZOr7bV.css +0 -1
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAiGatewayBaseUrl = getAiGatewayBaseUrl;
4
+ exports.getAiGatewayApiKey = getAiGatewayApiKey;
5
+ exports.getPlatformApiBaseUrl = getPlatformApiBaseUrl;
6
+ exports.getPlatformApiKey = getPlatformApiKey;
7
+ exports.hasPlatformApiConfig = hasPlatformApiConfig;
8
+ exports.getPlatformProviderId = getPlatformProviderId;
9
+ exports.getPlatformDefaultModel = getPlatformDefaultModel;
10
+ exports.getPlatformTimeoutMs = getPlatformTimeoutMs;
11
+ const provider_registry_1 = require("./provider-registry");
12
+ const DEFAULT_PLATFORM_PROVIDER = 'undefineds';
13
+ const DEFAULT_PLATFORM_MODEL = 'linx-lite';
14
+ const DEFAULT_PLATFORM_TIMEOUT_MS = 30_000;
15
+ function readTrimmedEnv(name) {
16
+ const value = process.env[name]?.trim();
17
+ return value ? value : undefined;
18
+ }
19
+ function getAiGatewayBaseUrl() {
20
+ const explicit = readTrimmedEnv('DEFAULT_API_BASE');
21
+ if (explicit) {
22
+ return explicit.replace(/\/$/, '');
23
+ }
24
+ return undefined;
25
+ }
26
+ function getAiGatewayApiKey() {
27
+ return readTrimmedEnv('DEFAULT_API_KEY');
28
+ }
29
+ function getPlatformApiBaseUrl() {
30
+ const explicit = readTrimmedEnv('DEFAULT_API_BASE');
31
+ if (explicit) {
32
+ return explicit.replace(/\/$/, '');
33
+ }
34
+ const aiGatewayBase = getAiGatewayBaseUrl();
35
+ if (!aiGatewayBase) {
36
+ const provider = getPlatformProviderId();
37
+ if (provider === DEFAULT_PLATFORM_PROVIDER) {
38
+ return undefined;
39
+ }
40
+ return (0, provider_registry_1.getDefaultBaseUrl)(provider);
41
+ }
42
+ return aiGatewayBase.endsWith('/v1') ? aiGatewayBase : `${aiGatewayBase}/v1`;
43
+ }
44
+ function getPlatformApiKey() {
45
+ return getAiGatewayApiKey() ?? '';
46
+ }
47
+ function hasPlatformApiConfig() {
48
+ return !!(getPlatformApiBaseUrl() || getPlatformApiKey());
49
+ }
50
+ function getPlatformProviderId() {
51
+ return readTrimmedEnv('DEFAULT_PROVIDER') ?? DEFAULT_PLATFORM_PROVIDER;
52
+ }
53
+ function getPlatformDefaultModel() {
54
+ return readTrimmedEnv('DEFAULT_MODEL') ?? DEFAULT_PLATFORM_MODEL;
55
+ }
56
+ function getPlatformTimeoutMs() {
57
+ const raw = readTrimmedEnv('DEFAULT_TIMEOUT_MS');
58
+ if (!raw) {
59
+ return DEFAULT_PLATFORM_TIMEOUT_MS;
60
+ }
61
+ const parsed = Number(raw);
62
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_PLATFORM_TIMEOUT_MS;
63
+ }
64
+ //# sourceMappingURL=platform-ai-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-ai-config.js","sourceRoot":"","sources":["../../../src/api/service/platform-ai-config.ts"],"names":[],"mappings":";;AAWA,kDAMC;AAED,gDAEC;AAED,sDAgBC;AAED,8CAEC;AAED,oDAEC;AAED,sDAEC;AAED,0DAEC;AAED,oDAQC;AAjED,2DAAwD;AAExD,MAAM,yBAAyB,GAAG,YAAY,CAAC;AAC/C,MAAM,sBAAsB,GAAG,WAAW,CAAC;AAC3C,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAE3C,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACnC,CAAC;AAED,SAAgB,mBAAmB;IACjC,MAAM,QAAQ,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAC;IACpD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,kBAAkB;IAChC,OAAO,cAAc,CAAC,iBAAiB,CAAC,CAAC;AAC3C,CAAC;AAED,SAAgB,qBAAqB;IACnC,MAAM,QAAQ,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAC;IACpD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,IAAI,QAAQ,KAAK,yBAAyB,EAAE,CAAC;YAC3C,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAA,qCAAiB,EAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,CAAC;AAC/E,CAAC;AAED,SAAgB,iBAAiB;IAC/B,OAAO,kBAAkB,EAAE,IAAI,EAAE,CAAC;AACpC,CAAC;AAED,SAAgB,oBAAoB;IAClC,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,IAAI,iBAAiB,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,SAAgB,qBAAqB;IACnC,OAAO,cAAc,CAAC,kBAAkB,CAAC,IAAI,yBAAyB,CAAC;AACzE,CAAC;AAED,SAAgB,uBAAuB;IACrC,OAAO,cAAc,CAAC,eAAe,CAAC,IAAI,sBAAsB,CAAC;AACnE,CAAC;AAED,SAAgB,oBAAoB;IAClC,MAAM,GAAG,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,2BAA2B,CAAC;IACrC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC;AACtF,CAAC","sourcesContent":["import { getDefaultBaseUrl } from './provider-registry';\n\nconst DEFAULT_PLATFORM_PROVIDER = 'undefineds';\nconst DEFAULT_PLATFORM_MODEL = 'linx-lite';\nconst DEFAULT_PLATFORM_TIMEOUT_MS = 30_000;\n\nfunction readTrimmedEnv(name: string): string | undefined {\n const value = process.env[name]?.trim();\n return value ? value : undefined;\n}\n\nexport function getAiGatewayBaseUrl(): string | undefined {\n const explicit = readTrimmedEnv('DEFAULT_API_BASE');\n if (explicit) {\n return explicit.replace(/\\/$/, '');\n }\n return undefined;\n}\n\nexport function getAiGatewayApiKey(): string | undefined {\n return readTrimmedEnv('DEFAULT_API_KEY');\n}\n\nexport function getPlatformApiBaseUrl(): string | undefined {\n const explicit = readTrimmedEnv('DEFAULT_API_BASE');\n if (explicit) {\n return explicit.replace(/\\/$/, '');\n }\n\n const aiGatewayBase = getAiGatewayBaseUrl();\n if (!aiGatewayBase) {\n const provider = getPlatformProviderId();\n if (provider === DEFAULT_PLATFORM_PROVIDER) {\n return undefined;\n }\n return getDefaultBaseUrl(provider);\n }\n\n return aiGatewayBase.endsWith('/v1') ? aiGatewayBase : `${aiGatewayBase}/v1`;\n}\n\nexport function getPlatformApiKey(): string {\n return getAiGatewayApiKey() ?? '';\n}\n\nexport function hasPlatformApiConfig(): boolean {\n return !!(getPlatformApiBaseUrl() || getPlatformApiKey());\n}\n\nexport function getPlatformProviderId(): string {\n return readTrimmedEnv('DEFAULT_PROVIDER') ?? DEFAULT_PLATFORM_PROVIDER;\n}\n\nexport function getPlatformDefaultModel(): string {\n return readTrimmedEnv('DEFAULT_MODEL') ?? DEFAULT_PLATFORM_MODEL;\n}\n\nexport function getPlatformTimeoutMs(): number {\n const raw = readTrimmedEnv('DEFAULT_TIMEOUT_MS');\n if (!raw) {\n return DEFAULT_PLATFORM_TIMEOUT_MS;\n }\n\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_PLATFORM_TIMEOUT_MS;\n}\n"]}
@@ -98,8 +98,7 @@ exports.startCommand = {
98
98
  }
99
99
  const supervisor = new supervisor_1.Supervisor();
100
100
  const cssBinary = require.resolve('@solid/community-server/bin/server.js');
101
- const cssModuleRoot = path_1.default.dirname(require.resolve('@solid/community-server/package.json'));
102
- const cssArgs = [cssBinary, '-c', configPath, '-m', cssModuleRoot, '-p', cssPort.toString(), '-b', baseUrl];
101
+ const cssArgs = [cssBinary, '-c', configPath, '-m', runtime_1.PACKAGE_ROOT, '-p', cssPort.toString(), '-b', baseUrl];
103
102
  if (idpUrl) {
104
103
  cssArgs.push('--idpUrl', idpUrl);
105
104
  }
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CommandModule } from 'yargs';\nimport path from 'path';\nimport fs from 'fs';\nimport { Supervisor } from '../../supervisor';\nimport { GatewayProxy, getFreePort, PACKAGE_ROOT } from '../../runtime';\n\ninterface StartArgs {\n mode?: string;\n config?: string;\n env?: string;\n port: number;\n host: string;\n}\n\nconst childJsRuntime = typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n ? (process.env.XPOD_NODE_BINARY ?? 'node')\n : process.execPath;\n\nfunction loadEnvFile(envPath: string): void {\n if (!fs.existsSync(envPath)) {\n console.warn(`Env file not found: ${envPath}`);\n return;\n }\n const content = fs.readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n}\n\nexport const startCommand: CommandModule<object, StartArgs> = {\n command: 'start',\n describe: 'Start xpod services',\n builder: (yargs) =>\n yargs\n .option('mode', {\n alias: 'm',\n type: 'string',\n choices: ['local', 'cloud'],\n description: 'Run mode',\n })\n .option('config', {\n alias: 'c',\n type: 'string',\n description: 'Path to config file (overrides --mode)',\n })\n .option('env', {\n alias: 'e',\n type: 'string',\n description: 'Path to .env file',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n description: 'Gateway port',\n default: 3000,\n })\n .option('host', {\n type: 'string',\n description: 'Gateway host',\n default: 'localhost',\n }),\n handler: async (argv) => {\n if (argv.env) {\n loadEnvFile(argv.env);\n }\n\n const mainPort =\n argv.port !== 3000\n ? argv.port\n : parseInt(process.env.XPOD_PORT ?? process.env.PORT ?? '3000', 10);\n\n let configPath: string;\n if (argv.config) {\n configPath = argv.config;\n } else if (argv.mode) {\n configPath = path.join(PACKAGE_ROOT, `config/${argv.mode}.json`);\n } else {\n configPath = path.join(PACKAGE_ROOT, 'config/local.json');\n }\n\n const cssPort = await getFreePort(mainPort + 1, argv.host);\n const apiPort = await getFreePort(cssPort + 1, argv.host);\n\n const baseUrl = process.env.CSS_BASE_URL || `http://${argv.host}:${mainPort}/`;\n\n // SP 模式:全部通过环境变量配置(.env.local 或 --env 参数)\n // XPOD_SERVICE_TOKEN, XPOD_NODE_ID, XPOD_NODE_TOKEN, XPOD_CLOUD_API_ENDPOINT, CSS_IDP_URL\n const idpUrl = process.env.CSS_IDP_URL || process.env.XPOD_CLOUD_API_ENDPOINT;\n\n console.log('Starting xpod...');\n console.log(` Gateway: ${baseUrl} (${argv.host}:${mainPort})`);\n console.log(` CSS (internal): http://localhost:${cssPort}`);\n console.log(` API (internal): http://localhost:${apiPort}`);\n if (idpUrl) {\n console.log(` SP mode: Cloud IdP = ${idpUrl}`);\n }\n\n const supervisor = new Supervisor();\n const cssBinary = require.resolve('@solid/community-server/bin/server.js');\n const cssModuleRoot = path.dirname(require.resolve('@solid/community-server/package.json'));\n\n const cssArgs = [cssBinary, '-c', configPath, '-m', cssModuleRoot, '-p', cssPort.toString(), '-b', baseUrl];\n if (idpUrl) {\n cssArgs.push('--idpUrl', idpUrl);\n }\n\n supervisor.register({\n name: 'css',\n command: childJsRuntime,\n args: cssArgs,\n env: {\n ...process.env as Record<string, string>,\n CSS_PORT: cssPort.toString(),\n CSS_BASE_URL: baseUrl,\n },\n });\n\n const isDevMode = __filename.endsWith('.ts');\n const apiArgs = isDevMode\n ? [\n '-r',\n require.resolve('ts-node/register/transpile-only'),\n path.resolve(__dirname, '..', '..', 'api', 'main.ts'),\n ]\n : [path.resolve(__dirname, '..', '..', 'api', 'main.js')];\n\n supervisor.register({\n name: 'api',\n command: childJsRuntime,\n args: apiArgs,\n env: {\n ...process.env as Record<string, string>,\n API_PORT: apiPort.toString(),\n XPOD_MAIN_PORT: mainPort.toString(),\n CSS_INTERNAL_URL: `http://localhost:${cssPort}`,\n CSS_BASE_URL: baseUrl,\n CSS_TOKEN_ENDPOINT: idpUrl\n ? `${idpUrl.replace(/\\/$/, '')}/.oidc/token`\n : `${baseUrl}.oidc/token`,\n },\n });\n\n const proxy = new GatewayProxy(mainPort, supervisor, '0.0.0.0', {\n exitOnStop: true,\n baseUrl,\n });\n proxy.setTargets({\n css: `http://localhost:${cssPort}`,\n api: `http://localhost:${apiPort}`,\n });\n\n await supervisor.startAll();\n await proxy.start();\n\n const shutdown = async (signal: string): Promise<void> => {\n console.log(`\\nReceived ${signal}, shutting down...`);\n await supervisor.stopAll();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n },\n};\n"]}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CommandModule } from 'yargs';\nimport path from 'path';\nimport fs from 'fs';\nimport { Supervisor } from '../../supervisor';\nimport { GatewayProxy, getFreePort, PACKAGE_ROOT } from '../../runtime';\n\ninterface StartArgs {\n mode?: string;\n config?: string;\n env?: string;\n port: number;\n host: string;\n}\n\nconst childJsRuntime = typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n ? (process.env.XPOD_NODE_BINARY ?? 'node')\n : process.execPath;\n\nfunction loadEnvFile(envPath: string): void {\n if (!fs.existsSync(envPath)) {\n console.warn(`Env file not found: ${envPath}`);\n return;\n }\n const content = fs.readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n}\n\nexport const startCommand: CommandModule<object, StartArgs> = {\n command: 'start',\n describe: 'Start xpod services',\n builder: (yargs) =>\n yargs\n .option('mode', {\n alias: 'm',\n type: 'string',\n choices: ['local', 'cloud'],\n description: 'Run mode',\n })\n .option('config', {\n alias: 'c',\n type: 'string',\n description: 'Path to config file (overrides --mode)',\n })\n .option('env', {\n alias: 'e',\n type: 'string',\n description: 'Path to .env file',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n description: 'Gateway port',\n default: 3000,\n })\n .option('host', {\n type: 'string',\n description: 'Gateway host',\n default: 'localhost',\n }),\n handler: async (argv) => {\n if (argv.env) {\n loadEnvFile(argv.env);\n }\n\n const mainPort =\n argv.port !== 3000\n ? argv.port\n : parseInt(process.env.XPOD_PORT ?? process.env.PORT ?? '3000', 10);\n\n let configPath: string;\n if (argv.config) {\n configPath = argv.config;\n } else if (argv.mode) {\n configPath = path.join(PACKAGE_ROOT, `config/${argv.mode}.json`);\n } else {\n configPath = path.join(PACKAGE_ROOT, 'config/local.json');\n }\n\n const cssPort = await getFreePort(mainPort + 1, argv.host);\n const apiPort = await getFreePort(cssPort + 1, argv.host);\n\n const baseUrl = process.env.CSS_BASE_URL || `http://${argv.host}:${mainPort}/`;\n\n // SP 模式:全部通过环境变量配置(.env.local 或 --env 参数)\n // XPOD_SERVICE_TOKEN, XPOD_NODE_ID, XPOD_NODE_TOKEN, XPOD_CLOUD_API_ENDPOINT, CSS_IDP_URL\n const idpUrl = process.env.CSS_IDP_URL || process.env.XPOD_CLOUD_API_ENDPOINT;\n\n console.log('Starting xpod...');\n console.log(` Gateway: ${baseUrl} (${argv.host}:${mainPort})`);\n console.log(` CSS (internal): http://localhost:${cssPort}`);\n console.log(` API (internal): http://localhost:${apiPort}`);\n if (idpUrl) {\n console.log(` SP mode: Cloud IdP = ${idpUrl}`);\n }\n\n const supervisor = new Supervisor();\n const cssBinary = require.resolve('@solid/community-server/bin/server.js');\n const cssArgs = [cssBinary, '-c', configPath, '-m', PACKAGE_ROOT, '-p', cssPort.toString(), '-b', baseUrl];\n if (idpUrl) {\n cssArgs.push('--idpUrl', idpUrl);\n }\n\n supervisor.register({\n name: 'css',\n command: childJsRuntime,\n args: cssArgs,\n env: {\n ...process.env as Record<string, string>,\n CSS_PORT: cssPort.toString(),\n CSS_BASE_URL: baseUrl,\n },\n });\n\n const isDevMode = __filename.endsWith('.ts');\n const apiArgs = isDevMode\n ? [\n '-r',\n require.resolve('ts-node/register/transpile-only'),\n path.resolve(__dirname, '..', '..', 'api', 'main.ts'),\n ]\n : [path.resolve(__dirname, '..', '..', 'api', 'main.js')];\n\n supervisor.register({\n name: 'api',\n command: childJsRuntime,\n args: apiArgs,\n env: {\n ...process.env as Record<string, string>,\n API_PORT: apiPort.toString(),\n XPOD_MAIN_PORT: mainPort.toString(),\n CSS_INTERNAL_URL: `http://localhost:${cssPort}`,\n CSS_BASE_URL: baseUrl,\n CSS_TOKEN_ENDPOINT: idpUrl\n ? `${idpUrl.replace(/\\/$/, '')}/.oidc/token`\n : `${baseUrl}.oidc/token`,\n },\n });\n\n const proxy = new GatewayProxy(mainPort, supervisor, '0.0.0.0', {\n exitOnStop: true,\n baseUrl,\n });\n proxy.setTargets({\n css: `http://localhost:${cssPort}`,\n api: `http://localhost:${apiPort}`,\n });\n\n await supervisor.startAll();\n await proxy.start();\n\n const shutdown = async (signal: string): Promise<void> => {\n console.log(`\\nReceived ${signal}, shutting down...`);\n await supervisor.stopAll();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n },\n};\n"]}
@@ -342,6 +342,9 @@
342
342
  "presignedRedirectEnabled": {
343
343
  "@id": "undefineds:dist/storage/accessors/MixDataAccessor.jsonld#MixDataAccessor_presignedRedirectEnabled"
344
344
  },
345
+ "mirrorContainersToUnstructured": {
346
+ "@id": "undefineds:dist/storage/accessors/MixDataAccessor.jsonld#MixDataAccessor_mirrorContainersToUnstructured"
347
+ },
345
348
  "structuredDataAccessor": {
346
349
  "@id": "undefineds:dist/storage/accessors/MixDataAccessor.jsonld#MixDataAccessor_structuredDataAccessor"
347
350
  },
@@ -8,6 +8,7 @@ const global_logger_factory_1 = require("global-logger-factory");
8
8
  const community_server_1 = require("@solid/community-server");
9
9
  const LogContext_1 = require("../logging/LogContext");
10
10
  const LockContext_1 = require("../util/LockContext");
11
+ const MetadataRequestContext_1 = require("../storage/MetadataRequestContext");
11
12
  const node_crypto_1 = __importDefault(require("node:crypto"));
12
13
  /**
13
14
  * HTTP Handler that provides request tracing capabilities.
@@ -39,6 +40,7 @@ class TracingHandler extends community_server_1.HttpHandler {
39
40
  // Enter logging context for this request
40
41
  LogContext_1.logContext.enterWith({ requestId });
41
42
  LockContext_1.lockContext.enterWith(new Map());
43
+ MetadataRequestContext_1.metadataRequestContext.enterWith({ metadataCache: new Map() });
42
44
  // Register finish listener to log completion
43
45
  input.response.on('finish', () => {
44
46
  const ms = Date.now() - startTime;
@@ -1 +1 @@
1
- {"version":3,"file":"TracingHandler.js","sourceRoot":"","sources":["../../src/http/TracingHandler.ts"],"names":[],"mappings":";;;;;;AAAA,iEAAqD;AACrD,8DAA6E;AAC7E,sDAAmD;AACnD,qDAAkD;AAClD,8DAAiC;AAEjC;;;;;;;;;;;;GAYG;AACH,MAAa,cAAe,SAAQ,8BAAW;IAA/C;;QACqB,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;IAmCjD,CAAC;IAjCiB,KAAK,CAAC,SAAS,CAAC,MAAwB;QACtD,sEAAsE;IACxE,CAAC;IAEe,KAAK,CAAC,MAAM,CAAC,KAAuB;QAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,qBAAM,CAAC,UAAU,EAAE,CAAC;QAC1F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,sBAAsB;QACtB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAEpD,yCAAyC;QACzC,uBAAU,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QACpC,yBAAW,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAEjC,6CAA6C;QAC7C,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,IAAI,GAAG,CAAC;YAEhD,+CAA+C;YAC/C,uBAAU,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE;gBACjC,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;oBACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC1F,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC1F,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,qEAAqE;IACvE,CAAC;CACF;AApCD,wCAoCC","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport { HttpHandler, type HttpHandlerInput } from '@solid/community-server';\nimport { logContext } from '../logging/LogContext';\nimport { lockContext } from '../util/LockContext';\nimport crypto from 'node:crypto';\n\n/**\n * HTTP Handler that provides request tracing capabilities.\n * \n * This handler:\n * 1. Reads or generates a Request ID (from X-Request-ID header or new UUID)\n * 2. Sets the X-Request-ID in the response header\n * 3. Enters the logging context with the request ID\n * 4. Logs request completion with status code and duration via response 'finish' event\n * \n * Designed to be used as the first handler in a SequenceHandler chain.\n * It sets up the tracing context and returns immediately, allowing\n * the SequenceHandler to continue to subsequent handlers.\n */\nexport class TracingHandler extends HttpHandler {\n protected readonly logger = getLoggerFor(this);\n\n public override async canHandle(_input: HttpHandlerInput): Promise<void> {\n // Always can handle - we just set up tracing context and pass through\n }\n\n public override async handle(input: HttpHandlerInput): Promise<void> {\n const headerId = input.request.headers['x-request-id'];\n const requestId = Array.isArray(headerId) ? headerId[0] : headerId || crypto.randomUUID();\n const startTime = Date.now();\n \n // Set response header\n input.response.setHeader('X-Request-ID', requestId);\n \n // Enter logging context for this request\n logContext.enterWith({ requestId });\n lockContext.enterWith(new Map());\n\n // Register finish listener to log completion\n input.response.on('finish', () => {\n const ms = Date.now() - startTime;\n const status = input.response.statusCode || 200;\n \n // Re-enter log context for the finish callback\n logContext.run({ requestId }, () => {\n if (status < 400) {\n this.logger.info(`${input.request.method} ${input.request.url} -> ${status} (${ms}ms)`);\n } else {\n this.logger.warn(`${input.request.method} ${input.request.url} -> ${status} (${ms}ms)`);\n }\n });\n });\n\n // Return immediately - SequenceHandler will continue to next handler\n }\n}\n"]}
1
+ {"version":3,"file":"TracingHandler.js","sourceRoot":"","sources":["../../src/http/TracingHandler.ts"],"names":[],"mappings":";;;;;;AAAA,iEAAqD;AACrD,8DAA6E;AAC7E,sDAAmD;AACnD,qDAAkD;AAClD,8EAA2E;AAC3E,8DAAiC;AAEjC;;;;;;;;;;;;GAYG;AACH,MAAa,cAAe,SAAQ,8BAAW;IAA/C;;QACqB,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;IAoCjD,CAAC;IAlCiB,KAAK,CAAC,SAAS,CAAC,MAAwB;QACtD,sEAAsE;IACxE,CAAC;IAEe,KAAK,CAAC,MAAM,CAAC,KAAuB;QAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,qBAAM,CAAC,UAAU,EAAE,CAAC;QAC1F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,sBAAsB;QACtB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAEpD,yCAAyC;QACzC,uBAAU,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QACpC,yBAAW,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACjC,+CAAsB,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAE/D,6CAA6C;QAC7C,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,IAAI,GAAG,CAAC;YAEhD,+CAA+C;YAC/C,uBAAU,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE;gBACjC,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;oBACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC1F,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC1F,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,qEAAqE;IACvE,CAAC;CACF;AArCD,wCAqCC","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport { HttpHandler, type HttpHandlerInput } from '@solid/community-server';\nimport { logContext } from '../logging/LogContext';\nimport { lockContext } from '../util/LockContext';\nimport { metadataRequestContext } from '../storage/MetadataRequestContext';\nimport crypto from 'node:crypto';\n\n/**\n * HTTP Handler that provides request tracing capabilities.\n * \n * This handler:\n * 1. Reads or generates a Request ID (from X-Request-ID header or new UUID)\n * 2. Sets the X-Request-ID in the response header\n * 3. Enters the logging context with the request ID\n * 4. Logs request completion with status code and duration via response 'finish' event\n * \n * Designed to be used as the first handler in a SequenceHandler chain.\n * It sets up the tracing context and returns immediately, allowing\n * the SequenceHandler to continue to subsequent handlers.\n */\nexport class TracingHandler extends HttpHandler {\n protected readonly logger = getLoggerFor(this);\n\n public override async canHandle(_input: HttpHandlerInput): Promise<void> {\n // Always can handle - we just set up tracing context and pass through\n }\n\n public override async handle(input: HttpHandlerInput): Promise<void> {\n const headerId = input.request.headers['x-request-id'];\n const requestId = Array.isArray(headerId) ? headerId[0] : headerId || crypto.randomUUID();\n const startTime = Date.now();\n \n // Set response header\n input.response.setHeader('X-Request-ID', requestId);\n \n // Enter logging context for this request\n logContext.enterWith({ requestId });\n lockContext.enterWith(new Map());\n metadataRequestContext.enterWith({ metadataCache: new Map() });\n\n // Register finish listener to log completion\n input.response.on('finish', () => {\n const ms = Date.now() - startTime;\n const status = input.response.statusCode || 200;\n \n // Re-enter log context for the finish callback\n logContext.run({ requestId }, () => {\n if (status < 400) {\n this.logger.info(`${input.request.method} ${input.request.url} -> ${status} (${ms}ms)`);\n } else {\n this.logger.warn(`${input.request.method} ${input.request.url} -> ${status} (${ms}ms)`);\n }\n });\n });\n\n // Return immediately - SequenceHandler will continue to next handler\n }\n}\n"]}
@@ -4,15 +4,17 @@ import type { IndexedStorage } from '@solid/community-server';
4
4
  * Maps `type` (container) and `id` (key) to rows in the table.
5
5
  */
6
6
  export declare class DrizzleIndexedStorage implements IndexedStorage<any> {
7
+ private readonly logger;
7
8
  private readonly db;
8
9
  private readonly tableName;
9
10
  private readonly definitions;
11
+ private readonly createdIndexes;
10
12
  private ready;
11
13
  constructor(connectionString: string, tablePrefix?: string);
12
14
  private toJsonSql;
13
15
  private ensureTable;
14
16
  defineType(type: string, description: any): Promise<void>;
15
- createIndex(): Promise<void>;
17
+ createIndex(type: string, key: string): Promise<void>;
16
18
  create(type: string, value: any): Promise<any>;
17
19
  has(type: string, id: string): Promise<boolean>;
18
20
  get(type: string, id: string): Promise<any | undefined>;
@@ -23,4 +25,11 @@ export declare class DrizzleIndexedStorage implements IndexedStorage<any> {
23
25
  delete(type: string, id: string): Promise<void>;
24
26
  entries(type: string): AsyncIterableIterator<any>;
25
27
  private matchesQuery;
28
+ private canPushDownQuery;
29
+ private isSupportedQueryValue;
30
+ private buildWhereClause;
31
+ private buildIndexName;
32
+ private toSqliteJsonPath;
33
+ private escapeSqlLiteral;
34
+ private logDuration;
26
35
  }
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DrizzleIndexedStorage = void 0;
7
+ const global_logger_factory_1 = require("global-logger-factory");
7
8
  const drizzle_orm_1 = require("drizzle-orm");
8
9
  const node_crypto_1 = __importDefault(require("node:crypto"));
9
10
  const db_1 = require("./db");
@@ -30,7 +31,9 @@ function parsePayload(value) {
30
31
  */
31
32
  class DrizzleIndexedStorage {
32
33
  constructor(connectionString, tablePrefix = 'identity_') {
34
+ this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
33
35
  this.definitions = new Map();
36
+ this.createdIndexes = new Set();
34
37
  this.ready = false;
35
38
  this.db = (0, db_1.getIdentityDatabase)(connectionString);
36
39
  this.tableName = `${tablePrefix}store`;
@@ -57,10 +60,29 @@ class DrizzleIndexedStorage {
57
60
  this.definitions.set(type, description);
58
61
  await this.ensureTable();
59
62
  }
60
- async createIndex() {
61
- // Indexes are not required for the current usage.
63
+ async createIndex(type, key) {
64
+ const started = Date.now();
65
+ await this.ensureTable();
66
+ if (key === 'id') {
67
+ return;
68
+ }
69
+ const cacheKey = `${type}:${key}`;
70
+ if (this.createdIndexes.has(cacheKey)) {
71
+ return;
72
+ }
73
+ if ((0, db_1.isDatabaseSqlite)(this.db)) {
74
+ const jsonPath = this.escapeSqlLiteral(this.toSqliteJsonPath(key));
75
+ await (0, db_1.executeStatement)(this.db, drizzle_orm_1.sql.raw(`CREATE INDEX IF NOT EXISTS "${this.buildIndexName(type, key)}" ON "${this.tableName}" (container, json_extract(payload, '${jsonPath}'))`));
76
+ }
77
+ else {
78
+ const escapedKey = this.escapeSqlLiteral(key);
79
+ await (0, db_1.executeStatement)(this.db, drizzle_orm_1.sql.raw(`CREATE INDEX IF NOT EXISTS "${this.buildIndexName(type, key)}" ON "${this.tableName}" (container, (jsonb_extract_path_text(payload, '${escapedKey}')))`));
80
+ }
81
+ this.createdIndexes.add(cacheKey);
82
+ this.logDuration('createIndex', started, { type, key }, 50, 500);
62
83
  }
63
84
  async create(type, value) {
85
+ const started = Date.now();
64
86
  await this.ensureTable();
65
87
  const id = node_crypto_1.default.randomUUID();
66
88
  const payload = serializePayload(value);
@@ -69,18 +91,23 @@ class DrizzleIndexedStorage {
69
91
  INSERT INTO ${tableNameId} (container, id, payload)
70
92
  VALUES (${type}, ${id}, ${this.toJsonSql(payload)})
71
93
  `);
94
+ this.logDuration('create', started, { type, fields: Object.keys(value ?? {}) }, 50, 500);
72
95
  return { id, ...value };
73
96
  }
74
97
  async has(type, id) {
98
+ const started = Date.now();
75
99
  await this.ensureTable();
76
100
  const tableNameId = drizzle_orm_1.sql.identifier([this.tableName]);
77
101
  const result = await (0, db_1.executeQuery)(this.db, (0, drizzle_orm_1.sql) `SELECT 1 FROM ${tableNameId} WHERE container = ${type} AND id = ${id} LIMIT 1`);
102
+ this.logDuration('has', started, { type, id }, 50, 500);
78
103
  return result.rows.length > 0;
79
104
  }
80
105
  async get(type, id) {
106
+ const started = Date.now();
81
107
  await this.ensureTable();
82
108
  const tableNameId = drizzle_orm_1.sql.identifier([this.tableName]);
83
109
  const result = await (0, db_1.executeQuery)(this.db, (0, drizzle_orm_1.sql) `SELECT payload FROM ${tableNameId} WHERE container = ${type} AND id = ${id} LIMIT 1`);
110
+ this.logDuration('get', started, { type, id }, 50, 500);
84
111
  if (result.rows.length === 0) {
85
112
  return undefined;
86
113
  }
@@ -88,21 +115,30 @@ class DrizzleIndexedStorage {
88
115
  return { id, ...payload };
89
116
  }
90
117
  async find(type, query) {
118
+ const started = Date.now();
91
119
  await this.ensureTable();
92
120
  const tableNameId = drizzle_orm_1.sql.identifier([this.tableName]);
93
- // Note: This fetches all rows for the container and filters in memory.
94
- // For high volume types, this should be optimized with JSON path queries if possible.
95
- const result = await (0, db_1.executeQuery)(this.db, (0, drizzle_orm_1.sql) `SELECT id, payload FROM ${tableNameId} WHERE container = ${type}`);
121
+ const normalizedQuery = (query ?? {});
122
+ const pushdown = this.canPushDownQuery(normalizedQuery);
123
+ const result = pushdown
124
+ ? await (0, db_1.executeQuery)(this.db, (0, drizzle_orm_1.sql) `SELECT id, payload FROM ${tableNameId} WHERE ${this.buildWhereClause(type, normalizedQuery)}`)
125
+ : await (0, db_1.executeQuery)(this.db, (0, drizzle_orm_1.sql) `SELECT id, payload FROM ${tableNameId} WHERE container = ${type}`);
96
126
  const matches = [];
97
127
  for (const row of result.rows) {
98
128
  const payload = {
99
129
  id: row.id,
100
130
  ...parsePayload(row.payload),
101
131
  };
102
- if (this.matchesQuery(type, payload, query)) {
132
+ if (this.matchesQuery(type, payload, normalizedQuery)) {
103
133
  matches.push(payload);
104
134
  }
105
135
  }
136
+ this.logDuration('find', started, {
137
+ type,
138
+ keys: Object.keys(normalizedQuery),
139
+ pushdown,
140
+ matched: matches.length,
141
+ }, 50, 500);
106
142
  return matches;
107
143
  }
108
144
  async findIds(type, query) {
@@ -110,6 +146,7 @@ class DrizzleIndexedStorage {
110
146
  return rows.map((row) => row.id);
111
147
  }
112
148
  async set(type, value) {
149
+ const started = Date.now();
113
150
  await this.ensureTable();
114
151
  const tableNameId = drizzle_orm_1.sql.identifier([this.tableName]);
115
152
  const { id, ...rest } = value;
@@ -119,6 +156,7 @@ class DrizzleIndexedStorage {
119
156
  SET payload = ${this.toJsonSql(payload)}
120
157
  WHERE container = ${type} AND id = ${id}
121
158
  `);
159
+ this.logDuration('set', started, { type, id, fields: Object.keys(rest) }, 50, 500);
122
160
  }
123
161
  async setField(type, id, key, value) {
124
162
  const current = await this.get(type, id);
@@ -129,9 +167,11 @@ class DrizzleIndexedStorage {
129
167
  await this.set(type, updated);
130
168
  }
131
169
  async delete(type, id) {
170
+ const started = Date.now();
132
171
  await this.ensureTable();
133
172
  const tableNameId = drizzle_orm_1.sql.identifier([this.tableName]);
134
173
  await (0, db_1.executeStatement)(this.db, (0, drizzle_orm_1.sql) `DELETE FROM ${tableNameId} WHERE container = ${type} AND id = ${id}`);
174
+ this.logDuration('delete', started, { type, id }, 50, 500);
135
175
  }
136
176
  async *entries(type) {
137
177
  await this.ensureTable();
@@ -154,6 +194,59 @@ class DrizzleIndexedStorage {
154
194
  }
155
195
  return true;
156
196
  }
197
+ canPushDownQuery(query) {
198
+ return Object.values(query).every((value) => this.isSupportedQueryValue(value));
199
+ }
200
+ isSupportedQueryValue(value) {
201
+ return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
202
+ }
203
+ buildWhereClause(type, query) {
204
+ const clauses = [(0, drizzle_orm_1.sql) `container = ${type}`];
205
+ for (const [key, value] of Object.entries(query)) {
206
+ if (key === 'id') {
207
+ clauses.push((0, drizzle_orm_1.sql) `id = ${String(value)}`);
208
+ continue;
209
+ }
210
+ if ((0, db_1.isDatabaseSqlite)(this.db)) {
211
+ const jsonPath = this.toSqliteJsonPath(key);
212
+ const wrappedValue = JSON.stringify({ value });
213
+ clauses.push((0, drizzle_orm_1.sql) `json_extract(payload, ${jsonPath}) = json_extract(${wrappedValue}, '$.value')`);
214
+ continue;
215
+ }
216
+ clauses.push((0, drizzle_orm_1.sql) `jsonb_extract_path_text(payload, ${key}) = ${String(value)}`);
217
+ }
218
+ return drizzle_orm_1.sql.join(clauses, (0, drizzle_orm_1.sql) ` AND `);
219
+ }
220
+ buildIndexName(type, key) {
221
+ const rawName = `${this.tableName}_${type}_${key}_idx`;
222
+ const normalized = rawName.replace(/[^a-zA-Z0-9_]/g, '_');
223
+ if (normalized.length <= 63) {
224
+ return normalized;
225
+ }
226
+ return `${normalized.slice(0, 54)}_${node_crypto_1.default.createHash('sha1').update(rawName).digest('hex').slice(0, 8)}`;
227
+ }
228
+ toSqliteJsonPath(key) {
229
+ const escaped = key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
230
+ return `$."${escaped}"`;
231
+ }
232
+ escapeSqlLiteral(value) {
233
+ return value.replace(/'/g, "''");
234
+ }
235
+ logDuration(operation, started, details, slowThresholdMs = 100, warnThresholdMs = 1000) {
236
+ const elapsedMs = Date.now() - started;
237
+ if (elapsedMs < slowThresholdMs) {
238
+ return;
239
+ }
240
+ const detailText = Object.entries(details)
241
+ .map(([key, value]) => `${key}=${Array.isArray(value) ? value.join(',') : String(value)}`)
242
+ .join(' ');
243
+ const message = `[timing] DrizzleIndexedStorage.${operation} ${detailText} took=${elapsedMs}ms`;
244
+ if (elapsedMs >= warnThresholdMs) {
245
+ this.logger.warn(message);
246
+ return;
247
+ }
248
+ this.logger.info(message);
249
+ }
157
250
  }
158
251
  exports.DrizzleIndexedStorage = DrizzleIndexedStorage;
159
252
  //# sourceMappingURL=DrizzleIndexedStorage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DrizzleIndexedStorage.js","sourceRoot":"","sources":["../../../src/identity/drizzle/DrizzleIndexedStorage.ts"],"names":[],"mappings":"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","sourcesContent":["import { sql } from 'drizzle-orm';\nimport crypto from 'node:crypto';\nimport type {\n CreateTypeObject,\n IndexedQuery,\n IndexedStorage,\n IndexTypeCollection,\n StringKey,\n TypeObject,\n ValueTypeDescription,\n} from '@solid/community-server';\nimport { \n getIdentityDatabase, \n IdentityDatabase, \n executeQuery, \n executeStatement,\n isDatabaseSqlite \n} from './db';\n\nfunction serializePayload(value: Record<string, unknown>): string {\n return JSON.stringify(value ?? {});\n}\n\nfunction parsePayload<T>(value: unknown): T {\n if (value == null) {\n return {} as T;\n }\n if (typeof value === 'string') {\n try {\n return JSON.parse(value) as T;\n } catch {\n return {} as T;\n }\n }\n return value as T;\n}\n\n/**\n * A generic Key-Value storage backed by a single SQL table.\n * Maps `type` (container) and `id` (key) to rows in the table.\n */\nexport class DrizzleIndexedStorage implements IndexedStorage<any> {\n private readonly db: IdentityDatabase;\n private readonly tableName: string;\n private readonly definitions: Map<string, Record<string, ValueTypeDescription<string>>> = new Map();\n private ready: boolean = false;\n\n public constructor(connectionString: string, tablePrefix = 'identity_') {\n this.db = getIdentityDatabase(connectionString);\n this.tableName = `${tablePrefix}store`;\n }\n\n private toJsonSql(payload: string): any {\n return isDatabaseSqlite(this.db) ? sql`${payload}` : sql`${payload}::jsonb`;\n }\n\n private async ensureTable(): Promise<void> {\n if (this.ready) return;\n \n const jsonType = isDatabaseSqlite(this.db) ? sql.raw('TEXT') : sql.raw('JSONB');\n const tableNameId = sql.identifier([this.tableName]);\n \n await executeStatement(this.db, sql`\n CREATE TABLE IF NOT EXISTS ${tableNameId} (\n container TEXT NOT NULL,\n id TEXT NOT NULL,\n payload ${jsonType} NOT NULL,\n PRIMARY KEY (container, id)\n )\n `);\n this.ready = true;\n }\n\n public async defineType(type: string, description: any): Promise<void> {\n this.definitions.set(type, description as Record<string, ValueTypeDescription<string>>);\n await this.ensureTable();\n }\n\n public async createIndex(): Promise<void> {\n // Indexes are not required for the current usage.\n }\n\n public async create(type: string, value: any): Promise<any> {\n await this.ensureTable();\n const id = crypto.randomUUID();\n const payload = serializePayload(value as Record<string, unknown>);\n const tableNameId = sql.identifier([this.tableName]);\n\n await executeStatement(this.db, sql`\n INSERT INTO ${tableNameId} (container, id, payload)\n VALUES (${type}, ${id}, ${this.toJsonSql(payload)})\n `);\n return { id, ...(value as Record<string, unknown>) };\n }\n\n public async has(type: string, id: string): Promise<boolean> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const result = await executeQuery(this.db, sql`SELECT 1 FROM ${tableNameId} WHERE container = ${type} AND id = ${id} LIMIT 1`);\n return result.rows.length > 0;\n }\n\n public async get(type: string, id: string): Promise<any | undefined> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const result = await executeQuery(this.db, sql`SELECT payload FROM ${tableNameId} WHERE container = ${type} AND id = ${id} LIMIT 1`);\n if (result.rows.length === 0) {\n return undefined;\n }\n const payload = parsePayload<Record<string, unknown>>(result.rows[0].payload);\n return { id, ...payload };\n }\n\n public async find(type: string, query: any): Promise<any[]> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n // Note: This fetches all rows for the container and filters in memory. \n // For high volume types, this should be optimized with JSON path queries if possible.\n const result = await executeQuery(this.db, sql`SELECT id, payload FROM ${tableNameId} WHERE container = ${type}`);\n const matches: any[] = [];\n for (const row of result.rows) {\n const payload = {\n id: row.id as string,\n ...parsePayload<Record<string, unknown>>(row.payload),\n };\n if (this.matchesQuery(type, payload, query as Record<string, unknown>)) {\n matches.push(payload);\n }\n }\n return matches;\n }\n\n public async findIds(type: string, query: any): Promise<string[]> {\n const rows = await this.find(type, query);\n return rows.map((row) => row.id as string);\n }\n\n public async set(type: string, value: any): Promise<void> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const { id, ...rest } = value as Record<string, unknown>;\n const payload = serializePayload(rest);\n \n await executeStatement(this.db, sql`\n UPDATE ${tableNameId}\n SET payload = ${this.toJsonSql(payload)}\n WHERE container = ${type} AND id = ${id}\n `);\n }\n\n public async setField(type: string, id: string, key: string, value: any): Promise<void> {\n const current = await this.get(type, id);\n if (!current) {\n return;\n }\n const updated = { ...current, [key]: value };\n await this.set(type, updated);\n }\n\n public async delete(type: string, id: string): Promise<void> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n await executeStatement(this.db, sql`DELETE FROM ${tableNameId} WHERE container = ${type} AND id = ${id}`);\n }\n\n public async *entries(type: string): AsyncIterableIterator<any> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const result = await executeQuery(this.db, sql`SELECT id, payload FROM ${tableNameId} WHERE container = ${type}`);\n for (const row of result.rows) {\n yield {\n id: row.id as string,\n ...parsePayload<Record<string, unknown>>(row.payload),\n };\n }\n }\n\n private matchesQuery(type: string, payload: any, query: any): boolean {\n // Basic in-memory implementation of query matching\n // This mirrors MemoryIndexedStorage behavior for compatibility\n for (const key of Object.keys(query)) {\n if (payload[key] !== query[key]) {\n return false;\n }\n }\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"DrizzleIndexedStorage.js","sourceRoot":"","sources":["../../../src/identity/drizzle/DrizzleIndexedStorage.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport { sql } from 'drizzle-orm';\nimport crypto from 'node:crypto';\nimport type {\n CreateTypeObject,\n IndexedQuery,\n IndexedStorage,\n IndexTypeCollection,\n StringKey,\n TypeObject,\n ValueTypeDescription,\n} from '@solid/community-server';\nimport { \n getIdentityDatabase, \n IdentityDatabase, \n executeQuery, \n executeStatement,\n isDatabaseSqlite \n} from './db';\n\nfunction serializePayload(value: Record<string, unknown>): string {\n return JSON.stringify(value ?? {});\n}\n\nfunction parsePayload<T>(value: unknown): T {\n if (value == null) {\n return {} as T;\n }\n if (typeof value === 'string') {\n try {\n return JSON.parse(value) as T;\n } catch {\n return {} as T;\n }\n }\n return value as T;\n}\n\n/**\n * A generic Key-Value storage backed by a single SQL table.\n * Maps `type` (container) and `id` (key) to rows in the table.\n */\nexport class DrizzleIndexedStorage implements IndexedStorage<any> {\n private readonly logger = getLoggerFor(this);\n private readonly db: IdentityDatabase;\n private readonly tableName: string;\n private readonly definitions: Map<string, Record<string, ValueTypeDescription<string>>> = new Map();\n private readonly createdIndexes: Set<string> = new Set();\n private ready: boolean = false;\n\n public constructor(connectionString: string, tablePrefix = 'identity_') {\n this.db = getIdentityDatabase(connectionString);\n this.tableName = `${tablePrefix}store`;\n }\n\n private toJsonSql(payload: string): any {\n return isDatabaseSqlite(this.db) ? sql`${payload}` : sql`${payload}::jsonb`;\n }\n\n private async ensureTable(): Promise<void> {\n if (this.ready) return;\n \n const jsonType = isDatabaseSqlite(this.db) ? sql.raw('TEXT') : sql.raw('JSONB');\n const tableNameId = sql.identifier([this.tableName]);\n \n await executeStatement(this.db, sql`\n CREATE TABLE IF NOT EXISTS ${tableNameId} (\n container TEXT NOT NULL,\n id TEXT NOT NULL,\n payload ${jsonType} NOT NULL,\n PRIMARY KEY (container, id)\n )\n `);\n this.ready = true;\n }\n\n public async defineType(type: string, description: any): Promise<void> {\n this.definitions.set(type, description as Record<string, ValueTypeDescription<string>>);\n await this.ensureTable();\n }\n\n public async createIndex(type: string, key: string): Promise<void> {\n const started = Date.now();\n await this.ensureTable();\n if (key === 'id') {\n return;\n }\n\n const cacheKey = `${type}:${key}`;\n if (this.createdIndexes.has(cacheKey)) {\n return;\n }\n\n if (isDatabaseSqlite(this.db)) {\n const jsonPath = this.escapeSqlLiteral(this.toSqliteJsonPath(key));\n await executeStatement(this.db, sql.raw(\n `CREATE INDEX IF NOT EXISTS \"${this.buildIndexName(type, key)}\" ON \"${this.tableName}\" (container, json_extract(payload, '${jsonPath}'))`,\n ));\n } else {\n const escapedKey = this.escapeSqlLiteral(key);\n await executeStatement(this.db, sql.raw(\n `CREATE INDEX IF NOT EXISTS \"${this.buildIndexName(type, key)}\" ON \"${this.tableName}\" (container, (jsonb_extract_path_text(payload, '${escapedKey}')))` ,\n ));\n }\n\n this.createdIndexes.add(cacheKey);\n this.logDuration('createIndex', started, { type, key }, 50, 500);\n }\n\n public async create(type: string, value: any): Promise<any> {\n const started = Date.now();\n await this.ensureTable();\n const id = crypto.randomUUID();\n const payload = serializePayload(value as Record<string, unknown>);\n const tableNameId = sql.identifier([this.tableName]);\n\n await executeStatement(this.db, sql`\n INSERT INTO ${tableNameId} (container, id, payload)\n VALUES (${type}, ${id}, ${this.toJsonSql(payload)})\n `);\n this.logDuration('create', started, { type, fields: Object.keys(value ?? {}) }, 50, 500);\n return { id, ...(value as Record<string, unknown>) };\n }\n\n public async has(type: string, id: string): Promise<boolean> {\n const started = Date.now();\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const result = await executeQuery(this.db, sql`SELECT 1 FROM ${tableNameId} WHERE container = ${type} AND id = ${id} LIMIT 1`);\n this.logDuration('has', started, { type, id }, 50, 500);\n return result.rows.length > 0;\n }\n\n public async get(type: string, id: string): Promise<any | undefined> {\n const started = Date.now();\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const result = await executeQuery(this.db, sql`SELECT payload FROM ${tableNameId} WHERE container = ${type} AND id = ${id} LIMIT 1`);\n this.logDuration('get', started, { type, id }, 50, 500);\n if (result.rows.length === 0) {\n return undefined;\n }\n const payload = parsePayload<Record<string, unknown>>(result.rows[0].payload);\n return { id, ...payload };\n }\n\n public async find(type: string, query: any): Promise<any[]> {\n const started = Date.now();\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const normalizedQuery = (query ?? {}) as Record<string, unknown>;\n const pushdown = this.canPushDownQuery(normalizedQuery);\n const result = pushdown\n ? await executeQuery(this.db, sql`SELECT id, payload FROM ${tableNameId} WHERE ${this.buildWhereClause(type, normalizedQuery)}`)\n : await executeQuery(this.db, sql`SELECT id, payload FROM ${tableNameId} WHERE container = ${type}`);\n const matches: any[] = [];\n for (const row of result.rows) {\n const payload = {\n id: row.id as string,\n ...parsePayload<Record<string, unknown>>(row.payload),\n };\n if (this.matchesQuery(type, payload, normalizedQuery)) {\n matches.push(payload);\n }\n }\n this.logDuration('find', started, {\n type,\n keys: Object.keys(normalizedQuery),\n pushdown,\n matched: matches.length,\n }, 50, 500);\n return matches;\n }\n\n public async findIds(type: string, query: any): Promise<string[]> {\n const rows = await this.find(type, query);\n return rows.map((row) => row.id as string);\n }\n\n public async set(type: string, value: any): Promise<void> {\n const started = Date.now();\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const { id, ...rest } = value as Record<string, unknown>;\n const payload = serializePayload(rest);\n \n await executeStatement(this.db, sql`\n UPDATE ${tableNameId}\n SET payload = ${this.toJsonSql(payload)}\n WHERE container = ${type} AND id = ${id}\n `);\n this.logDuration('set', started, { type, id, fields: Object.keys(rest) }, 50, 500);\n }\n\n public async setField(type: string, id: string, key: string, value: any): Promise<void> {\n const current = await this.get(type, id);\n if (!current) {\n return;\n }\n const updated = { ...current, [key]: value };\n await this.set(type, updated);\n }\n\n public async delete(type: string, id: string): Promise<void> {\n const started = Date.now();\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n await executeStatement(this.db, sql`DELETE FROM ${tableNameId} WHERE container = ${type} AND id = ${id}`);\n this.logDuration('delete', started, { type, id }, 50, 500);\n }\n\n public async *entries(type: string): AsyncIterableIterator<any> {\n await this.ensureTable();\n const tableNameId = sql.identifier([this.tableName]);\n const result = await executeQuery(this.db, sql`SELECT id, payload FROM ${tableNameId} WHERE container = ${type}`);\n for (const row of result.rows) {\n yield {\n id: row.id as string,\n ...parsePayload<Record<string, unknown>>(row.payload),\n };\n }\n }\n\n private matchesQuery(type: string, payload: any, query: any): boolean {\n // Basic in-memory implementation of query matching\n // This mirrors MemoryIndexedStorage behavior for compatibility\n for (const key of Object.keys(query)) {\n if (payload[key] !== query[key]) {\n return false;\n }\n }\n return true;\n }\n\n private canPushDownQuery(query: Record<string, unknown>): boolean {\n return Object.values(query).every((value) => this.isSupportedQueryValue(value));\n }\n\n private isSupportedQueryValue(value: unknown): value is string | number | boolean {\n return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';\n }\n\n private buildWhereClause(type: string, query: Record<string, unknown>): any {\n const clauses = [sql`container = ${type}`];\n\n for (const [key, value] of Object.entries(query)) {\n if (key === 'id') {\n clauses.push(sql`id = ${String(value)}`);\n continue;\n }\n\n if (isDatabaseSqlite(this.db)) {\n const jsonPath = this.toSqliteJsonPath(key);\n const wrappedValue = JSON.stringify({ value });\n clauses.push(sql`json_extract(payload, ${jsonPath}) = json_extract(${wrappedValue}, '$.value')`);\n continue;\n }\n\n clauses.push(sql`jsonb_extract_path_text(payload, ${key}) = ${String(value)}`);\n }\n\n return sql.join(clauses, sql` AND `);\n }\n\n private buildIndexName(type: string, key: string): string {\n const rawName = `${this.tableName}_${type}_${key}_idx`;\n const normalized = rawName.replace(/[^a-zA-Z0-9_]/g, '_');\n if (normalized.length <= 63) {\n return normalized;\n }\n\n return `${normalized.slice(0, 54)}_${crypto.createHash('sha1').update(rawName).digest('hex').slice(0, 8)}`;\n }\n\n private toSqliteJsonPath(key: string): string {\n const escaped = key.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `$.\"${escaped}\"`;\n }\n\n private escapeSqlLiteral(value: string): string {\n return value.replace(/'/g, \"''\");\n }\n\n private logDuration(\n operation: string,\n started: number,\n details: Record<string, unknown>,\n slowThresholdMs = 100,\n warnThresholdMs = 1000,\n ): void {\n const elapsedMs = Date.now() - started;\n if (elapsedMs < slowThresholdMs) {\n return;\n }\n\n const detailText = Object.entries(details)\n .map(([key, value]) => `${key}=${Array.isArray(value) ? value.join(',') : String(value)}`)\n .join(' ');\n const message = `[timing] DrizzleIndexedStorage.${operation} ${detailText} took=${elapsedMs}ms`;\n\n if (elapsedMs >= warnThresholdMs) {\n this.logger.warn(message);\n return;\n }\n\n this.logger.info(message);\n }\n}\n"]}
@@ -40,6 +40,10 @@
40
40
  }
41
41
  ],
42
42
  "memberFields": [
43
+ {
44
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_logger",
45
+ "memberFieldName": "logger"
46
+ },
43
47
  {
44
48
  "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_db",
45
49
  "memberFieldName": "db"
@@ -52,6 +56,10 @@
52
56
  "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_definitions",
53
57
  "memberFieldName": "definitions"
54
58
  },
59
+ {
60
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_createdIndexes",
61
+ "memberFieldName": "createdIndexes"
62
+ },
55
63
  {
56
64
  "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_ready",
57
65
  "memberFieldName": "ready"
@@ -115,6 +123,34 @@
115
123
  {
116
124
  "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_matchesQuery",
117
125
  "memberFieldName": "matchesQuery"
126
+ },
127
+ {
128
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_canPushDownQuery",
129
+ "memberFieldName": "canPushDownQuery"
130
+ },
131
+ {
132
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_isSupportedQueryValue",
133
+ "memberFieldName": "isSupportedQueryValue"
134
+ },
135
+ {
136
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_buildWhereClause",
137
+ "memberFieldName": "buildWhereClause"
138
+ },
139
+ {
140
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_buildIndexName",
141
+ "memberFieldName": "buildIndexName"
142
+ },
143
+ {
144
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_toSqliteJsonPath",
145
+ "memberFieldName": "toSqliteJsonPath"
146
+ },
147
+ {
148
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_escapeSqlLiteral",
149
+ "memberFieldName": "escapeSqlLiteral"
150
+ },
151
+ {
152
+ "@id": "undefineds:dist/identity/drizzle/DrizzleIndexedStorage.jsonld#DrizzleIndexedStorage__member_logDuration",
153
+ "memberFieldName": "logDuration"
118
154
  }
119
155
  ],
120
156
  "constructorArguments": [
package/dist/main.js CHANGED
@@ -218,14 +218,13 @@ async function startRuntime(options) {
218
218
  logger.info(` - API (internal): http://localhost:${apiPort}`);
219
219
  const supervisor = new supervisor_1.Supervisor();
220
220
  const cssBinary = require.resolve('@solid/community-server/bin/server.js');
221
- const cssModuleRoot = path_1.default.dirname(require.resolve('@solid/community-server/package.json'));
222
221
  supervisor.register({
223
222
  name: 'css',
224
223
  command: childJsRuntime,
225
224
  args: [
226
225
  cssBinary,
227
226
  '-c', configPath,
228
- '-m', cssModuleRoot,
227
+ '-m', runtime_1.PACKAGE_ROOT,
229
228
  '-p', cssPort.toString(),
230
229
  '-b', baseUrl,
231
230
  ],