@heavybit/shared-lib 2.1.0 → 2.7.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 (296) hide show
  1. package/README.md +163 -2
  2. package/dist/cjs/access/index.js +9 -1
  3. package/dist/cjs/access/index.js.map +1 -1
  4. package/dist/cjs/approvals/index.js +137 -0
  5. package/dist/cjs/approvals/index.js.map +1 -0
  6. package/dist/cjs/audit/index.js +74 -0
  7. package/dist/cjs/audit/index.js.map +1 -0
  8. package/dist/cjs/cache/index.js +90 -16
  9. package/dist/cjs/cache/index.js.map +1 -1
  10. package/dist/cjs/cache/keyspace.js +101 -0
  11. package/dist/cjs/cache/keyspace.js.map +1 -0
  12. package/dist/cjs/common/circuit-breaker.js +74 -0
  13. package/dist/cjs/common/circuit-breaker.js.map +1 -0
  14. package/dist/cjs/common/index.js +4 -0
  15. package/dist/cjs/common/index.js.map +1 -1
  16. package/dist/cjs/common/internal-client.js +177 -0
  17. package/dist/cjs/common/internal-client.js.map +1 -0
  18. package/dist/cjs/common/internal-constants.js +12 -0
  19. package/dist/cjs/common/internal-constants.js.map +1 -0
  20. package/dist/cjs/common/internal-service-auth.js +160 -0
  21. package/dist/cjs/common/internal-service-auth.js.map +1 -0
  22. package/dist/cjs/common/money.js +215 -0
  23. package/dist/cjs/common/money.js.map +1 -0
  24. package/dist/cjs/common/phone.js +41 -22
  25. package/dist/cjs/common/phone.js.map +1 -1
  26. package/dist/cjs/common/time.js +28 -2
  27. package/dist/cjs/common/time.js.map +1 -1
  28. package/dist/cjs/config/index.js +139 -19
  29. package/dist/cjs/config/index.js.map +1 -1
  30. package/dist/cjs/contracts/notification-dispatch.js +1 -1
  31. package/dist/cjs/database/db.js +37 -0
  32. package/dist/cjs/database/db.js.map +1 -0
  33. package/dist/cjs/database/index.js +22 -51
  34. package/dist/cjs/database/index.js.map +1 -1
  35. package/dist/cjs/database/pagination.js +88 -0
  36. package/dist/cjs/database/pagination.js.map +1 -0
  37. package/dist/cjs/database/pool.js +60 -0
  38. package/dist/cjs/database/pool.js.map +1 -0
  39. package/dist/cjs/database/scoped-repository.js +132 -0
  40. package/dist/cjs/database/scoped-repository.js.map +1 -0
  41. package/dist/cjs/database/scopes.js +166 -0
  42. package/dist/cjs/database/scopes.js.map +1 -0
  43. package/dist/cjs/database/table-names.js +14 -0
  44. package/dist/cjs/database/table-names.js.map +1 -0
  45. package/dist/cjs/database/tables.js +71 -0
  46. package/dist/cjs/database/tables.js.map +1 -0
  47. package/dist/cjs/express/auth.js +64 -50
  48. package/dist/cjs/express/auth.js.map +1 -1
  49. package/dist/cjs/express/index.js +2 -0
  50. package/dist/cjs/express/index.js.map +1 -1
  51. package/dist/cjs/express/internal-caller.js +52 -0
  52. package/dist/cjs/express/internal-caller.js.map +1 -0
  53. package/dist/cjs/express/step-up.js +41 -0
  54. package/dist/cjs/express/step-up.js.map +1 -0
  55. package/dist/cjs/http/index.js +3 -71
  56. package/dist/cjs/http/index.js.map +1 -1
  57. package/dist/cjs/identity/index.js +269 -67
  58. package/dist/cjs/identity/index.js.map +1 -1
  59. package/dist/cjs/identity/step-up.js +52 -0
  60. package/dist/cjs/identity/step-up.js.map +1 -0
  61. package/dist/cjs/index.js +6 -0
  62. package/dist/cjs/index.js.map +1 -1
  63. package/dist/cjs/knex/columns.js +36 -0
  64. package/dist/cjs/knex/columns.js.map +1 -0
  65. package/dist/cjs/knex/index.js +26 -43
  66. package/dist/cjs/knex/index.js.map +1 -1
  67. package/dist/cjs/knex/migration-helpers.js +57 -0
  68. package/dist/cjs/knex/migration-helpers.js.map +1 -0
  69. package/dist/cjs/logging/redact.js +6 -11
  70. package/dist/cjs/logging/redact.js.map +1 -1
  71. package/dist/cjs/messaging/base-consumer.js +36 -0
  72. package/dist/cjs/messaging/base-consumer.js.map +1 -0
  73. package/dist/cjs/messaging/consumer.js +142 -73
  74. package/dist/cjs/messaging/consumer.js.map +1 -1
  75. package/dist/cjs/messaging/envelope.js +53 -10
  76. package/dist/cjs/messaging/envelope.js.map +1 -1
  77. package/dist/cjs/messaging/idempotency.js +95 -8
  78. package/dist/cjs/messaging/idempotency.js.map +1 -1
  79. package/dist/cjs/messaging/index.js +2 -1
  80. package/dist/cjs/messaging/index.js.map +1 -1
  81. package/dist/cjs/messaging/outbox.js +97 -55
  82. package/dist/cjs/messaging/outbox.js.map +1 -1
  83. package/dist/cjs/messaging/publisher.js +86 -38
  84. package/dist/cjs/messaging/publisher.js.map +1 -1
  85. package/dist/cjs/messaging/staff-notifier.js +4 -4
  86. package/dist/cjs/messaging/staff-notifier.js.map +1 -1
  87. package/dist/cjs/messaging/topology.js +41 -5
  88. package/dist/cjs/messaging/topology.js.map +1 -1
  89. package/dist/cjs/rate-limit/index.js +57 -6
  90. package/dist/cjs/rate-limit/index.js.map +1 -1
  91. package/dist/cjs/rate-limit/keys.js +47 -0
  92. package/dist/cjs/rate-limit/keys.js.map +1 -0
  93. package/dist/cjs/socket/index.js +127 -16
  94. package/dist/cjs/socket/index.js.map +1 -1
  95. package/dist/cjs/socket/ticket.js +124 -0
  96. package/dist/cjs/socket/ticket.js.map +1 -0
  97. package/dist/cjs/testing/index.js +23 -14
  98. package/dist/cjs/testing/index.js.map +1 -1
  99. package/dist/esm/access/index.js +9 -1
  100. package/dist/esm/access/index.js.map +1 -1
  101. package/dist/esm/approvals/index.js +127 -0
  102. package/dist/esm/approvals/index.js.map +1 -0
  103. package/dist/esm/audit/index.js +70 -0
  104. package/dist/esm/audit/index.js.map +1 -0
  105. package/dist/esm/cache/index.js +70 -13
  106. package/dist/esm/cache/index.js.map +1 -1
  107. package/dist/esm/cache/keyspace.js +95 -0
  108. package/dist/esm/cache/keyspace.js.map +1 -0
  109. package/dist/esm/common/circuit-breaker.js +70 -0
  110. package/dist/esm/common/circuit-breaker.js.map +1 -0
  111. package/dist/esm/common/index.js +4 -0
  112. package/dist/esm/common/index.js.map +1 -1
  113. package/dist/esm/common/internal-client.js +173 -0
  114. package/dist/esm/common/internal-client.js.map +1 -0
  115. package/dist/esm/common/internal-constants.js +9 -0
  116. package/dist/esm/common/internal-constants.js.map +1 -0
  117. package/dist/esm/common/internal-service-auth.js +150 -0
  118. package/dist/esm/common/internal-service-auth.js.map +1 -0
  119. package/dist/esm/common/money.js +207 -0
  120. package/dist/esm/common/money.js.map +1 -0
  121. package/dist/esm/common/phone.js +41 -22
  122. package/dist/esm/common/phone.js.map +1 -1
  123. package/dist/esm/common/time.js +27 -2
  124. package/dist/esm/common/time.js.map +1 -1
  125. package/dist/esm/config/index.js +135 -18
  126. package/dist/esm/config/index.js.map +1 -1
  127. package/dist/esm/contracts/notification-dispatch.js +1 -1
  128. package/dist/esm/database/db.js +32 -0
  129. package/dist/esm/database/db.js.map +1 -0
  130. package/dist/esm/database/index.js +9 -45
  131. package/dist/esm/database/index.js.map +1 -1
  132. package/dist/esm/database/pagination.js +81 -0
  133. package/dist/esm/database/pagination.js.map +1 -0
  134. package/dist/esm/database/pool.js +51 -0
  135. package/dist/esm/database/pool.js.map +1 -0
  136. package/dist/esm/database/scoped-repository.js +128 -0
  137. package/dist/esm/database/scoped-repository.js.map +1 -0
  138. package/dist/esm/database/scopes.js +157 -0
  139. package/dist/esm/database/scopes.js.map +1 -0
  140. package/dist/esm/database/table-names.js +11 -0
  141. package/dist/esm/database/table-names.js.map +1 -0
  142. package/dist/esm/database/tables.js +61 -0
  143. package/dist/esm/database/tables.js.map +1 -0
  144. package/dist/esm/express/auth.js +62 -48
  145. package/dist/esm/express/auth.js.map +1 -1
  146. package/dist/esm/express/index.js +2 -0
  147. package/dist/esm/express/index.js.map +1 -1
  148. package/dist/esm/express/internal-caller.js +49 -0
  149. package/dist/esm/express/internal-caller.js.map +1 -0
  150. package/dist/esm/express/step-up.js +38 -0
  151. package/dist/esm/express/step-up.js.map +1 -0
  152. package/dist/esm/http/index.js +3 -70
  153. package/dist/esm/http/index.js.map +1 -1
  154. package/dist/esm/identity/index.js +246 -64
  155. package/dist/esm/identity/index.js.map +1 -1
  156. package/dist/esm/identity/step-up.js +47 -0
  157. package/dist/esm/identity/step-up.js.map +1 -0
  158. package/dist/esm/index.js +6 -0
  159. package/dist/esm/index.js.map +1 -1
  160. package/dist/esm/knex/columns.js +28 -0
  161. package/dist/esm/knex/columns.js.map +1 -0
  162. package/dist/esm/knex/index.js +8 -34
  163. package/dist/esm/knex/index.js.map +1 -1
  164. package/dist/esm/knex/migration-helpers.js +51 -0
  165. package/dist/esm/knex/migration-helpers.js.map +1 -0
  166. package/dist/esm/logging/redact.js +3 -7
  167. package/dist/esm/logging/redact.js.map +1 -1
  168. package/dist/esm/messaging/base-consumer.js +32 -0
  169. package/dist/esm/messaging/base-consumer.js.map +1 -0
  170. package/dist/esm/messaging/consumer.js +139 -71
  171. package/dist/esm/messaging/consumer.js.map +1 -1
  172. package/dist/esm/messaging/envelope.js +50 -10
  173. package/dist/esm/messaging/envelope.js.map +1 -1
  174. package/dist/esm/messaging/idempotency.js +91 -7
  175. package/dist/esm/messaging/idempotency.js.map +1 -1
  176. package/dist/esm/messaging/index.js +2 -1
  177. package/dist/esm/messaging/index.js.map +1 -1
  178. package/dist/esm/messaging/outbox.js +97 -54
  179. package/dist/esm/messaging/outbox.js.map +1 -1
  180. package/dist/esm/messaging/publisher.js +86 -38
  181. package/dist/esm/messaging/publisher.js.map +1 -1
  182. package/dist/esm/messaging/staff-notifier.js +4 -4
  183. package/dist/esm/messaging/staff-notifier.js.map +1 -1
  184. package/dist/esm/messaging/topology.js +39 -4
  185. package/dist/esm/messaging/topology.js.map +1 -1
  186. package/dist/esm/rate-limit/index.js +41 -6
  187. package/dist/esm/rate-limit/index.js.map +1 -1
  188. package/dist/esm/rate-limit/keys.js +43 -0
  189. package/dist/esm/rate-limit/keys.js.map +1 -0
  190. package/dist/esm/socket/index.js +112 -17
  191. package/dist/esm/socket/index.js.map +1 -1
  192. package/dist/esm/socket/ticket.js +117 -0
  193. package/dist/esm/socket/ticket.js.map +1 -0
  194. package/dist/esm/testing/index.js +24 -15
  195. package/dist/esm/testing/index.js.map +1 -1
  196. package/dist/types/access/index.d.ts +9 -3
  197. package/dist/types/access/index.d.ts.map +1 -1
  198. package/dist/types/approvals/index.d.ts +99 -0
  199. package/dist/types/approvals/index.d.ts.map +1 -0
  200. package/dist/types/audit/index.d.ts +82 -0
  201. package/dist/types/audit/index.d.ts.map +1 -0
  202. package/dist/types/cache/index.d.ts +64 -14
  203. package/dist/types/cache/index.d.ts.map +1 -1
  204. package/dist/types/cache/keyspace.d.ts +84 -0
  205. package/dist/types/cache/keyspace.d.ts.map +1 -0
  206. package/dist/types/common/circuit-breaker.d.ts +51 -0
  207. package/dist/types/common/circuit-breaker.d.ts.map +1 -0
  208. package/dist/types/common/index.d.ts +4 -0
  209. package/dist/types/common/index.d.ts.map +1 -1
  210. package/dist/types/common/internal-client.d.ts +116 -0
  211. package/dist/types/common/internal-client.d.ts.map +1 -0
  212. package/dist/types/common/internal-constants.d.ts +9 -0
  213. package/dist/types/common/internal-constants.d.ts.map +1 -0
  214. package/dist/types/common/internal-service-auth.d.ts +102 -0
  215. package/dist/types/common/internal-service-auth.d.ts.map +1 -0
  216. package/dist/types/common/money.d.ts +104 -0
  217. package/dist/types/common/money.d.ts.map +1 -0
  218. package/dist/types/common/phone.d.ts +25 -15
  219. package/dist/types/common/phone.d.ts.map +1 -1
  220. package/dist/types/common/time.d.ts +20 -2
  221. package/dist/types/common/time.d.ts.map +1 -1
  222. package/dist/types/config/index.d.ts +251 -27
  223. package/dist/types/config/index.d.ts.map +1 -1
  224. package/dist/types/contracts/notification-dispatch.d.ts +13 -13
  225. package/dist/types/database/db.d.ts +46 -0
  226. package/dist/types/database/db.d.ts.map +1 -0
  227. package/dist/types/database/index.d.ts +9 -22
  228. package/dist/types/database/index.d.ts.map +1 -1
  229. package/dist/types/database/pagination.d.ts +68 -0
  230. package/dist/types/database/pagination.d.ts.map +1 -0
  231. package/dist/types/database/pool.d.ts +39 -0
  232. package/dist/types/database/pool.d.ts.map +1 -0
  233. package/dist/types/database/scoped-repository.d.ts +92 -0
  234. package/dist/types/database/scoped-repository.d.ts.map +1 -0
  235. package/dist/types/database/scopes.d.ts +159 -0
  236. package/dist/types/database/scopes.d.ts.map +1 -0
  237. package/dist/types/database/table-names.d.ts +13 -0
  238. package/dist/types/database/table-names.d.ts.map +1 -0
  239. package/dist/types/database/tables.d.ts +748 -0
  240. package/dist/types/database/tables.d.ts.map +1 -0
  241. package/dist/types/express/auth.d.ts +40 -24
  242. package/dist/types/express/auth.d.ts.map +1 -1
  243. package/dist/types/express/index.d.ts +2 -0
  244. package/dist/types/express/index.d.ts.map +1 -1
  245. package/dist/types/express/internal-caller.d.ts +53 -0
  246. package/dist/types/express/internal-caller.d.ts.map +1 -0
  247. package/dist/types/express/step-up.d.ts +38 -0
  248. package/dist/types/express/step-up.d.ts.map +1 -0
  249. package/dist/types/http/index.d.ts +3 -31
  250. package/dist/types/http/index.d.ts.map +1 -1
  251. package/dist/types/identity/index.d.ts +159 -21
  252. package/dist/types/identity/index.d.ts.map +1 -1
  253. package/dist/types/identity/step-up.d.ts +41 -0
  254. package/dist/types/identity/step-up.d.ts.map +1 -0
  255. package/dist/types/index.d.ts +6 -0
  256. package/dist/types/index.d.ts.map +1 -1
  257. package/dist/types/knex/columns.d.ts +15 -0
  258. package/dist/types/knex/columns.d.ts.map +1 -0
  259. package/dist/types/knex/index.d.ts +3 -11
  260. package/dist/types/knex/index.d.ts.map +1 -1
  261. package/dist/types/knex/migration-helpers.d.ts +28 -0
  262. package/dist/types/knex/migration-helpers.d.ts.map +1 -0
  263. package/dist/types/logging/redact.d.ts +2 -2
  264. package/dist/types/logging/redact.d.ts.map +1 -1
  265. package/dist/types/messaging/base-consumer.d.ts +33 -0
  266. package/dist/types/messaging/base-consumer.d.ts.map +1 -0
  267. package/dist/types/messaging/consumer.d.ts +59 -21
  268. package/dist/types/messaging/consumer.d.ts.map +1 -1
  269. package/dist/types/messaging/envelope.d.ts +50 -11
  270. package/dist/types/messaging/envelope.d.ts.map +1 -1
  271. package/dist/types/messaging/idempotency.d.ts +60 -3
  272. package/dist/types/messaging/idempotency.d.ts.map +1 -1
  273. package/dist/types/messaging/index.d.ts +7 -0
  274. package/dist/types/messaging/index.d.ts.map +1 -1
  275. package/dist/types/messaging/outbox.d.ts +62 -22
  276. package/dist/types/messaging/outbox.d.ts.map +1 -1
  277. package/dist/types/messaging/publisher.d.ts +54 -21
  278. package/dist/types/messaging/publisher.d.ts.map +1 -1
  279. package/dist/types/messaging/staff-notifier.d.ts +9 -9
  280. package/dist/types/messaging/staff-notifier.d.ts.map +1 -1
  281. package/dist/types/messaging/staff-recipients.d.ts +1 -1
  282. package/dist/types/messaging/topology.d.ts +40 -8
  283. package/dist/types/messaging/topology.d.ts.map +1 -1
  284. package/dist/types/rate-limit/index.d.ts +40 -4
  285. package/dist/types/rate-limit/index.d.ts.map +1 -1
  286. package/dist/types/rate-limit/keys.d.ts +52 -0
  287. package/dist/types/rate-limit/keys.d.ts.map +1 -0
  288. package/dist/types/socket/index.d.ts +86 -2
  289. package/dist/types/socket/index.d.ts.map +1 -1
  290. package/dist/types/socket/ticket.d.ts +90 -0
  291. package/dist/types/socket/ticket.d.ts.map +1 -0
  292. package/dist/types/testing/index.d.ts +31 -10
  293. package/dist/types/testing/index.d.ts.map +1 -1
  294. package/dist/types/types/index.d.ts +26 -14
  295. package/dist/types/types/index.d.ts.map +1 -1
  296. package/package.json +3 -1
