@tstdl/base 0.93.86 → 0.93.89

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 (318) hide show
  1. package/ai/genkit/helpers.d.ts +3 -1
  2. package/ai/genkit/helpers.js +3 -3
  3. package/api/server/gateway.d.ts +3 -0
  4. package/api/server/gateway.js +15 -4
  5. package/api/server/middlewares/catch-error.middleware.js +2 -4
  6. package/api/server/middlewares/cors.middleware.js +2 -3
  7. package/api/server/middlewares/csrf.middleware.d.ts +41 -0
  8. package/api/server/middlewares/csrf.middleware.js +108 -0
  9. package/api/server/middlewares/index.d.ts +1 -0
  10. package/api/server/middlewares/index.js +1 -0
  11. package/api/server/module.d.ts +8 -2
  12. package/api/server/module.js +14 -8
  13. package/api/server/tests/csrf.middleware.test.js +91 -0
  14. package/audit/drizzle/{0000_bored_stick.sql → 0000_lumpy_thunderball.sql} +3 -3
  15. package/audit/drizzle/meta/0000_snapshot.json +4 -4
  16. package/audit/drizzle/meta/_journal.json +2 -9
  17. package/audit/module.d.ts +4 -1
  18. package/audit/module.js +3 -2
  19. package/audit/schemas.d.ts +1 -1
  20. package/audit/types.d.ts +1 -1
  21. package/audit/types.js +1 -1
  22. package/authentication/client/authentication.service.d.ts +14 -1
  23. package/authentication/client/authentication.service.js +82 -23
  24. package/authentication/client/http-client.middleware.d.ts +6 -0
  25. package/authentication/client/http-client.middleware.js +36 -0
  26. package/authentication/client/module.js +8 -2
  27. package/authentication/models/service-account.model.d.ts +2 -2
  28. package/authentication/models/service-account.model.js +10 -5
  29. package/authentication/models/subject.model.d.ts +19 -5
  30. package/authentication/models/subject.model.js +25 -29
  31. package/authentication/models/system-account.model.d.ts +3 -2
  32. package/authentication/models/system-account.model.js +11 -5
  33. package/authentication/models/user.model.d.ts +2 -11
  34. package/authentication/models/user.model.js +5 -16
  35. package/authentication/server/authentication-api-request-token.provider.d.ts +0 -2
  36. package/authentication/server/authentication-api-request-token.provider.js +3 -11
  37. package/authentication/server/authentication.api-controller.d.ts +1 -2
  38. package/authentication/server/authentication.api-controller.js +8 -9
  39. package/authentication/server/authentication.audit.d.ts +3 -2
  40. package/authentication/server/authentication.service.d.ts +27 -1
  41. package/authentication/server/authentication.service.js +67 -18
  42. package/authentication/server/drizzle/{0000_normal_paper_doll.sql → 0000_soft_tag.sql} +25 -32
  43. package/authentication/server/drizzle/meta/0000_snapshot.json +180 -205
  44. package/authentication/server/drizzle/meta/_journal.json +2 -2
  45. package/authentication/server/helper.js +9 -2
  46. package/authentication/server/module.d.ts +4 -1
  47. package/authentication/server/module.js +9 -5
  48. package/authentication/server/schemas.d.ts +2 -1
  49. package/authentication/server/schemas.js +2 -2
  50. package/authentication/server/subject.service.d.ts +14 -8
  51. package/authentication/server/subject.service.js +86 -84
  52. package/authentication/tests/authentication-ancillary.service.test.d.ts +1 -0
  53. package/authentication/tests/authentication-ancillary.service.test.js +13 -0
  54. package/authentication/tests/authentication-secret-requirements.validator.test.d.ts +1 -0
  55. package/authentication/tests/authentication-secret-requirements.validator.test.js +29 -0
  56. package/authentication/tests/authentication.api-controller.test.d.ts +1 -0
  57. package/authentication/tests/authentication.api-controller.test.js +88 -0
  58. package/authentication/tests/authentication.api-request-token.provider.test.d.ts +1 -0
  59. package/authentication/tests/authentication.api-request-token.provider.test.js +48 -0
  60. package/authentication/tests/authentication.client-middleware.test.d.ts +1 -0
  61. package/authentication/tests/authentication.client-middleware.test.js +23 -0
  62. package/authentication/tests/authentication.client-service.test.d.ts +1 -0
  63. package/authentication/tests/authentication.client-service.test.js +70 -0
  64. package/authentication/tests/authentication.service.test.d.ts +1 -0
  65. package/authentication/tests/authentication.service.test.js +186 -0
  66. package/authentication/tests/authentication.test-ancillary-service.d.ts +9 -0
  67. package/authentication/tests/authentication.test-ancillary-service.js +27 -0
  68. package/authentication/tests/helper.test.d.ts +1 -0
  69. package/authentication/tests/helper.test.js +107 -0
  70. package/authentication/tests/secret-requirements.error.test.d.ts +1 -0
  71. package/authentication/tests/secret-requirements.error.test.js +14 -0
  72. package/authentication/tests/subject.service.test.d.ts +1 -0
  73. package/authentication/tests/subject.service.test.js +140 -0
  74. package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +1 -1
  75. package/circuit-breaker/postgres/drizzle/meta/_journal.json +2 -2
  76. package/circuit-breaker/postgres/module.d.ts +7 -1
  77. package/circuit-breaker/postgres/module.js +8 -6
  78. package/circuit-breaker/tests/circuit-breaker.test.js +2 -22
  79. package/document-management/api/document-management.api.js +2 -6
  80. package/document-management/server/services/document-validation.service.js +6 -5
  81. package/document-management/server/services/document-workflow.service.js +5 -5
  82. package/document-management/service-models/document-folders.view-model.d.ts +5 -2
  83. package/document-management/service-models/document-folders.view-model.js +42 -9
  84. package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
  85. package/examples/document-management/main.js +4 -4
  86. package/http/client/adapters/undici.adapter.d.ts +7 -5
  87. package/http/client/adapters/undici.adapter.js +13 -10
  88. package/http/client/module.d.ts +3 -1
  89. package/http/client/module.js +8 -9
  90. package/http/server/http-server.d.ts +2 -0
  91. package/http/server/node/module.d.ts +6 -2
  92. package/http/server/node/module.js +6 -4
  93. package/http/server/node/node-http-server.d.ts +2 -0
  94. package/http/server/node/node-http-server.js +7 -0
  95. package/http/types.d.ts +1 -1
  96. package/key-value-store/postgres/module.d.ts +7 -1
  97. package/key-value-store/postgres/module.js +7 -3
  98. package/lock/postgres/lock.js +0 -1
  99. package/lock/postgres/module.d.ts +7 -1
  100. package/lock/postgres/module.js +9 -5
  101. package/logger/formatter.d.ts +2 -0
  102. package/logger/formatters/json.js +2 -2
  103. package/logger/formatters/pretty-print.js +8 -10
  104. package/logger/logger.d.ts +1 -1
  105. package/logger/logger.js +15 -12
  106. package/message-bus/local/module.d.ts +5 -2
  107. package/message-bus/local/module.js +5 -4
  108. package/module/module.d.ts +2 -1
  109. package/module/module.js +3 -0
  110. package/module/modules/web-server.module.d.ts +11 -6
  111. package/module/modules/web-server.module.js +15 -10
  112. package/orm/decorators.d.ts +24 -1
  113. package/orm/decorators.js +40 -4
  114. package/orm/index.d.ts +1 -1
  115. package/orm/index.js +1 -1
  116. package/orm/query/base.d.ts +17 -17
  117. package/orm/query/base.js +1 -1
  118. package/orm/repository.types.d.ts +46 -2
  119. package/orm/schemas/tsvector.js +1 -1
  120. package/orm/server/drizzle/schema-converter.d.ts +3 -1
  121. package/orm/server/drizzle/schema-converter.js +120 -14
  122. package/orm/server/index.d.ts +1 -0
  123. package/orm/server/index.js +1 -0
  124. package/orm/server/module.d.ts +4 -2
  125. package/orm/server/module.js +6 -5
  126. package/orm/server/query-converter.d.ts +6 -3
  127. package/orm/server/query-converter.js +33 -21
  128. package/orm/server/repository-config.d.ts +8 -0
  129. package/orm/server/repository-config.js +8 -0
  130. package/orm/server/repository.d.ts +117 -43
  131. package/orm/server/repository.js +758 -254
  132. package/orm/server/transaction.d.ts +4 -2
  133. package/orm/server/transaction.js +14 -5
  134. package/orm/server/transactional.d.ts +6 -2
  135. package/orm/server/transactional.js +39 -9
  136. package/orm/server/types.d.ts +2 -0
  137. package/orm/sqls/case-when.d.ts +25 -0
  138. package/orm/sqls/case-when.js +54 -0
  139. package/orm/sqls/index.d.ts +2 -0
  140. package/orm/sqls/index.js +2 -0
  141. package/orm/{sqls.d.ts → sqls/sqls.d.ts} +67 -19
  142. package/orm/{sqls.js → sqls/sqls.js} +116 -22
  143. package/orm/tests/data-types.test.d.ts +1 -0
  144. package/orm/tests/data-types.test.js +39 -0
  145. package/orm/tests/decorators.test.d.ts +1 -0
  146. package/orm/tests/decorators.test.js +77 -0
  147. package/orm/tests/encryption.test.d.ts +1 -0
  148. package/orm/tests/encryption.test.js +34 -0
  149. package/orm/tests/query-complex.test.d.ts +1 -0
  150. package/orm/tests/query-complex.test.js +203 -0
  151. package/orm/tests/query-converter-complex.test.d.ts +1 -0
  152. package/orm/tests/query-converter-complex.test.js +126 -0
  153. package/orm/tests/query-converter.test.d.ts +1 -0
  154. package/orm/tests/query-converter.test.js +123 -0
  155. package/orm/tests/repository-advanced.test.d.ts +1 -0
  156. package/orm/tests/repository-advanced.test.js +232 -0
  157. package/orm/tests/repository-attributes.test.d.ts +1 -0
  158. package/orm/tests/repository-attributes.test.js +99 -0
  159. package/orm/tests/repository-comprehensive.test.d.ts +1 -0
  160. package/orm/tests/repository-comprehensive.test.js +187 -0
  161. package/orm/tests/repository-coverage.test.d.ts +1 -0
  162. package/orm/tests/repository-coverage.test.js +303 -0
  163. package/orm/tests/repository-cti-complex.test.d.ts +1 -0
  164. package/orm/tests/repository-cti-complex.test.js +170 -0
  165. package/orm/tests/repository-cti-embedded.test.d.ts +1 -0
  166. package/orm/tests/repository-cti-embedded.test.js +188 -0
  167. package/orm/tests/repository-cti-extensive.test.d.ts +1 -0
  168. package/orm/tests/repository-cti-extensive.test.js +308 -0
  169. package/orm/tests/repository-cti-mapping.test.d.ts +1 -0
  170. package/orm/tests/repository-cti-mapping.test.js +121 -0
  171. package/orm/tests/repository-cti-search.test.d.ts +1 -0
  172. package/orm/tests/repository-cti-search.test.js +152 -0
  173. package/orm/tests/repository-cti-soft-delete.test.d.ts +1 -0
  174. package/orm/tests/repository-cti-soft-delete.test.js +115 -0
  175. package/orm/tests/repository-cti-transactions.test.d.ts +1 -0
  176. package/orm/tests/repository-cti-transactions.test.js +126 -0
  177. package/orm/tests/repository-cti-upsert-many.test.d.ts +1 -0
  178. package/orm/tests/repository-cti-upsert-many.test.js +127 -0
  179. package/orm/tests/repository-cti.test.d.ts +1 -0
  180. package/orm/tests/repository-cti.test.js +456 -0
  181. package/orm/tests/repository-edge-cases.test.d.ts +1 -0
  182. package/orm/tests/repository-edge-cases.test.js +216 -0
  183. package/orm/tests/repository-expiration.test.d.ts +1 -0
  184. package/orm/tests/repository-expiration.test.js +153 -0
  185. package/orm/tests/repository-extra-coverage.test.d.ts +1 -0
  186. package/orm/tests/repository-extra-coverage.test.js +546 -0
  187. package/orm/tests/repository-mapping.test.d.ts +1 -0
  188. package/orm/tests/repository-mapping.test.js +71 -0
  189. package/orm/tests/repository-regression.test.d.ts +1 -0
  190. package/orm/tests/repository-regression.test.js +330 -0
  191. package/orm/tests/repository-search-coverage.test.d.ts +1 -0
  192. package/orm/tests/repository-search-coverage.test.js +129 -0
  193. package/orm/tests/repository-search.test.d.ts +1 -0
  194. package/orm/tests/repository-search.test.js +116 -0
  195. package/orm/tests/repository-soft-delete.test.d.ts +1 -0
  196. package/orm/tests/repository-soft-delete.test.js +143 -0
  197. package/orm/tests/repository-transactions-nested.test.d.ts +1 -0
  198. package/orm/tests/repository-transactions-nested.test.js +202 -0
  199. package/orm/tests/repository-types.test.d.ts +1 -0
  200. package/orm/tests/repository-types.test.js +218 -0
  201. package/orm/tests/schema-converter.test.d.ts +1 -0
  202. package/orm/tests/schema-converter.test.js +81 -0
  203. package/orm/tests/schema-generation.test.d.ts +1 -0
  204. package/orm/tests/schema-generation.test.js +127 -0
  205. package/orm/tests/sql-helpers.test.d.ts +1 -0
  206. package/orm/tests/sql-helpers.test.js +67 -0
  207. package/orm/tests/transaction-safety.test.d.ts +1 -0
  208. package/orm/tests/transaction-safety.test.js +81 -0
  209. package/orm/tests/transactional.test.d.ts +1 -0
  210. package/orm/tests/transactional.test.js +224 -0
  211. package/orm/tests/utils.test.d.ts +1 -0
  212. package/orm/tests/utils.test.js +70 -0
  213. package/orm/utils.d.ts +7 -0
  214. package/orm/utils.js +26 -6
  215. package/package.json +12 -7
  216. package/pool/pool.js +1 -1
  217. package/rate-limit/index.d.ts +2 -0
  218. package/rate-limit/index.js +2 -0
  219. package/rate-limit/postgres/drizzle/0000_watery_rage.sql +7 -0
  220. package/{queue → rate-limit}/postgres/drizzle/meta/0000_snapshot.json +14 -39
  221. package/rate-limit/postgres/drizzle/meta/_journal.json +13 -0
  222. package/{queue → rate-limit}/postgres/drizzle.config.js +1 -1
  223. package/rate-limit/postgres/index.d.ts +4 -0
  224. package/rate-limit/postgres/index.js +4 -0
  225. package/rate-limit/postgres/module.d.ts +12 -0
  226. package/rate-limit/postgres/module.js +28 -0
  227. package/rate-limit/postgres/postgres-rate-limiter.d.ts +9 -0
  228. package/rate-limit/postgres/postgres-rate-limiter.js +56 -0
  229. package/rate-limit/postgres/rate-limit.model.d.ts +8 -0
  230. package/rate-limit/postgres/rate-limit.model.js +35 -0
  231. package/rate-limit/postgres/rate-limiter.provider.d.ts +6 -0
  232. package/rate-limit/postgres/rate-limiter.provider.js +21 -0
  233. package/rate-limit/postgres/schemas.d.ts +3 -0
  234. package/rate-limit/postgres/schemas.js +4 -0
  235. package/rate-limit/provider.d.ts +9 -0
  236. package/rate-limit/provider.js +2 -0
  237. package/rate-limit/rate-limiter.d.ts +35 -0
  238. package/rate-limit/rate-limiter.js +3 -0
  239. package/rate-limit/tests/postgres-rate-limiter.test.d.ts +1 -0
  240. package/rate-limit/tests/postgres-rate-limiter.test.js +92 -0
  241. package/signals/implementation/configure.d.ts +3 -0
  242. package/signals/implementation/configure.js +3 -0
  243. package/sse/data-stream-source.d.ts +1 -1
  244. package/sse/data-stream-source.js +6 -6
  245. package/task-queue/enqueue-batch.d.ts +17 -0
  246. package/task-queue/enqueue-batch.js +24 -0
  247. package/{queue → task-queue}/index.d.ts +1 -1
  248. package/{queue → task-queue}/index.js +1 -1
  249. package/task-queue/postgres/drizzle/0000_thin_black_panther.sql +74 -0
  250. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +592 -0
  251. package/task-queue/postgres/drizzle/meta/_journal.json +13 -0
  252. package/task-queue/postgres/drizzle.config.d.ts +2 -0
  253. package/task-queue/postgres/drizzle.config.js +11 -0
  254. package/task-queue/postgres/index.d.ts +4 -0
  255. package/task-queue/postgres/index.js +4 -0
  256. package/task-queue/postgres/module.d.ts +12 -0
  257. package/task-queue/postgres/module.js +28 -0
  258. package/task-queue/postgres/schemas.d.ts +16 -0
  259. package/task-queue/postgres/schemas.js +8 -0
  260. package/task-queue/postgres/task-queue.d.ts +83 -0
  261. package/task-queue/postgres/task-queue.js +1054 -0
  262. package/task-queue/postgres/task-queue.provider.d.ts +7 -0
  263. package/{queue/postgres/queue.provider.js → task-queue/postgres/task-queue.provider.js} +8 -8
  264. package/task-queue/postgres/task.model.d.ts +39 -0
  265. package/task-queue/postgres/task.model.js +178 -0
  266. package/{queue → task-queue}/provider.d.ts +3 -3
  267. package/task-queue/provider.js +2 -0
  268. package/{queue → task-queue}/task-context.d.ts +7 -7
  269. package/{queue → task-queue}/task-context.js +8 -8
  270. package/{queue/queue.d.ts → task-queue/task-queue.d.ts} +128 -59
  271. package/task-queue/task-queue.js +200 -0
  272. package/task-queue/tests/complex.test.d.ts +1 -0
  273. package/task-queue/tests/complex.test.js +299 -0
  274. package/task-queue/tests/dependencies.test.d.ts +1 -0
  275. package/task-queue/tests/dependencies.test.js +174 -0
  276. package/task-queue/tests/queue.test.d.ts +1 -0
  277. package/task-queue/tests/queue.test.js +334 -0
  278. package/task-queue/tests/worker.test.d.ts +1 -0
  279. package/task-queue/tests/worker.test.js +163 -0
  280. package/test1.js +1 -1
  281. package/test4.js +2 -2
  282. package/unit-test/index.d.ts +1 -0
  283. package/unit-test/index.js +1 -0
  284. package/unit-test/integration-setup.d.ts +55 -0
  285. package/unit-test/integration-setup.js +182 -0
  286. package/utils/patterns.d.ts +3 -0
  287. package/utils/patterns.js +6 -1
  288. package/audit/drizzle/0001_previous_network.sql +0 -2
  289. package/audit/drizzle/meta/0001_snapshot.json +0 -195
  290. package/queue/enqueue-batch.d.ts +0 -17
  291. package/queue/enqueue-batch.js +0 -18
  292. package/queue/postgres/drizzle/0000_zippy_moondragon.sql +0 -11
  293. package/queue/postgres/drizzle/0001_certain_wild_pack.sql +0 -2
  294. package/queue/postgres/drizzle/0002_dear_meggan.sql +0 -2
  295. package/queue/postgres/drizzle/0003_tricky_venom.sql +0 -30
  296. package/queue/postgres/drizzle/meta/0001_snapshot.json +0 -103
  297. package/queue/postgres/drizzle/meta/0002_snapshot.json +0 -90
  298. package/queue/postgres/drizzle/meta/0003_snapshot.json +0 -288
  299. package/queue/postgres/drizzle/meta/_journal.json +0 -34
  300. package/queue/postgres/index.d.ts +0 -4
  301. package/queue/postgres/index.js +0 -4
  302. package/queue/postgres/module.d.ts +0 -9
  303. package/queue/postgres/module.js +0 -29
  304. package/queue/postgres/queue.d.ts +0 -60
  305. package/queue/postgres/queue.js +0 -681
  306. package/queue/postgres/queue.provider.d.ts +0 -7
  307. package/queue/postgres/schemas.d.ts +0 -14
  308. package/queue/postgres/schemas.js +0 -6
  309. package/queue/postgres/task.model.d.ts +0 -24
  310. package/queue/postgres/task.model.js +0 -115
  311. package/queue/provider.js +0 -2
  312. package/queue/queue.js +0 -131
  313. package/queue/tests/queue.test.js +0 -623
  314. package/test3.d.ts +0 -1
  315. package/test3.js +0 -47
  316. /package/{queue/tests/queue.test.d.ts → api/server/tests/csrf.middleware.test.d.ts} +0 -0
  317. /package/circuit-breaker/postgres/drizzle/{0000_hard_shocker.sql → 0000_cooing_korath.sql} +0 -0
  318. /package/{queue → rate-limit}/postgres/drizzle.config.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.86",
