@undefineds.co/xpod 0.3.31 → 0.3.33

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 (218) hide show
  1. package/dist/api/auth/AuthContext.d.ts +3 -2
  2. package/dist/api/auth/AuthContext.js +2 -1
  3. package/dist/api/auth/AuthContext.js.map +1 -1
  4. package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +2 -12
  5. package/dist/api/auth/ClientCredentialsAuthenticator.js +4 -4
  6. package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
  7. package/dist/api/auth/ServiceTokenAuthenticator.d.ts +2 -2
  8. package/dist/api/auth/ServiceTokenAuthenticator.js.map +1 -1
  9. package/dist/api/chatkit/pod-store.d.ts +3 -0
  10. package/dist/api/chatkit/pod-store.js +93 -59
  11. package/dist/api/chatkit/pod-store.js.map +1 -1
  12. package/dist/api/chatkit/schema.d.ts +5 -6
  13. package/dist/api/container/business-token.d.ts +1 -1
  14. package/dist/api/container/business-token.js +5 -1
  15. package/dist/api/container/business-token.js.map +1 -1
  16. package/dist/api/container/common.js +14 -10
  17. package/dist/api/container/common.js.map +1 -1
  18. package/dist/api/container/routes.js +16 -3
  19. package/dist/api/container/routes.js.map +1 -1
  20. package/dist/api/container/types.d.ts +2 -4
  21. package/dist/api/container/types.js.map +1 -1
  22. package/dist/api/handlers/ChatHandler.d.ts +1 -1
  23. package/dist/api/handlers/ChatHandler.js +1 -1
  24. package/dist/api/handlers/ChatHandler.js.map +1 -1
  25. package/dist/api/handlers/EdgeNodeSignalHandler.js +3 -1
  26. package/dist/api/handlers/EdgeNodeSignalHandler.js.map +1 -1
  27. package/dist/api/handlers/PodManagementHandler.d.ts +2 -0
  28. package/dist/api/handlers/PodManagementHandler.js +114 -12
  29. package/dist/api/handlers/PodManagementHandler.js.map +1 -1
  30. package/dist/api/handlers/ProvisionHandler.d.ts +27 -0
  31. package/dist/api/handlers/ProvisionHandler.js +339 -32
  32. package/dist/api/handlers/ProvisionHandler.js.map +1 -1
  33. package/dist/api/handlers/QuotaHandler.js +0 -12
  34. package/dist/api/handlers/QuotaHandler.js.map +1 -1
  35. package/dist/api/handlers/index.d.ts +0 -1
  36. package/dist/api/handlers/index.js +0 -1
  37. package/dist/api/handlers/index.js.map +1 -1
  38. package/dist/api/matrix/PodMatrixStore.js +26 -21
  39. package/dist/api/matrix/PodMatrixStore.js.map +1 -1
  40. package/dist/api/runs/InngestRunExecutionBackend.d.ts +2 -2
  41. package/dist/api/runs/schema.d.ts +5 -7
  42. package/dist/api/runs/store.js +6 -4
  43. package/dist/api/runs/store.js.map +1 -1
  44. package/dist/api/runtime.js +3 -3
  45. package/dist/api/runtime.js.map +1 -1
  46. package/dist/api/tasks/InngestTaskScheduler.d.ts +4 -4
  47. package/dist/api/tasks/schema.d.ts +17 -13
  48. package/dist/api/tasks/schema.js +7 -2
  49. package/dist/api/tasks/schema.js.map +1 -1
  50. package/dist/api/tasks/store.js +1 -2
  51. package/dist/api/tasks/store.js.map +1 -1
  52. package/dist/components/context.jsonld +12 -0
  53. package/dist/edge/EdgeNodeAgent.d.ts +1 -1
  54. package/dist/edge/EdgeNodeAgent.js +1 -1
  55. package/dist/edge/EdgeNodeAgent.js.map +1 -1
  56. package/dist/edge/EdgeNodeDnsCoordinator.d.ts +1 -0
  57. package/dist/edge/EdgeNodeDnsCoordinator.js +9 -3
  58. package/dist/edge/EdgeNodeDnsCoordinator.js.map +1 -1
  59. package/dist/edge/EdgeNodeDnsCoordinator.jsonld +4 -0
  60. package/dist/edge/EdgeNodeHealthProbeService.d.ts +3 -0
  61. package/dist/edge/EdgeNodeHealthProbeService.js +22 -2
  62. package/dist/edge/EdgeNodeHealthProbeService.js.map +1 -1
  63. package/dist/edge/EdgeNodeHealthProbeService.jsonld +12 -0
  64. package/dist/http/ClusterIngressRouter.js +6 -3
  65. package/dist/http/ClusterIngressRouter.js.map +1 -1
  66. package/dist/http/ClusterWebSocketConfigurator.js +6 -2
  67. package/dist/http/ClusterWebSocketConfigurator.js.map +1 -1
  68. package/dist/http/EdgeNodeDirectDebugHttpHandler.d.ts +2 -0
  69. package/dist/http/EdgeNodeDirectDebugHttpHandler.js +18 -3
  70. package/dist/http/EdgeNodeDirectDebugHttpHandler.js.map +1 -1
  71. package/dist/http/EdgeNodeDirectDebugHttpHandler.jsonld +8 -0
  72. package/dist/http/EdgeNodeProxyHttpHandler.js +6 -2
  73. package/dist/http/EdgeNodeProxyHttpHandler.js.map +1 -1
  74. package/dist/http/cluster/PodMigrationHttpHandler.d.ts +2 -2
  75. package/dist/http/cluster/PodMigrationHttpHandler.js +2 -2
  76. package/dist/http/cluster/PodMigrationHttpHandler.js.map +1 -1
  77. package/dist/http/quota/QuotaAdminHttpHandler.js +27 -21
  78. package/dist/http/quota/QuotaAdminHttpHandler.js.map +1 -1
  79. package/dist/http/search/SearchHttpHandler.js +2 -2
  80. package/dist/http/search/SearchHttpHandler.js.map +1 -1
  81. package/dist/identity/drizzle/AccountRepository.d.ts +4 -22
  82. package/dist/identity/drizzle/AccountRepository.js +9 -113
  83. package/dist/identity/drizzle/AccountRepository.js.map +1 -1
  84. package/dist/identity/drizzle/AccountRoleRepository.d.ts +5 -5
  85. package/dist/identity/drizzle/AccountRoleRepository.js +204 -97
  86. package/dist/identity/drizzle/AccountRoleRepository.js.map +1 -1
  87. package/dist/identity/drizzle/DdnsRepository.d.ts +5 -20
  88. package/dist/identity/drizzle/DdnsRepository.js +13 -49
  89. package/dist/identity/drizzle/DdnsRepository.js.map +1 -1
  90. package/dist/identity/drizzle/EdgeNodeRepository.d.ts +13 -6
  91. package/dist/identity/drizzle/EdgeNodeRepository.js +167 -66
  92. package/dist/identity/drizzle/EdgeNodeRepository.js.map +1 -1
  93. package/dist/identity/drizzle/PodLookupRepository.d.ts +7 -36
  94. package/dist/identity/drizzle/PodLookupRepository.js +103 -126
  95. package/dist/identity/drizzle/PodLookupRepository.js.map +1 -1
  96. package/dist/identity/drizzle/ServiceTokenRepository.d.ts +13 -1
  97. package/dist/identity/drizzle/ServiceTokenRepository.js +7 -0
  98. package/dist/identity/drizzle/ServiceTokenRepository.js.map +1 -1
  99. package/dist/identity/drizzle/db.d.ts +2 -1
  100. package/dist/identity/drizzle/db.js +173 -297
  101. package/dist/identity/drizzle/db.js.map +1 -1
  102. package/dist/identity/drizzle/schema.pg.d.ts +3 -11
  103. package/dist/identity/drizzle/schema.pg.js +10 -45
  104. package/dist/identity/drizzle/schema.pg.js.map +1 -1
  105. package/dist/identity/drizzle/schema.sqlite.d.ts +88 -531
  106. package/dist/identity/drizzle/schema.sqlite.js +13 -46
  107. package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
  108. package/dist/identity/oidc/ScopedPickWebIdHandler.d.ts +3 -0
  109. package/dist/identity/oidc/ScopedPickWebIdHandler.js +18 -6
  110. package/dist/identity/oidc/ScopedPickWebIdHandler.js.map +1 -1
  111. package/dist/identity/oidc/ScopedPickWebIdHandler.jsonld +22 -0
  112. package/dist/provision/ProvisionCodeCodec.js +10 -1
  113. package/dist/provision/ProvisionCodeCodec.js.map +1 -1
  114. package/dist/provision/ProvisionPodCreator.d.ts +8 -2
  115. package/dist/provision/ProvisionPodCreator.js +134 -41
  116. package/dist/provision/ProvisionPodCreator.js.map +1 -1
  117. package/dist/provision/ProvisionPodCreator.jsonld +38 -3
  118. package/dist/quota/DrizzleQuotaService.d.ts +0 -4
  119. package/dist/quota/DrizzleQuotaService.js +1 -21
  120. package/dist/quota/DrizzleQuotaService.js.map +1 -1
  121. package/dist/quota/DrizzleQuotaService.jsonld +0 -16
  122. package/dist/quota/NoopQuotaService.d.ts +0 -4
  123. package/dist/quota/NoopQuotaService.js +0 -8
  124. package/dist/quota/NoopQuotaService.js.map +1 -1
  125. package/dist/quota/NoopQuotaService.jsonld +0 -16
  126. package/dist/quota/QuotaService.d.ts +0 -4
  127. package/dist/quota/QuotaService.js.map +1 -1
  128. package/dist/quota/QuotaService.jsonld +0 -16
  129. package/dist/service/EdgeNodeSignalClient.d.ts +0 -2
  130. package/dist/service/EdgeNodeSignalClient.js +0 -4
  131. package/dist/service/EdgeNodeSignalClient.js.map +1 -1
  132. package/dist/service/PodMigrationService.d.ts +2 -2
  133. package/dist/service/PodMigrationService.js +4 -4
  134. package/dist/service/PodMigrationService.js.map +1 -1
  135. package/dist/setup/LocalSetupServiceTokenRepository.d.ts +22 -0
  136. package/dist/setup/LocalSetupServiceTokenRepository.js +68 -0
  137. package/dist/setup/LocalSetupServiceTokenRepository.js.map +1 -0
  138. package/dist/storage/quota/PerAccountQuotaStrategy.js +2 -2
  139. package/dist/storage/quota/PerAccountQuotaStrategy.js.map +1 -1
  140. package/dist/storage/quota/UsageRepository.d.ts +10 -32
  141. package/dist/storage/quota/UsageRepository.js +84 -281
  142. package/dist/storage/quota/UsageRepository.js.map +1 -1
  143. package/dist/storage/vector/VectorIndexingListener.js +2 -2
  144. package/dist/storage/vector/VectorIndexingListener.js.map +1 -1
  145. package/dist/subdomain/SubdomainService.d.ts +1 -1
  146. package/dist/subdomain/SubdomainService.js +1 -1
  147. package/dist/subdomain/SubdomainService.js.map +1 -1
  148. package/dist/subdomain/SubdomainService.jsonld +1 -1
  149. package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.d.ts +21 -0
  150. package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.d.ts.map +1 -0
  151. package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.js +85 -0
  152. package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.js.map +1 -0
  153. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.d.ts +10 -0
  154. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.d.ts.map +1 -0
  155. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.js +365 -0
  156. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.js.map +1 -0
  157. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.d.ts +1 -0
  158. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.d.ts.map +1 -1
  159. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.js +3 -1
  160. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.js.map +1 -1
  161. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/insert-query-builder.d.ts.map +1 -1
  162. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/insert-query-builder.js +5 -1
  163. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/insert-query-builder.js.map +1 -1
  164. package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.d.ts +2 -0
  165. package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.d.ts.map +1 -1
  166. package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.js +2 -1
  167. package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.js.map +1 -1
  168. package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.d.ts +18 -0
  169. package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.d.ts.map +1 -1
  170. package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.js +234 -10
  171. package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.js.map +1 -1
  172. package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.d.ts +13 -0
  173. package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.d.ts.map +1 -1
  174. package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.js +19 -0
  175. package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.js.map +1 -1
  176. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.d.ts +21 -0
  177. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.d.ts.map +1 -0
  178. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.js +78 -0
  179. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.js.map +1 -0
  180. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.d.ts +10 -0
  181. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.d.ts.map +1 -0
  182. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.js +362 -0
  183. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.js.map +1 -0
  184. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.d.ts +1 -0
  185. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.d.ts.map +1 -1
  186. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.js +1 -0
  187. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.js.map +1 -1
  188. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/insert-query-builder.d.ts.map +1 -1
  189. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/insert-query-builder.js +5 -1
  190. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/insert-query-builder.js.map +1 -1
  191. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.d.ts +2 -0
  192. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.d.ts.map +1 -1
  193. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.js +1 -0
  194. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.js.map +1 -1
  195. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.d.ts +18 -0
  196. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.d.ts.map +1 -1
  197. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.js +225 -10
  198. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.js.map +1 -1
  199. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.d.ts +13 -0
  200. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.d.ts.map +1 -1
  201. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.js +19 -0
  202. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.js.map +1 -1
  203. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.d.ts +5 -4
  204. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.d.ts.map +1 -1
  205. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.js +4 -3
  206. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.js.map +1 -1
  207. package/node_modules/@undefineds.co/drizzle-solid/dist/index.d.ts +5 -4
  208. package/node_modules/@undefineds.co/drizzle-solid/dist/index.d.ts.map +1 -1
  209. package/node_modules/@undefineds.co/drizzle-solid/dist/index.js +20 -3
  210. package/node_modules/@undefineds.co/drizzle-solid/dist/index.js.map +1 -1
  211. package/node_modules/@undefineds.co/drizzle-solid/package.json +1 -1
  212. package/package.json +3 -3
  213. package/dist/api/handlers/ApiKeyHandler.d.ts +0 -15
  214. package/dist/api/handlers/ApiKeyHandler.js +0 -153
  215. package/dist/api/handlers/ApiKeyHandler.js.map +0 -1
  216. package/dist/api/store/DrizzleClientCredentialsStore.d.ts +0 -51
  217. package/dist/api/store/DrizzleClientCredentialsStore.js +0 -115
  218. package/dist/api/store/DrizzleClientCredentialsStore.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/identity/drizzle/db.ts"],"names":[],"mappings":"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","sourcesContent":["import { Pool, types } from 'pg';\nimport { drizzle as drizzlePg } from 'drizzle-orm/node-postgres';\nimport type { SQL } from 'drizzle-orm/sql';\nimport * as pgSchema from './schema.pg';\nimport * as sqliteSchema from './schema.sqlite';\nimport { getSharedPool, releaseSharedPool } from '../../storage/database/PostgresPoolManager';\nimport { getSqliteRuntime, type SqliteDatabase } from '../../storage/SqliteRuntime';\n\n// Use 'any' to allow both PostgreSQL and SQLite database instances\n// The actual type depends on the connection string at runtime\nexport type IdentityDatabase = any;\nexport type IdentitySchema = typeof pgSchema | typeof sqliteSchema;\n\n/**\n * Get the appropriate schema for the given database connection.\n * This provides a unified abstraction layer over PG and SQLite schemas.\n *\n * @example\n * const schema = getSchema(db);\n * await db.select().from(schema.accountUsage).where(eq(schema.accountUsage.accountId, id));\n */\nexport function getSchema(db: IdentityDatabase): typeof pgSchema | typeof sqliteSchema {\n return isDatabaseSqlite(db) ? sqliteSchema : pgSchema;\n}\n\n/**\n * Standardized query result format across databases.\n */\nexport interface QueryResult<T = Record<string, unknown>> {\n rows: T[];\n}\n\ninterface CachedConnection {\n db: IdentityDatabase;\n schema: IdentitySchema;\n isSqlite: boolean;\n close: () => Promise<void>;\n}\n\nconst dbCache = new Map<string, CachedConnection>();\nconst dbInitPromises = new WeakMap<object, Promise<void>>();\n\nconst JSON_OIDS = [114, 3802];\n\ntype SqliteDdlExecutor = Pick<SqliteDatabase, 'exec' | 'prepare'>;\n\nfor (const oid of JSON_OIDS) {\n // Explicitly return raw string to avoid \"Type Conflict\" with CSS\n // and to satisfy PgQuintStore's parseVector expecting a string.\n types.setTypeParser(oid, (value) => value);\n}\n\n/**\n * Returns true if the connection string is a SQLite URL.\n */\nexport function isSqliteUrl(connectionString: string): boolean {\n return connectionString.startsWith('sqlite:');\n}\n\n/**\n * Get or create a Drizzle database connection with the appropriate schema.\n * Supports both PostgreSQL and SQLite.\n */\nexport function getIdentityDatabase(connectionString: string): IdentityDatabase {\n const cached = dbCache.get(connectionString);\n if (cached) {\n return cached.db;\n }\n\n if (isSqliteUrl(connectionString)) {\n const filename = connectionString.replace('sqlite:', '');\n const isMemory = filename === ':memory:' || filename.startsWith(':memory:');\n const sqliteRuntime = getSqliteRuntime();\n const sqlite = sqliteRuntime.openDatabase(isMemory ? ':memory:' : filename);\n\n if (!isMemory) {\n sqlite.pragma('journal_mode = WAL');\n sqlite.pragma('busy_timeout = 5000');\n sqlite.pragma('synchronous = NORMAL');\n }\n\n const db = sqliteRuntime.createDrizzleDatabase(sqlite);\n\n ensureSqliteTables(sqlite);\n\n dbInitPromises.set(db as object, Promise.resolve());\n dbCache.set(connectionString, {\n db,\n schema: sqliteSchema,\n isSqlite: true,\n close: async () => { sqlite.close(); },\n });\n return db;\n }\n\n // PostgreSQL: use shared pool to avoid connection exhaustion and deadlocks\n const pool = getSharedPool({ connectionString });\n const db = drizzlePg(pool);\n const initPromise = (async(): Promise<void> => {\n await ensurePostgresTables(pool);\n await migratePgColumns(pool);\n })();\n dbInitPromises.set(db as object, initPromise);\n initPromise.catch((err) => {\n console.error(`[IdentityDB] PG migration failed: ${err}`);\n });\n dbCache.set(connectionString, {\n db,\n schema: pgSchema,\n isSqlite: false,\n close: async () => { \n // Release reference to shared pool instead of ending it\n releaseSharedPool({ connectionString }); \n },\n });\n return db;\n}\n\n/**\n * Get the schema for a given connection string.\n */\nexport function getIdentitySchema(connectionString: string): IdentitySchema {\n const cached = dbCache.get(connectionString);\n if (cached) {\n return cached.schema;\n }\n // Initialize connection to populate cache\n getIdentityDatabase(connectionString);\n return dbCache.get(connectionString)!.schema;\n}\n\n/**\n * Safely get a Drizzle database connection, returning undefined on error.\n * Use this when the identity database is optional (e.g., for usage tracking).\n */\nexport function tryGetIdentityDatabase(connectionString: string): IdentityDatabase | undefined {\n try {\n return getIdentityDatabase(connectionString);\n } catch {\n return undefined;\n }\n}\n\nexport async function closeAllIdentityConnections(): Promise<void> {\n await Promise.all([...dbCache.values()].map(({ close }) => close()));\n dbCache.clear();\n}\n\n/**\n * Check if a database connection is SQLite.\n * SQLite drizzle has `all()` method but no `execute()` method.\n * PostgreSQL drizzle has `execute()` method but no `all()` method.\n */\nexport function isDatabaseSqlite(db: IdentityDatabase): boolean {\n if ((db as any)?.$xpodSqliteRuntime) {\n return true;\n }\n return typeof db.all === 'function' && typeof db.execute !== 'function';\n}\n\nasync function ensureDatabaseReady(db: IdentityDatabase): Promise<void> {\n const initPromise = dbInitPromises.get(db as object);\n if (initPromise) {\n await initPromise;\n }\n}\n\n/**\n * Execute a SQL query uniformly across PostgreSQL and SQLite.\n * Returns a standardized result with rows array.\n *\n * @example\n * const result = await executeQuery(db, sql`SELECT * FROM users WHERE id = ${userId}`);\n * if (result.rows.length > 0) { ... }\n */\nexport async function executeQuery<T = Record<string, unknown>>(\n db: IdentityDatabase,\n query: SQL,\n): Promise<QueryResult<T>> {\n await ensureDatabaseReady(db);\n if (isDatabaseSqlite(db)) {\n // SQLite: db.all() returns array directly\n const rows = db.all(query) as T[];\n return { rows };\n }\n // PostgreSQL: db.execute() returns { rows: [...] }\n return db.execute(query) as Promise<QueryResult<T>>;\n}\n\n/**\n * Execute a SQL statement that doesn't return rows (INSERT, UPDATE, DELETE).\n * Works uniformly across PostgreSQL and SQLite.\n */\nexport async function executeStatement(\n db: IdentityDatabase,\n query: SQL,\n): Promise<void> {\n await ensureDatabaseReady(db);\n if (isDatabaseSqlite(db)) {\n // SQLite: db.run() for statements\n db.run(query);\n return;\n }\n // PostgreSQL: db.execute() works for statements too\n await db.execute(query);\n}\n\n/**\n * Convert a Date to a value suitable for the database.\n * SQLite uses Unix timestamps (seconds), PostgreSQL uses Date objects.\n */\nexport function toDbTimestamp(db: IdentityDatabase, date: Date): number | Date {\n return isDatabaseSqlite(db) ? Math.floor(date.getTime() / 1000) : date;\n}\n\n/**\n * Parse a timestamp value from database result to Date.\n * Handles both Unix timestamps (SQLite) and Date objects (PostgreSQL).\n */\nexport function fromDbTimestamp(value: unknown): Date | undefined {\n if (value === null || value === undefined) {\n return undefined;\n }\n if (value instanceof Date) {\n return value;\n }\n if (typeof value === 'number') {\n return new Date(value * 1000);\n }\n if (typeof value === 'string') {\n return new Date(value);\n }\n return undefined;\n}\n\n/**\n * Ensure SQLite tables exist (simple DDL for local/dev mode).\n */\nfunction ensureSqliteTables(sqlite: SqliteDdlExecutor): void {\n sqlite.exec(`\n CREATE TABLE IF NOT EXISTS identity_account_usage (\n account_id TEXT PRIMARY KEY,\n storage_bytes INTEGER NOT NULL DEFAULT 0,\n ingress_bytes INTEGER NOT NULL DEFAULT 0,\n egress_bytes INTEGER NOT NULL DEFAULT 0,\n storage_limit_bytes INTEGER,\n bandwidth_limit_bps INTEGER,\n compute_seconds INTEGER NOT NULL DEFAULT 0,\n tokens_used INTEGER NOT NULL DEFAULT 0,\n compute_limit_seconds INTEGER,\n token_limit_monthly INTEGER,\n period_start INTEGER,\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS identity_pod_usage (\n pod_id TEXT PRIMARY KEY,\n account_id TEXT NOT NULL,\n storage_url TEXT,\n storage_bytes INTEGER NOT NULL DEFAULT 0,\n ingress_bytes INTEGER NOT NULL DEFAULT 0,\n egress_bytes INTEGER NOT NULL DEFAULT 0,\n storage_limit_bytes INTEGER,\n bandwidth_limit_bps INTEGER,\n compute_seconds INTEGER NOT NULL DEFAULT 0,\n tokens_used INTEGER NOT NULL DEFAULT 0,\n compute_limit_seconds INTEGER,\n token_limit_monthly INTEGER,\n period_start INTEGER,\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS identity_edge_node (\n id TEXT PRIMARY KEY,\n display_name TEXT,\n token_hash TEXT NOT NULL,\n account_id TEXT,\n node_type TEXT DEFAULT 'edge',\n subdomain TEXT UNIQUE,\n access_mode TEXT,\n ipv4 TEXT,\n public_port INTEGER,\n public_url TEXT,\n service_token_hash TEXT,\n provision_code_hash TEXT,\n internal_ip TEXT,\n internal_port INTEGER,\n hostname TEXT,\n ipv6 TEXT,\n version TEXT,\n capabilities TEXT,\n metadata TEXT,\n connectivity_status TEXT DEFAULT 'unknown',\n last_connectivity_check INTEGER,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n last_seen INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS identity_edge_node_pod (\n node_id TEXT NOT NULL REFERENCES identity_edge_node(id) ON DELETE CASCADE,\n base_url TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS api_client_credentials (\n client_id TEXT PRIMARY KEY,\n client_secret_encrypted TEXT NOT NULL,\n web_id TEXT NOT NULL,\n account_id TEXT NOT NULL,\n display_name TEXT,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS identity_ddns_domain (\n domain TEXT PRIMARY KEY,\n status TEXT DEFAULT 'active',\n provider TEXT,\n zone_id TEXT,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS identity_ddns_record (\n subdomain TEXT PRIMARY KEY,\n domain TEXT NOT NULL,\n ip_address TEXT,\n ipv6_address TEXT,\n record_type TEXT DEFAULT 'A',\n node_id TEXT,\n username TEXT,\n status TEXT DEFAULT 'active',\n banned_reason TEXT,\n ttl INTEGER DEFAULT 60,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS identity_service_token (\n id TEXT PRIMARY KEY,\n token_hash TEXT NOT NULL UNIQUE,\n service_type TEXT NOT NULL,\n service_id TEXT NOT NULL,\n scopes TEXT NOT NULL,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n expires_at INTEGER\n );\n `);\n\n // Migrate existing tables: add new columns if missing\n migrateSqliteColumns(sqlite);\n}\n\n/**\n * Add columns that may be missing from older databases.\n * SQLite ALTER TABLE ADD COLUMN is idempotent-safe via try/catch.\n */\nfunction migrateSqliteColumns(sqlite: SqliteDdlExecutor): void {\n const addColumn = (table: string, column: string, type: string): void => {\n try {\n sqlite.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);\n } catch {\n // Column already exists — ignore\n }\n };\n\n if (sqliteColumnExists(sqlite, 'identity_edge_node', 'owner_account_id')) {\n try {\n sqlite.exec('ALTER TABLE identity_edge_node DROP COLUMN owner_account_id');\n } catch {\n // Older SQLite runtimes may not support DROP COLUMN. Ignore and keep runtime-compatible schema.\n }\n }\n const edgeNodeColumns: Array<[string, string]> = [\n [ 'node_type', `TEXT DEFAULT 'edge'` ],\n [ 'subdomain', 'TEXT' ],\n [ 'access_mode', 'TEXT' ],\n [ 'ipv4', 'TEXT' ],\n [ 'public_port', 'INTEGER' ],\n [ 'public_url', 'TEXT' ],\n [ 'service_token_hash', 'TEXT' ],\n [ 'provision_code_hash', 'TEXT' ],\n [ 'internal_ip', 'TEXT' ],\n [ 'internal_port', 'INTEGER' ],\n [ 'hostname', 'TEXT' ],\n [ 'ipv6', 'TEXT' ],\n [ 'version', 'TEXT' ],\n [ 'capabilities', 'TEXT' ],\n [ 'metadata', 'TEXT' ],\n [ 'connectivity_status', `TEXT DEFAULT 'unknown'` ],\n [ 'last_connectivity_check', 'INTEGER' ],\n [ 'last_seen', 'INTEGER' ],\n ];\n for (const [column, type] of edgeNodeColumns) {\n addColumn('identity_edge_node', column, type);\n }\n\n // Usage tables: compute/token columns\n addColumn('identity_account_usage', 'compute_seconds', 'INTEGER NOT NULL DEFAULT 0');\n addColumn('identity_account_usage', 'tokens_used', 'INTEGER NOT NULL DEFAULT 0');\n addColumn('identity_account_usage', 'compute_limit_seconds', 'INTEGER');\n addColumn('identity_account_usage', 'token_limit_monthly', 'INTEGER');\n addColumn('identity_account_usage', 'period_start', 'INTEGER');\n addColumn('identity_pod_usage', 'compute_seconds', 'INTEGER NOT NULL DEFAULT 0');\n addColumn('identity_pod_usage', 'tokens_used', 'INTEGER NOT NULL DEFAULT 0');\n addColumn('identity_pod_usage', 'compute_limit_seconds', 'INTEGER');\n addColumn('identity_pod_usage', 'token_limit_monthly', 'INTEGER');\n addColumn('identity_pod_usage', 'period_start', 'INTEGER');\n addColumn('identity_pod_usage', 'storage_url', 'TEXT');\n}\n\nfunction sqliteColumnExists(sqlite: SqliteDdlExecutor, table: string, column: string): boolean {\n const rows = sqlite.prepare<{ name: string }>(`PRAGMA table_info(${table})`).all();\n return rows.some((row) => row.name === column);\n}\n\n/**\n * Add columns that may be missing from older PostgreSQL databases.\n * Uses IF NOT EXISTS via information_schema check + ALTER TABLE.\n */\nasync function migratePgColumns(pool: { query: (sql: string) => Promise<any> }): Promise<void> {\n const addColumn = async (table: string, column: string, type: string): Promise<void> => {\n try {\n await pool.query(\n `DO $$ BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = '${table}' AND column_name = '${column}'\n ) THEN\n ALTER TABLE ${table} ADD COLUMN ${column} ${type};\n END IF;\n END $$;`,\n );\n } catch {\n // Ignore errors (table might not exist yet)\n }\n };\n\n // Usage tables: compute/token columns\n await addColumn('identity_account_usage', 'compute_seconds', 'BIGINT NOT NULL DEFAULT 0');\n await addColumn('identity_account_usage', 'tokens_used', 'BIGINT NOT NULL DEFAULT 0');\n await addColumn('identity_account_usage', 'compute_limit_seconds', 'BIGINT');\n await addColumn('identity_account_usage', 'token_limit_monthly', 'BIGINT');\n await addColumn('identity_account_usage', 'period_start', 'TIMESTAMP WITH TIME ZONE');\n await addColumn('identity_pod_usage', 'compute_seconds', 'BIGINT NOT NULL DEFAULT 0');\n await addColumn('identity_pod_usage', 'tokens_used', 'BIGINT NOT NULL DEFAULT 0');\n await addColumn('identity_pod_usage', 'compute_limit_seconds', 'BIGINT');\n await addColumn('identity_pod_usage', 'token_limit_monthly', 'BIGINT');\n await addColumn('identity_pod_usage', 'period_start', 'TIMESTAMP WITH TIME ZONE');\n await addColumn('identity_pod_usage', 'storage_url', 'TEXT');\n\n // Service token table\n try {\n await pool.query(`\n CREATE TABLE IF NOT EXISTS identity_service_token (\n id TEXT PRIMARY KEY,\n token_hash TEXT NOT NULL UNIQUE,\n service_type TEXT NOT NULL,\n service_id TEXT NOT NULL,\n scopes TEXT NOT NULL,\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMP WITH TIME ZONE\n );\n `);\n } catch {\n // Ignore if already exists\n }\n}\n\n\nasync function ensurePostgresTables(pool: Pool): Promise<void> {\n await pool.query(`\n CREATE TABLE IF NOT EXISTS identity_account_usage (\n account_id TEXT PRIMARY KEY,\n storage_bytes BIGINT NOT NULL DEFAULT 0,\n ingress_bytes BIGINT NOT NULL DEFAULT 0,\n egress_bytes BIGINT NOT NULL DEFAULT 0,\n storage_limit_bytes BIGINT,\n bandwidth_limit_bps BIGINT,\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n );\n\n CREATE TABLE IF NOT EXISTS identity_pod_usage (\n pod_id TEXT PRIMARY KEY,\n account_id TEXT NOT NULL,\n storage_url TEXT,\n storage_bytes BIGINT NOT NULL DEFAULT 0,\n ingress_bytes BIGINT NOT NULL DEFAULT 0,\n egress_bytes BIGINT NOT NULL DEFAULT 0,\n storage_limit_bytes BIGINT,\n bandwidth_limit_bps BIGINT,\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n );\n\n CREATE TABLE IF NOT EXISTS identity_edge_node (\n id TEXT PRIMARY KEY,\n display_name TEXT,\n token_hash TEXT NOT NULL,\n account_id TEXT,\n node_type TEXT DEFAULT 'edge',\n subdomain TEXT UNIQUE,\n access_mode TEXT,\n ipv4 TEXT,\n public_port BIGINT,\n public_url TEXT,\n service_token_hash TEXT,\n provision_code_hash TEXT,\n internal_ip TEXT,\n internal_port BIGINT,\n hostname TEXT,\n ipv6 TEXT,\n version TEXT,\n capabilities JSONB,\n metadata JSONB,\n connectivity_status TEXT DEFAULT 'unknown',\n last_connectivity_check TIMESTAMPTZ,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n last_seen TIMESTAMPTZ\n );\n\n CREATE TABLE IF NOT EXISTS identity_edge_node_pod (\n node_id TEXT NOT NULL REFERENCES identity_edge_node(id) ON DELETE CASCADE,\n base_url TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS api_client_credentials (\n client_id TEXT PRIMARY KEY,\n client_secret_encrypted TEXT NOT NULL,\n web_id TEXT NOT NULL,\n account_id TEXT NOT NULL,\n display_name TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n );\n\n CREATE TABLE IF NOT EXISTS identity_ddns_domain (\n domain TEXT PRIMARY KEY,\n status TEXT DEFAULT 'active',\n provider TEXT,\n zone_id TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n );\n\n CREATE TABLE IF NOT EXISTS identity_ddns_record (\n subdomain TEXT PRIMARY KEY,\n domain TEXT NOT NULL,\n ip_address TEXT,\n ipv6_address TEXT,\n record_type TEXT DEFAULT 'A',\n node_id TEXT,\n username TEXT,\n status TEXT DEFAULT 'active',\n banned_reason TEXT,\n ttl INTEGER DEFAULT 60,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n );\n\n CREATE TABLE IF NOT EXISTS identity_service_token (\n id TEXT PRIMARY KEY,\n token_hash TEXT NOT NULL UNIQUE,\n service_type TEXT NOT NULL,\n service_id TEXT NOT NULL,\n scopes TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ\n );\n `);\n\n await migratePostgresColumns(pool);\n}\n\nasync function migratePostgresColumns(pool: Pool): Promise<void> {\n const addColumn = async (table: string, column: string, type: string): Promise<void> => {\n await pool.query(`ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS ${column} ${type}`);\n };\n\n await pool.query('ALTER TABLE identity_edge_node DROP COLUMN IF EXISTS owner_account_id');\n await pool.query(`\n DO $$\n BEGIN\n IF EXISTS (\n SELECT 1\n FROM information_schema.columns\n WHERE table_name = 'identity_edge_node' AND column_name = 'public_ip'\n ) AND NOT EXISTS (\n SELECT 1\n FROM information_schema.columns\n WHERE table_name = 'identity_edge_node' AND column_name = 'ipv4'\n ) THEN\n ALTER TABLE identity_edge_node RENAME COLUMN public_ip TO ipv4;\n END IF;\n END $$;\n `);\n\n const edgeNodeColumns: Array<[string, string]> = [\n [ 'node_type', `TEXT DEFAULT 'edge'` ],\n [ 'subdomain', 'TEXT' ],\n [ 'access_mode', 'TEXT' ],\n [ 'ipv4', 'TEXT' ],\n [ 'public_port', 'BIGINT' ],\n [ 'public_url', 'TEXT' ],\n [ 'service_token_hash', 'TEXT' ],\n [ 'provision_code_hash', 'TEXT' ],\n [ 'internal_ip', 'TEXT' ],\n [ 'internal_port', 'BIGINT' ],\n [ 'hostname', 'TEXT' ],\n [ 'ipv6', 'TEXT' ],\n [ 'version', 'TEXT' ],\n [ 'capabilities', 'JSONB' ],\n [ 'metadata', 'JSONB' ],\n [ 'connectivity_status', `TEXT DEFAULT 'unknown'` ],\n [ 'last_connectivity_check', 'TIMESTAMPTZ' ],\n [ 'last_seen', 'TIMESTAMPTZ' ],\n ];\n for (const [column, type] of edgeNodeColumns) {\n await addColumn('identity_edge_node', column, type);\n }\n}\n"]}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/identity/drizzle/db.ts"],"names":[],"mappings":"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","sourcesContent":["import { Pool, types } from 'pg';\nimport { drizzle as drizzlePg } from 'drizzle-orm/node-postgres';\nimport { sql } from 'drizzle-orm';\nimport type { SQL } from 'drizzle-orm/sql';\nimport * as pgSchema from './schema.pg';\nimport * as sqliteSchema from './schema.sqlite';\nimport { getSharedPool, releaseSharedPool } from '../../storage/database/PostgresPoolManager';\nimport { getSqliteRuntime, type SqliteDatabase } from '../../storage/SqliteRuntime';\n\n// Use 'any' to allow both PostgreSQL and SQLite database instances\n// The actual type depends on the connection string at runtime\nexport type IdentityDatabase = any;\nexport type IdentitySchema = typeof pgSchema | typeof sqliteSchema;\n\n/**\n * Get the appropriate schema for the given database connection.\n * This provides a unified abstraction layer over PG and SQLite schemas.\n *\n * @example\n * const schema = getSchema(db);\n * await db.select().from(schema.usage).where(eq(schema.usage.scopeId, id));\n */\nexport function getSchema(db: IdentityDatabase): typeof pgSchema | typeof sqliteSchema {\n return isDatabaseSqlite(db) ? sqliteSchema : pgSchema;\n}\n\n/**\n * Standardized query result format across databases.\n */\nexport interface QueryResult<T = Record<string, unknown>> {\n rows: T[];\n}\n\ninterface CachedConnection {\n db: IdentityDatabase;\n schema: IdentitySchema;\n isSqlite: boolean;\n close: () => Promise<void>;\n}\n\nconst dbCache = new Map<string, CachedConnection>();\nconst dbInitPromises = new WeakMap<object, Promise<void>>();\nconst cloudClusterInitPromises = new WeakMap<object, Promise<void>>();\n\nconst JSON_OIDS = [114, 3802];\n\ntype SqliteDdlExecutor = Pick<SqliteDatabase, 'exec'>;\n\nfor (const oid of JSON_OIDS) {\n // Explicitly return raw string to avoid \"Type Conflict\" with CSS\n // and to satisfy PgQuintStore's parseVector expecting a string.\n types.setTypeParser(oid, (value) => value);\n}\n\n/**\n * Returns true if the connection string is a SQLite URL.\n */\nexport function isSqliteUrl(connectionString: string): boolean {\n return connectionString.startsWith('sqlite:');\n}\n\n/**\n * Get or create a Drizzle database connection with the appropriate schema.\n * Supports both PostgreSQL and SQLite.\n */\nexport function getIdentityDatabase(connectionString: string): IdentityDatabase {\n const cached = dbCache.get(connectionString);\n if (cached) {\n return cached.db;\n }\n\n if (isSqliteUrl(connectionString)) {\n const filename = connectionString.replace('sqlite:', '');\n const isMemory = filename === ':memory:' || filename.startsWith(':memory:');\n const sqliteRuntime = getSqliteRuntime();\n const sqlite = sqliteRuntime.openDatabase(isMemory ? ':memory:' : filename);\n\n if (!isMemory) {\n sqlite.pragma('journal_mode = WAL');\n sqlite.pragma('busy_timeout = 5000');\n sqlite.pragma('synchronous = NORMAL');\n }\n\n const db = sqliteRuntime.createDrizzleDatabase(sqlite);\n\n ensureSqliteTables(sqlite);\n\n dbInitPromises.set(db as object, Promise.resolve());\n dbCache.set(connectionString, {\n db,\n schema: sqliteSchema,\n isSqlite: true,\n close: async () => { sqlite.close(); },\n });\n return db;\n }\n\n // PostgreSQL: use shared pool to avoid connection exhaustion and deadlocks\n const pool = getSharedPool({ connectionString });\n const db = drizzlePg(pool);\n const initPromise = (async(): Promise<void> => {\n await ensurePostgresTables(pool);\n await migratePgColumns(pool);\n })();\n dbInitPromises.set(db as object, initPromise);\n initPromise.catch((err) => {\n console.error(`[IdentityDB] PG migration failed: ${err}`);\n });\n dbCache.set(connectionString, {\n db,\n schema: pgSchema,\n isSqlite: false,\n close: async () => { \n // Release reference to shared pool instead of ending it\n releaseSharedPool({ connectionString }); \n },\n });\n return db;\n}\n\n/**\n * Get the schema for a given connection string.\n */\nexport function getIdentitySchema(connectionString: string): IdentitySchema {\n const cached = dbCache.get(connectionString);\n if (cached) {\n return cached.schema;\n }\n // Initialize connection to populate cache\n getIdentityDatabase(connectionString);\n return dbCache.get(connectionString)!.schema;\n}\n\n/**\n * Safely get a Drizzle database connection, returning undefined on error.\n * Use this when the identity database is optional (e.g., for usage tracking).\n */\nexport function tryGetIdentityDatabase(connectionString: string): IdentityDatabase | undefined {\n try {\n return getIdentityDatabase(connectionString);\n } catch {\n return undefined;\n }\n}\n\nexport async function closeAllIdentityConnections(): Promise<void> {\n await Promise.all([...dbCache.values()].map(({ close }) => close()));\n dbCache.clear();\n}\n\n/**\n * Check if a database connection is SQLite.\n * SQLite drizzle has `all()` method but no `execute()` method.\n * PostgreSQL drizzle has `execute()` method but no `all()` method.\n */\nexport function isDatabaseSqlite(db: IdentityDatabase): boolean {\n if ((db as any)?.$xpodSqliteRuntime) {\n return true;\n }\n return typeof db.all === 'function' && typeof db.execute !== 'function';\n}\n\nasync function ensureDatabaseReady(db: IdentityDatabase): Promise<void> {\n const initPromise = dbInitPromises.get(db as object);\n if (initPromise) {\n await initPromise;\n }\n}\n\n/**\n * Execute a SQL query uniformly across PostgreSQL and SQLite.\n * Returns a standardized result with rows array.\n *\n * @example\n * const result = await executeQuery(db, sql`SELECT * FROM users WHERE id = ${userId}`);\n * if (result.rows.length > 0) { ... }\n */\nexport async function executeQuery<T = Record<string, unknown>>(\n db: IdentityDatabase,\n query: SQL,\n): Promise<QueryResult<T>> {\n await ensureDatabaseReady(db);\n if (isDatabaseSqlite(db)) {\n // SQLite: db.all() returns array directly\n const rows = db.all(query) as T[];\n return { rows };\n }\n // PostgreSQL: db.execute() returns { rows: [...] }\n return db.execute(query) as Promise<QueryResult<T>>;\n}\n\n/**\n * Execute a SQL statement that doesn't return rows (INSERT, UPDATE, DELETE).\n * Works uniformly across PostgreSQL and SQLite.\n */\nexport async function executeStatement(\n db: IdentityDatabase,\n query: SQL,\n): Promise<void> {\n await ensureDatabaseReady(db);\n if (isDatabaseSqlite(db)) {\n // SQLite: db.run() for statements\n db.run(query);\n return;\n }\n // PostgreSQL: db.execute() works for statements too\n await db.execute(query);\n}\n\nexport async function ensureCloudClusterTables(db: IdentityDatabase): Promise<void> {\n await ensureDatabaseReady(db);\n\n if (db && typeof db === 'object') {\n const cached = cloudClusterInitPromises.get(db as object);\n if (cached) {\n await cached;\n return;\n }\n\n const initPromise = doEnsureCloudClusterTables(db).catch((error) => {\n cloudClusterInitPromises.delete(db as object);\n throw error;\n });\n cloudClusterInitPromises.set(db as object, initPromise);\n await initPromise;\n return;\n }\n\n await doEnsureCloudClusterTables(db);\n}\n\nasync function doEnsureCloudClusterTables(db: IdentityDatabase): Promise<void> {\n\n if (isDatabaseSqlite(db)) {\n db.run(sql`\n CREATE TABLE IF NOT EXISTS cluster_ddns_record (\n subdomain TEXT PRIMARY KEY,\n domain TEXT NOT NULL,\n ip_address TEXT,\n ipv6_address TEXT,\n record_type TEXT DEFAULT 'A',\n node_id TEXT,\n username TEXT,\n status TEXT DEFAULT 'active',\n banned_reason TEXT,\n ttl INTEGER DEFAULT 60,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n )\n `);\n db.run(sql`\n CREATE TABLE IF NOT EXISTS cluster_service_token (\n id TEXT PRIMARY KEY,\n token_hash TEXT NOT NULL UNIQUE,\n service_type TEXT NOT NULL,\n service_id TEXT NOT NULL,\n scopes TEXT NOT NULL,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n expires_at INTEGER\n )\n `);\n db.run(sql`\n CREATE TABLE IF NOT EXISTS cluster_node (\n id TEXT PRIMARY KEY,\n display_name TEXT,\n token_hash TEXT NOT NULL,\n node_type TEXT DEFAULT 'edge',\n subdomain TEXT UNIQUE,\n access_mode TEXT,\n ipv4 TEXT,\n public_port INTEGER,\n public_url TEXT,\n service_token_hash TEXT,\n provision_code_hash TEXT,\n internal_ip TEXT,\n internal_port INTEGER,\n hostname TEXT,\n ipv6 TEXT,\n version TEXT,\n capabilities TEXT,\n metadata TEXT,\n pod_base_urls TEXT,\n connectivity_status TEXT DEFAULT 'unknown',\n last_connectivity_check INTEGER,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n last_seen INTEGER\n )\n `);\n db.run(sql`CREATE INDEX IF NOT EXISTS idx_cluster_ddns_record_domain ON cluster_ddns_record(domain)`);\n db.run(sql`CREATE INDEX IF NOT EXISTS idx_cluster_ddns_record_node ON cluster_ddns_record(node_id)`);\n db.run(sql`CREATE INDEX IF NOT EXISTS idx_cluster_node_subdomain ON cluster_node(subdomain)`);\n db.run(sql`CREATE INDEX IF NOT EXISTS idx_cluster_node_access_mode ON cluster_node(access_mode)`);\n db.run(sql`CREATE INDEX IF NOT EXISTS idx_cluster_node_connectivity_status ON cluster_node(connectivity_status)`);\n return;\n }\n\n await db.execute(sql`\n CREATE TABLE IF NOT EXISTS cluster_ddns_record (\n subdomain TEXT PRIMARY KEY,\n domain TEXT NOT NULL,\n ip_address TEXT,\n ipv6_address TEXT,\n record_type TEXT DEFAULT 'A',\n node_id TEXT,\n username TEXT,\n status TEXT DEFAULT 'active',\n banned_reason TEXT,\n ttl INTEGER DEFAULT 60,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n )\n `);\n await db.execute(sql`\n CREATE TABLE IF NOT EXISTS cluster_service_token (\n id TEXT PRIMARY KEY,\n token_hash TEXT NOT NULL UNIQUE,\n service_type TEXT NOT NULL,\n service_id TEXT NOT NULL,\n scopes TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ\n )\n `);\n await db.execute(sql`\n CREATE TABLE IF NOT EXISTS cluster_node (\n id TEXT PRIMARY KEY,\n display_name TEXT,\n token_hash TEXT NOT NULL,\n node_type TEXT DEFAULT 'edge',\n subdomain TEXT UNIQUE,\n access_mode TEXT,\n ipv4 TEXT,\n public_port BIGINT,\n public_url TEXT,\n service_token_hash TEXT,\n provision_code_hash TEXT,\n internal_ip TEXT,\n internal_port BIGINT,\n hostname TEXT,\n ipv6 TEXT,\n version TEXT,\n capabilities JSONB,\n metadata JSONB,\n pod_base_urls TEXT,\n connectivity_status TEXT DEFAULT 'unknown',\n last_connectivity_check TIMESTAMPTZ,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n last_seen TIMESTAMPTZ\n )\n `);\n await db.execute(sql`CREATE INDEX IF NOT EXISTS idx_cluster_ddns_record_domain ON cluster_ddns_record(domain)`);\n await db.execute(sql`CREATE INDEX IF NOT EXISTS idx_cluster_ddns_record_node ON cluster_ddns_record(node_id)`);\n await db.execute(sql`CREATE INDEX IF NOT EXISTS idx_cluster_node_subdomain ON cluster_node(subdomain)`);\n await db.execute(sql`CREATE INDEX IF NOT EXISTS idx_cluster_node_access_mode ON cluster_node(access_mode)`);\n await db.execute(sql`CREATE INDEX IF NOT EXISTS idx_cluster_node_connectivity_status ON cluster_node(connectivity_status)`);\n}\n\n/**\n * Convert a Date to a value suitable for the database.\n * SQLite uses Unix timestamps (seconds), PostgreSQL uses Date objects.\n */\nexport function toDbTimestamp(db: IdentityDatabase, date: Date): number | Date {\n return isDatabaseSqlite(db) ? Math.floor(date.getTime() / 1000) : date;\n}\n\n/**\n * Parse a timestamp value from database result to Date.\n * Handles both Unix timestamps (SQLite) and Date objects (PostgreSQL).\n */\nexport function fromDbTimestamp(value: unknown): Date | undefined {\n if (value === null || value === undefined) {\n return undefined;\n }\n if (value instanceof Date) {\n return value;\n }\n if (typeof value === 'number') {\n return new Date(value * 1000);\n }\n if (typeof value === 'string') {\n return new Date(value);\n }\n return undefined;\n}\n\n/**\n * Ensure SQLite tables exist (simple DDL for local/dev mode).\n */\nfunction ensureSqliteTables(sqlite: SqliteDdlExecutor): void {\n sqlite.exec(`\n CREATE TABLE IF NOT EXISTS identity_usage (\n scope_type TEXT NOT NULL,\n scope_id TEXT NOT NULL,\n account_id TEXT NOT NULL,\n storage_bytes INTEGER NOT NULL DEFAULT 0,\n ingress_bytes INTEGER NOT NULL DEFAULT 0,\n egress_bytes INTEGER NOT NULL DEFAULT 0,\n storage_limit_bytes INTEGER,\n bandwidth_limit_bps INTEGER,\n compute_seconds INTEGER NOT NULL DEFAULT 0,\n tokens_used INTEGER NOT NULL DEFAULT 0,\n compute_limit_seconds INTEGER,\n token_limit_monthly INTEGER,\n period_start INTEGER,\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n PRIMARY KEY (scope_type, scope_id)\n );\n\n `);\n\n // Migrate existing tables: add new columns if missing\n migrateSqliteColumns(sqlite);\n}\n\n/**\n * Add columns that may be missing from older databases.\n * SQLite ALTER TABLE ADD COLUMN is idempotent-safe via try/catch.\n */\nfunction migrateSqliteColumns(sqlite: SqliteDdlExecutor): void {\n const addColumn = (table: string, column: string, type: string): void => {\n try {\n sqlite.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);\n } catch {\n // Column already exists — ignore\n }\n };\n\n // Usage table: compute/token columns\n addColumn('identity_usage', 'compute_seconds', 'INTEGER NOT NULL DEFAULT 0');\n addColumn('identity_usage', 'tokens_used', 'INTEGER NOT NULL DEFAULT 0');\n addColumn('identity_usage', 'compute_limit_seconds', 'INTEGER');\n addColumn('identity_usage', 'token_limit_monthly', 'INTEGER');\n addColumn('identity_usage', 'period_start', 'INTEGER');\n}\n\n/**\n * Add columns that may be missing from older PostgreSQL databases.\n * Uses IF NOT EXISTS via information_schema check + ALTER TABLE.\n */\nasync function migratePgColumns(pool: { query: (sql: string) => Promise<any> }): Promise<void> {\n const addColumn = async (table: string, column: string, type: string): Promise<void> => {\n try {\n await pool.query(\n `DO $$ BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = '${table}' AND column_name = '${column}'\n ) THEN\n ALTER TABLE ${table} ADD COLUMN ${column} ${type};\n END IF;\n END $$;`,\n );\n } catch {\n // Ignore errors (table might not exist yet)\n }\n };\n\n // Usage table: compute/token columns\n await addColumn('identity_usage', 'compute_seconds', 'BIGINT NOT NULL DEFAULT 0');\n await addColumn('identity_usage', 'tokens_used', 'BIGINT NOT NULL DEFAULT 0');\n await addColumn('identity_usage', 'compute_limit_seconds', 'BIGINT');\n await addColumn('identity_usage', 'token_limit_monthly', 'BIGINT');\n await addColumn('identity_usage', 'period_start', 'TIMESTAMP WITH TIME ZONE');\n\n}\n\n\nasync function ensurePostgresTables(pool: Pool): Promise<void> {\n await pool.query(`\n CREATE TABLE IF NOT EXISTS identity_usage (\n scope_type TEXT NOT NULL,\n scope_id TEXT NOT NULL,\n account_id TEXT NOT NULL,\n storage_bytes BIGINT NOT NULL DEFAULT 0,\n ingress_bytes BIGINT NOT NULL DEFAULT 0,\n egress_bytes BIGINT NOT NULL DEFAULT 0,\n storage_limit_bytes BIGINT,\n bandwidth_limit_bps BIGINT,\n compute_seconds BIGINT NOT NULL DEFAULT 0,\n tokens_used BIGINT NOT NULL DEFAULT 0,\n compute_limit_seconds BIGINT,\n token_limit_monthly BIGINT,\n period_start TIMESTAMPTZ,\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n PRIMARY KEY (scope_type, scope_id)\n );\n\n `);\n\n await migratePostgresColumns(pool);\n}\n\nasync function migratePostgresColumns(pool: Pool): Promise<void> {\n void pool;\n}\n"]}
