@tstdl/base 0.93.181 → 0.93.183

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 (353) hide show
  1. package/api/server/api-request-token.provider.js +1 -1
  2. package/api/server/gateway.js +8 -3
  3. package/authentication/authentication.api.d.ts +13 -40
  4. package/authentication/authentication.api.js +5 -14
  5. package/authentication/client/authentication.service.d.ts +6 -14
  6. package/authentication/client/authentication.service.js +22 -4
  7. package/authentication/client/module.d.ts +1 -1
  8. package/authentication/client/module.js +4 -4
  9. package/authentication/models/index.d.ts +1 -0
  10. package/authentication/models/index.js +1 -0
  11. package/authentication/models/totp-results.model.d.ts +11 -0
  12. package/authentication/models/totp-results.model.js +37 -0
  13. package/authentication/server/authentication.api-controller.d.ts +3 -3
  14. package/authentication/server/authentication.api-controller.js +31 -4
  15. package/authentication/server/authentication.service.d.ts +5 -14
  16. package/authentication/server/authentication.service.js +6 -4
  17. package/core.d.ts +0 -5
  18. package/core.js +0 -8
  19. package/document-management/api/document-management.api.d.ts +2 -2
  20. package/document-management/service-models/document.service-model.d.ts +1 -1
  21. package/examples/config.d.ts +25 -0
  22. package/examples/config.js +26 -0
  23. package/notification/server/module.d.ts +1 -1
  24. package/notification/server/module.js +1 -1
  25. package/package.json +5 -5
  26. package/signals/api.d.ts +5 -1
  27. package/signals/api.js +3 -1
  28. package/signals/implementation/api.d.ts +13 -5
  29. package/signals/implementation/api.js +7 -1
  30. package/signals/implementation/asserts.d.ts +2 -2
  31. package/signals/implementation/asserts.js +3 -3
  32. package/signals/implementation/computed.d.ts +7 -34
  33. package/signals/implementation/computed.js +14 -83
  34. package/signals/implementation/configure.js +6 -2
  35. package/signals/implementation/effect.d.ts +65 -46
  36. package/signals/implementation/effect.js +97 -62
  37. package/signals/implementation/index.d.ts +2 -4
  38. package/signals/implementation/index.js +2 -4
  39. package/signals/implementation/linked_signal.d.ts +36 -0
  40. package/signals/implementation/linked_signal.js +34 -0
  41. package/signals/implementation/primitive/computed.d.ts +55 -0
  42. package/signals/implementation/primitive/computed.js +107 -0
  43. package/signals/implementation/primitive/effect.d.ts +26 -0
  44. package/signals/implementation/primitive/effect.js +31 -0
  45. package/signals/implementation/{equality.d.ts → primitive/equality.d.ts} +1 -1
  46. package/signals/implementation/{equality.js → primitive/equality.js} +1 -1
  47. package/signals/implementation/primitive/errors.d.ts +10 -0
  48. package/signals/implementation/{errors.js → primitive/errors.js} +3 -4
  49. package/signals/implementation/primitive/formatter.d.ts +19 -0
  50. package/signals/implementation/primitive/formatter.js +136 -0
  51. package/signals/implementation/{graph.d.ts → primitive/graph.d.ts} +68 -36
  52. package/signals/implementation/primitive/graph.js +386 -0
  53. package/signals/implementation/primitive/linked_signal.d.ts +46 -0
  54. package/signals/implementation/primitive/linked_signal.js +110 -0
  55. package/signals/implementation/primitive/signal.d.ts +31 -0
  56. package/signals/implementation/primitive/signal.js +80 -0
  57. package/signals/implementation/primitive/untracked.d.ts +12 -0
  58. package/signals/implementation/primitive/untracked.js +23 -0
  59. package/signals/implementation/{watch.d.ts → primitive/watch.d.ts} +1 -2
  60. package/signals/implementation/{watch.js → primitive/watch.js} +22 -16
  61. package/signals/implementation/resource/api.d.ts +275 -0
  62. package/signals/implementation/resource/api.js +26 -0
  63. package/signals/implementation/resource/debounce.d.ts +13 -0
  64. package/signals/implementation/resource/debounce.js +113 -0
  65. package/signals/implementation/resource/from_snapshots.d.ts +16 -0
  66. package/signals/implementation/resource/from_snapshots.js +44 -0
  67. package/signals/implementation/resource/index.d.ts +11 -0
  68. package/signals/implementation/resource/index.js +11 -0
  69. package/signals/implementation/resource/resource.d.ts +110 -0
  70. package/signals/implementation/resource/resource.js +402 -0
  71. package/signals/implementation/root_effect_scheduler.d.ts +50 -0
  72. package/signals/implementation/root_effect_scheduler.js +66 -0
  73. package/signals/implementation/signal.d.ts +42 -18
  74. package/signals/implementation/signal.js +29 -49
  75. package/signals/implementation/to-observable.d.ts +12 -5
  76. package/signals/implementation/to-observable.js +12 -2
  77. package/signals/implementation/to-signal.d.ts +9 -18
  78. package/signals/implementation/to-signal.js +46 -13
  79. package/signals/implementation/untracked.d.ts +1 -1
  80. package/signals/implementation/untracked.js +3 -11
  81. package/signals/operators/debounce.d.ts +8 -0
  82. package/signals/operators/debounce.js +19 -0
  83. package/signals/operators/derive-async.js +43 -15
  84. package/signals/operators/index.d.ts +2 -0
  85. package/signals/operators/index.js +2 -0
  86. package/signals/operators/throttle.d.ts +8 -0
  87. package/signals/operators/throttle.js +31 -0
  88. package/ai/genkit/tests/multi-region.test.d.ts +0 -2
  89. package/ai/genkit/tests/multi-region.test.js +0 -179
  90. package/ai/genkit/tests/token-limit-fallback.test.d.ts +0 -2
  91. package/ai/genkit/tests/token-limit-fallback.test.js +0 -209
  92. package/ai/prompts/tests/prompt-builder.test.d.ts +0 -1
  93. package/ai/prompts/tests/prompt-builder.test.js +0 -22
  94. package/ai/tests/instructions-formatter.test.d.ts +0 -1
  95. package/ai/tests/instructions-formatter.test.js +0 -116
  96. package/ai/tests/steering.test.d.ts +0 -1
  97. package/ai/tests/steering.test.js +0 -37
  98. package/api/client/tests/api-client.test.d.ts +0 -1
  99. package/api/client/tests/api-client.test.js +0 -194
  100. package/api/server/tests/csrf.middleware.test.d.ts +0 -1
  101. package/api/server/tests/csrf.middleware.test.js +0 -91
  102. package/authentication/tests/authentication-password-requirements.validator.test.d.ts +0 -1
  103. package/authentication/tests/authentication-password-requirements.validator.test.js +0 -29
  104. package/authentication/tests/authentication.api-controller.test.d.ts +0 -1
  105. package/authentication/tests/authentication.api-controller.test.js +0 -156
  106. package/authentication/tests/authentication.api-request-token.provider.test.d.ts +0 -1
  107. package/authentication/tests/authentication.api-request-token.provider.test.js +0 -48
  108. package/authentication/tests/authentication.client-error-handling.test.d.ts +0 -1
  109. package/authentication/tests/authentication.client-error-handling.test.js +0 -123
  110. package/authentication/tests/authentication.client-middleware.test.d.ts +0 -1
  111. package/authentication/tests/authentication.client-middleware.test.js +0 -118
  112. package/authentication/tests/authentication.client-service-methods.test.d.ts +0 -1
  113. package/authentication/tests/authentication.client-service-methods.test.js +0 -177
  114. package/authentication/tests/authentication.client-service-refresh.test.d.ts +0 -1
  115. package/authentication/tests/authentication.client-service-refresh.test.js +0 -153
  116. package/authentication/tests/authentication.client-service.test.d.ts +0 -1
  117. package/authentication/tests/authentication.client-service.test.js +0 -76
  118. package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +0 -1
  119. package/authentication/tests/authentication.refresh-busy-loop.test.js +0 -84
  120. package/authentication/tests/authentication.service.test.d.ts +0 -1
  121. package/authentication/tests/authentication.service.test.js +0 -167
  122. package/authentication/tests/authentication.test-ancillary-service.d.ts +0 -9
  123. package/authentication/tests/authentication.test-ancillary-service.js +0 -27
  124. package/authentication/tests/brute-force-protection.test.d.ts +0 -1
  125. package/authentication/tests/brute-force-protection.test.js +0 -211
  126. package/authentication/tests/helper.test.d.ts +0 -1
  127. package/authentication/tests/helper.test.js +0 -122
  128. package/authentication/tests/password-requirements.error.test.d.ts +0 -1
  129. package/authentication/tests/password-requirements.error.test.js +0 -14
  130. package/authentication/tests/remember.api.test.d.ts +0 -1
  131. package/authentication/tests/remember.api.test.js +0 -117
  132. package/authentication/tests/remember.service.test.d.ts +0 -1
  133. package/authentication/tests/remember.service.test.js +0 -83
  134. package/authentication/tests/subject.service.test.d.ts +0 -1
  135. package/authentication/tests/subject.service.test.js +0 -140
  136. package/authentication/tests/suspended-subject.test.d.ts +0 -1
  137. package/authentication/tests/suspended-subject.test.js +0 -120
  138. package/authentication/tests/totp.enrollment.test.d.ts +0 -1
  139. package/authentication/tests/totp.enrollment.test.js +0 -123
  140. package/authentication/tests/totp.login.test.d.ts +0 -1
  141. package/authentication/tests/totp.login.test.js +0 -213
  142. package/authentication/tests/totp.recovery-codes.test.d.ts +0 -1
  143. package/authentication/tests/totp.recovery-codes.test.js +0 -97
  144. package/authentication/tests/totp.status.test.d.ts +0 -1
  145. package/authentication/tests/totp.status.test.js +0 -72
  146. package/cancellation/tests/coverage.test.d.ts +0 -1
  147. package/cancellation/tests/coverage.test.js +0 -49
  148. package/cancellation/tests/leak.test.d.ts +0 -1
  149. package/cancellation/tests/leak.test.js +0 -35
  150. package/cancellation/tests/token.test.d.ts +0 -1
  151. package/cancellation/tests/token.test.js +0 -136
  152. package/circuit-breaker/tests/circuit-breaker.test.d.ts +0 -1
  153. package/circuit-breaker/tests/circuit-breaker.test.js +0 -116
  154. package/cryptography/tests/cryptography.test.d.ts +0 -1
  155. package/cryptography/tests/cryptography.test.js +0 -175
  156. package/cryptography/tests/jwt.test.d.ts +0 -1
  157. package/cryptography/tests/jwt.test.js +0 -54
  158. package/cryptography/tests/modern.test.d.ts +0 -1
  159. package/cryptography/tests/modern.test.js +0 -105
  160. package/cryptography/tests/module.test.d.ts +0 -1
  161. package/cryptography/tests/module.test.js +0 -100
  162. package/cryptography/tests/totp.test.d.ts +0 -1
  163. package/cryptography/tests/totp.test.js +0 -108
  164. package/document-management/tests/ai-config-hierarchy.test.d.ts +0 -1
  165. package/document-management/tests/ai-config-hierarchy.test.js +0 -59
  166. package/document-management/tests/ai-config-integration.test.d.ts +0 -1
  167. package/document-management/tests/ai-config-integration.test.js +0 -125
  168. package/document-management/tests/ai-config-merge.test.d.ts +0 -1
  169. package/document-management/tests/ai-config-merge.test.js +0 -46
  170. package/document-management/tests/document-management-ai-overrides.test.d.ts +0 -1
  171. package/document-management/tests/document-management-ai-overrides.test.js +0 -63
  172. package/document-management/tests/document-management-core.test.d.ts +0 -1
  173. package/document-management/tests/document-management-core.test.js +0 -157
  174. package/document-management/tests/document-management.api.test.d.ts +0 -1
  175. package/document-management/tests/document-management.api.test.js +0 -101
  176. package/document-management/tests/document-statistics.service.test.d.ts +0 -1
  177. package/document-management/tests/document-statistics.service.test.js +0 -498
  178. package/document-management/tests/document-validation-ai-overrides.test.d.ts +0 -1
  179. package/document-management/tests/document-validation-ai-overrides.test.js +0 -87
  180. package/document-management/tests/document.service.test.d.ts +0 -1
  181. package/document-management/tests/document.service.test.js +0 -143
  182. package/document-management/tests/enum-helpers.test.d.ts +0 -1
  183. package/document-management/tests/enum-helpers.test.js +0 -452
  184. package/document-management/tests/helper.d.ts +0 -24
  185. package/document-management/tests/helper.js +0 -39
  186. package/errors/tests/format.test.d.ts +0 -1
  187. package/errors/tests/format.test.js +0 -84
  188. package/http/tests/server-timing.test.d.ts +0 -1
  189. package/http/tests/server-timing.test.js +0 -42
  190. package/injector/tests/advanced.test.d.ts +0 -1
  191. package/injector/tests/advanced.test.js +0 -116
  192. package/injector/tests/async-init.test.d.ts +0 -1
  193. package/injector/tests/async-init.test.js +0 -77
  194. package/injector/tests/basic.test.d.ts +0 -1
  195. package/injector/tests/basic.test.js +0 -114
  196. package/injector/tests/hierarchical.test.d.ts +0 -1
  197. package/injector/tests/hierarchical.test.js +0 -59
  198. package/injector/tests/leak.test.d.ts +0 -1
  199. package/injector/tests/leak.test.js +0 -45
  200. package/injector/tests/lifecycles.test.d.ts +0 -1
  201. package/injector/tests/lifecycles.test.js +0 -109
  202. package/logger/tests/pretty-print.test.d.ts +0 -1
  203. package/logger/tests/pretty-print.test.js +0 -60
  204. package/notification/tests/notification-api.test.d.ts +0 -1
  205. package/notification/tests/notification-api.test.js +0 -124
  206. package/notification/tests/notification-client.test.d.ts +0 -1
  207. package/notification/tests/notification-client.test.js +0 -101
  208. package/notification/tests/notification-flow.test.d.ts +0 -1
  209. package/notification/tests/notification-flow.test.js +0 -296
  210. package/notification/tests/notification-sse.service.test.d.ts +0 -1
  211. package/notification/tests/notification-sse.service.test.js +0 -43
  212. package/notification/tests/notification-type.service.test.d.ts +0 -1
  213. package/notification/tests/notification-type.service.test.js +0 -41
  214. package/object-storage/s3/tests/s3.object-storage.integration.test.d.ts +0 -1
  215. package/object-storage/s3/tests/s3.object-storage.integration.test.js +0 -303
  216. package/orm/tests/build-jsonb.test.d.ts +0 -1
  217. package/orm/tests/build-jsonb.test.js +0 -39
  218. package/orm/tests/data-types.test.d.ts +0 -1
  219. package/orm/tests/data-types.test.js +0 -39
  220. package/orm/tests/database-extension.test.d.ts +0 -1
  221. package/orm/tests/database-extension.test.js +0 -63
  222. package/orm/tests/database-migration.test.d.ts +0 -1
  223. package/orm/tests/database-migration.test.js +0 -83
  224. package/orm/tests/decorators.test.d.ts +0 -1
  225. package/orm/tests/decorators.test.js +0 -77
  226. package/orm/tests/encryption.test.d.ts +0 -1
  227. package/orm/tests/encryption.test.js +0 -31
  228. package/orm/tests/query-complex.test.d.ts +0 -1
  229. package/orm/tests/query-complex.test.js +0 -172
  230. package/orm/tests/query-converter-complex.test.d.ts +0 -1
  231. package/orm/tests/query-converter-complex.test.js +0 -131
  232. package/orm/tests/query-converter.test.d.ts +0 -1
  233. package/orm/tests/query-converter.test.js +0 -123
  234. package/orm/tests/repository-advanced.test.d.ts +0 -1
  235. package/orm/tests/repository-advanced.test.js +0 -189
  236. package/orm/tests/repository-attributes.test.d.ts +0 -1
  237. package/orm/tests/repository-attributes.test.js +0 -83
  238. package/orm/tests/repository-compound-primary-key.test.d.ts +0 -2
  239. package/orm/tests/repository-compound-primary-key.test.js +0 -226
  240. package/orm/tests/repository-comprehensive.test.d.ts +0 -1
  241. package/orm/tests/repository-comprehensive.test.js +0 -162
  242. package/orm/tests/repository-coverage.test.d.ts +0 -2
  243. package/orm/tests/repository-coverage.test.js +0 -242
  244. package/orm/tests/repository-cti-complex.test.d.ts +0 -1
  245. package/orm/tests/repository-cti-complex.test.js +0 -151
  246. package/orm/tests/repository-cti-embedded.test.d.ts +0 -1
  247. package/orm/tests/repository-cti-embedded.test.js +0 -178
  248. package/orm/tests/repository-cti-extensive.test.d.ts +0 -2
  249. package/orm/tests/repository-cti-extensive.test.js +0 -279
  250. package/orm/tests/repository-cti-mapping.test.d.ts +0 -2
  251. package/orm/tests/repository-cti-mapping.test.js +0 -108
  252. package/orm/tests/repository-cti-search.test.d.ts +0 -1
  253. package/orm/tests/repository-cti-search.test.js +0 -141
  254. package/orm/tests/repository-cti-soft-delete.test.d.ts +0 -2
  255. package/orm/tests/repository-cti-soft-delete.test.js +0 -103
  256. package/orm/tests/repository-cti-transactions.test.d.ts +0 -1
  257. package/orm/tests/repository-cti-transactions.test.js +0 -112
  258. package/orm/tests/repository-cti-upsert-many.test.d.ts +0 -2
  259. package/orm/tests/repository-cti-upsert-many.test.js +0 -115
  260. package/orm/tests/repository-cti.test.d.ts +0 -2
  261. package/orm/tests/repository-cti.test.js +0 -390
  262. package/orm/tests/repository-edge-cases.test.d.ts +0 -1
  263. package/orm/tests/repository-edge-cases.test.js +0 -178
  264. package/orm/tests/repository-expiration.test.d.ts +0 -2
  265. package/orm/tests/repository-expiration.test.js +0 -140
  266. package/orm/tests/repository-extra-coverage.test.d.ts +0 -2
  267. package/orm/tests/repository-extra-coverage.test.js +0 -402
  268. package/orm/tests/repository-mapping.test.d.ts +0 -2
  269. package/orm/tests/repository-mapping.test.js +0 -65
  270. package/orm/tests/repository-regression.test.d.ts +0 -1
  271. package/orm/tests/repository-regression.test.js +0 -288
  272. package/orm/tests/repository-search-coverage.test.d.ts +0 -1
  273. package/orm/tests/repository-search-coverage.test.js +0 -107
  274. package/orm/tests/repository-search.test.d.ts +0 -1
  275. package/orm/tests/repository-search.test.js +0 -105
  276. package/orm/tests/repository-soft-delete.test.d.ts +0 -1
  277. package/orm/tests/repository-soft-delete.test.js +0 -118
  278. package/orm/tests/repository-transactions-nested.test.d.ts +0 -1
  279. package/orm/tests/repository-transactions-nested.test.js +0 -178
  280. package/orm/tests/repository-types.test.d.ts +0 -1
  281. package/orm/tests/repository-types.test.js +0 -184
  282. package/orm/tests/repository-undelete.test.d.ts +0 -2
  283. package/orm/tests/repository-undelete.test.js +0 -201
  284. package/orm/tests/schema-converter.test.d.ts +0 -1
  285. package/orm/tests/schema-converter.test.js +0 -82
  286. package/orm/tests/schema-generation.test.d.ts +0 -2
  287. package/orm/tests/schema-generation.test.js +0 -174
  288. package/orm/tests/sql-helpers.test.d.ts +0 -1
  289. package/orm/tests/sql-helpers.test.js +0 -67
  290. package/orm/tests/transaction-safety.test.d.ts +0 -1
  291. package/orm/tests/transaction-safety.test.js +0 -81
  292. package/orm/tests/transactional.test.d.ts +0 -1
  293. package/orm/tests/transactional.test.js +0 -215
  294. package/orm/tests/utils.test.d.ts +0 -1
  295. package/orm/tests/utils.test.js +0 -70
  296. package/pdf/tests/utils.test.d.ts +0 -1
  297. package/pdf/tests/utils.test.js +0 -187
  298. package/process/tests/spawn.test.d.ts +0 -1
  299. package/process/tests/spawn.test.js +0 -182
  300. package/rate-limit/tests/postgres-rate-limiter.test.d.ts +0 -1
  301. package/rate-limit/tests/postgres-rate-limiter.test.js +0 -84
  302. package/renderer/tests/renderer.test.d.ts +0 -1
  303. package/renderer/tests/renderer.test.js +0 -88
  304. package/rpc/tests/rpc.integration.test.d.ts +0 -1
  305. package/rpc/tests/rpc.integration.test.js +0 -615
  306. package/signals/implementation/errors.d.ts +0 -2
  307. package/signals/implementation/graph.js +0 -312
  308. package/signals/implementation/writable-signal.d.ts +0 -48
  309. package/signals/implementation/writable-signal.js +0 -32
  310. package/task-queue/tests/coverage-branch.test.d.ts +0 -1
  311. package/task-queue/tests/coverage-branch.test.js +0 -395
  312. package/task-queue/tests/coverage-enhancement.test.d.ts +0 -1
  313. package/task-queue/tests/coverage-enhancement.test.js +0 -150
  314. package/task-queue/tests/dag.test.d.ts +0 -1
  315. package/task-queue/tests/dag.test.js +0 -188
  316. package/task-queue/tests/dependencies.test.d.ts +0 -1
  317. package/task-queue/tests/dependencies.test.js +0 -296
  318. package/task-queue/tests/enqueue-batch.test.d.ts +0 -1
  319. package/task-queue/tests/enqueue-batch.test.js +0 -125
  320. package/task-queue/tests/enqueue-item.test.d.ts +0 -1
  321. package/task-queue/tests/enqueue-item.test.js +0 -12
  322. package/task-queue/tests/fan-out-spawning.test.d.ts +0 -1
  323. package/task-queue/tests/fan-out-spawning.test.js +0 -94
  324. package/task-queue/tests/idempotent-replacement.test.d.ts +0 -1
  325. package/task-queue/tests/idempotent-replacement.test.js +0 -114
  326. package/task-queue/tests/missing-idempotent-tasks.test.d.ts +0 -1
  327. package/task-queue/tests/missing-idempotent-tasks.test.js +0 -39
  328. package/task-queue/tests/optimization-edge-cases.test.d.ts +0 -1
  329. package/task-queue/tests/optimization-edge-cases.test.js +0 -124
  330. package/task-queue/tests/queue-generic.test.d.ts +0 -1
  331. package/task-queue/tests/queue-generic.test.js +0 -8
  332. package/task-queue/tests/queue.test.d.ts +0 -1
  333. package/task-queue/tests/queue.test.js +0 -756
  334. package/task-queue/tests/shutdown.test.d.ts +0 -1
  335. package/task-queue/tests/shutdown.test.js +0 -41
  336. package/task-queue/tests/task-context.test.d.ts +0 -1
  337. package/task-queue/tests/task-context.test.js +0 -7
  338. package/task-queue/tests/task-union.test.d.ts +0 -1
  339. package/task-queue/tests/task-union.test.js +0 -18
  340. package/task-queue/tests/transactions.test.d.ts +0 -1
  341. package/task-queue/tests/transactions.test.js +0 -47
  342. package/task-queue/tests/typing.test.d.ts +0 -1
  343. package/task-queue/tests/typing.test.js +0 -9
  344. package/task-queue/tests/worker.test.d.ts +0 -1
  345. package/task-queue/tests/worker.test.js +0 -258
  346. package/task-queue/tests/zombie-parent.test.d.ts +0 -1
  347. package/task-queue/tests/zombie-parent.test.js +0 -45
  348. package/task-queue/tests/zombie-recovery.test.d.ts +0 -1
  349. package/task-queue/tests/zombie-recovery.test.js +0 -51
  350. package/utils/tests/backoff.test.d.ts +0 -1
  351. package/utils/tests/backoff.test.js +0 -41
  352. package/utils/tests/retry-with-backoff.test.d.ts +0 -1
  353. package/utils/tests/retry-with-backoff.test.js +0 -49