3
+ "version": "0.93.89",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -97,9 +97,11 @@
97
97
  "./pool": "./pool/index.js",
98
98
  "./process": "./process/index.js",
99
99
  "./promise": "./promise/index.js",
100
- "./queue": "./queue/index.js",
101
- "./queue/postgres": "./queue/postgres/index.js",
100
+ "./task-queue": "./task-queue/index.js",
101
+ "./task-queue/postgres": "./task-queue/postgres/index.js",
102
102
  "./random": "./random/index.js",
103
+ "./rate-limit": "./rate-limit/index.js",
104
+ "./rate-limit/postgres": "./rate-limit/postgres/index.js",
103
105
  "./reflection": "./reflection/index.js",
104
106
  "./rpc": "./rpc/index.js",
105
107
  "./rpc/endpoints": "./rpc/endpoints/index.js",
@@ -122,6 +124,7 @@
122
124
  "./text": "./text/index.js",
123
125
  "./threading": "./threading/index.js",
124
126
  "./types": "./types/index.js",
127
+ "./unit-test": "./unit-test/index.js",
125
128
  "./utils": "./utils/index.js",
126
129
  "./utils/array": "./utils/array/index.js",
127
130
  "./utils/async-hook": "./utils/async-hook/index.js",
@@ -140,12 +143,12 @@
140
143
  "reflect-metadata": "^0.2",
