@revealui/db 0.2.0

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 (191) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +137 -0
  3. package/dist/audit-store.d.ts +56 -0
  4. package/dist/audit-store.d.ts.map +1 -0
  5. package/dist/audit-store.js +120 -0
  6. package/dist/audit-store.js.map +1 -0
  7. package/dist/client/index.d.ts +214 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +396 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/types.d.ts +109 -0
  12. package/dist/client/types.d.ts.map +1 -0
  13. package/dist/client/types.js +10 -0
  14. package/dist/client/types.js.map +1 -0
  15. package/dist/crypto.d.ts +27 -0
  16. package/dist/crypto.d.ts.map +1 -0
  17. package/dist/crypto.js +68 -0
  18. package/dist/crypto.js.map +1 -0
  19. package/dist/index.d.ts +29 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +31 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/log-transport.d.ts +20 -0
  24. package/dist/log-transport.d.ts.map +1 -0
  25. package/dist/log-transport.js +49 -0
  26. package/dist/log-transport.js.map +1 -0
  27. package/dist/pool.d.ts +36 -0
  28. package/dist/pool.d.ts.map +1 -0
  29. package/dist/pool.js +218 -0
  30. package/dist/pool.js.map +1 -0
  31. package/dist/queries/boards.d.ts +138 -0
  32. package/dist/queries/boards.d.ts.map +1 -0
  33. package/dist/queries/boards.js +87 -0
  34. package/dist/queries/boards.js.map +1 -0
  35. package/dist/queries/code-provenance.d.ts +250 -0
  36. package/dist/queries/code-provenance.d.ts.map +1 -0
  37. package/dist/queries/code-provenance.js +130 -0
  38. package/dist/queries/code-provenance.js.map +1 -0
  39. package/dist/queries/optimized-queries.d.ts +89 -0
  40. package/dist/queries/optimized-queries.d.ts.map +1 -0
  41. package/dist/queries/optimized-queries.js +371 -0
  42. package/dist/queries/optimized-queries.js.map +1 -0
  43. package/dist/queries/ticket-comments.d.ts +37 -0
  44. package/dist/queries/ticket-comments.d.ts.map +1 -0
  45. package/dist/queries/ticket-comments.js +52 -0
  46. package/dist/queries/ticket-comments.js.map +1 -0
  47. package/dist/queries/ticket-labels.d.ts +69 -0
  48. package/dist/queries/ticket-labels.d.ts.map +1 -0
  49. package/dist/queries/ticket-labels.js +51 -0
  50. package/dist/queries/ticket-labels.js.map +1 -0
  51. package/dist/queries/tickets.d.ts +301 -0
  52. package/dist/queries/tickets.d.ts.map +1 -0
  53. package/dist/queries/tickets.js +89 -0
  54. package/dist/queries/tickets.js.map +1 -0
  55. package/dist/queries/todos.d.ts +37 -0
  56. package/dist/queries/todos.d.ts.map +1 -0
  57. package/dist/queries/todos.js +37 -0
  58. package/dist/queries/todos.js.map +1 -0
  59. package/dist/schema/agents.d.ts +1413 -0
  60. package/dist/schema/agents.d.ts.map +1 -0
  61. package/dist/schema/agents.js +207 -0
  62. package/dist/schema/agents.js.map +1 -0
  63. package/dist/schema/api-keys.d.ts +298 -0
  64. package/dist/schema/api-keys.d.ts.map +1 -0
  65. package/dist/schema/api-keys.js +53 -0
  66. package/dist/schema/api-keys.js.map +1 -0
  67. package/dist/schema/app-logs.d.ts +168 -0
  68. package/dist/schema/app-logs.d.ts.map +1 -0
  69. package/dist/schema/app-logs.js +25 -0
  70. package/dist/schema/app-logs.js.map +1 -0
  71. package/dist/schema/audit-log.d.ts +174 -0
  72. package/dist/schema/audit-log.d.ts.map +1 -0
  73. package/dist/schema/audit-log.js +37 -0
  74. package/dist/schema/audit-log.js.map +1 -0
  75. package/dist/schema/cms.d.ts +1015 -0
  76. package/dist/schema/cms.d.ts.map +1 -0
  77. package/dist/schema/cms.js +137 -0
  78. package/dist/schema/cms.js.map +1 -0
  79. package/dist/schema/code-provenance.d.ts +488 -0
  80. package/dist/schema/code-provenance.d.ts.map +1 -0
  81. package/dist/schema/code-provenance.js +72 -0
  82. package/dist/schema/code-provenance.js.map +1 -0
  83. package/dist/schema/collab-edits.d.ts +165 -0
  84. package/dist/schema/collab-edits.d.ts.map +1 -0
  85. package/dist/schema/collab-edits.js +21 -0
  86. package/dist/schema/collab-edits.js.map +1 -0
  87. package/dist/schema/crdt-operations.d.ts +153 -0
  88. package/dist/schema/crdt-operations.d.ts.map +1 -0
  89. package/dist/schema/crdt-operations.js +30 -0
  90. package/dist/schema/crdt-operations.js.map +1 -0
  91. package/dist/schema/error-events.d.ts +223 -0
  92. package/dist/schema/error-events.d.ts.map +1 -0
  93. package/dist/schema/error-events.js +44 -0
  94. package/dist/schema/error-events.js.map +1 -0
  95. package/dist/schema/index.d.ts +130 -0
  96. package/dist/schema/index.d.ts.map +1 -0
  97. package/dist/schema/index.js +310 -0
  98. package/dist/schema/index.js.map +1 -0
  99. package/dist/schema/licenses.d.ts +189 -0
  100. package/dist/schema/licenses.d.ts.map +1 -0
  101. package/dist/schema/licenses.js +39 -0
  102. package/dist/schema/licenses.js.map +1 -0
  103. package/dist/schema/node-ids.d.ts +122 -0
  104. package/dist/schema/node-ids.d.ts.map +1 -0
  105. package/dist/schema/node-ids.js +25 -0
  106. package/dist/schema/node-ids.js.map +1 -0
  107. package/dist/schema/pages.d.ts +488 -0
  108. package/dist/schema/pages.d.ts.map +1 -0
  109. package/dist/schema/pages.js +70 -0
  110. package/dist/schema/pages.js.map +1 -0
  111. package/dist/schema/password-reset-tokens.d.ts +137 -0
  112. package/dist/schema/password-reset-tokens.d.ts.map +1 -0
  113. package/dist/schema/password-reset-tokens.js +26 -0
  114. package/dist/schema/password-reset-tokens.js.map +1 -0
  115. package/dist/schema/query.d.ts +11 -0
  116. package/dist/schema/query.d.ts.map +1 -0
  117. package/dist/schema/query.js +11 -0
  118. package/dist/schema/query.js.map +1 -0
  119. package/dist/schema/rate-limits.d.ts +212 -0
  120. package/dist/schema/rate-limits.d.ts.map +1 -0
  121. package/dist/schema/rate-limits.js +38 -0
  122. package/dist/schema/rate-limits.js.map +1 -0
  123. package/dist/schema/rest.d.ts +31 -0
  124. package/dist/schema/rest.d.ts.map +1 -0
  125. package/dist/schema/rest.js +37 -0
  126. package/dist/schema/rest.js.map +1 -0
  127. package/dist/schema/sites.d.ts +365 -0
  128. package/dist/schema/sites.d.ts.map +1 -0
  129. package/dist/schema/sites.js +62 -0
  130. package/dist/schema/sites.js.map +1 -0
  131. package/dist/schema/tickets.d.ts +1118 -0
  132. package/dist/schema/tickets.d.ts.map +1 -0
  133. package/dist/schema/tickets.js +150 -0
  134. package/dist/schema/tickets.js.map +1 -0
  135. package/dist/schema/todos.d.ts +98 -0
  136. package/dist/schema/todos.d.ts.map +1 -0
  137. package/dist/schema/todos.js +12 -0
  138. package/dist/schema/todos.js.map +1 -0
  139. package/dist/schema/users.d.ts +503 -0
  140. package/dist/schema/users.d.ts.map +1 -0
  141. package/dist/schema/users.js +75 -0
  142. package/dist/schema/users.js.map +1 -0
  143. package/dist/schema/vector.d.ts +9 -0
  144. package/dist/schema/vector.d.ts.map +1 -0
  145. package/dist/schema/vector.js +9 -0
  146. package/dist/schema/vector.js.map +1 -0
  147. package/dist/schema/waitlist.d.ts +151 -0
  148. package/dist/schema/waitlist.d.ts.map +1 -0
  149. package/dist/schema/waitlist.js +17 -0
  150. package/dist/schema/waitlist.js.map +1 -0
  151. package/dist/schema/yjs-documents.d.ts +116 -0
  152. package/dist/schema/yjs-documents.d.ts.map +1 -0
  153. package/dist/schema/yjs-documents.js +15 -0
  154. package/dist/schema/yjs-documents.js.map +1 -0
  155. package/dist/types/database.d.ts +740 -0
  156. package/dist/types/database.d.ts.map +1 -0
  157. package/dist/types/database.js +151 -0
  158. package/dist/types/database.js.map +1 -0
  159. package/dist/types/discover.d.ts +83 -0
  160. package/dist/types/discover.d.ts.map +1 -0
  161. package/dist/types/discover.js +271 -0
  162. package/dist/types/discover.js.map +1 -0
  163. package/dist/types/extract-relationships.d.ts +115 -0
  164. package/dist/types/extract-relationships.d.ts.map +1 -0
  165. package/dist/types/extract-relationships.js +455 -0
  166. package/dist/types/extract-relationships.js.map +1 -0
  167. package/dist/types/generate-contracts.d.ts +19 -0
  168. package/dist/types/generate-contracts.d.ts.map +1 -0
  169. package/dist/types/generate-contracts.js +128 -0
  170. package/dist/types/generate-contracts.js.map +1 -0
  171. package/dist/types/generate-zod-schemas.d.ts +20 -0
  172. package/dist/types/generate-zod-schemas.d.ts.map +1 -0
  173. package/dist/types/generate-zod-schemas.js +128 -0
  174. package/dist/types/generate-zod-schemas.js.map +1 -0
  175. package/dist/types/generate.d.ts +17 -0
  176. package/dist/types/generate.d.ts.map +1 -0
  177. package/dist/types/generate.js +298 -0
  178. package/dist/types/generate.js.map +1 -0
  179. package/dist/types/index.d.ts +19 -0
  180. package/dist/types/index.d.ts.map +1 -0
  181. package/dist/types/index.js +19 -0
  182. package/dist/types/index.js.map +1 -0
  183. package/dist/types/introspect.d.ts +75 -0
  184. package/dist/types/introspect.d.ts.map +1 -0
  185. package/dist/types/introspect.js +187 -0
  186. package/dist/types/introspect.js.map +1 -0
  187. package/dist/types/stripe-schema.d.ts +893 -0
  188. package/dist/types/stripe-schema.d.ts.map +1 -0
  189. package/dist/types/stripe-schema.js +112 -0
  190. package/dist/types/stripe-schema.js.map +1 -0
  191. package/package.json +154 -0
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @revealui/db - Database Package
3
+ *
4
+ * Provides Drizzle ORM schema definitions and database client for RevealUI.
5
+ * Designed for Neon Postgres with pgvector extension.
6
+ *
7
+ * ## Usage
8
+ *
9
+ * ### Core (Schema)
10
+ * ```typescript
11
+ * import { users, sites, pages } from '@revealui/db/schema'
12
+ * ```
13
+ *
14
+ * ### Client
15
+ * ```typescript
16
+ * import { getClient } from '@revealui/db/client'
17
+ * const db = getClient()
18
+ * ```
19
+ *
20
+ * ### Full Package
21
+ * ```typescript
22
+ * import { getClient, users, sites, pages } from '@revealui/db'
23
+ * ```
24
+ */
25
+ // Re-export audit store (persistent backend for @revealui/ai audit trail)
26
+ export { DrizzleAuditStore } from './audit-store.js';
27
+ // Re-export client utilities
28
+ export { closeAllPools, createClient, getClient, getPoolMetrics, getRestClient, getVectorClient, resetClient, schema, withTransaction, } from './client/index.js';
29
+ // Re-export everything from core (schema)
30
+ export * from './schema/index.js';
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,0EAA0E;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,6BAA6B;AAC7B,OAAO,EACL,aAAa,EACb,YAAY,EAIZ,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,WAAW,EACX,MAAM,EACN,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAC1B,0CAA0C;AAC1C,cAAc,mBAAmB,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * DB Log Transport
3
+ *
4
+ * Returns an onLog handler compatible with the Logger class in @revealui/utils.
5
+ * Persists warn/error/fatal entries to the `app_logs` NeonDB table.
6
+ *
7
+ * Only writes in production (NODE_ENV=production). All writes are fire-and-forget
8
+ * — the handler never throws or blocks the caller.
9
+ *
10
+ * Usage (call once at app startup):
11
+ * import { createDbLogHandler } from '@revealui/db/log-transport'
12
+ * import { logger } from '@revealui/utils/logger'
13
+ *
14
+ * if (process.env.NODE_ENV === 'production') {
15
+ * logger.addLogHandler(createDbLogHandler('api'))
16
+ * }
17
+ */
18
+ import type { LogEntry } from '@revealui/utils/logger';
19
+ export declare function createDbLogHandler(app: string): (entry: LogEntry) => void;
20
+ //# sourceMappingURL=log-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-transport.d.ts","sourceRoot":"","sources":["../src/log-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAMtD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CA2BzE"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * DB Log Transport
3
+ *
4
+ * Returns an onLog handler compatible with the Logger class in @revealui/utils.
5
+ * Persists warn/error/fatal entries to the `app_logs` NeonDB table.
6
+ *
7
+ * Only writes in production (NODE_ENV=production). All writes are fire-and-forget
8
+ * — the handler never throws or blocks the caller.
9
+ *
10
+ * Usage (call once at app startup):
11
+ * import { createDbLogHandler } from '@revealui/db/log-transport'
12
+ * import { logger } from '@revealui/utils/logger'
13
+ *
14
+ * if (process.env.NODE_ENV === 'production') {
15
+ * logger.addLogHandler(createDbLogHandler('api'))
16
+ * }
17
+ */
18
+ import { getClient } from './client/index.js';
19
+ import { appLogs } from './schema/app-logs.js';
20
+ const SHIP_LEVELS = new Set(['warn', 'error', 'fatal']);
21
+ export function createDbLogHandler(app) {
22
+ return (entry) => {
23
+ if (!SHIP_LEVELS.has(entry.level))
24
+ return;
25
+ if (process.env.NODE_ENV !== 'production')
26
+ return;
27
+ // Merge context + error into a single data object
28
+ const data = {};
29
+ if (entry.context && Object.keys(entry.context).length > 0) {
30
+ Object.assign(data, entry.context);
31
+ }
32
+ if (entry.error) {
33
+ data.error = entry.error;
34
+ }
35
+ const db = getClient();
36
+ db.insert(appLogs)
37
+ .values({
38
+ level: entry.level,
39
+ message: entry.message,
40
+ app,
41
+ environment: process.env.NODE_ENV ?? 'production',
42
+ requestId: entry.context?.requestId ?? null,
43
+ userId: entry.context?.userId ?? null,
44
+ data: Object.keys(data).length > 0 ? data : null,
45
+ })
46
+ .catch(() => { }); // never throw back to the logger
47
+ };
48
+ }
49
+ //# sourceMappingURL=log-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-transport.js","sourceRoot":"","sources":["../src/log-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAE9C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAEvD,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,CAAC,KAAe,EAAQ,EAAE;QAC/B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAM;QACzC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;YAAE,OAAM;QAEjD,kDAAkD;QAClD,MAAM,IAAI,GAA4B,EAAE,CAAA;QACxC,IAAI,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QACpC,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;QAC1B,CAAC;QAED,MAAM,EAAE,GAAG,SAAS,EAAE,CAAA;QACtB,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC;YACN,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG;YACH,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY;YACjD,SAAS,EAAG,KAAK,CAAC,OAAO,EAAE,SAAgC,IAAI,IAAI;YACnE,MAAM,EAAG,KAAK,CAAC,OAAO,EAAE,MAA6B,IAAI,IAAI;YAC7D,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;SACjD,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA,CAAC,iCAAiC;IACtD,CAAC,CAAA;AACH,CAAC"}
package/dist/pool.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Optimized Database Connection Pool
3
+ *
4
+ * Configured for high performance and reliability
5
+ */
6
+ import { Pool } from 'pg';
7
+ /**
8
+ * Create connection pool
9
+ */
10
+ export declare const pool: Pool;
11
+ export declare function checkDatabaseHealth(): Promise<{
12
+ healthy: boolean;
13
+ stats: {
14
+ totalCount: number;
15
+ idleCount: number;
16
+ waitingCount: number;
17
+ };
18
+ }>;
19
+ export declare function getPoolStats(): {
20
+ totalCount: number;
21
+ idleCount: number;
22
+ waitingCount: number;
23
+ maxConnections: number | undefined;
24
+ minConnections: number | undefined;
25
+ utilization: number;
26
+ };
27
+ /**
28
+ * Log pool stats periodically
29
+ */
30
+ export declare function startPoolMonitoring(intervalMs?: number): void;
31
+ /**
32
+ * Pre-warm the connection pool
33
+ */
34
+ export declare function warmupPool(): Promise<void>;
35
+ export default pool;
36
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,IAAI,EAAoC,MAAM,IAAI,CAAA;AA8E3D;;GAEG;AACH,eAAO,MAAM,IAAI,MAAuB,CAAA;AAuExC,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAA;QAClB,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;CACF,CAAC,CAgCD;AAMD,wBAAgB,YAAY;;;;;;;EAS3B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,GAAE,MAAc,QAqB7D;AAMD;;GAEG;AACH,wBAAsB,UAAU,kBA6B/B;AAMD,eAAe,IAAI,CAAA"}
package/dist/pool.js ADDED
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Optimized Database Connection Pool
3
+ *
4
+ * Configured for high performance and reliability
5
+ */
6
+ import { getSSLConfig } from '@revealui/utils/database';
7
+ import { logger } from '@revealui/utils/logger';
8
+ import { Pool } from 'pg';
9
+ /**
10
+ * Get SSL configuration based on environment
11
+ */
12
+ function getPoolSSLConfig() {
13
+ // If DATABASE_URL is available, use it to determine SSL config
14
+ const databaseUrl = process.env.DATABASE_URL || process.env.POSTGRES_URL;
15
+ if (databaseUrl) {
16
+ return getSSLConfig(databaseUrl);
17
+ }
18
+ // Fallback to legacy DATABASE_SSL environment variable
19
+ return process.env.DATABASE_SSL === 'true' ? { rejectUnauthorized: true } : false;
20
+ }
21
+ /**
22
+ * Connection pool configuration optimized for performance
23
+ */
24
+ const poolConfig = {
25
+ // Connection details
26
+ host: process.env.DATABASE_HOST || 'localhost',
27
+ port: parseInt(process.env.DATABASE_PORT || '5432', 10),
28
+ database: process.env.DATABASE_NAME,
29
+ user: process.env.DATABASE_USER,
30
+ password: process.env.DATABASE_PASSWORD,
31
+ // SSL configuration (auto-detected from connection string if available)
32
+ ssl: getPoolSSLConfig(),
33
+ // ===========================================================================
34
+ // CONNECTION POOL SETTINGS
35
+ // ===========================================================================
36
+ // Maximum number of clients in the pool
37
+ // Higher for high-traffic applications
38
+ max: parseInt(process.env.DATABASE_POOL_MAX || '20', 10),
39
+ // Minimum number of clients in the pool
40
+ // Keeps connections warm
41
+ min: parseInt(process.env.DATABASE_POOL_MIN || '5', 10),
42
+ // Maximum time (ms) a client can be idle before being closed
43
+ // Lower value = more aggressive cleanup
44
+ idleTimeoutMillis: parseInt(process.env.DATABASE_IDLE_TIMEOUT || '30000', 10), // 30 seconds
45
+ // Maximum time (ms) to wait for a connection
46
+ // Fail fast if pool is exhausted
47
+ connectionTimeoutMillis: parseInt(process.env.DATABASE_CONNECTION_TIMEOUT || '5000', 10), // 5 seconds
48
+ // ===========================================================================
49
+ // QUERY SETTINGS
50
+ // ===========================================================================
51
+ // Maximum execution time for queries (PostgreSQL setting)
52
+ // Prevents long-running queries from blocking
53
+ statement_timeout: parseInt(process.env.DATABASE_STATEMENT_TIMEOUT || '10000', 10), // 10 seconds
54
+ // Maximum execution time for queries (Node.js setting)
55
+ query_timeout: parseInt(process.env.DATABASE_QUERY_TIMEOUT || '10000', 10), // 10 seconds
56
+ // ===========================================================================
57
+ // PERFORMANCE SETTINGS
58
+ // ===========================================================================
59
+ // Allow the pool to close when all clients are idle
60
+ // Good for serverless/lambda environments
61
+ allowExitOnIdle: process.env.NODE_ENV !== 'production',
62
+ // Application name (shows in pg_stat_activity)
63
+ application_name: process.env.APP_NAME || 'revealui',
64
+ };
65
+ /**
66
+ * Create connection pool
67
+ */
68
+ export const pool = new Pool(poolConfig);
69
+ // ===========================================================================
70
+ // ERROR HANDLING
71
+ // ===========================================================================
72
+ pool.on('error', (err) => {
73
+ logger.error('Unexpected error on idle database client', err instanceof Error ? err : new Error(String(err)));
74
+ });
75
+ pool.on('connect', async (client) => {
76
+ const pid = client.processID;
77
+ logger.info(`Database connection established (PID: ${pid})`);
78
+ try {
79
+ // Set timezone
80
+ await client.query("SET timezone TO 'UTC'");
81
+ // Set statement timeout
82
+ await client.query(`SET statement_timeout TO ${poolConfig.statement_timeout || 10000}`);
83
+ // Enable query statistics
84
+ await client.query('SET track_io_timing = on');
85
+ }
86
+ catch (error) {
87
+ logger.error('Error initializing database client', error instanceof Error ? error : new Error(String(error)));
88
+ }
89
+ });
90
+ pool.on('acquire', (client) => {
91
+ const pid = client.processID;
92
+ logger.debug(`Database client acquired (PID: ${pid})`);
93
+ });
94
+ pool.on('remove', (client) => {
95
+ const pid = client.processID;
96
+ logger.info(`Database client removed (PID: ${pid})`);
97
+ });
98
+ // ===========================================================================
99
+ // GRACEFUL SHUTDOWN
100
+ // ===========================================================================
101
+ async function gracefulShutdown(signal) {
102
+ logger.info('Closing database pool', { signal });
103
+ try {
104
+ await pool.end();
105
+ logger.info('Database pool closed successfully');
106
+ process.exit(0);
107
+ }
108
+ catch (error) {
109
+ logger.error('Error closing database pool', error instanceof Error ? error : new Error(String(error)));
110
+ process.exit(1);
111
+ }
112
+ }
113
+ process.on('SIGTERM', () => void gracefulShutdown('SIGTERM'));
114
+ process.on('SIGINT', () => void gracefulShutdown('SIGINT'));
115
+ // ===========================================================================
116
+ // HEALTH CHECK
117
+ // ===========================================================================
118
+ export async function checkDatabaseHealth() {
119
+ try {
120
+ // Test connection
121
+ const client = await pool.connect();
122
+ await client.query('SELECT 1');
123
+ client.release();
124
+ // Get pool stats
125
+ const stats = {
126
+ totalCount: pool.totalCount,
127
+ idleCount: pool.idleCount,
128
+ waitingCount: pool.waitingCount,
129
+ };
130
+ return {
131
+ healthy: true,
132
+ stats,
133
+ };
134
+ }
135
+ catch (error) {
136
+ logger.error('Database health check failed', error instanceof Error ? error : new Error(String(error)));
137
+ return {
138
+ healthy: false,
139
+ stats: {
140
+ totalCount: pool.totalCount,
141
+ idleCount: pool.idleCount,
142
+ waitingCount: pool.waitingCount,
143
+ },
144
+ };
145
+ }
146
+ }
147
+ // ===========================================================================
148
+ // POOL MONITORING
149
+ // ===========================================================================
150
+ export function getPoolStats() {
151
+ return {
152
+ totalCount: pool.totalCount, // Total clients
153
+ idleCount: pool.idleCount, // Idle clients
154
+ waitingCount: pool.waitingCount, // Waiting requests
155
+ maxConnections: poolConfig.max,
156
+ minConnections: poolConfig.min,
157
+ utilization: ((pool.totalCount - pool.idleCount) / (poolConfig.max || 20)) * 100,
158
+ };
159
+ }
160
+ /**
161
+ * Log pool stats periodically
162
+ */
163
+ export function startPoolMonitoring(intervalMs = 60000) {
164
+ setInterval(() => {
165
+ const stats = getPoolStats();
166
+ logger.info('Database pool stats', {
167
+ ...stats,
168
+ utilizationPercent: `${stats.utilization.toFixed(1)}%`,
169
+ timestamp: new Date().toISOString(),
170
+ });
171
+ // Warn if pool is near capacity
172
+ if (stats.utilization > 80) {
173
+ logger.warn('Database pool utilization high', { utilization: stats.utilization });
174
+ }
175
+ // Warn if many requests are waiting
176
+ if (stats.waitingCount > 5) {
177
+ logger.warn('Many requests waiting for database connection', {
178
+ waitingCount: stats.waitingCount,
179
+ });
180
+ }
181
+ }, intervalMs);
182
+ }
183
+ // ===========================================================================
184
+ // CONNECTION WARMUP
185
+ // ===========================================================================
186
+ /**
187
+ * Pre-warm the connection pool
188
+ */
189
+ export async function warmupPool() {
190
+ logger.info('Warming up database pool');
191
+ const warmupConnections = Math.min(poolConfig.min || 5, poolConfig.max || 20);
192
+ const clients = [];
193
+ try {
194
+ // Acquire minimum connections
195
+ for (let i = 0; i < warmupConnections; i++) {
196
+ const client = await pool.connect();
197
+ clients.push(client);
198
+ }
199
+ logger.info(`Warmed up ${warmupConnections} database connections`);
200
+ // Release all clients
201
+ for (const client of clients) {
202
+ client.release();
203
+ }
204
+ }
205
+ catch (error) {
206
+ logger.error('Error warming up pool', error instanceof Error ? error : new Error(String(error)));
207
+ // Release any acquired clients
208
+ for (const client of clients) {
209
+ client.release();
210
+ }
211
+ throw error;
212
+ }
213
+ }
214
+ // ===========================================================================
215
+ // EXPORTS
216
+ // ===========================================================================
217
+ export default pool;
218
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Board database queries
3
+ */
4
+ import type { DatabaseClient } from '../client/types.js';
5
+ export declare function getAllBoards(db: DatabaseClient, tenantId?: string): Promise<{
6
+ id: string;
7
+ schemaVersion: string;
8
+ tenantId: string | null;
9
+ name: string;
10
+ slug: string;
11
+ description: string | null;
12
+ ownerId: string | null;
13
+ isDefault: boolean;
14
+ settings: unknown;
15
+ createdAt: Date;
16
+ updatedAt: Date;
17
+ }[]>;
18
+ export declare function getBoardById(db: DatabaseClient, id: string): Promise<{
19
+ id: string;
20
+ schemaVersion: string;
21
+ tenantId: string | null;
22
+ name: string;
23
+ slug: string;
24
+ description: string | null;
25
+ ownerId: string | null;
26
+ isDefault: boolean;
27
+ settings: unknown;
28
+ createdAt: Date;
29
+ updatedAt: Date;
30
+ } | null>;
31
+ export declare function getBoardBySlug(db: DatabaseClient, slug: string, tenantId?: string): Promise<{
32
+ id: string;
33
+ schemaVersion: string;
34
+ tenantId: string | null;
35
+ name: string;
36
+ slug: string;
37
+ description: string | null;
38
+ ownerId: string | null;
39
+ isDefault: boolean;
40
+ settings: unknown;
41
+ createdAt: Date;
42
+ updatedAt: Date;
43
+ } | null>;
44
+ /**
45
+ * Create a board with default kanban columns.
46
+ */
47
+ export declare function createBoard(db: DatabaseClient, data: {
48
+ id: string;
49
+ name: string;
50
+ slug: string;
51
+ description?: string;
52
+ ownerId?: string;
53
+ tenantId?: string;
54
+ isDefault?: boolean;
55
+ }): Promise<{
56
+ id: string;
57
+ name: string;
58
+ schemaVersion: string;
59
+ createdAt: Date;
60
+ updatedAt: Date;
61
+ ownerId: string | null;
62
+ slug: string;
63
+ description: string | null;
64
+ settings: unknown;
65
+ isDefault: boolean;
66
+ tenantId: string | null;
67
+ } | undefined>;
68
+ export declare function updateBoard(db: DatabaseClient, id: string, data: Partial<{
69
+ name: string;
70
+ slug: string;
71
+ description: string;
72
+ ownerId: string | null;
73
+ }>): Promise<{
74
+ id: string;
75
+ schemaVersion: string;
76
+ tenantId: string | null;
77
+ name: string;
78
+ slug: string;
79
+ description: string | null;
80
+ ownerId: string | null;
81
+ isDefault: boolean;
82
+ settings: unknown;
83
+ createdAt: Date;
84
+ updatedAt: Date;
85
+ } | null>;
86
+ export declare function deleteBoard(db: DatabaseClient, id: string): Promise<void>;
87
+ export declare function getColumnsByBoard(db: DatabaseClient, boardId: string): Promise<{
88
+ id: string;
89
+ boardId: string;
90
+ name: string;
91
+ slug: string;
92
+ position: number;
93
+ wipLimit: number | null;
94
+ color: string | null;
95
+ isDefault: boolean;
96
+ createdAt: Date;
97
+ updatedAt: Date;
98
+ }[]>;
99
+ export declare function createColumn(db: DatabaseClient, data: {
100
+ id: string;
101
+ boardId: string;
102
+ name: string;
103
+ slug: string;
104
+ position: number;
105
+ wipLimit?: number;
106
+ color?: string;
107
+ }): Promise<{
108
+ id: string;
109
+ name: string;
110
+ createdAt: Date;
111
+ updatedAt: Date;
112
+ slug: string;
113
+ isDefault: boolean;
114
+ boardId: string;
115
+ position: number;
116
+ wipLimit: number | null;
117
+ color: string | null;
118
+ } | undefined>;
119
+ export declare function updateColumn(db: DatabaseClient, id: string, data: Partial<{
120
+ name: string;
121
+ slug: string;
122
+ position: number;
123
+ wipLimit: number | null;
124
+ color: string | null;
125
+ }>): Promise<{
126
+ id: string;
127
+ boardId: string;
128
+ name: string;
129
+ slug: string;
130
+ position: number;
131
+ wipLimit: number | null;
132
+ color: string | null;
133
+ isDefault: boolean;
134
+ createdAt: Date;
135
+ updatedAt: Date;
136
+ } | null>;
137
+ export declare function deleteColumn(db: DatabaseClient, id: string): Promise<void>;
138
+ //# sourceMappingURL=boards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boards.d.ts","sourceRoot":"","sources":["../../src/queries/boards.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAWxD,wBAAsB,YAAY,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,MAAM;;;;;;;;;;;;KAKvE;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;UAGhE;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;;;;;;;;;;;;UAWvF;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE;IACJ,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;;;;;;;;;;;;eAoBF;AAED,wBAAsB,WAAW,CAC/B,EAAE,EAAE,cAAc,EAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;;;;;;;;;;;;UAS3F;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,iBAE/D;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM;;;;;;;;;;;KAM1E;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE;IACJ,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;;;;;;;;;;;eAIF;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,cAAc,EAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CAAC;;;;;;;;;;;UASH;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,iBAEhE"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Board database queries
3
+ */
4
+ import { eq } from 'drizzle-orm';
5
+ import { boardColumns, boards } from '../schema/tickets.js';
6
+ const DEFAULT_COLUMNS = [
7
+ { name: 'Backlog', slug: 'backlog', position: 0 },
8
+ { name: 'To Do', slug: 'todo', position: 1, isDefault: true },
9
+ { name: 'In Progress', slug: 'in-progress', position: 2 },
10
+ { name: 'Review', slug: 'review', position: 3 },
11
+ { name: 'Done', slug: 'done', position: 4 },
12
+ ];
13
+ export async function getAllBoards(db, tenantId) {
14
+ if (tenantId) {
15
+ return db.select().from(boards).where(eq(boards.tenantId, tenantId)).orderBy(boards.createdAt);
16
+ }
17
+ return db.select().from(boards).orderBy(boards.createdAt);
18
+ }
19
+ export async function getBoardById(db, id) {
20
+ const result = await db.select().from(boards).where(eq(boards.id, id)).limit(1);
21
+ return result[0] ?? null;
22
+ }
23
+ export async function getBoardBySlug(db, slug, tenantId) {
24
+ const conditions = [eq(boards.slug, slug)];
25
+ if (tenantId)
26
+ conditions.push(eq(boards.tenantId, tenantId));
27
+ const { and } = await import('drizzle-orm');
28
+ const result = await db
29
+ .select()
30
+ .from(boards)
31
+ .where(and(...conditions))
32
+ .limit(1);
33
+ return result[0] ?? null;
34
+ }
35
+ /**
36
+ * Create a board with default kanban columns.
37
+ */
38
+ export async function createBoard(db, data) {
39
+ const result = await db.insert(boards).values(data).returning();
40
+ const board = result[0];
41
+ if (board) {
42
+ // Create default columns
43
+ await db.insert(boardColumns).values(DEFAULT_COLUMNS.map((col, _i) => ({
44
+ id: `${board.id}-col-${col.slug}`,
45
+ boardId: board.id,
46
+ name: col.name,
47
+ slug: col.slug,
48
+ position: col.position,
49
+ isDefault: 'isDefault' in col ? col.isDefault : false,
50
+ })));
51
+ }
52
+ return board;
53
+ }
54
+ export async function updateBoard(db, id, data) {
55
+ const result = await db
56
+ .update(boards)
57
+ .set({ ...data, updatedAt: new Date() })
58
+ .where(eq(boards.id, id))
59
+ .returning();
60
+ return result[0] ?? null;
61
+ }
62
+ export async function deleteBoard(db, id) {
63
+ await db.delete(boards).where(eq(boards.id, id));
64
+ }
65
+ export async function getColumnsByBoard(db, boardId) {
66
+ return db
67
+ .select()
68
+ .from(boardColumns)
69
+ .where(eq(boardColumns.boardId, boardId))
70
+ .orderBy(boardColumns.position);
71
+ }
72
+ export async function createColumn(db, data) {
73
+ const result = await db.insert(boardColumns).values(data).returning();
74
+ return result[0];
75
+ }
76
+ export async function updateColumn(db, id, data) {
77
+ const result = await db
78
+ .update(boardColumns)
79
+ .set({ ...data, updatedAt: new Date() })
80
+ .where(eq(boardColumns.id, id))
81
+ .returning();
82
+ return result[0] ?? null;
83
+ }
84
+ export async function deleteColumn(db, id) {
85
+ await db.delete(boardColumns).where(eq(boardColumns.id, id));
86
+ }
87
+ //# sourceMappingURL=boards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/queries/boards.ts"],"names":[],"mappings":"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"}