@@ -1,10 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
1
8
  import { Observable } from 'rxjs';
2
- import type { SignalsInjector } from '../api.js';
3
- import type { Signal } from './api.js';
9
+ import type { Signal, SignalsInjector } from '../api.js';
4
10
  /**
5
11
  * Options for `toObservable`.
6
- *
7
- * @developerPreview
8
12
  */
9
13
  export interface ToObservableOptions {
10
14
  /**
@@ -16,8 +20,11 @@ export interface ToObservableOptions {
16
20
  injector?: SignalsInjector;
17
21
  }
18
22
  /**
19
- * Exposes the value of an `Signal` as an RxJS `Observable`.
23
+ * Exposes the value of an Angular `Signal` as an RxJS `Observable`.
24
+ * As it reflects a state, the observable will always emit the latest value upon subscription.
20
25
  *
21
26
  * The signal's value will be propagated into the `Observable`'s subscribers using an `effect`.
27
+ *
28
+ * `toObservable` must be called in an injection context unless an injector is provided via options.
22
29
  */
23
30
  export declare function toObservable<T>(source: Signal<T>, options?: ToObservableOptions): Observable<T>;
@@ -1,10 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
1
8
  import { Observable } from 'rxjs';
2
9
  import { effect } from './effect.js';
3
10
  import { untracked } from './untracked.js';
4
11
  /**
5
- * Exposes the value of an `Signal` as an RxJS `Observable`.
12
+ * Exposes the value of an Angular `Signal` as an RxJS `Observable`.
13
+ * As it reflects a state, the observable will always emit the latest value upon subscription.
6
14
  *
7
15
  * The signal's value will be propagated into the `Observable`'s subscribers using an `effect`.
16
+ *
17
+ * `toObservable` must be called in an injection context unless an injector is provided via options.
8
18
  */
9
19
  export function toObservable(source, options) {
10
20
  return new Observable((subscriber) => {
@@ -16,7 +26,7 @@ export function toObservable(source, options) {
16
26
  catch (error) {
17
27
  untracked(() => subscriber.error(error));
18
28
  }
19
- }, { allowSignalWrites: true, injector: options?.injector, manualCleanup: true });
29
+ }, { injector: options?.injector, manualCleanup: true });
20
30
  return () => effectRef.destroy();
21
31
  });