141
144
  "rxjs": "^7.8",
142
145
  "ts-pattern": "^5.9",
143
- "type-fest": "^5.3"
146
+ "type-fest": "^5.4"
144
147
  },
145
148
  "peerDependencies": {
146
149
  "@genkit-ai/google-genai": "^1.27",
147
150
  "@google-cloud/storage": "^7.18",
148
- "@google/genai": "^1.35",
151
+ "@google/genai": "^1.38",
149
152
  "@toon-format/toon": "^2.1.0",
150
153
  "@tstdl/angular": "^0.93",
151
154
  "@zxcvbn-ts/core": "^3.0",
@@ -159,7 +162,7 @@
159
162
  "minio": "^8.0",
160
163
  "mjml": "^4.18",
161
164
  "nodemailer": "^7.0",
162
- "pg": "^8.16",
165
+ "pg": "^8.17",
163
166
  "playwright": "^1.57",
164
167
  "preact": "^10.28",
165
168
  "preact-render-to-string": "^6.6",
@@ -181,6 +184,8 @@
181
184
  "@types/node": "25",
182
185
  "@types/nodemailer": "7.0",
183
186
  "@types/pg": "8.16",
187
+ "@vitest/coverage-v8": "4.0",
188
+ "@vitest/ui": "4.0",
184
189
  "concurrently": "9.2",
185
190
  "drizzle-kit": "0.31",
186
191
  "eslint": "9.39",
@@ -190,7 +195,7 @@
190
195
  "typedoc-plugin-markdown": "4.9",
191
196
  "typedoc-plugin-missing-exports": "4.1",
192
197
  "typescript": "5.9",
193
- "typescript-eslint": "8.52",
198
+ "typescript-eslint": "8.53",
194
199
  "vite-tsconfig-paths": "6.0",
195
200
  "vitest": "4.0"
196
201
  },