@@ -1,9 +1,5 @@
1
1
  import { z } from 'zod';
2
- /**
3
- * Environment building blocks. Services compose the pieces they need:
4
- *
5
- * const env = loadEnv(serviceEnv.merge(databaseEnv).merge(messagingEnv).extend({ MY_VAR: z.string() }));
6
- */
2
+ /** Service identity, logging, CORS and the gateway signing secret. */
7
3
  export declare const serviceEnv: z.ZodObject<{
8
4
  NODE_ENV: z.ZodDefault<z.ZodEnum<["development", "test", "staging", "production"]>>;
9
5
  PORT: z.ZodNumber;
@@ -12,29 +8,46 @@ export declare const serviceEnv: z.ZodObject<{
12
8
  APP_NAME: z.ZodDefault<z.ZodString>;
13
9
  LOG_LEVEL: z.ZodOptional<z.ZodEnum<["error", "warn", "info", "http", "debug"]>>;
14
10
  CORS_ORIGINS: z.ZodDefault<z.ZodString>;
15
- /** Verifies gateway-signed identity headers. */
16
- GATEWAY_SHARED_SECRET: z.ZodString;
17
- /** Authenticates service-to-service `/internal/*` calls. */
18
- INTERNAL_SERVICE_SECRET: z.ZodString;
11
+ /** Verifies gateway-signed identity headers (v2); at least 32 characters, same value on the gateway and every service. */
12
+ GATEWAY_SIGNING_SECRET: z.ZodString;
19
13
  }, "strip", z.ZodTypeAny, {
20
- NODE_ENV: "production" | "test" | "development" | "staging";
14
+ NODE_ENV: "development" | "test" | "staging" | "production";
21
15
  PORT: number;
22
16
  SERVICE_NAME: string;
23
17
  APP_NAME: string;
24
18
  CORS_ORIGINS: string;
25
- GATEWAY_SHARED_SECRET: string;
26
- INTERNAL_SERVICE_SECRET: string;
27
- LOG_LEVEL?: "info" | "debug" | "error" | "warn" | "http" | undefined;
19
+ GATEWAY_SIGNING_SECRET: string;
20
+ LOG_LEVEL?: "error" | "warn" | "info" | "http" | "debug" | undefined;
28
21
  }, {
29
22
  PORT: number;
30
23
  SERVICE_NAME: string;
31
- GATEWAY_SHARED_SECRET: string;
32
- INTERNAL_SERVICE_SECRET: string;
33
- NODE_ENV?: "production" | "test" | "development" | "staging" | undefined;
34
- LOG_LEVEL?: "info" | "debug" | "error" | "warn" | "http" | undefined;
24
+ GATEWAY_SIGNING_SECRET: string;
25
+ NODE_ENV?: "development" | "test" | "staging" | "production" | undefined;
35
26
  APP_NAME?: string | undefined;
27
+ LOG_LEVEL?: "error" | "warn" | "info" | "http" | "debug" | undefined;
36
28
  CORS_ORIGINS?: string | undefined;
37
29
  }>;
30
+ /**
31
+ * Service-to-service credentials. Optional here because development may run without them;
32
+ * `assertInternalServiceAuthConfigured` enforces them in staging and production.
33
+ */
34
+ export declare const internalServiceEnv: z.ZodObject<{
35
+ /** This service's own name (its compose service name), sent with every internal call. */
36
+ INTERNAL_SERVICE_NAME: z.ZodOptional<z.ZodString>;
37
+ /** This service's own secret (at least 32 characters), sent with every internal call. */
38
+ INTERNAL_SERVICE_CREDENTIAL: z.ZodOptional<z.ZodString>;
39
+ /** JSON map of caller name → secret this service accepts from that caller. */
40
+ INTERNAL_SERVICE_CREDENTIALS: z.ZodOptional<z.ZodString>;
41
+ }, "strip", z.ZodTypeAny, {
42
+ INTERNAL_SERVICE_NAME?: string | undefined;
43
+ INTERNAL_SERVICE_CREDENTIAL?: string | undefined;
44
+ INTERNAL_SERVICE_CREDENTIALS?: string | undefined;
45
+ }, {
46
+ INTERNAL_SERVICE_NAME?: string | undefined;
47
+ INTERNAL_SERVICE_CREDENTIAL?: string | undefined;
48
+ INTERNAL_SERVICE_CREDENTIALS?: string | undefined;
49
+ }>;
50
+ /** Database connection env vars (MySQL defaults). */
38
51
  export declare const databaseEnv: z.ZodObject<{
39
52
  DB_HOST: z.ZodDefault<z.ZodString>;
40
53
  DB_PORT: z.ZodDefault<z.ZodNumber>;
@@ -57,6 +70,7 @@ export declare const databaseEnv: z.ZodObject<{
57
70
  DB_PASSWORD?: string | undefined;
58
71
  DB_POOL_MAX?: number | undefined;
59
72
  }>;
73
+ /** RabbitMQ connection and queue-prefix env vars. */
60
74
  export declare const messagingEnv: z.ZodObject<{
61
75
  RABBITMQ_URL: z.ZodOptional<z.ZodString>;
62
76
  RABBITMQ_HOST: z.ZodDefault<z.ZodString>;
@@ -86,30 +100,240 @@ export declare const messagingEnv: z.ZodObject<{
86
100
  QUEUE_PREFIX?: string | undefined;
87
101
  RABBITMQ_ENABLED?: "true" | "false" | undefined;
88
102
  }>;
103
+ /** Redis connection env vars. Keys are prefixed by the keyspace (`createRedisKeyspace`), never by the client. */
89
104
  export declare const redisEnv: z.ZodObject<{
105
+ /** Full connection URL; overrides host/port/password when set. */
90
106
  REDIS_URL: z.ZodOptional<z.ZodString>;
107
+ REDIS_HOST: z.ZodDefault<z.ZodString>;
108
+ REDIS_PORT: z.ZodDefault<z.ZodNumber>;
109
+ REDIS_PASSWORD: z.ZodOptional<z.ZodString>;
91
110
  REDIS_DB: z.ZodDefault<z.ZodNumber>;
92
- /** Key prefix, e.g. `app:dev:` — never share one between apps or environments. */
93
- REDIS_PREFIX: z.ZodDefault<z.ZodString>;
111
+ /**
112
+ * Environment segment of every Redis key (`{app}:{env}:{service}:…`), e.g. `dev`, `staging`, `prod`.
113
+ * Required in staging and production; never share one between environments.
114
+ */
115
+ CACHE_KEY_PREFIX: z.ZodOptional<z.ZodString>;
94
116
  }, "strip", z.ZodTypeAny, {
117
+ REDIS_HOST: string;
118
+ REDIS_PORT: number;
95
119
  REDIS_DB: number;
96
- REDIS_PREFIX: string;
97
120
  REDIS_URL?: string | undefined;
121
+ REDIS_PASSWORD?: string | undefined;
122
+ CACHE_KEY_PREFIX?: string | undefined;
98
123
  }, {
99
124
  REDIS_URL?: string | undefined;
125
+ REDIS_HOST?: string | undefined;
126
+ REDIS_PORT?: number | undefined;
127
+ REDIS_PASSWORD?: string | undefined;
100
128
  REDIS_DB?: number | undefined;
101
- REDIS_PREFIX?: string | undefined;
129
+ CACHE_KEY_PREFIX?: string | undefined;
102
130
  }>;
103
- /** Builds an AMQP URL from discrete env vars (or returns RABBITMQ_URL when set). */
131
+ /**
132
+ * Builds an AMQP URL from discrete env vars (or returns RABBITMQ_URL when set). User, password and vhost are URL-encoded.
133
+ *
134
+ * @param env Parsed {@link messagingEnv} values.
135
+ * @returns An `amqp://` URL.
136
+ * @example const url = amqpUrlFromEnv(parseEnv(messagingEnv));
137
+ */
104
138
  export declare function amqpUrlFromEnv(env: z.infer<typeof messagingEnv>): string;
105
- /** Reads `KEY=value` lines from a dotenv file into process.env without overriding set values. */
139
+ /**
140
+ * Reads `KEY=value` lines from a dotenv file into process.env without overriding set values. Missing file is a no-op.
141
+ *
142
+ * @param path Dotenv file (default `./.env`).
143
+ * @example loadDotEnv(resolve(__dirname, '../.env.test'));
144
+ */
106
145
  export declare function loadDotEnv(path?: string): void;
146
+ /** Thrown by the env loader when required variables are missing or invalid; lists every problem. */
107
147
  export declare class ConfigError extends Error {
108
148
  }
109
- /** Loads `.env` (if present) and validates process.env. Throws ConfigError listing every problem. */
110
- export declare function loadEnv<S extends z.ZodTypeAny>(schema: S, source?: NodeJS.ProcessEnv, options?: {
149
+ /**
150
+ * The base environment every service validates: service identity, gateway secret, database, Redis,
151
+ * RabbitMQ and internal-service credentials. `loadEnv` merges a service's own schema onto it.
152
+ */
153
+ export declare const baseEnv: z.ZodObject<{
154
+ NODE_ENV: z.ZodDefault<z.ZodEnum<["development", "test", "staging", "production"]>>;
155
+ PORT: z.ZodNumber;
156
+ SERVICE_NAME: z.ZodString;
157
+ /** Short app identifier used in exchange names and key prefixes (e.g. `myapp`). */
158
+ APP_NAME: z.ZodDefault<z.ZodString>;
159
+ LOG_LEVEL: z.ZodOptional<z.ZodEnum<["error", "warn", "info", "http", "debug"]>>;
160
+ CORS_ORIGINS: z.ZodDefault<z.ZodString>;
161
+ /** Verifies gateway-signed identity headers (v2); at least 32 characters, same value on the gateway and every service. */
162
+ GATEWAY_SIGNING_SECRET: z.ZodString;
163
+ } & {
164
+ DB_HOST: z.ZodDefault<z.ZodString>;
165
+ DB_PORT: z.ZodDefault<z.ZodNumber>;
166
+ DB_USER: z.ZodDefault<z.ZodString>;
167
+ DB_PASSWORD: z.ZodDefault<z.ZodString>;
168
+ DB_NAME: z.ZodString;
169
+ DB_POOL_MAX: z.ZodDefault<z.ZodNumber>;
170
+ } & {
171
+ /** Full connection URL; overrides host/port/password when set. */
172
+ REDIS_URL: z.ZodOptional<z.ZodString>;
173
+ REDIS_HOST: z.ZodDefault<z.ZodString>;
174
+ REDIS_PORT: z.ZodDefault<z.ZodNumber>;
175
+ REDIS_PASSWORD: z.ZodOptional<z.ZodString>;
176
+ REDIS_DB: z.ZodDefault<z.ZodNumber>;
177
+ /**
178
+ * Environment segment of every Redis key (`{app}:{env}:{service}:…`), e.g. `dev`, `staging`, `prod`.
179
+ * Required in staging and production; never share one between environments.
180
+ */
181
+ CACHE_KEY_PREFIX: z.ZodOptional<z.ZodString>;
182
+ } & {
183
+ RABBITMQ_URL: z.ZodOptional<z.ZodString>;
184
+ RABBITMQ_HOST: z.ZodDefault<z.ZodString>;
185
+ RABBITMQ_PORT: z.ZodDefault<z.ZodNumber>;
186
+ RABBITMQ_USER: z.ZodDefault<z.ZodString>;
187
+ RABBITMQ_PASSWORD: z.ZodDefault<z.ZodString>;
188
+ RABBITMQ_VHOST: z.ZodDefault<z.ZodString>;
189
+ /** Environment prefix for queue and exchange names (`dev`, `staging`, `prod`). */
190
+ QUEUE_PREFIX: z.ZodDefault<z.ZodString>;
191
+ RABBITMQ_ENABLED: z.ZodEffects<z.ZodDefault<z.ZodEnum<["true", "false"]>>, boolean, "true" | "false" | undefined>;
192
+ } & {
193
+ /** This service's own name (its compose service name), sent with every internal call. */
194
+ INTERNAL_SERVICE_NAME: z.ZodOptional<z.ZodString>;
195
+ /** This service's own secret (at least 32 characters), sent with every internal call. */
196
+ INTERNAL_SERVICE_CREDENTIAL: z.ZodOptional<z.ZodString>;
197
+ /** JSON map of caller name → secret this service accepts from that caller. */
198
+ INTERNAL_SERVICE_CREDENTIALS: z.ZodOptional<z.ZodString>;
199
+ }, "strip", z.ZodTypeAny, {
200
+ NODE_ENV: "development" | "test" | "staging" | "production";
201
+ PORT: number;
202
+ SERVICE_NAME: string;
203
+ APP_NAME: string;
204
+ CORS_ORIGINS: string;
205
+ GATEWAY_SIGNING_SECRET: string;
206
+ DB_HOST: string;
207
+ DB_PORT: number;
208
+ DB_USER: string;
209
+ DB_PASSWORD: string;
210
+ DB_NAME: string;
211
+ DB_POOL_MAX: number;
212
+ RABBITMQ_HOST: string;
213
+ RABBITMQ_PORT: number;
214
+ RABBITMQ_USER: string;
215
+ RABBITMQ_PASSWORD: string;
216
+ RABBITMQ_VHOST: string;
217
+ QUEUE_PREFIX: string;
218
+ RABBITMQ_ENABLED: boolean;
219
+ REDIS_HOST: string;
220
+ REDIS_PORT: number;
221
+ REDIS_DB: number;
222
+ LOG_LEVEL?: "error" | "warn" | "info" | "http" | "debug" | undefined;
223
+ INTERNAL_SERVICE_NAME?: string | undefined;
224
+ INTERNAL_SERVICE_CREDENTIAL?: string | undefined;
225
+ INTERNAL_SERVICE_CREDENTIALS?: string | undefined;
226
+ RABBITMQ_URL?: string | undefined;
227
+ REDIS_URL?: string | undefined;
228
+ REDIS_PASSWORD?: string | undefined;
229
+ CACHE_KEY_PREFIX?: string | undefined;
230
+ }, {
231
+ PORT: number;
232
+ SERVICE_NAME: string;
233
+ GATEWAY_SIGNING_SECRET: string;
234
+ DB_NAME: string;
235
+ NODE_ENV?: "development" | "test" | "staging" | "production" | undefined;
236
+ APP_NAME?: string | undefined;
237
+ LOG_LEVEL?: "error" | "warn" | "info" | "http" | "debug" | undefined;
238
+ CORS_ORIGINS?: string | undefined;
239
+ INTERNAL_SERVICE_NAME?: string | undefined;
240
+ INTERNAL_SERVICE_CREDENTIAL?: string | undefined;
241
+ INTERNAL_SERVICE_CREDENTIALS?: string | undefined;
242
+ DB_HOST?: string | undefined;
243
+ DB_PORT?: number | undefined;
244
+ DB_USER?: string | undefined;
245
+ DB_PASSWORD?: string | undefined;
246
+ DB_POOL_MAX?: number | undefined;
247
+ RABBITMQ_URL?: string | undefined;
248
+ RABBITMQ_HOST?: string | undefined;
249
+ RABBITMQ_PORT?: number | undefined;
250
+ RABBITMQ_USER?: string | undefined;
251
+ RABBITMQ_PASSWORD?: string | undefined;
252
+ RABBITMQ_VHOST?: string | undefined;
253
+ QUEUE_PREFIX?: string | undefined;
254
+ RABBITMQ_ENABLED?: "true" | "false" | undefined;
255
+ REDIS_URL?: string | undefined;
256
+ REDIS_HOST?: string | undefined;
257
+ REDIS_PORT?: number | undefined;
258
+ REDIS_PASSWORD?: string | undefined;
259
+ REDIS_DB?: number | undefined;
260
+ CACHE_KEY_PREFIX?: string | undefined;
261
+ }>;
262
+ /** Variables that have a development default but must be set explicitly in staging and production. */
263
+ export declare const DEPLOYED_REQUIRED_ENV: readonly string[];
264
+ /**
265
+ * True for NODE_ENV values that must name their environments explicitly (staging, production).
266
+ *
267
+ * @param nodeEnv NODE_ENV value (default `process.env.NODE_ENV`).
268
+ * @returns Whether it is a deployed environment.
269
+ * @example isDeployedNodeEnv('production') // true
270
+ */
271
+ export declare function isDeployedNodeEnv(nodeEnv?: string | undefined): boolean;
272
+ /** One problem with one variable. Holds the variable name and kind of problem only, never its value. */
273
+ export interface EnvProblem {
274
+ name: string;
275
+ problem: 'missing' | 'invalid';
276
+ }
277
+ type EnvSource = Record<string, string | undefined>;
278
+ /**
279
+ * Formats problems as `NAME: missing|invalid` lines (names only — values are never printed, because
280
+ * Zod's own messages can echo them).
281
+ *
282
+ * @param problems Problems from validation.
283
+ * @returns A multi-line message.
284
+ * @example formatEnvProblems([{ name: 'DB_NAME', problem: 'missing' }]) // 'Invalid environment configuration:\n DB_NAME: missing'
285
+ */
286
+ export declare function formatEnvProblems(problems: EnvProblem[]): string;
287
+ /** Options for {@link parseEnv}. */
288
+ export interface ParseEnvOptions {
289
+ /** Read `./.env` first when `source` is `process.env` (default true). */
111
290
  dotenv?: boolean;
112
- }): z.infer<S>;
113
- /** Comma-separated env value → trimmed, non-empty list. */
291
+ /** Names that must be set when NODE_ENV is staging or production (default {@link DEPLOYED_REQUIRED_ENV}). */
292
+ deployedRequired?: readonly string[];
293
+ }
294
+ /**
295
+ * Validates `source` against `schema` without merging the base or exiting. Use for partial configs
296
+ * (scripts, tests) and wherever the caller handles the error.
297
+ *
298
+ * @param schema Any Zod schema over the env object.
299
+ * @param source Values to validate (default process.env).
300
+ * @param options Dotenv and deployed-environment checks.
301
+ * @returns The parsed, typed config.
302
+ * @throws ConfigError listing every missing or invalid variable by name (never its value).
303
+ * @example const env = parseEnv(databaseEnv, { DB_NAME: 'app_test' });
304
+ */
305
+ export declare function parseEnv<S extends z.ZodTypeAny>(schema: S, source?: EnvSource, options?: ParseEnvOptions): z.infer<S>;
306
+ /** Options for {@link loadEnv}: parse options plus source, base and injectable output/exit. */
307
+ export interface LoadEnvOptions extends ParseEnvOptions {
308
+ /** Values to validate (default process.env). */
309
+ source?: EnvSource;
310
+ /** Base schema merged under the service schema (default {@link baseEnv}). */
311
+ base?: z.AnyZodObject;
312
+ /** Where the problem list is written (default stderr). */
313
+ write?: (text: string) => void;
314
+ /** Called with exit code 1 on failure (default `process.exit`). */
315
+ exit?: (code: number) => never;
316
+ }
317
+ /**
318
+ * Service startup config: merges the base env schema with the service's own, validates, and on
319
+ * failure prints the missing/invalid variable **names** (never values) and exits non-zero.
320
+ *
321
+ * @param schema The service's own variables (default none).
322
+ * @param options Source, base override and injectable write/exit for tests.
323
+ * @returns The parsed, typed config (base + service variables).
324
+ * @example
325
+ * export const config = loadEnv(z.object({ UPSTREAM_INTERNAL_URL: z.string().url() }));
326
+ */
327
+ export declare function loadEnv<S extends z.AnyZodObject = z.ZodObject<Record<string, never>>, B extends z.AnyZodObject = typeof baseEnv>(schema?: S, options?: LoadEnvOptions & {
328
+ base?: B;
329
+ }): z.infer<B> & z.infer<S>;
330
+ /**
331
+ * Comma-separated env value → trimmed, non-empty list.
332
+ *
333
+ * @param value Raw env value.
334
+ * @returns The list (empty when unset).
335
+ * @example listFromEnv(' a, b ,,c') // ['a', 'b', 'c']
336
+ */
114
337
  export declare const listFromEnv: (value: string | undefined) => string[];
338
+ export {};
115
339
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,UAAU;;;;IAIrB,mFAAmF;;;;IAInF,gDAAgD;;IAEhD,4DAA4D;;;;;;;;;;;;;;;;;;;;EAE5D,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;IAOvB,kFAAkF;;;;;;;;;;;;;;;;;;;;;EAGlF,CAAC;AAEH,eAAO,MAAM,QAAQ;;;IAGnB,kFAAkF;;;;;;;;;;EAElF,CAAC;AAEH,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,GAAG,MAAM,CAIxE;AAED,iGAAiG;AACjG,wBAAgB,UAAU,CAAC,IAAI,SAAiC,GAAG,IAAI,CAYtE;AAED,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAEzC,qGAAqG;AACrG,wBAAgB,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAE,MAAM,CAAC,UAAwB,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAQlJ;AAED,2DAA2D;AAC3D,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,EAAmE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -44,7 +44,7 @@ export type DispatchValue = z.infer<typeof dispatchValueSchema>;
44
44
  * Who receives a dispatch. `userId` is needed for per-user channels such as an in-app feed;
45
45
  * addresses with no account behind them carry only `email`.
46
46
  *
47
- * @example { email: 'wanjiru@example.com', name: 'Wanjiru', userId: '01J…', timezone: 'Africa/Nairobi' }
47
+ * @example { email: 'ada@example.com', name: 'Ada', userId: '01J…', timezone: 'Europe/Lisbon' }
48
48
  */
49
49
  export declare const dispatchRecipientSchema: z.ZodObject<{
50
50
  email: z.ZodString;
@@ -55,14 +55,14 @@ export declare const dispatchRecipientSchema: z.ZodObject<{
55
55
  timezone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
56
56
  }, "strip", z.ZodTypeAny, {
57
57
  email: string;
58
- userId?: string | null | undefined;
59
58
  name?: string | undefined;
59
+ userId?: string | null | undefined;
60
60
  locale?: string | null | undefined;
61
61
  timezone?: string | null | undefined;
62
62
  }, {
63
63
  email: string;
64
- userId?: string | null | undefined;
65
64
  name?: string | undefined;
65
+ userId?: string | null | undefined;
66
66
  locale?: string | null | undefined;
67
67
  timezone?: string | null | undefined;
68
68
  }>;
@@ -116,14 +116,14 @@ export declare function createNotificationDispatchSchema<const C extends string,
116
116
  timezone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
117
117
  }, "strip", z.ZodTypeAny, {
118
118
  email: string;
119
- userId?: string | null | undefined;
120
119
  name?: string | undefined;
120
+ userId?: string | null | undefined;
121
121
  locale?: string | null | undefined;
122
122
  timezone?: string | null | undefined;
123
123
  }, {
124
124
  email: string;
125
- userId?: string | null | undefined;
126
125
  name?: string | undefined;
126
+ userId?: string | null | undefined;
127
127
  locale?: string | null | undefined;
128
128
  timezone?: string | null | undefined;
129
129
  }>;
@@ -148,14 +148,14 @@ export declare function createNotificationDispatchSchema<const C extends string,
148
148
  timezone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
149
149
  }, "strip", z.ZodTypeAny, {
150
150
  email: string;
151
- userId?: string | null | undefined;
152
151
  name?: string | undefined;
152
+ userId?: string | null | undefined;
153
153
  locale?: string | null | undefined;
154
154
  timezone?: string | null | undefined;
155
155
  }, {
156
156
  email: string;
157
- userId?: string | null | undefined;
158
157
  name?: string | undefined;
158
+ userId?: string | null | undefined;
159
159
  locale?: string | null | undefined;
160
160
  timezone?: string | null | undefined;
161
161
  }>;
@@ -180,14 +180,14 @@ export declare function createNotificationDispatchSchema<const C extends string,
180
180
  timezone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
181
181
  }, "strip", z.ZodTypeAny, {
182
182
  email: string;
183
- userId?: string | null | undefined;
184
183
  name?: string | undefined;
184
+ userId?: string | null | undefined;
185
185
  locale?: string | null | undefined;
186
186
  timezone?: string | null | undefined;
187
187
  }, {
188
188
  email: string;
189
- userId?: string | null | undefined;
190
189
  name?: string | undefined;
190
+ userId?: string | null | undefined;
191
191
  locale?: string | null | undefined;
192
192
  timezone?: string | null | undefined;
193
193
  }>;
@@ -212,14 +212,14 @@ export declare function createNotificationDispatchSchema<const C extends string,
212
212
  timezone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
213
213
  }, "strip", z.ZodTypeAny, {
214
214
  email: string;
215
- userId?: string | null | undefined;
216
215
  name?: string | undefined;
216
+ userId?: string | null | undefined;
217
217
  locale?: string | null | undefined;
218
218
  timezone?: string | null | undefined;
219
219
  }, {
220
220
  email: string;
221
- userId?: string | null | undefined;
222
221
  name?: string | undefined;
222
+ userId?: string | null | undefined;
223
223
  locale?: string | null | undefined;
224
224
  timezone?: string | null | undefined;
225
225
  }>;