22
32
  }
@@ -1,14 +1,10 @@
1
+ /** biome-ignore-all lint: <explanation> */
2
+ import type { Observable, Subscribable } from 'rxjs';
3
+ import { type SignalsInjector } from '../api.js';
4
+ import type { Signal, ValueEqualityFn } from './api.js';
1
5
  /**
2
- * @license
3
- * Copyright Google LLC All Rights Reserved.
4
- *
5
- * Use of this source code is governed by an MIT-style license that can be
6
- * found in the LICENSE file at https://angular.io/license
6
+ * Options for `toSignal`.
7
7
  */
8
- import type { Observable, Subscribable } from 'rxjs';
9
- import type { SignalsInjector } from '../api.js';
10
- import type { Signal } from './api.js';
11
- import type { ValueEqualityFn } from './equality.js';
12
8
  export interface ToSignalOptions<T> {
13
9
  /**
14
10
  * Initial value for the signal produced by `toSignal`.
@@ -40,21 +36,16 @@ export interface ToSignalOptions<T> {
40
36
  * until the `Observable` itself completes.
41
37
  */
42
38
  manualCleanup?: boolean;
43
- /**
44
- * Whether `toSignal` should throw errors from the Observable error channel back to RxJS, where
45
- * they'll be processed as uncaught exceptions.
46
- *
47
- * In practice, this means that the signal returned by `toSignal` will keep returning the last
48
- * good value forever, as Observables which error produce no further values. This option emulates
49
- * the behavior of the `async` pipe.
50
- */
51
- rejectErrors?: boolean;
52
39
  /**
53
40
  * A comparison function which defines equality for values emitted by the observable.
54
41
  *
55
42
  * Equality comparisons are executed against the initial value if one is provided.
56
43
  */
57
44
  equal?: ValueEqualityFn<T>;
45
+ /**
46
+ * A debug name for the signal. Used in Angular DevTools to identify the signal.
47
+ */
48
+ debugName?: string;
58
49
  }