@@ -1,20 +1,12 @@
1
- export declare const accountUsage: any;
2
- export declare const podUsage: any;
1
+ export declare const usage: any;
3
2
  /**
4
- * DDNS 域名池表
5
- * 管理可用的 DDNS 域名
6
- */
7
- export declare const ddnsDomains: any;
8
- /**
9
- * DDNS 记录表
3
+ * Cloud cluster DDNS 记录表
10
4
  * 已分配的子域名记录
11
5
  */
12
6
  export declare const ddnsRecords: any;
13
7
  export declare const edgeNodes: any;
14
- export declare const edgeNodePods: any;
15
- export declare const apiClientCredentials: any;
16
8
  /**
17
- * Service Token 表
9
+ * Cloud cluster Service Token 表
18
10
  * 用于服务间认证 (Business, Local SP, Cloud, Compute)
19
11
  */
20
12
  export declare const serviceTokens: any;
@@ -1,27 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serviceTokens = exports.apiClientCredentials = exports.edgeNodePods = exports.edgeNodes = exports.ddnsRecords = exports.ddnsDomains = exports.podUsage = exports.accountUsage = void 0;
3
+ exports.serviceTokens = exports.edgeNodes = exports.ddnsRecords = exports.usage = void 0;
4
4
  const pg_core_1 = require("drizzle-orm/pg-core");