package/pool/pool.js CHANGED
@@ -86,7 +86,7 @@ export class Pool {
86
86
  await this.disposeInstance(instance);
87
87
  }
88
88
  catch (disposeError) {
89
- this.logger.error(disposeError);
89
+ this.logger.error('Error disposing instance', disposeError);
90
90
  }
91
91
  }
92
92
  else {
@@ -0,0 +1,2 @@
1
+ export * from './rate-limiter.js';
2
+ export * from './provider.js';
@@ -0,0 +1,2 @@
1
+ export * from './rate-limiter.js';
2
+ export * from './provider.js';
@@ -0,0 +1,7 @@
1
+ CREATE TABLE "rate_limit"."rate_limit" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "resource" text NOT NULL,
4
+ "tokens" double precision NOT NULL,
5
+ "last_refill_timestamp" timestamp with time zone NOT NULL,
6
+ CONSTRAINT "rate_limit_resource_unique" UNIQUE("resource")
7
+ );
@@ -1,12 +1,12 @@
1
1
  {
2
- "id": "1a2e63a5-b780-4f4d-ae41-ce8369aa1cf0",
2
+ "id": "0270ac12-b454-4601-b7e9-f825d71b1f4e",
3
3
  "prevId": "00000000-0000-0000-0000-000000000000",
4
4
  "version": "7",
5
5
  "dialect": "postgresql",
6
6
  "tables": {
7
- "queue.job": {
8
- "name": "job",
9
- "schema": "queue",
7
+ "rate_limit.rate_limit": {
8
+ "name": "rate_limit",
9
+ "schema": "rate_limit",
10
10
  "columns": {
11
11
  "id": {
12
12
  "name": "id",
@@ -15,46 +15,22 @@
15
15
  "notNull": true,
16
16
  "default": "gen_random_uuid()"
17
17
  },
18
- "queue": {
19
- "name": "queue",
18
+ "resource": {
19
+ "name": "resource",
20
20
  "type": "text",
21
21
  "primaryKey": false,
22
22
  "notNull": true
23
23
  },
24
- "tag": {
25
- "name": "tag",
26
- "type": "text",
27
- "primaryKey": false,
28
- "notNull": false
29
- },
30
- "priority": {
31
- "name": "priority",
32
- "type": "integer",
33
- "primaryKey": false,
34
- "notNull": true
35
- },
36
- "enqueue_timestamp": {
37
- "name": "enqueue_timestamp",
38
- "type": "timestamp with time zone",
39
- "primaryKey": false,
40
- "notNull": true
41
- },
42
- "tries": {
43
- "name": "tries",
44
- "type": "integer",
24
+ "tokens": {
25
+ "name": "tokens",
26
+ "type": "double precision",
45
27
  "primaryKey": false,
46
28
  "notNull": true
47
29
  },
48
- "last_dequeue_timestamp": {
49
- "name": "last_dequeue_timestamp",
30
+ "last_refill_timestamp": {
31
+ "name": "last_refill_timestamp",
50
32
  "type": "timestamp with time zone",
51
33
  "primaryKey": false,
52
- "notNull": false
53
- },
54
- "data": {
55
- "name": "data",
56
- "type": "jsonb",
57
- "primaryKey": false,
58
34
  "notNull": true
59
35
  }
60
36
  },
@@ -62,12 +38,11 @@
62
38
  "foreignKeys": {},
63
39
  "compositePrimaryKeys": {},
64
40
  "uniqueConstraints": {
65
- "job_queue_tag_unique": {
66
- "name": "job_queue_tag_unique",
41
+ "rate_limit_resource_unique": {
42
+ "name": "rate_limit_resource_unique",
67
43
  "nullsNotDistinct": false,
68
44
  "columns": [
69
- "queue",
70
- "tag"
45
+ "resource"
71
46
  ]
72
47
  }
73
48
  },
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "postgresql",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "7",
8
+ "when": 1768608042456,
9
+ "tag": "0000_watery_rage",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
@@ -5,7 +5,7 @@ export default defineConfig({
5
5
  out: relative('./', resolve(__dirname, './drizzle/').replace('dist', 'source')),
6
6
  schema: resolve(__dirname, './schemas.js'),
7
7
  migrations: {
8
- schema: 'queue',
8
+ schema: 'rate_limit',
9
9
  table: '_migrations',
10
10
  },
11
11
  });
@@ -0,0 +1,4 @@
1
+ export * from './module.js';
2
+ export * from './postgres-rate-limiter.js';
3
+ export * from './rate-limit.model.js';
4
+ export * from './rate-limiter.provider.js';
@@ -0,0 +1,4 @@
1
+ export * from './module.js';
2
+ export * from './postgres-rate-limiter.js';
3
+ export * from './rate-limit.model.js';
4
+ export * from './rate-limiter.provider.js';
@@ -0,0 +1,12 @@
1
+ import { Injector } from '../../injector/injector.js';
2
+ import { type DatabaseConfig } from '../../orm/server/index.js';
3
+ export declare class PostgresRateLimiterModuleConfig {
4
+ database?: DatabaseConfig;
5
+ }
6
+ /**
7
+ * configure rate limit module
8
+ */
9
+ export declare function configurePostgresRateLimiter({ injector, ...config }?: PostgresRateLimiterModuleConfig & {
10
+ injector?: Injector;
11
+ }): void;
12
+ export declare function migratePostgresRateLimiterSchema(): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { inject } from '../../injector/index.js';
2
+ import { Injector } from '../../injector/injector.js';
3
+ import { Database, migrate } from '../../orm/server/index.js';
4
+ import { RateLimiterProvider } from '../provider.js';
5
+ import { RateLimiter } from '../rate-limiter.js';
6
+ import { PostgresRateLimiter } from './postgres-rate-limiter.js';
7
+ import { PostgresRateLimiterProvider } from './rate-limiter.provider.js';
8
+ export class PostgresRateLimiterModuleConfig {
9
+ database;
10
+ }
11
+ /**
12
+ * configure rate limit module
13
+ */
14
+ export function configurePostgresRateLimiter({ injector, ...config } = {}) {
15
+ const targetInjector = injector ?? Injector;
16
+ targetInjector.register(PostgresRateLimiterModuleConfig, { useValue: config });
17
+ targetInjector.registerSingleton(RateLimiterProvider, { useToken: PostgresRateLimiterProvider });
18
+ targetInjector.registerSingleton(RateLimiter, { useToken: PostgresRateLimiter });
19
+ }
20
+ export async function migratePostgresRateLimiterSchema() {
21
+ const connection = inject(PostgresRateLimiterModuleConfig, undefined, { optional: true })?.database?.connection;
22
+ const database = inject(Database, connection);
23
+ await migrate(database, {
24
+ migrationsSchema: 'rate_limit',
25
+ migrationsTable: '_migrations',
26
+ migrationsFolder: import.meta.resolve('./drizzle'),
27
+ });
28
+ }
@@ -0,0 +1,9 @@
1
+ import { RateLimiter } from '../rate-limiter.js';
2
+ export declare class PostgresRateLimiter extends RateLimiter {
3
+ #private;
4
+ readonly burstCapacity: number;
5
+ readonly refillIntervalMs: number;
6
+ readonly refillRate: number;
7
+ tryAcquire(resource: string, cost?: number): Promise<boolean>;
8
+ refund(resource: string, amount: number): Promise<void>;
9
+ }
@@ -0,0 +1,56 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { gte, sql } from 'drizzle-orm';
8
+ import { injectArgument, provide, Singleton } from '../../injector/index.js';
9
+ import { least, TRANSACTION_TIMESTAMP } from '../../orm/index.js';
10
+ import { DatabaseConfig, injectRepository } from '../../orm/server/index.js';
11
+ import { isDefined, isString } from '../../utils/type-guards.js';
12
+ import { RateLimiter } from '../rate-limiter.js';
13
+ import { PostgresRateLimiterModuleConfig } from './module.js';
14
+ import { PostgresRateLimit } from './rate-limit.model.js';
15
+ import { rateLimit } from './schemas.js';
16
+ let PostgresRateLimiter = class PostgresRateLimiter extends RateLimiter {
17
+ #repository = injectRepository(PostgresRateLimit);
18
+ #config = injectArgument(this);
19
+ burstCapacity = isString(this.#config) ? 100 : this.#config.burstCapacity;
20
+ refillIntervalMs = isString(this.#config) ? 1000 : this.#config.refillIntervalMs;
21
+ refillRate = this.burstCapacity / this.refillIntervalMs;
22
+ async tryAcquire(resource, cost = 1) {
23
+ if (cost <= 0) {
24
+ return true;
25
+ }
26
+ if (cost > this.burstCapacity) {
27
+ return false;
28
+ }
29
+ // Atomic Upsert with Conditional Update
30
+ // 1. If row exists: Calculate new balance (current + refill), cap at burst.
31
+ // Update ONLY IF new balance >= cost.
32
+ // 2. If row missing: Insert with (burst - cost).
33
+ // RETURNING clause will only return a row if the INSERT or UPDATE actually happened.
34
+ const nowMs = sql `(EXTRACT(EPOCH FROM ${TRANSACTION_TIMESTAMP}) * 1000)`;
35
+ const lastRefillMs = sql `(EXTRACT(EPOCH FROM ${rateLimit.lastRefillTimestamp}) * 1000)`;
36
+ const tokensToAdd = sql `(${nowMs} - ${lastRefillMs}) * ${this.refillRate}`;
37
+ const newTokensExpression = least(this.burstCapacity, sql `${rateLimit.tokens} + ${tokensToAdd}`);
38
+ const result = await this.#repository.tryUpsert('resource', { resource, tokens: this.burstCapacity - cost, lastRefillTimestamp: TRANSACTION_TIMESTAMP }, { tokens: sql `${newTokensExpression} - ${cost}`, lastRefillTimestamp: TRANSACTION_TIMESTAMP }, { set: gte(newTokensExpression, cost) });
39
+ return isDefined(result);
40
+ }
41
+ async refund(resource, amount) {
42
+ if (amount <= 0) {
43
+ return;
44
+ }
45
+ await this.#repository.updateByQuery({ resource }, { tokens: least(this.burstCapacity, sql `${rateLimit.tokens} + ${amount}`) });
46
+ }
47
+ };
48
+ PostgresRateLimiter = __decorate([
49
+ Singleton({
50
+ argumentIdentityProvider: JSON.stringify,
51
+ providers: [
52
+ provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(PostgresRateLimiterModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: 2 }) }),
53
+ ],
54
+ })
55
+ ], PostgresRateLimiter);
56
+ export { PostgresRateLimiter };
@@ -0,0 +1,8 @@
1
+ import { BaseEntity } from '../../orm/index.js';
2
+ import type { Timestamp } from '../../orm/types.js';
3
+ export declare class PostgresRateLimit extends BaseEntity {
4
+ static readonly entityName = "RateLimit";
5
+ resource: string;
6
+ tokens: number;
7
+ lastRefillTimestamp: Timestamp;
8
+ }
@@ -0,0 +1,35 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { BaseEntity, Table, Unique } from '../../orm/index.js';
11
+ import { TimestampProperty } from '../../orm/schemas/timestamp.js';
12
+ import { NumberProperty, StringProperty } from '../../schema/index.js';
13
+ let PostgresRateLimit = class PostgresRateLimit extends BaseEntity {
14
+ static entityName = 'RateLimit';
15
+ resource;
16
+ tokens;
17
+ lastRefillTimestamp;
18
+ };
19
+ __decorate([
20
+ StringProperty(),
21
+ __metadata("design:type", String)
22
+ ], PostgresRateLimit.prototype, "resource", void 0);
23
+ __decorate([
24
+ NumberProperty(),
25
+ __metadata("design:type", Number)
26
+ ], PostgresRateLimit.prototype, "tokens", void 0);
27
+ __decorate([
28
+ TimestampProperty(),
29
+ __metadata("design:type", Number)
30
+ ], PostgresRateLimit.prototype, "lastRefillTimestamp", void 0);
31
+ PostgresRateLimit = __decorate([
32
+ Table('rate_limit', { schema: 'rate_limit' }),
33
+ Unique(['resource'])
34
+ ], PostgresRateLimit);
35
+ export { PostgresRateLimit };
@@ -0,0 +1,6 @@
1
+ import { RateLimiterProvider } from '../provider.js';
2
+ import { RateLimiter, type RateLimiterConfig } from '../rate-limiter.js';
3
+ export declare class PostgresRateLimiterProvider extends RateLimiterProvider {
4
+ #private;
5
+ get(resource: string, config: RateLimiterConfig): RateLimiter;
6
+ }
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { inject, Singleton } from '../../injector/index.js';
8
+ import { Injector } from '../../injector/injector.js';
9
+ import { RateLimiterProvider } from '../provider.js';
10
+ import { RateLimiter } from '../rate-limiter.js';
11
+ import { PostgresRateLimiter } from './postgres-rate-limiter.js';
12
+ let PostgresRateLimiterProvider = class PostgresRateLimiterProvider extends RateLimiterProvider {
13
+ #injector = inject(Injector);
14
+ get(resource, config) {
15
+ return this.#injector.resolve(PostgresRateLimiter, { ...config, resource });
16
+ }
17
+ };
18
+ PostgresRateLimiterProvider = __decorate([
19
+ Singleton()
20
+ ], PostgresRateLimiterProvider);
21
+ export { PostgresRateLimiterProvider };
@@ -0,0 +1,3 @@
1
+ import { PostgresRateLimit } from './rate-limit.model.js';
2
+ export declare const rateLimitSchema: import("../../orm/server/index.js").DatabaseSchema<"rate_limit">;
3
+ export declare const rateLimit: import("../../orm/server/types.js").PgTableFromType<typeof PostgresRateLimit, "rate_limit">;
@@ -0,0 +1,4 @@
1
+ import { databaseSchema } from '../../orm/server/index.js';
2
+ import { PostgresRateLimit } from './rate-limit.model.js';
3
+ export const rateLimitSchema = databaseSchema('rate_limit');
4
+ export const rateLimit = rateLimitSchema.getTable(PostgresRateLimit);
@@ -0,0 +1,9 @@
1
+ import type { RateLimiter, RateLimiterConfig } from './rate-limiter.js';
2
+ export declare abstract class RateLimiterProvider {
3
+ /**
4
+ * Gets a RateLimiter instance for the specified resource and configuration.
5
+ * @param resource The unique name of the rate limiter.
6
+ * @param config The configuration for the rate limiter.
7
+ */
8
+ abstract get(resource: string, config: RateLimiterConfig): RateLimiter;
9
+ }
@@ -0,0 +1,2 @@
1
+ export class RateLimiterProvider {
2
+ }
@@ -0,0 +1,35 @@
1
+ import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
2
+ import { Transactional } from '../orm/server/transactional.js';
3
+ export type RateLimiterConfig = {
4
+ /**
5
+ * Maximum number of tokens the bucket can hold.
6
+ */
7
+ burstCapacity: number;
8
+ /**
9
+ * Time in milliseconds in which the bucket refills to its full burst capacity.
10
+ */
11
+ refillIntervalMs: number;
12
+ };
13
+ export type RateLimiterArgument = string | (RateLimiterConfig & {
14
+ resource: string;
15
+ });
16
+ export declare abstract class RateLimiter extends Transactional implements Resolvable<RateLimiterArgument> {
17
+ readonly [resolveArgumentType]: RateLimiterArgument;
18
+ abstract readonly burstCapacity: number;
19
+ abstract readonly refillIntervalMs: number;
20
+ /**
21
+ * Attempts to acquire the specified number of tokens for a resource.
22
+ * @param resource The resource identifier to acquire tokens for.
23
+ * @param cost The number of tokens to acquire. Defaults to 1.
24
+ * @param transaction Optional transaction to participate in.
25
+ * @returns A promise that resolves to true if tokens were successfully acquired, false otherwise.
26
+ */
27
+ abstract tryAcquire(resource: string, cost?: number): Promise<boolean>;
28
+ /**
29
+ * Refunds tokens back to the bucket for a resource.
30
+ * @param resource The resource identifier to refund tokens to.
31
+ * @param amount The number of tokens to refund.
32
+ * @param transaction Optional transaction to participate in.
33
+ */
34
+ abstract refund(resource: string, amount: number): Promise<void>;
35
+ }
@@ -0,0 +1,3 @@
1
+ import { Transactional } from '../orm/server/transactional.js';
2
+ export class RateLimiter extends Transactional {
3
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,92 @@
1
+ import { afterAll, describe, expect, it } from 'vitest';
2
+ import { RateLimiterProvider } from '../../rate-limit/index.js';
3
+ import { setupIntegrationTest } from '../../unit-test/index.js';
4
+ import { timeout } from '../../utils/timing.js';
5
+ describe('PostgresRateLimiter Integration Tests', () => {
6
+ let injector;
7
+ let rateLimiter;
8
+ const limiterName = `test-limiter-${Date.now()}`;
9
+ async function getLimiter() {
10
+ if (injector == null) {
11
+ ({ injector } = await setupIntegrationTest({ modules: { rateLimiter: true } }));
12
+ }
13
+ const rateLimiterProvider = injector.resolve(RateLimiterProvider);
14
+ return rateLimiterProvider.get(limiterName, {
15
+ burstCapacity: 10,
16
+ refillIntervalMs: 1000, // 10 tokens per second -> 1 token per 100ms
17
+ });
18
+ }
19
+ afterAll(async () => {
20
+ await injector?.dispose();
21
+ }, 15000);
22
+ it('should acquire tokens successfully', async () => {
23
+ rateLimiter = await getLimiter();
24
+ const resource = 'res-1';
25
+ const result = await rateLimiter.tryAcquire(resource, 5);
26
+ expect(result).toBe(true);
27
+ const result2 = await rateLimiter.tryAcquire(resource, 5);
28
+ expect(result2).toBe(true);
29
+ const result3 = await rateLimiter.tryAcquire(resource, 1);
30
+ expect(result3).toBe(false);
31
+ });
32
+ it('should refill tokens over time', async () => {
33
+ rateLimiter = await getLimiter();
34
+ const resource = 'res-2';
35
+ await rateLimiter.tryAcquire(resource, 10);
36
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
37
+ // Wait for 2 tokens (200ms)
38
+ await timeout(250);
39
+ expect(await rateLimiter.tryAcquire(resource, 2)).toBe(true);
40
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
41
+ });
42
+ it('should refund tokens', async () => {
43
+ rateLimiter = await getLimiter();
44
+ const resource = 'res-3';
45
+ await rateLimiter.tryAcquire(resource, 10);
46
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
47
+ await rateLimiter.refund(resource, 5);
48
+ expect(await rateLimiter.tryAcquire(resource, 5)).toBe(true);
49
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
50
+ });
51
+ it('should handle fractional tokens', async () => {
52
+ rateLimiter = await getLimiter();
53
+ const resource = 'res-4';
54
+ await rateLimiter.tryAcquire(resource, 9.5);
55
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
56
+ expect(await rateLimiter.tryAcquire(resource, 0.5)).toBe(true);
57
+ });
58
+ it('should handle concurrent acquisitions', async () => {
59
+ rateLimiter = await getLimiter();
60
+ const resource = 'res-concurrent';
61
+ // Initialize
62
+ await rateLimiter.tryAcquire(resource, 0);
63
+ const results = await Promise.all(Array.from({ length: 20 }).map(() => rateLimiter.tryAcquire(resource, 1)));
64
+ const successCount = results.filter(Boolean).length;
65
+ expect(successCount).toBe(10);
66
+ }, 15000);
67
+ it('should always allow zero or negative cost', async () => {
68
+ rateLimiter = await getLimiter();
69
+ const resource = 'res-zero';
70
+ expect(await rateLimiter.tryAcquire(resource, 0)).toBe(true);
71
+ expect(await rateLimiter.tryAcquire(resource, -1)).toBe(true);
72
+ });
73
+ it('should reject cost greater than burst capacity', async () => {
74
+ rateLimiter = await getLimiter();
75
+ const resource = 'res-large';
76
+ // Burst capacity is 10
77
+ expect(await rateLimiter.tryAcquire(resource, 11)).toBe(false);
78
+ });
79
+ it('should cap tokens at burst capacity on refill', async () => {
80
+ rateLimiter = await getLimiter();
81
+ const resource = 'res-refill-cap';
82
+ // Drain
83
+ await rateLimiter.tryAcquire(resource, 10);
84
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
85
+ // Wait for full refill (1s) + extra
86
+ await timeout(1200);
87
+ // Should only have 10 tokens
88
+ expect(await rateLimiter.tryAcquire(resource, 10)).toBe(true);
89
+ // Should be empty again immediately
90
+ expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
91
+ });
92
+ });
@@ -1 +1,4 @@
1
+ /**
2
+ * registers default signals implementation in container
3
+ */
1
4
  export declare function configureDefaultSignalsImplementation(): void;
@@ -6,6 +6,9 @@ import { toObservable } from './to-observable.js';
6
6
  import { toSignal } from './to-signal.js';
7
7
  import { untracked } from './untracked.js';
8
8
  import { signal } from './writable-signal.js';
9
+ /**
10
+ * registers default signals implementation in container
11
+ */
9
12
  export function configureDefaultSignalsImplementation() {
10
13
  configureSignals({
11
14
  signal,
@@ -13,7 +13,7 @@ export declare class DataStreamSource<T> {
13
13
  #private;
14
14
  readonly eventSource: ServerSentEventsSource;
15
15
  readonly closed: import("../signals/api.js").Signal<boolean>;
16
- constructor(options?: DataStreamSourceOptions);
16
+ constructor({ delta, errorFormatter }?: DataStreamSourceOptions);
17
17
  static fromIterable<T>(iterable: AnyIterable<T>, options?: DataStreamSourceOptions): DataStreamSource<T>;
18
18
  send(data: T): Promise<void>;
19
19
  close(): Promise<void>;
@@ -14,14 +14,14 @@ const jsonDiffPatch = createDiffPatch({
14
14
  },
15
15
  });
16
16
  export class DataStreamSource {
17
- #options;
17
+ #useDelta;
18
18
  #errorFormatter;
19
19
  eventSource = new ServerSentEventsSource();
20
20
  closed = this.eventSource.closed;
21
21
  #lastData;
22
- constructor(options = { delta: true }) {
23
- this.#options = options;
24
- this.#errorFormatter = options.errorFormatter ?? defaultErrorFormatter;
22
+ constructor({ delta = true, errorFormatter } = {}) {
23
+ this.#useDelta = delta;
24
+ this.#errorFormatter = errorFormatter ?? defaultErrorFormatter;
25
25
  }
26
26
  static fromIterable(iterable, options) {
27
27
  const source = new DataStreamSource(options);
@@ -47,14 +47,14 @@ export class DataStreamSource {
47
47
  if (this.eventSource.closed()) {
48
48
  throw new Error('Cannot send data to a closed DataStreamSource connection.');
49
49
  }
50
- if (this.#options.delta && isDefined(this.#lastData)) {
50
+ if (this.#useDelta && isDefined(this.#lastData)) {
51
51
  const delta = jsonDiffPatch.diff(this.#lastData, data);
52
52
  await this.eventSource.sendJson({ name: 'delta', data: delta });
53
53
  }
54
54
  else {
55
55
  await this.eventSource.sendJson({ name: 'data', data });
56
56
  }
57
- if (this.#options.delta) {
57
+ if (this.#useDelta) {
58
58
  this.#lastData = data;
59
59
  }
60
60
  }