59
50
  export declare function toSignal<T>(source: Observable<T> | Subscribable<T>): Signal<T | undefined>;
60
51
  export declare function toSignal<T>(source: Observable<T> | Subscribable<T>, options: NoInfer<ToSignalOptions<T | undefined>> & {
@@ -1,9 +1,18 @@
1
1
  /* eslint-disable */
2
- import { registerFinalization } from '../../memory/finalization.js';
2
+ /** biome-ignore-all lint: <explanation> */
3
+ /**
4
+ * @license
5
+ * Copyright Google LLC All Rights Reserved.
6
+ *
7
+ * Use of this source code is governed by an MIT-style license that can be
8
+ * found in the LICENSE file at https://angular.dev/license
9
+ */
10
+ import { isDevMode } from '../../core.js';
11
+ import { defineEnum } from '../../enumeration/index.js';
12
+ import { registerFinalization } from '../../memory/index.js';
13
+ import { signal } from '../api.js';
3
14
  import { assertNotInReactiveContext } from './asserts.js';
4
15
  import { computed } from './computed.js';
5
- import { signal } from './writable-signal.js';
6
- import { defineEnum } from '../../enumeration/enumeration.js';
7
16
  /**
8
17
  * Get the current value of an `Observable` as a reactive `Signal`.
9
18
  *
@@ -15,22 +24,36 @@ import { defineEnum } from '../../enumeration/enumeration.js';
15
24
  * With `requireSync` set to `true`, `toSignal` will assert that the `Observable` produces a value
16
25
  * immediately upon subscription. No `initialValue` is needed in this case, and the returned signal
17
26
  * does not include an `undefined` type.
27
+ *
28
+ * By default, the subscription will be automatically cleaned up when the current [injection
29
+ * context](guide/di/dependency-injection-context) is destroyed. For example, when `toSignal` is
30
+ * called during the construction of a component, the subscription will be cleaned up when the
31
+ * component is destroyed. If an injection context is not available, an explicit `Injector` can be
32
+ * passed instead.
33
+ *
34
+ * If the subscription should persist until the `Observable` itself completes, the `manualCleanup`
35
+ * option can be specified instead, which disables the automatic subscription teardown. No injection
36
+ * context is needed in this configuration as well.
37
+ *
38
+ * @see [RxJS interop with Angular signals](ecosystem/rxjs-interop)
18
39
  */
19
40
  export function toSignal(source, options) {
20
- assertNotInReactiveContext(toSignal, 'Invoking `toSignal` causes new subscriptions every time. ' +
21
- 'Consider moving `toSignal` outside of the reactive context and read the signal value where needed.');
41
+ isDevMode() &&
42
+ assertNotInReactiveContext(toSignal, 'Invoking `toSignal` causes new subscriptions every time. ' +
43
+ 'Consider moving `toSignal` outside of the reactive context and read the signal value where needed.');
22
44
  const equal = makeToSignalEqual(options?.equal);
23
45
  // Note: T is the Observable value type, and U is the initial value type. They don't have to be
24
46
  // the same - the returned signal gives values of type `T`.
25
47
  let state;
26
48
  if (options?.requireSync) {
27
49
  // Initially the signal is in a `NoValue` state.
28
- state = signal({ kind: StateKind.NoValue }, { equal });
50
+ state = signal({ kind: StateKind.NoValue }, { equal, ...(isDevMode() ? createDebugNameObject(options?.debugName, 'state') : undefined) });
29
51
  }
30
52
  else {
31
53
  // If an initial value was passed, use it. Otherwise, use `undefined` as the initial value.
32
- state = signal({ kind: StateKind.Value, value: options?.initialValue }, { equal });
54
+ state = signal({ kind: StateKind.Value, value: options?.initialValue }, { equal, ...(isDevMode() ? createDebugNameObject(options?.debugName, 'state') : undefined) });
33
55
  }
56
+ let destroyUnregisterFn;
34
57
  // Note: This code cannot run inside a reactive context (see assertion above). If we'd support
35
58
  // this, we would subscribe to the observable outside of the current reactive context, avoiding
36
59
  // that side-effect signal reads/writes are attribute to the current consumer. The current
@@ -40,12 +63,11 @@ export function toSignal(source, options) {
40
63
  const sub = source.subscribe({
41
64
  next: (value) => state.set({ kind: StateKind.Value, value }),
42
65
  error: (error) => {
43
- if (options?.rejectErrors) {
44
- // Kick the error back to RxJS. It will be caught and rethrown in a macrotask, which causes
45
- // the error to end up as an uncaught exception.
46
- throw error;
47
- }
48
66
  state.set({ kind: StateKind.Error, error });
67
+ destroyUnregisterFn?.();
68
+ },
69
+ complete: () => {
70
+ destroyUnregisterFn?.();
49
71
  },
50
72
  // Completion of the Observable is meaningless to the signal. Signals don't have a concept of
51
73
  // "complete".
@@ -66,13 +88,24 @@ export function toSignal(source, options) {
66
88
  // This shouldn't really happen because the error is thrown on creation.
67
89
  throw new Error('`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.');
68
90
  }
69
- }, { equal: options?.equal });
91
+ }, {
92
+ equal: options?.equal,
93
+ ...(isDevMode() ? createDebugNameObject(options?.debugName, 'source') : undefined),
94
+ });
70
95
  registerFinalization(result, () => sub.unsubscribe());
71
96
  return result;
72
97
  }
73
98
  function makeToSignalEqual(userEquality = Object.is) {
74
99
  return (a, b) => a.kind === StateKind.Value && b.kind === StateKind.Value && userEquality(a.value, b.value);
75
100
  }
101
+ /**
102
+ * Creates a debug name object for an internal toSignal signal.
103
+ */
104
+ function createDebugNameObject(toSignalDebugName, internalSignalDebugName) {
105
+ return {
106
+ debugName: `toSignal${toSignalDebugName ? '#' + toSignalDebugName : ''}.${internalSignalDebugName}`,
107
+ };
108
+ }
76
109
  const StateKind = defineEnum('StateKind', {
77
110
  NoValue: 0,
78
111
  Value: 1,
@@ -3,7 +3,7 @@
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  *
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
- * found in the LICENSE file at https://angular.io/license
6
+ * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
8
  /**
9
9
  * Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
@@ -3,21 +3,13 @@
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  *
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
- * found in the LICENSE file at https://angular.io/license
6
+ * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
- import { setActiveConsumer } from './graph.js';
8
+ import { untracked as untrackedPrimitive } from './primitive/untracked.js';
9
9
  /**
10
10
  * Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
11
11
  * can, optionally, return a value.
12
12
  */
13
13
  export function untracked(nonReactiveReadsFn) {
14
- const prevConsumer = setActiveConsumer(null);
15
- // We are not trying to catch any particular errors here, just making sure that the consumers
16
- // stack is restored in case of errors.
17
- try {
18
- return nonReactiveReadsFn();
19
- }
20
- finally {
21
- setActiveConsumer(prevConsumer);
22
- }
14
+ return untrackedPrimitive(nonReactiveReadsFn);
23
15
  }
@@ -0,0 +1,8 @@
1
+ import { type Signal } from '../api.js';
2
+ /**
3
+ * Creates a signal that debounces the value of the source signal.
4
+ * @param source The source signal.
5
+ * @param ms The debounce time in milliseconds.
6
+ * @returns A signal that debounces the source signal.
7
+ */
8
+ export declare function debounce<T>(source: Signal<T>, ms: number): Signal<T>;
@@ -0,0 +1,19 @@
1
+ import { registerFinalization } from '../../memory/finalization.js';
2
+ import { effect, signal, untracked } from '../api.js';
3
+ /**
4
+ * Creates a signal that debounces the value of the source signal.
5
+ * @param source The source signal.
6
+ * @param ms The debounce time in milliseconds.
7
+ * @returns A signal that debounces the source signal.
8
+ */
9
+ export function debounce(source, ms) {
10
+ const debouncedSignal = signal(untracked(source));
11
+ const effectRef = effect((onCleanup) => {
12
+ const value = source();
13
+ const timeout = setTimeout(() => debouncedSignal.set(value), ms);
14
+ onCleanup(() => clearTimeout(timeout));
15
+ });
16
+ const result = debouncedSignal.asReadonly();
17
+ registerFinalization(result, () => effectRef.destroy());
18
+ return result;
19
+ }
@@ -1,4 +1,4 @@
1
- import { Subject, concatAll, exhaustAll, from, isObservable, mergeAll, of, switchAll, takeUntil } from 'rxjs';
1
+ import { BehaviorSubject, Subject, concatAll, exhaustAll, filter, from, isObservable, map, materialize, mergeAll, of, switchAll, takeUntil } from 'rxjs';
2
2
  import { registerFinalization } from '../../memory/finalization.js';
3
3
  import { isPromise } from '../../utils/type-guards.js';
4
4
  import { computed, effect, toSignal, untracked } from '../api.js';
@@ -8,28 +8,56 @@ const operatorMap = {
8
8
  exhaust: exhaustAll,
9
9
  switch: switchAll,
10
10
  };
11
+ /**
12
+ * Derives a signal from an asynchronous source (Promise or Observable).
13
+ *
14
+ * @param source A function that returns a value, a Promise, or an Observable.
15
+ * @param options Options for the signal and the async behavior.
16
+ *
17
+ * @warning If `requireSync: true` is used, the source MUST emit synchronously.
18
+ * Since Promises are always resolved asynchronously (on the microtask queue),
19
+ * they will ALWAYS throw an error if used with `requireSync: true`.
20
+ *
21
+ * @returns A Signal that represents the latest value from the async source.
22
+ */
11
23
  export function deriveAsync(source, options) {
12
- const outerSource = computed(() => {
13
- const rawSource = source();
14
- if (isPromise(rawSource)) {
15
- return from(rawSource);
16
- }
17
- if (isObservable(rawSource)) {
18
- return rawSource;
19
- }
20
- return of(rawSource);
21
- });
22
- const source$ = new Subject();
24
+ const initialRaw = untracked(source);
25
+ const initialSource = isPromise(initialRaw) ? from(initialRaw) : isObservable(initialRaw) ? initialRaw : of(initialRaw);
26
+ const source$ = new BehaviorSubject(initialSource);
23
27
  const destroy$ = new Subject();
24
28
  const operator = operatorMap[options?.behavior ?? 'switch'];
25
- const valueSource$ = source$.pipe(operator(), takeUntil(destroy$));
26
- const result = toSignal(valueSource$, options);
29
+ const valueSource$ = source$.pipe(map((inner$) => inner$.pipe(materialize(), filter((n) => n.kind != 'C'))), operator(), takeUntil(destroy$));
30
+ const notificationSignal = toSignal(valueSource$, {
31
+ requireSync: options?.requireSync,
32
+ injector: options?.injector,
33
+ manualCleanup: options?.manualCleanup,
34
+ debugName: options?.debugName ? `${options.debugName}-notifications` : undefined,
35
+ initialValue: undefined,
36
+ });
37
+ const result = computed(() => {
38
+ const notification = notificationSignal();
39
+ if (notification === undefined) {
40
+ return options?.initialValue;
41
+ }
42
+ if (notification.kind === 'E') {
43
+ throw notification.error;
44
+ }
45
+ return notification.value;
46
+ }, { equal: options?.equal });
47
+ let firstRun = true;
27
48
  const effectRef = effect(() => {
28
- const observableInput = outerSource();
49
+ const rawSource = source();
50
+ if (firstRun) {
51
+ firstRun = false;
52
+ return;
53
+ }
54
+ const observableInput = isPromise(rawSource) ? from(rawSource) : isObservable(rawSource) ? rawSource : of(rawSource);
29
55
  untracked(() => source$.next(observableInput));
30
56
  });
31
57
  registerFinalization(result, () => {
32
58
  destroy$.next();
59
+ destroy$.complete();
60
+ source$.complete();
33
61
  effectRef.destroy();
34
62
  });
35
63
  return result;
@@ -1,5 +1,7 @@
1
1
  export * from './combine.js';
2
+ export * from './debounce.js';
2
3
  export * from './defer.js';
3
4
  export * from './derive-async.js';
4
5
  export * from './map.js';
5
6
  export * from './switchAll.js';
7
+ export * from './throttle.js';
@@ -1,5 +1,7 @@
1
1
  export * from './combine.js';
2
+ export * from './debounce.js';
2
3
  export * from './defer.js';
3
4
  export * from './derive-async.js';
4
5
  export * from './map.js';
5
6
  export * from './switchAll.js';
7
+ export * from './throttle.js';
@@ -0,0 +1,8 @@
1
+ import { type Signal } from '../api.js';
2
+ /**
3
+ * Creates a signal that throttles the value of the source signal.
4
+ * @param source The source signal.
5
+ * @param ms The throttle time in milliseconds.
6
+ * @returns A signal that throttles the source signal.
7
+ */
8
+ export declare function throttle<T>(source: Signal<T>, ms: number): Signal<T>;
@@ -0,0 +1,31 @@
1
+ import { registerFinalization } from '../../memory/finalization.js';
2
+ import { effect, signal, untracked } from '../api.js';
3
+ /**
4
+ * Creates a signal that throttles the value of the source signal.
5
+ * @param source The source signal.
6
+ * @param ms The throttle time in milliseconds.
7
+ * @returns A signal that throttles the source signal.
8
+ */
9
+ export function throttle(source, ms) {
10
+ const throttledSignal = signal(untracked(source));
11
+ let lastUpdate = 0;
12
+ const effectRef = effect((onCleanup) => {
13
+ const value = source();
14
+ const now = Date.now();
15
+ const remaining = ms - (now - lastUpdate);
16
+ if (remaining <= 0) {
17
+ lastUpdate = now;
18
+ throttledSignal.set(value);
19
+ }
20
+ else {
21
+ const timeout = setTimeout(() => {
22
+ lastUpdate = Date.now();
23
+ throttledSignal.set(value);
24
+ }, remaining);
25
+ onCleanup(() => clearTimeout(timeout));
26
+ }
27
+ });
28
+ const result = throttledSignal.asReadonly();
29
+ registerFinalization(result, () => effectRef.destroy());
30
+ return result;
31
+ }
@@ -1,2 +0,0 @@
1
- /** biome-ignore-all lint/suspicious/useAwait: defineModel requires async */
2
- export {};
@@ -1,179 +0,0 @@
1
- /** biome-ignore-all lint/suspicious/useAwait: defineModel requires async */
2
- import { genkit, GenkitError, z } from 'genkit';
3
- import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
4
- import { CircuitBreakerState } from '../../../circuit-breaker/index.js';
5
- import { CircuitBreakerProvider } from '../../../circuit-breaker/provider.js';
6
- import { Logger } from '../../../logger/logger.js';
7
- import { setupIntegrationTest } from '../../../testing/index.js';
8
- import { vertexAiMultiLocation } from '../multi-region.plugin.js';
9
- vi.mock('../../../utils/array/index.js', async (importOriginal) => {
10
- const actual = await importOriginal();
11
- return {
12
- ...actual,
13
- shuffle: vi.fn((items) => [...items]),
14
- };
15
- });
16
- vi.mock('@genkit-ai/google-genai', () => ({
17
- // biome-ignore lint/style/useNamingConvention: given
18
- vertexAI: {
19
- model: vi.fn((name) => ({
20
- name: `vertexai/${name}`,
21
- info: { label: 'mock' },
22
- configSchema: z.object({}),
23
- })),
24
- },
25
- // biome-ignore lint/style/useNamingConvention: given
26
- googleAI: vi.fn(),
27
- }));
28
- describe('Genkit vertexai-multi-location Plugin Tests', () => {
29
- let ai;
30
- let cbProvider;
31
- let logger;
32
- beforeAll(async () => {
33
- const { injector } = await setupIntegrationTest({ modules: { circuitBreaker: true } });
34
- cbProvider = injector.resolve(CircuitBreakerProvider);
35
- logger = injector.resolve(Logger, 'Test');
36
- });
37
- beforeEach(async () => {
38
- vi.clearAllMocks();
39
- ai = genkit({
40
- plugins: [
41
- vertexAiMultiLocation({
42
- locations: ['region-1', 'region-2'],
43
- circuitBreakerProvider: cbProvider,
44
- logger,
45
- circuitBreakerConfig: { resetTimeout: 1_000_000, threshold: 1 },
46
- }),
47
- ],
48
- });
49
- const config = { threshold: 1, resetTimeout: 1_000_000 };
50
- await cbProvider.provide('genkit:vertex-ai:location:region-1', config).recordSuccess();
51
- await cbProvider.provide('genkit:vertex-ai:location:region-2', config).recordSuccess();
52
- await cbProvider.provide('genkit:vertex-ai:location:cb-fail', config).recordSuccess();
53
- await cbProvider.provide('genkit:vertex-ai:location:cb-success', config).recordSuccess();
54
- });
55
- it('should route to a location successfully', async () => {
56
- // Register a mock for the regional model in the registry
57
- ai.defineModel({
58
- name: 'vertexai/gemini-2.5-flash',
59
- }, async (request) => {
60
- return {
61
- message: {
62
- role: 'model',
63
- content: [{ text: `hello from ${request.config?.location}` }],
64
- },
65
- };
66
- });
67
- const response = await ai.generate({
68
- model: 'vertexai-multi-location/gemini-2.5-flash',
69
- prompt: 'test',
70
- });
71
- expect(response.text).toContain('hello from');
72
- });
73
- it('should failover on 429 error', async () => {
74
- let callCount = 0;
75
- // Overwrite the mock model to fail once
76
- ai.defineModel({
77
- name: 'vertexai/gemini-2.5-flash',
78
- }, async (request) => {
79
- callCount++;
80
- if (callCount === 1) {
81
- throw new GenkitError({ status: 'RESOURCE_EXHAUSTED', message: 'Rate limit exceeded' });
82
- }
83
- return {
84
- message: {
85
- role: 'model',
86
- content: [{ text: `success from ${request.config?.location}` }],
87
- },
88
- };
89
- });
90
- const response = await ai.generate({
91
- model: 'vertexai-multi-location/gemini-2.5-flash',
92
- prompt: 'test',
93
- });
94
- expect(response.text).toContain('success from');
95
- expect(callCount).toBe(2);
96
- });
97
- it('should trip circuit breaker on 429 and skip location', async () => {
98
- const locationToFail = 'cb-fail';
99
- const locationToSuccess = 'cb-success';
100
- const locations = [locationToFail, locationToSuccess];
101
- ai = genkit({
102
- plugins: [
103
- vertexAiMultiLocation({
104
- locations,
105
- circuitBreakerProvider: cbProvider,
106
- logger,
107
- circuitBreakerConfig: { resetTimeout: 1000000, threshold: 1 },
108
- }),
109
- ],
110
- });
111
- ai.defineModel({
112
- name: 'vertexai/gemini-2.5-flash',
113
- }, async (request) => {
114
- if (request.config?.location === locationToFail) {
115
- throw new GenkitError({ status: 'RESOURCE_EXHAUSTED', message: 'Rate limit' });
116
- }
117
- return {
118
- message: {
119
- role: 'model',
120
- content: [{ text: `success from ${request.config?.location}` }],
121
- },
122
- };
123
- });
124
- // First call to trip the breaker for 'locationToFail'
125
- const response1 = await ai.generate({
126
- model: 'vertexai-multi-location/gemini-2.5-flash',
127
- prompt: 'test',
128
- });
129
- expect(response1.text).toBe('success from cb-success');
130
- const cb = cbProvider.provide(`genkit:vertex-ai:location:${locationToFail}`, { threshold: 1, resetTimeout: 1000000 });
131
- const status = await cb.check();
132
- expect(status.state).toBe(CircuitBreakerState.Open);
133
- expect(status.allowed).toBe(false);
134
- // Second call should skip 'locationToFail' automatically
135
- const response2 = await ai.generate({
136
- model: 'vertexai-multi-location/gemini-2.5-flash',
137
- prompt: 'test',
138
- });
139
- expect(response2.text).toBe('success from cb-success');
140
- });
141
- it('should throw if no locations are provided', async () => {
142
- expect(() => {
143
- vertexAiMultiLocation({
144
- locations: [],
145
- circuitBreakerProvider: cbProvider,
146
- logger,
147
- });
148
- }).toThrow('At least one location must be provided');
149
- });
150
- it('should throw if all locations are unhealthy', async () => {
151
- const ai2 = genkit({
152
- plugins: [
153
- vertexAiMultiLocation({
154
- locations: ['unhealthy-1'],
155
- circuitBreakerProvider: cbProvider,
156
- logger,
157
- circuitBreakerConfig: { resetTimeout: 1000000, threshold: 1 },
158
- }),
159
- ],
160
- });
161
- // Manually trip the circuit breaker
162
- const cb = cbProvider.provide('genkit:vertex-ai:location:unhealthy-1', { threshold: 1, resetTimeout: 1000000 });
163
- await cb.recordFailure();
164
- ai2.defineModel({
165
- name: 'vertexai/gemini-2.5-flash',
166
- }, async () => {
167
- return {
168
- message: {
169
- role: 'model',
170
- content: [{ text: 'success' }],
171
- },
172
- };
173
- });
174
- await expect(ai2.generate({
175
- model: 'vertexai-multi-location/gemini-2.5-flash',
176
- prompt: 'test',
177
- })).rejects.toThrow('All locations were skipped because they are unhealthy');
178
- });
179
- });
@@ -1,2 +0,0 @@
1
- /** biome-ignore-all lint/suspicious/useAwait: defineModel requires async */
2
- export {};