5
5
  const bigint_1 = require("drizzle-orm/pg-core/columns/bigint");
6
6
  const integer_1 = require("drizzle-orm/pg-core/columns/integer");
7
- exports.accountUsage = (0, pg_core_1.pgTable)('identity_account_usage', {
8
- accountId: (0, pg_core_1.text)('account_id').primaryKey(),
9
- storageBytes: (0, bigint_1.bigint)('storage_bytes', { mode: 'number' }).notNull().default(0),
10
- ingressBytes: (0, bigint_1.bigint)('ingress_bytes', { mode: 'number' }).notNull().default(0),
11
- egressBytes: (0, bigint_1.bigint)('egress_bytes', { mode: 'number' }).notNull().default(0),
12
- storageLimitBytes: (0, bigint_1.bigint)('storage_limit_bytes', { mode: 'number' }),
13
- bandwidthLimitBps: (0, bigint_1.bigint)('bandwidth_limit_bps', { mode: 'number' }),
14
- computeSeconds: (0, bigint_1.bigint)('compute_seconds', { mode: 'number' }).notNull().default(0),
15
- tokensUsed: (0, bigint_1.bigint)('tokens_used', { mode: 'number' }).notNull().default(0),
16
- computeLimitSeconds: (0, bigint_1.bigint)('compute_limit_seconds', { mode: 'number' }),
17
- tokenLimitMonthly: (0, bigint_1.bigint)('token_limit_monthly', { mode: 'number' }),
18
- periodStart: (0, pg_core_1.timestamp)('period_start', { withTimezone: true, mode: 'date' }),
19
- updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
20
- });
21
- exports.podUsage = (0, pg_core_1.pgTable)('identity_pod_usage', {
22
- podId: (0, pg_core_1.text)('pod_id').primaryKey(),
7
+ exports.usage = (0, pg_core_1.pgTable)('identity_usage', {
8
+ scopeType: (0, pg_core_1.text)('scope_type').notNull(), // 'account' | 'pod'
9
+ scopeId: (0, pg_core_1.text)('scope_id').notNull(),
23
10
  accountId: (0, pg_core_1.text)('account_id').notNull(),
24
- storageUrl: (0, pg_core_1.text)('storage_url'),
25
11
  storageBytes: (0, bigint_1.bigint)('storage_bytes', { mode: 'number' }).notNull().default(0),
26
12
  ingressBytes: (0, bigint_1.bigint)('ingress_bytes', { mode: 'number' }).notNull().default(0),
27
13
  egressBytes: (0, bigint_1.bigint)('egress_bytes', { mode: 'number' }).notNull().default(0),
@@ -35,21 +21,10 @@ exports.podUsage = (0, pg_core_1.pgTable)('identity_pod_usage', {
35
21
  updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
36
22
  });
37
23
  /**
38
- * DDNS 域名池表
39
- * 管理可用的 DDNS 域名
40
- */
41
- exports.ddnsDomains = (0, pg_core_1.pgTable)('identity_ddns_domain', {
42
- domain: (0, pg_core_1.text)('domain').primaryKey(), // undefineds.xyz
43
- status: (0, pg_core_1.text)('status').default('active'), // 'active' | 'suspended'
44
- provider: (0, pg_core_1.text)('provider'), // 'cloudflare' | 'tencent'
45
- zoneId: (0, pg_core_1.text)('zone_id'), // DNS Zone ID
46
- createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
47
- });
48
- /**
49
- * DDNS 记录表
24
+ * Cloud cluster DDNS 记录表
50
25
  * 已分配的子域名记录
51
26
  */
52
- exports.ddnsRecords = (0, pg_core_1.pgTable)('identity_ddns_record', {
27
+ exports.ddnsRecords = (0, pg_core_1.pgTable)('cluster_ddns_record', {
53
28
  subdomain: (0, pg_core_1.text)('subdomain').primaryKey(), // alice
54
29
  domain: (0, pg_core_1.text)('domain').notNull(), // undefineds.xyz
55
30
  ipAddress: (0, pg_core_1.text)('ip_address'),
@@ -63,7 +38,7 @@ exports.ddnsRecords = (0, pg_core_1.pgTable)('identity_ddns_record', {
63
38
  createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
64
39
  updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
65
40
  });
66
- exports.edgeNodes = (0, pg_core_1.pgTable)('identity_edge_node', {
41
+ exports.edgeNodes = (0, pg_core_1.pgTable)('cluster_node', {
67
42
  id: (0, pg_core_1.text)('id').primaryKey(),
68
43
  displayName: (0, pg_core_1.text)('display_name'),
69
44
  tokenHash: (0, pg_core_1.text)('token_hash').notNull(),
@@ -84,28 +59,18 @@ exports.edgeNodes = (0, pg_core_1.pgTable)('identity_edge_node', {
84
59
  // JSON fields
85
60
  capabilities: (0, pg_core_1.text)('capabilities'), // JSON string: 能力列表
86
61
  metadata: (0, pg_core_1.text)('metadata'), // JSON string: 复杂对象 (tunnel, certificate, metrics)
62
+ podBaseUrls: (0, pg_core_1.text)('pod_base_urls'), // JSON string: node-owned Pod/storage URL prefixes
87
63
  connectivityStatus: (0, pg_core_1.text)('connectivity_status').default('unknown'),
88
64
  lastConnectivityCheck: (0, pg_core_1.timestamp)('last_connectivity_check', { withTimezone: true, mode: 'date' }),
89
65
  createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
90
66
  updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
91
67
  lastSeen: (0, pg_core_1.timestamp)('last_seen', { withTimezone: true, mode: 'date' }),
92
68
  });
93
- exports.edgeNodePods = (0, pg_core_1.pgTable)('identity_edge_node_pod', {
94
- nodeId: (0, pg_core_1.text)('node_id').notNull().references(() => exports.edgeNodes.id, { onDelete: 'cascade' }),
95
- baseUrl: (0, pg_core_1.text)('base_url').notNull(),
96
- });
97
- exports.apiClientCredentials = (0, pg_core_1.pgTable)('identity_api_client_credentials', {
98
- clientId: (0, pg_core_1.text)('client_id').primaryKey(),
99
- webId: (0, pg_core_1.text)('web_id').notNull(),
100
- accountId: (0, pg_core_1.text)('account_id').notNull(),
101
- displayName: (0, pg_core_1.text)('display_name'),
102
- createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
103
- });
104
69
  /**
105
- * Service Token 表
70
+ * Cloud cluster Service Token 表
106
71
  * 用于服务间认证 (Business, Local SP, Cloud, Compute)
107
72
  */
108
- exports.serviceTokens = (0, pg_core_1.pgTable)('identity_service_token', {
73
+ exports.serviceTokens = (0, pg_core_1.pgTable)('cluster_service_token', {
109
74
  id: (0, pg_core_1.text)('id').primaryKey(),
110
75
  tokenHash: (0, pg_core_1.text)('token_hash').notNull().unique(),
111
76
  serviceType: (0, pg_core_1.text)('service_type').notNull(), // 'local' | 'business' | 'cloud' | 'compute'
@@ -1 +1 @@
1
- {"version":3,"file":"schema.pg.js","sourceRoot":"","sources":["../../../src/identity/drizzle/schema.pg.ts"],"names":[],"mappings":"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","sourcesContent":["import { pgTable, text, timestamp } from 'drizzle-orm/pg-core';\nimport { bigint as pgBigint } from 'drizzle-orm/pg-core/columns/bigint';\nimport { integer } from 'drizzle-orm/pg-core/columns/integer';\n\nexport const accountUsage = pgTable('identity_account_usage', {\n accountId: text('account_id').primaryKey(),\n storageBytes: pgBigint('storage_bytes', { mode: 'number' }).notNull().default(0),\n ingressBytes: pgBigint('ingress_bytes', { mode: 'number' }).notNull().default(0),\n egressBytes: pgBigint('egress_bytes', { mode: 'number' }).notNull().default(0),\n storageLimitBytes: pgBigint('storage_limit_bytes', { mode: 'number' }),\n bandwidthLimitBps: pgBigint('bandwidth_limit_bps', { mode: 'number' }),\n computeSeconds: pgBigint('compute_seconds', { mode: 'number' }).notNull().default(0),\n tokensUsed: pgBigint('tokens_used', { mode: 'number' }).notNull().default(0),\n computeLimitSeconds: pgBigint('compute_limit_seconds', { mode: 'number' }),\n tokenLimitMonthly: pgBigint('token_limit_monthly', { mode: 'number' }),\n periodStart: timestamp('period_start', { withTimezone: true, mode: 'date' }),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\nexport const podUsage = pgTable('identity_pod_usage', {\n podId: text('pod_id').primaryKey(),\n accountId: text('account_id').notNull(),\n storageUrl: text('storage_url'),\n storageBytes: pgBigint('storage_bytes', { mode: 'number' }).notNull().default(0),\n ingressBytes: pgBigint('ingress_bytes', { mode: 'number' }).notNull().default(0),\n egressBytes: pgBigint('egress_bytes', { mode: 'number' }).notNull().default(0),\n storageLimitBytes: pgBigint('storage_limit_bytes', { mode: 'number' }),\n bandwidthLimitBps: pgBigint('bandwidth_limit_bps', { mode: 'number' }),\n computeSeconds: pgBigint('compute_seconds', { mode: 'number' }).notNull().default(0),\n tokensUsed: pgBigint('tokens_used', { mode: 'number' }).notNull().default(0),\n computeLimitSeconds: pgBigint('compute_limit_seconds', { mode: 'number' }),\n tokenLimitMonthly: pgBigint('token_limit_monthly', { mode: 'number' }),\n periodStart: timestamp('period_start', { withTimezone: true, mode: 'date' }),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\n/**\n * DDNS 域名池表\n * 管理可用的 DDNS 域名\n */\nexport const ddnsDomains = pgTable('identity_ddns_domain', {\n domain: text('domain').primaryKey(), // undefineds.xyz\n status: text('status').default('active'), // 'active' | 'suspended'\n provider: text('provider'), // 'cloudflare' | 'tencent'\n zoneId: text('zone_id'), // DNS Zone ID\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\n/**\n * DDNS 记录表\n * 已分配的子域名记录\n */\nexport const ddnsRecords = pgTable('identity_ddns_record', {\n subdomain: text('subdomain').primaryKey(), // alice\n domain: text('domain').notNull(), // undefineds.xyz\n ipAddress: text('ip_address'),\n ipv6Address: text('ipv6_address'),\n recordType: text('record_type').default('A'), // 'A' | 'AAAA'\n nodeId: text('node_id'), // 关联的节点 ID\n username: text('username'), // 关联的用户名\n status: text('status').default('active'), // 'active' | 'banned'\n bannedReason: text('banned_reason'),\n ttl: integer('ttl').default(60),\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\nexport const edgeNodes = pgTable('identity_edge_node', {\n id: text('id').primaryKey(),\n displayName: text('display_name'),\n tokenHash: text('token_hash').notNull(),\n nodeType: text('node_type').default('edge'), // 'center' | 'edge' | 'sp'\n subdomain: text('subdomain').unique(),\n accessMode: text('access_mode'),\n ipv4: text('ipv4'), // IPv4 地址\n publicPort: pgBigint('public_port', { mode: 'number' }),\n publicUrl: text('public_url'), // SP 的公网地址 (e.g. https://sp.example)\n serviceTokenHash: text('service_token_hash'), // Cloud → SP 回调认证 token (明文)\n provisionCodeHash: text('provision_code_hash'), // bind 时用户传入的配对码 (hash)\n internalIp: text('internal_ip'), // Internal network IP\n internalPort: pgBigint('internal_port', { mode: 'number' }),\n // Extracted from metadata\n hostname: text('hostname'), // 节点主机名\n ipv6: text('ipv6'), // IPv6 地址\n version: text('version'), // Agent 版本\n // JSON fields\n capabilities: text('capabilities'), // JSON string: 能力列表\n metadata: text('metadata'), // JSON string: 复杂对象 (tunnel, certificate, metrics)\n connectivityStatus: text('connectivity_status').default('unknown'),\n lastConnectivityCheck: timestamp('last_connectivity_check', { withTimezone: true, mode: 'date' }),\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n lastSeen: timestamp('last_seen', { withTimezone: true, mode: 'date' }),\n});\n\nexport const edgeNodePods = pgTable('identity_edge_node_pod', {\n nodeId: text('node_id').notNull().references(() => edgeNodes.id, { onDelete: 'cascade' }),\n baseUrl: text('base_url').notNull(),\n});\n\nexport const apiClientCredentials = pgTable('identity_api_client_credentials', {\n clientId: text('client_id').primaryKey(),\n webId: text('web_id').notNull(),\n accountId: text('account_id').notNull(),\n displayName: text('display_name'),\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\n/**\n * Service Token 表\n * 用于服务间认证 (Business, Local SP, Cloud, Compute)\n */\nexport const serviceTokens = pgTable('identity_service_token', {\n id: text('id').primaryKey(),\n tokenHash: text('token_hash').notNull().unique(),\n serviceType: text('service_type').notNull(), // 'local' | 'business' | 'cloud' | 'compute'\n serviceId: text('service_id').notNull(),\n scopes: text('scopes').notNull(), // JSON array: [\"quota:write\",\"usage:read\"]\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n expiresAt: timestamp('expires_at', { withTimezone: true, mode: 'date' }),\n});\n"]}
1
+ {"version":3,"file":"schema.pg.js","sourceRoot":"","sources":["../../../src/identity/drizzle/schema.pg.ts"],"names":[],"mappings":"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","sourcesContent":["import { pgTable, text, timestamp } from 'drizzle-orm/pg-core';\nimport { bigint as pgBigint } from 'drizzle-orm/pg-core/columns/bigint';\nimport { integer } from 'drizzle-orm/pg-core/columns/integer';\n\nexport const usage = pgTable('identity_usage', {\n scopeType: text('scope_type').notNull(), // 'account' | 'pod'\n scopeId: text('scope_id').notNull(),\n accountId: text('account_id').notNull(),\n storageBytes: pgBigint('storage_bytes', { mode: 'number' }).notNull().default(0),\n ingressBytes: pgBigint('ingress_bytes', { mode: 'number' }).notNull().default(0),\n egressBytes: pgBigint('egress_bytes', { mode: 'number' }).notNull().default(0),\n storageLimitBytes: pgBigint('storage_limit_bytes', { mode: 'number' }),\n bandwidthLimitBps: pgBigint('bandwidth_limit_bps', { mode: 'number' }),\n computeSeconds: pgBigint('compute_seconds', { mode: 'number' }).notNull().default(0),\n tokensUsed: pgBigint('tokens_used', { mode: 'number' }).notNull().default(0),\n computeLimitSeconds: pgBigint('compute_limit_seconds', { mode: 'number' }),\n tokenLimitMonthly: pgBigint('token_limit_monthly', { mode: 'number' }),\n periodStart: timestamp('period_start', { withTimezone: true, mode: 'date' }),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\n/**\n * Cloud cluster DDNS 记录表\n * 已分配的子域名记录\n */\nexport const ddnsRecords = pgTable('cluster_ddns_record', {\n subdomain: text('subdomain').primaryKey(), // alice\n domain: text('domain').notNull(), // undefineds.xyz\n ipAddress: text('ip_address'),\n ipv6Address: text('ipv6_address'),\n recordType: text('record_type').default('A'), // 'A' | 'AAAA'\n nodeId: text('node_id'), // 关联的节点 ID\n username: text('username'), // 关联的用户名\n status: text('status').default('active'), // 'active' | 'banned'\n bannedReason: text('banned_reason'),\n ttl: integer('ttl').default(60),\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n});\n\nexport const edgeNodes = pgTable('cluster_node', {\n id: text('id').primaryKey(),\n displayName: text('display_name'),\n tokenHash: text('token_hash').notNull(),\n nodeType: text('node_type').default('edge'), // 'center' | 'edge' | 'sp'\n subdomain: text('subdomain').unique(),\n accessMode: text('access_mode'),\n ipv4: text('ipv4'), // IPv4 地址\n publicPort: pgBigint('public_port', { mode: 'number' }),\n publicUrl: text('public_url'), // SP 的公网地址 (e.g. https://sp.example)\n serviceTokenHash: text('service_token_hash'), // Cloud → SP 回调认证 token (明文)\n provisionCodeHash: text('provision_code_hash'), // bind 时用户传入的配对码 (hash)\n internalIp: text('internal_ip'), // Internal network IP\n internalPort: pgBigint('internal_port', { mode: 'number' }),\n // Extracted from metadata\n hostname: text('hostname'), // 节点主机名\n ipv6: text('ipv6'), // IPv6 地址\n version: text('version'), // Agent 版本\n // JSON fields\n capabilities: text('capabilities'), // JSON string: 能力列表\n metadata: text('metadata'), // JSON string: 复杂对象 (tunnel, certificate, metrics)\n podBaseUrls: text('pod_base_urls'), // JSON string: node-owned Pod/storage URL prefixes\n connectivityStatus: text('connectivity_status').default('unknown'),\n lastConnectivityCheck: timestamp('last_connectivity_check', { withTimezone: true, mode: 'date' }),\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n lastSeen: timestamp('last_seen', { withTimezone: true, mode: 'date' }),\n});\n\n/**\n * Cloud cluster Service Token 表\n * 用于服务间认证 (Business, Local SP, Cloud, Compute)\n */\nexport const serviceTokens = pgTable('cluster_service_token', {\n id: text('id').primaryKey(),\n tokenHash: text('token_hash').notNull().unique(),\n serviceType: text('service_type').notNull(), // 'local' | 'business' | 'cloud' | 'compute'\n serviceId: text('service_id').notNull(),\n scopes: text('scopes').notNull(), // JSON array: [\"quota:write\",\"usage:read\"]\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),\n expiresAt: timestamp('expires_at', { withTimezone: true, mode: 'date' }),\n});\n"]}