@@ -244,14 +244,14 @@ export declare function createNotificationDispatchSchema<const C extends string,
244
244
  timezone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
245
245
  }, "strip", z.ZodTypeAny, {
246
246
  email: string;
247
- userId?: string | null | undefined;
248
247
  name?: string | undefined;
248
+ userId?: string | null | undefined;
249
249
  locale?: string | null | undefined;
250
250
  timezone?: string | null | undefined;
251
251
  }, {
252
252
  email: string;
253
- userId?: string | null | undefined;
254
253
  name?: string | undefined;
254
+ userId?: string | null | undefined;
255
255
  locale?: string | null | undefined;
256
256
  timezone?: string | null | undefined;
257
257
  }>;
@@ -0,0 +1,46 @@
1
+ import type { Knex } from 'knex';
2
+ import { type MySql2Database } from 'drizzle-orm/mysql2';
3
+ import type mysql from 'mysql2/promise';
4
+ import type { databaseEnv } from '../config/index.js';
5
+ import type { z } from 'zod';
6
+ import { type MysqlConnectionOptions } from './pool.js';
7
+ /** The `DB_*` variables of `baseEnv` (see `databaseEnv` in the config module). */
8
+ export type DatabaseEnv = z.infer<typeof databaseEnv>;
9
+ /** A Drizzle database over a mysql2 pool. */
10
+ export type Database<TSchema extends Record<string, unknown> = Record<string, never>> = MySql2Database<TSchema>;
11
+ /** The transaction handle passed to `db.transaction(async (tx) => …)`. */
12
+ export type Tx<TSchema extends Record<string, unknown> = Record<string, never>> = Parameters<Parameters<Database<TSchema>['transaction']>[0]>[0];
13
+ /** What {@link createDb} returns. The service container owns it and closes it on shutdown. */
14
+ export interface DbHandle<TSchema extends Record<string, unknown>> {
15
+ db: Database<TSchema>;
16
+ /** Readiness probe (`SELECT 1`); rejects when the database is unreachable. */
17
+ ping(): Promise<void>;
18
+ /** Drains and closes the pool. */
19
+ close(): Promise<void>;
20
+ }
21
+ /** Options for {@link createDb}. */
22
+ export interface CreateDbOptions<TSchema extends Record<string, unknown>> {
23
+ /** Validated env (`config` from `loadEnv`). */
24
+ env: DatabaseEnv;
25
+ /** The service's Drizzle schema (tables and relations). */
26
+ schema: TSchema;
27
+ /** Pre-built pool (tests). Default: a utf8mb4, UTC pool sized by `DB_POOL_MAX`. */
28
+ pool?: mysql.Pool;
29
+ }
30
+ /**
31
+ * Creates the service's Drizzle database. There is no module-level singleton: call it once in
32
+ * `container.ts` and inject `db` into repositories.
33
+ *
34
+ * @example const { db, ping, close } = createDb({ env: config, schema });
35
+ */
36
+ export declare function createDb<TSchema extends Record<string, unknown>>(options: CreateDbOptions<TSchema>): DbHandle<TSchema>;
37
+ /**
38
+ * Knex config for a service's `knexfile.js`. Knex runs **migrations and seeds only** (`.cjs` files
39
+ * in `./migrations` and `./seeds`); repositories use Drizzle.
40
+ *
41
+ * @example module.exports = knexConfig(config);
42
+ */
43
+ export declare function knexConfig(env: DatabaseEnv): Knex.Config;
44
+ /** Maps the validated `DB_*` env to connection options. */
45
+ export declare function connectionOptions(env: DatabaseEnv): MysqlConnectionOptions;
46
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/database/db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEtG,kFAAkF;AAClF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,6CAA6C;AAC7C,MAAM,MAAM,QAAQ,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;AAEhH,0EAA0E;AAC1E,MAAM,MAAM,EAAE,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjJ,8FAA8F;AAC9F,MAAM,WAAW,QAAQ,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/D,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACtB,8EAA8E;IAC9E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,kCAAkC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtE,+CAA+C;IAC/C,GAAG,EAAE,WAAW,CAAC;IACjB,2DAA2D;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,mFAAmF;IACnF,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAStH;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC,MAAM,CAExD;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,sBAAsB,CAE1E"}
@@ -1,25 +1,12 @@
1
- import type { Knex } from 'knex';
2
- import mysql from 'mysql2/promise';
3
- export interface MysqlConnectionOptions {
4
- host: string;
5
- port: number;
6
- user: string;
7
- password: string;
8
- database: string;
9
- poolMax?: number;
10
- }
11
1
  /**
12
- * mysql2 pool for Drizzle. Sessions run in UTC and utf8mb4 so timestamps and emoji round-trip
13
- * unchanged regardless of server defaults.
2
+ * `@heavybit/shared-lib/database`: Drizzle data access for services. Repositories use Drizzle
3
+ * through {@link ScopedRepository} and the scopes in `scopes.ts`; raw scoped queries and Knex in
4
+ * `src/` are forbidden. Knex is for migrations and seeds only (`knexConfig`, `@heavybit/shared-lib/knex`).
14
5
  */
15
- export declare function createMysqlPool(options: MysqlConnectionOptions): mysql.Pool;
16
- /** Knex config for migrations/seeds and query-builder use (same session settings as the pool). */
17
- export declare function createKnexConfig(options: MysqlConnectionOptions & {
18
- migrationsDir?: string;
19
- seedsDir?: string;
20
- }): Knex.Config;
21
- /** Readiness probe helper. */
22
- export declare function pingMysql(pool: mysql.Pool): Promise<void>;
23
- /** Escapes `%`, `_` and `\` for use inside a LIKE pattern. */
24
- export declare function escapeLike(value: string): string;
6
+ export * from './pool.js';
7
+ export * from './db.js';
8
+ export * from './scopes.js';
9
+ export * from './scoped-repository.js';
10
+ export * from './pagination.js';
11
+ export * from './tables.js';
25
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/database/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAEnC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,KAAK,CAAC,IAAI,CAe3E;AAED,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,MAAM,CAgB7H;AAED,8BAA8B;AAC9B,wBAAsB,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/database/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ import type { CursorPage } from '../types/index.js';
3
+ /**
4
+ * Cursor (keyset) pagination (D6). Clients send `?cursor=&limit=`; the cursor is an opaque
5
+ * base64url token of `{ sortKey, id }` (the last row's sort value plus an id tie-breaker).
6
+ * Dependency-light: usable from controllers without the database subpath.
7
+ */
8
+ /** Largest page size a client may ask for. */
9
+ export declare const MAX_PAGE_LIMIT = 100;
10
+ /** Page size when the client sends none. */
11
+ export declare const DEFAULT_PAGE_LIMIT = 20;
12
+ /** `{ cursor?, limit }` query schema: limit 1–100, default 20; unknown keys are stripped. */
13
+ export declare const cursorQuerySchema: z.ZodObject<{
14
+ cursor: z.ZodOptional<z.ZodString>;
15
+ limit: z.ZodDefault<z.ZodNumber>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ limit: number;
18
+ cursor?: string | undefined;
19
+ }, {
20
+ limit?: number | undefined;
21
+ cursor?: string | undefined;
22
+ }>;
23
+ /** Parsed cursor query. */
24
+ export type CursorQuery = z.infer<typeof cursorQuerySchema>;
25
+ /** Sort values a cursor can carry. Dates are carried as ISO strings. */
26
+ export type CursorSortKey = string | number | null;
27
+ /** The decoded content of a cursor. */
28
+ export interface DecodedCursor {
29
+ sortKey: CursorSortKey;
30
+ id: string;
31
+ }
32
+ /**
33
+ * Validates `{ cursor, limit }` from a query string.
34
+ *
35
+ * @throws ValidationError (422) with field errors when invalid.
36
+ * @example const { cursor, limit } = parseCursorQuery(req.query);
37
+ */
38
+ export declare function parseCursorQuery(input: {
39
+ cursor?: unknown;
40
+ limit?: unknown;
41
+ } | undefined): CursorQuery;
42
+ /**
43
+ * Encodes a cursor. Date sort keys become ISO strings.
44
+ *
45
+ * @example encodeCursor({ sortKey: row.createdAt, id: row.id })
46
+ */
47
+ export declare function encodeCursor(cursor: {
48
+ sortKey: CursorSortKey | Date;
49
+ id: string;
50
+ }): string;
51
+ /**
52
+ * Decodes a cursor produced by {@link encodeCursor}.
53
+ *
54
+ * @throws ValidationError (422, field `cursor`) for anything malformed or tampered with.
55
+ */
56
+ export declare function decodeCursor(token: string): DecodedCursor;
57
+ /**
58
+ * Builds a page from `limit + 1` fetched rows: the extra row only signals that more exist.
59
+ *
60
+ * @param rows Rows fetched with `limit + 1`.
61
+ * @param limit The page size.
62
+ * @param cursorOf Extracts `{ sortKey, id }` from a row for the next cursor.
63
+ */
64
+ export declare function buildCursorPage<T>(rows: T[], limit: number, cursorOf: (row: T) => {
65
+ sortKey: CursorSortKey | Date;
66
+ id: string;
67
+ }): CursorPage<T>;
68
+ //# sourceMappingURL=pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/database/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD;;;;GAIG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAGrC,6FAA6F;AAC7F,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AAEH,2BAA2B;AAC3B,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAEnD,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAAG,WAAW,CAItG;AAMD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAG1F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAczD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK;IAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAK/I"}
@@ -0,0 +1,39 @@
1
+ import type { Knex } from 'knex';
2
+ import mysql from 'mysql2/promise';
3
+ /** Connection settings for {@link createMysqlPool} and {@link createKnexConfig}. */
4
+ export interface MysqlConnectionOptions {
5
+ /** Server host name. */
6
+ host: string;
7
+ /** Server port. */
8
+ port: number;
9
+ /** Database user. */
10
+ user: string;
11
+ /** Database password (never logged). */
12
+ password: string;
13
+ /** The service's own database. */
14
+ database: string;
15
+ /** Maximum pool connections (default 10). */
16
+ poolMax?: number;
17
+ }
18
+ /** Knex-only options for {@link createKnexConfig}. */
19
+ export interface KnexConfigOptions extends MysqlConnectionOptions {
20
+ /** Migrations folder (default `./migrations`). */
21
+ migrationsDir?: string;
22
+ /** Seeds folder (default `./seeds`). */
23
+ seedsDir?: string;
24
+ }
25
+ /**
26
+ * mysql2 pool for Drizzle. Sessions run in UTC and utf8mb4 so timestamps and emoji round-trip
27
+ * unchanged regardless of server defaults.
28
+ */
29
+ export declare function createMysqlPool(options: MysqlConnectionOptions): mysql.Pool;
30
+ /**
31
+ * Knex config for migrations and seeds: mysql2, utf8mb4, UTC, `.cjs` files only. Services call it
32
+ * through `knexConfig(env)` in their `knexfile.js`.
33
+ */
34
+ export declare function createKnexConfig(options: KnexConfigOptions): Knex.Config;
35
+ /** Readiness probe helper. */
36
+ export declare function pingMysql(pool: mysql.Pool): Promise<void>;
37
+ /** Escapes `%`, `_` and `\` for use inside a LIKE pattern. */
38
+ export declare function escapeLike(value: string): string;
39
+ //# sourceMappingURL=pool.d.ts.map