@tstdl/base 0.92.167 → 0.93.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 (317) hide show
  1. package/application/application.d.ts +12 -18
  2. package/application/application.js +48 -69
  3. package/application/index.d.ts +1 -5
  4. package/application/index.js +1 -5
  5. package/application/providers.d.ts +10 -0
  6. package/application/providers.js +54 -0
  7. package/audit/audit.model.d.ts +15 -0
  8. package/audit/audit.model.js +73 -0
  9. package/audit/auditor.d.ts +42 -0
  10. package/audit/auditor.js +111 -0
  11. package/audit/index.d.ts +3 -0
  12. package/audit/index.js +3 -0
  13. package/audit/types.d.ts +22 -0
  14. package/audit/types.js +19 -0
  15. package/authentication/client/authentication.service.d.ts +1 -3
  16. package/authentication/client/authentication.service.js +4 -5
  17. package/browser/browser-context-controller.d.ts +2 -4
  18. package/browser/browser-context-controller.js +5 -6
  19. package/browser/browser-controller.d.ts +2 -4
  20. package/browser/browser-controller.js +3 -4
  21. package/browser/browser.service.d.ts +1 -3
  22. package/browser/browser.service.js +1 -2
  23. package/browser/page-controller.d.ts +2 -4
  24. package/browser/page-controller.js +7 -8
  25. package/browser/utils.js +3 -3
  26. package/cancellation/token.d.ts +104 -41
  27. package/cancellation/token.js +125 -54
  28. package/core.d.ts +1 -13
  29. package/core.js +1 -46
  30. package/disposable/disposable.d.ts +0 -8
  31. package/disposable/disposable.js +1 -3
  32. package/disposable/index.d.ts +0 -6
  33. package/disposable/index.js +0 -6
  34. package/disposable/using.d.ts +0 -1
  35. package/disposable/using.js +2 -3
  36. package/distributed-loop/distributed-loop.js +2 -2
  37. package/errors/utils.js +4 -1
  38. package/examples/api/authentication.js +11 -5
  39. package/examples/api/basic-overview.js +17 -12
  40. package/examples/api/custom-authentication.js +13 -7
  41. package/examples/api/streaming.js +15 -12
  42. package/examples/browser/basic.js +6 -3
  43. package/examples/document-management/main.js +6 -3
  44. package/examples/http/client.js +7 -3
  45. package/examples/mail/basic.js +9 -7
  46. package/examples/pdf/basic.js +8 -6
  47. package/examples/template/basic.js +7 -5
  48. package/http/client/http-client-request.d.ts +1 -2
  49. package/http/client/http-client-request.js +1 -2
  50. package/http/server/http-server.d.ts +1 -3
  51. package/http/server/http-server.js +0 -1
  52. package/http/server/node/node-http-server.d.ts +1 -2
  53. package/http/server/node/node-http-server.js +1 -2
  54. package/import.js +1 -1
  55. package/injector/injector.d.ts +1 -1
  56. package/injector/types.d.ts +3 -4
  57. package/lock/lock.d.ts +40 -21
  58. package/lock/lock.js +74 -1
  59. package/lock/postgres/drizzle/0000_busy_tattoo.sql +7 -0
  60. package/lock/postgres/drizzle/meta/0000_snapshot.json +65 -0
  61. package/lock/postgres/drizzle/meta/_journal.json +13 -0
  62. package/lock/postgres/drizzle.config.js +11 -0
  63. package/lock/postgres/index.d.ts +2 -0
  64. package/lock/postgres/index.js +2 -0
  65. package/lock/postgres/lock.d.ts +14 -0
  66. package/lock/postgres/lock.js +127 -0
  67. package/lock/postgres/models/index.d.ts +2 -0
  68. package/lock/postgres/models/index.js +2 -0
  69. package/lock/postgres/models/lock.model.d.ts +7 -0
  70. package/{examples/orm/user.model.js → lock/postgres/models/lock.model.js} +22 -30
  71. package/lock/postgres/models/schemas.d.ts +3 -0
  72. package/lock/postgres/models/schemas.js +4 -0
  73. package/lock/postgres/module.d.ts +6 -0
  74. package/lock/postgres/module.js +26 -0
  75. package/lock/postgres/provider.d.ts +6 -0
  76. package/lock/postgres/provider.js +29 -0
  77. package/lock/provider.d.ts +12 -2
  78. package/lock/provider.js +24 -1
  79. package/lock/web/web-lock.d.ts +4 -3
  80. package/lock/web/web-lock.js +49 -42
  81. package/lock/web/web-lock.provider.d.ts +0 -3
  82. package/lock/web/web-lock.provider.js +5 -22
  83. package/logger/formatter.d.ts +13 -0
  84. package/logger/formatter.js +3 -0
  85. package/logger/formatters/index.d.ts +2 -0
  86. package/logger/formatters/index.js +2 -0
  87. package/logger/formatters/json.d.ts +5 -0
  88. package/logger/formatters/json.js +33 -0
  89. package/logger/formatters/pretty-print.d.ts +5 -0
  90. package/logger/formatters/pretty-print.js +55 -0
  91. package/logger/index.d.ts +5 -2
  92. package/logger/index.js +5 -2
  93. package/logger/level.d.ts +10 -8
  94. package/logger/level.js +9 -9
  95. package/logger/logger.d.ts +21 -30
  96. package/logger/logger.js +98 -26
  97. package/logger/manager.d.ts +20 -0
  98. package/logger/manager.js +86 -0
  99. package/logger/tokens.d.ts +1 -1
  100. package/logger/tokens.js +1 -1
  101. package/logger/transport.d.ts +14 -0
  102. package/logger/transport.js +16 -0
  103. package/logger/transports/console.d.ts +14 -0
  104. package/logger/transports/console.js +36 -0
  105. package/logger/transports/index.d.ts +1 -0
  106. package/logger/transports/index.js +1 -0
  107. package/mail/clients/nodemailer.mail-client.d.ts +0 -1
  108. package/mail/clients/nodemailer.mail-client.js +9 -7
  109. package/message-bus/local/local-message-bus.js +2 -2
  110. package/message-bus/message-bus-base.d.ts +2 -3
  111. package/message-bus/message-bus-base.js +5 -6
  112. package/message-bus/message-bus.d.ts +1 -2
  113. package/message-bus/message-bus.js +1 -2
  114. package/module/index.d.ts +0 -2
  115. package/module/index.js +0 -2
  116. package/module/module.d.ts +17 -18
  117. package/module/module.js +47 -12
  118. package/module/modules/function.module.d.ts +6 -6
  119. package/module/modules/function.module.js +25 -9
  120. package/module/modules/web-server.module.d.ts +2 -10
  121. package/module/modules/web-server.module.js +3 -11
  122. package/openid-connect/index.d.ts +0 -2
  123. package/openid-connect/index.js +0 -2
  124. package/openid-connect/oidc-state.model.d.ts +4 -5
  125. package/openid-connect/oidc-state.model.js +51 -1
  126. package/openid-connect/oidc.service-model.d.ts +1 -1
  127. package/openid-connect/oidc.service.d.ts +2 -6
  128. package/openid-connect/oidc.service.js +24 -37
  129. package/orm/decorators.d.ts +10 -1
  130. package/orm/decorators.js +8 -0
  131. package/orm/server/repository.d.ts +3 -1
  132. package/orm/server/repository.js +32 -3
  133. package/package.json +19 -29
  134. package/pdf/pdf.service.js +9 -9
  135. package/pool/pool.d.ts +1 -3
  136. package/pool/pool.js +3 -4
  137. package/queue/postgres/job.model.d.ts +1 -2
  138. package/queue/postgres/job.model.js +1 -2
  139. package/queue/postgres/module.js +1 -1
  140. package/threading/thread-pool.d.ts +1 -3
  141. package/threading/thread-pool.js +7 -8
  142. package/utils/format-error.d.ts +7 -0
  143. package/utils/format-error.js +59 -17
  144. package/utils/function/memoize.d.ts +22 -7
  145. package/utils/function/memoize.js +82 -23
  146. package/utils/index.d.ts +1 -0
  147. package/utils/index.js +1 -0
  148. package/utils/object/dereference.d.ts +51 -19
  149. package/utils/object/dereference.js +52 -43
  150. package/utils/timing.js +2 -2
  151. package/utils/try-chain.d.ts +22 -0
  152. package/utils/try-chain.js +46 -0
  153. package/database/entity-repository.d.ts +0 -50
  154. package/database/entity-repository.js +0 -3
  155. package/database/entity.d.ts +0 -7
  156. package/database/entity.js +0 -1
  157. package/database/id.d.ts +0 -1
  158. package/database/id.js +0 -9
  159. package/database/index.d.ts +0 -11
  160. package/database/index.js +0 -11
  161. package/database/module.d.ts +0 -8
  162. package/database/module.js +0 -11
  163. package/database/mongo/classes.d.ts +0 -21
  164. package/database/mongo/classes.js +0 -26
  165. package/database/mongo/index.d.ts +0 -15
  166. package/database/mongo/index.js +0 -15
  167. package/database/mongo/model/document.d.ts +0 -29
  168. package/database/mongo/model/document.js +0 -63
  169. package/database/mongo/model/index.d.ts +0 -1
  170. package/database/mongo/model/index.js +0 -1
  171. package/database/mongo/module.d.ts +0 -8
  172. package/database/mongo/module.js +0 -68
  173. package/database/mongo/mongo-base.repository.d.ts +0 -103
  174. package/database/mongo/mongo-base.repository.js +0 -263
  175. package/database/mongo/mongo-bulk.d.ts +0 -35
  176. package/database/mongo/mongo-bulk.js +0 -90
  177. package/database/mongo/mongo-entity-repository.d.ts +0 -98
  178. package/database/mongo/mongo-entity-repository.js +0 -278
  179. package/database/mongo/operations.d.ts +0 -10
  180. package/database/mongo/operations.js +0 -54
  181. package/database/mongo/query-converter.d.ts +0 -6
  182. package/database/mongo/query-converter.js +0 -83
  183. package/database/mongo/simple-entity-repository.d.ts +0 -7
  184. package/database/mongo/simple-entity-repository.js +0 -6
  185. package/database/mongo/types.d.ts +0 -50
  186. package/database/mongo/types.js +0 -3
  187. package/database/query.d.ts +0 -121
  188. package/database/query.js +0 -7
  189. package/database/utils.d.ts +0 -2
  190. package/database/utils.js +0 -3
  191. package/disposable/async-disposer.d.ts +0 -35
  192. package/disposable/async-disposer.js +0 -125
  193. package/examples/orm/drizzle.config.js +0 -6
  194. package/examples/orm/schemas.d.ts +0 -3
  195. package/examples/orm/schemas.js +0 -4
  196. package/examples/orm/test.d.ts +0 -1
  197. package/examples/orm/test.js +0 -11
  198. package/examples/orm/user.model.d.ts +0 -13
  199. package/key-value-store/mongo/index.d.ts +0 -6
  200. package/key-value-store/mongo/index.js +0 -6
  201. package/key-value-store/mongo/module.d.ts +0 -8
  202. package/key-value-store/mongo/module.js +0 -18
  203. package/key-value-store/mongo/mongo-key-value-store.provider.d.ts +0 -8
  204. package/key-value-store/mongo/mongo-key-value-store.provider.js +0 -26
  205. package/key-value-store/mongo/mongo-key-value.model.d.ts +0 -7
  206. package/key-value-store/mongo/mongo-key-value.model.js +0 -1
  207. package/key-value-store/mongo/mongo-key-value.repository.d.ts +0 -10
  208. package/key-value-store/mongo/mongo-key-value.repository.js +0 -31
  209. package/key-value-store/mongo/mongo-key-value.store.d.ts +0 -15
  210. package/key-value-store/mongo/mongo-key-value.store.js +0 -82
  211. package/key-value-store/mongo/tokens.d.ts +0 -3
  212. package/key-value-store/mongo/tokens.js +0 -2
  213. package/lock/mongo/index.d.ts +0 -5
  214. package/lock/mongo/index.js +0 -5
  215. package/lock/mongo/lock.d.ts +0 -14
  216. package/lock/mongo/lock.js +0 -125
  217. package/lock/mongo/model.d.ts +0 -6
  218. package/lock/mongo/model.js +0 -1
  219. package/lock/mongo/module.d.ts +0 -12
  220. package/lock/mongo/module.js +0 -20
  221. package/lock/mongo/mongo-lock-repository.d.ts +0 -14
  222. package/lock/mongo/mongo-lock-repository.js +0 -67
  223. package/lock/mongo/provider.d.ts +0 -8
  224. package/lock/mongo/provider.js +0 -36
  225. package/logger/console/index.d.ts +0 -1
  226. package/logger/console/index.js +0 -1
  227. package/logger/console/logger.d.ts +0 -11
  228. package/logger/console/logger.js +0 -64
  229. package/logger/noop/index.d.ts +0 -1
  230. package/logger/noop/index.js +0 -1
  231. package/logger/noop/logger.d.ts +0 -9
  232. package/logger/noop/logger.js +0 -21
  233. package/migration/index.d.ts +0 -9
  234. package/migration/index.js +0 -9
  235. package/migration/migration-state-repository.d.ts +0 -4
  236. package/migration/migration-state-repository.js +0 -3
  237. package/migration/migration-state.d.ts +0 -6
  238. package/migration/migration-state.js +0 -1
  239. package/migration/migrator.d.ts +0 -23
  240. package/migration/migrator.js +0 -76
  241. package/migration/mongo/index.d.ts +0 -2
  242. package/migration/mongo/index.js +0 -2
  243. package/migration/mongo/migration-state-repository.d.ts +0 -11
  244. package/migration/mongo/migration-state-repository.js +0 -32
  245. package/migration/mongo/module.d.ts +0 -12
  246. package/migration/mongo/module.js +0 -17
  247. package/module/module-base.d.ts +0 -18
  248. package/module/module-base.js +0 -40
  249. package/module/module-metric-reporter.d.ts +0 -29
  250. package/module/module-metric-reporter.js +0 -62
  251. package/openid-connect/mongo-oidc-state.repository.d.ts +0 -21
  252. package/openid-connect/mongo-oidc-state.repository.js +0 -52
  253. package/openid-connect/oidc-state.repository.d.ts +0 -4
  254. package/openid-connect/oidc-state.repository.js +0 -3
  255. package/process-shutdown.d.ts +0 -9
  256. package/process-shutdown.js +0 -65
  257. package/queue/mongo/index.d.ts +0 -4
  258. package/queue/mongo/index.js +0 -4
  259. package/queue/mongo/job.d.ts +0 -12
  260. package/queue/mongo/job.js +0 -1
  261. package/queue/mongo/mongo-job.repository.d.ts +0 -13
  262. package/queue/mongo/mongo-job.repository.js +0 -54
  263. package/queue/mongo/queue.d.ts +0 -38
  264. package/queue/mongo/queue.js +0 -266
  265. package/queue/mongo/queue.provider.d.ts +0 -18
  266. package/queue/mongo/queue.provider.js +0 -38
  267. package/search-index/elastic/config.d.ts +0 -8
  268. package/search-index/elastic/config.js +0 -26
  269. package/search-index/elastic/index.d.ts +0 -8
  270. package/search-index/elastic/index.js +0 -8
  271. package/search-index/elastic/keyword-rewriter.d.ts +0 -8
  272. package/search-index/elastic/keyword-rewriter.js +0 -18
  273. package/search-index/elastic/model/elastic-query.d.ts +0 -16
  274. package/search-index/elastic/model/elastic-query.js +0 -1
  275. package/search-index/elastic/model/index-mapping.d.ts +0 -26
  276. package/search-index/elastic/model/index-mapping.js +0 -4
  277. package/search-index/elastic/model/index.d.ts +0 -3
  278. package/search-index/elastic/model/index.js +0 -3
  279. package/search-index/elastic/model/sort.d.ts +0 -8
  280. package/search-index/elastic/model/sort.js +0 -1
  281. package/search-index/elastic/module.d.ts +0 -10
  282. package/search-index/elastic/module.js +0 -49
  283. package/search-index/elastic/query-builder/boolean-query-builder.d.ts +0 -11
  284. package/search-index/elastic/query-builder/boolean-query-builder.js +0 -52
  285. package/search-index/elastic/query-builder/index.d.ts +0 -1
  286. package/search-index/elastic/query-builder/index.js +0 -1
  287. package/search-index/elastic/query-converter.d.ts +0 -9
  288. package/search-index/elastic/query-converter.js +0 -183
  289. package/search-index/elastic/search-index.d.ts +0 -30
  290. package/search-index/elastic/search-index.js +0 -144
  291. package/search-index/elastic/sort-converter.d.ts +0 -4
  292. package/search-index/elastic/sort-converter.js +0 -14
  293. package/search-index/elastic/types.d.ts +0 -5
  294. package/search-index/elastic/types.js +0 -1
  295. package/search-index/error.d.ts +0 -10
  296. package/search-index/error.js +0 -14
  297. package/search-index/index.d.ts +0 -3
  298. package/search-index/index.js +0 -3
  299. package/search-index/memory/index.d.ts +0 -1
  300. package/search-index/memory/index.js +0 -1
  301. package/search-index/memory/memory-search-index.d.ts +0 -19
  302. package/search-index/memory/memory-search-index.js +0 -144
  303. package/search-index/search-index.d.ts +0 -46
  304. package/search-index/search-index.js +0 -31
  305. package/search-index/search-result.d.ts +0 -12
  306. package/search-index/search-result.js +0 -1
  307. package/theme/adapters/css-adapter.d.ts +0 -5
  308. package/theme/adapters/css-adapter.js +0 -29
  309. package/theme/adapters/index.d.ts +0 -2
  310. package/theme/adapters/index.js +0 -2
  311. package/theme/adapters/tailwind-adapter.d.ts +0 -18
  312. package/theme/adapters/tailwind-adapter.js +0 -32
  313. package/theme/index.d.ts +0 -1
  314. package/theme/index.js +0 -1
  315. package/theme/theme-service.d.ts +0 -43
  316. package/theme/theme-service.js +0 -128
  317. /package/{examples/orm → lock/postgres}/drizzle.config.d.ts +0 -0
@@ -1,67 +1,93 @@
1
1
  import { BehaviorSubject, defer, filter, first, firstValueFrom, from, fromEvent, isObservable, map, skip, take } from 'rxjs';
2
- import { noopOperator } from '../rxjs-utils/noop.js';
2
+ import { match, P } from 'ts-pattern';
3
+ import { registerFinalization } from '../memory/finalization.js';
3
4
  import { noop } from '../utils/noop.js';
4
5
  import { isBoolean } from '../utils/type-guards.js';
6
+ /**
7
+ * A read-only view of a CancellationToken's state.
8
+ *
9
+ * It allows consumers to subscribe to state changes, await cancellation,
10
+ * or convert to other signal types (like AbortSignal) without being able
11
+ * to change the token's state.
12
+ *
13
+ * It is both `PromiseLike<void>` (resolves when set) and `Subscribable<void>`
14
+ * (emits when set).
15
+ */
5
16
  export class CancellationSignal {
6
- #stateSubject;
17
+ _stateSubject;
7
18
  /**
8
- * Observable which emits the current state and every state change.
19
+ * Observable which emits the current state (true for set, false for unset)
20
+ * and any subsequent state changes.
9
21
  */
10
- state$ = defer(() => this.#stateSubject);
22
+ state$ = defer(() => this._stateSubject);
11
23
  /**
12
- * Observable which emits when this token is set.
24
+ * Observable which emits `void` only when the token becomes set.
13
25
  */
14
26
  set$ = this.state$.pipe(filter((state) => state), map(() => undefined));
15
27
  /**
16
- * Observable which emits when this token is unset.
28
+ * Observable which emits `void` only when the token becomes unset.
17
29
  */
18
30
  unset$ = this.state$.pipe(filter((state) => !state), map(() => undefined));
19
31
  /**
20
- * Returns a promise which is resolved when this token changes its state.
32
+ * A promise that resolves with the next state of the token.
21
33
  */
22
34
  get $state() {
35
+ // skip(1) to wait for the *next* change, not the current state.
23
36
  return firstValueFrom(this.state$.pipe(skip(1)));
24
37
  }
25
38
  /**
26
- * Returns a promise which is resolved when this token is set.
39
+ * A promise that resolves when the token is next set.
40
+ * If the token is already set, it resolves immediately.
27
41
  */
28
42
  get $set() {
29
- return firstValueFrom(this.set$);
43
+ return firstValueFrom(this.set$.pipe(first()));
30
44
  }
31
45
  /**
32
- * Returns a promise which is resolved when this token is unset.
46
+ * A promise that resolves when the token is next unset.
47
+ * If the token is already unset, it resolves immediately.
33
48
  */
34
49
  get $unset() {
35
- return firstValueFrom(this.unset$);
50
+ return firstValueFrom(this.unset$.pipe(first()));
36
51
  }
52
+ /**
53
+ * The current state of the token.
54
+ * @returns `true` if set, `false` if unset.
55
+ */
37
56
  get state() {
38
- return this.#stateSubject.value;
57
+ return this._stateSubject.value;
39
58
  }
40
59
  /**
41
- * Whether this token is set.
60
+ * Whether the token is currently in a 'set' state.
42
61
  */
43
62
  get isSet() {
44
- return this.#stateSubject.value;
63
+ return this._stateSubject.value;
45
64
  }
46
65
  /**
47
- * Whether this token is unset.
66
+ * Whether the token is currently in an 'unset' state.
48
67
  */
49
68
  get isUnset() {
50
- return !this.#stateSubject.value;
69
+ return !this._stateSubject.value;
51
70
  }
71
+ /**
72
+ * @internal
73
+ */
52
74
  constructor(stateSubject) {
53
- this.#stateSubject = stateSubject;
75
+ this._stateSubject = stateSubject;
54
76
  }
55
77
  /**
56
- * Returns an AbortSignal.
78
+ * Returns a standard `AbortSignal` that is aborted when this token is set.
79
+ * Useful for interoperability with APIs like `fetch`.
57
80
  */
58
81
  asAbortSignal() {
59
82
  const abortController = new AbortController();
60
- this.set$.pipe(first()).subscribe(() => abortController.abort());
61
- return abortController.signal;
83
+ const subscription = this.set$.pipe(first()).subscribe(() => abortController.abort());
84
+ const signal = abortController.signal;
85
+ registerFinalization(signal, (subscription) => subscription.unsubscribe(), subscription);
86
+ return signal;
62
87
  }
63
88
  /**
64
- * Create a new token and connect it to this instance.
89
+ * Creates a new `CancellationToken` that is connected to this one.
90
+ * State changes from this token will propagate to the new child token.
65
91
  * @see {@link connect}
66
92
  */
67
93
  createChild(config) {
@@ -70,99 +96,144 @@ export class CancellationSignal {
70
96
  return child;
71
97
  }
72
98
  /**
73
- * Propagate events from this instance to `target`. Events from the `target` are *not* propagated to this instance.
74
- * @param target receiver to connect
99
+ * Propagates state changes from this token to a target `CancellationToken`.
100
+ * @param target The token to receive state updates.
101
+ * @param config Configuration for the connection.
75
102
  */
76
103
  connect(target, config) {
77
104
  CancellationToken.connect(this.state$, target, config);
78
105
  }
106
+ /**
107
+ * Allows this object to be awaited. The promise resolves when the token is set.
108
+ * Implements the `PromiseLike<void>` interface.
109
+ */
79
110
  async then(onfulfilled) {
80
111
  await this.$set;
81
112
  return onfulfilled?.();
82
113
  }
114
+ /**
115
+ * Subscribes to notifications for when the token becomes set.
116
+ * This is an alias for `this.set$.subscribe(observer)`.
117
+ * Implements the `Subscribable<void>` interface.
118
+ */
83
119
  subscribe(observer) {
84
120
  return this.set$.subscribe(observer);
85
121
  }
86
122
  }
123
+ /**
124
+ * A CancellationToken represents a unit of work that can be cancelled.
125
+ * It can be explicitly set/unset, completed, or errored.
126
+ *
127
+ * You can create child tokens, connect them to other async primitives
128
+ * (Promises, AbortSignals), and pass around its read-only `signal`
129
+ * to consumers that should only react to cancellation, not trigger it.
130
+ */
87
131
  export class CancellationToken extends CancellationSignal {
88
- #stateSubject;
89
132
  #signal;
90
- /** Signal for this token */
133
+ /**
134
+ * A read-only view of this token.
135
+ * Useful for passing to functions that should only be able to check for
136
+ * cancellation but not trigger it.
137
+ */
91
138
  get signal() {
92
- return (this.#signal ??= new CancellationSignal(this.#stateSubject));
139
+ return (this.#signal ??= new CancellationSignal(this._stateSubject));
93
140
  }
94
141
  /**
95
- * @param initialState which state to initialze this token to
96
- * - `false`: unset
97
- * - `true`: set
98
- * @default false
142
+ * @param initialState The initial state of the token. `false` (unset) by default.
99
143
  */
100
144
  constructor(initialState = false) {
101
145
  const stateSubject = new BehaviorSubject(initialState);
102
146
  super(stateSubject);
103
- this.#stateSubject = stateSubject;
104
147
  }
105
148
  static from(source, config) {
106
- const source$ = (source instanceof AbortSignal) ? fromEvent(source, 'abort', () => true)
107
- : isObservable(source) ? source.pipe(map((state) => (isBoolean(state) ? state : true)))
108
- : from(source).pipe(map(() => true));
149
+ const source$ = match(source)
150
+ .with(P.instanceOf(AbortSignal), (signal) => fromEvent(signal, 'abort').pipe(map(() => true)))
151
+ .with(P.when(isObservable), (obs) => obs.pipe(map((state) => (isBoolean(state) ? state : true))))
152
+ .otherwise((source) => from(source).pipe(map(() => true)));
109
153
  const token = new CancellationToken();
110
154
  CancellationToken.connect(source$, token, config);
111
155
  return token;
112
156
  }
113
- static connect(state$, target, config = {}) {
157
+ /**
158
+ * Connects an observable state source to a target token.
159
+ * @param source$ The observable providing boolean state.
160
+ * @param target The CancellationToken to update.
161
+ * @param config The connection configuration.
162
+ */
163
+ static connect(source$, target, config = {}) {
114
164
  const { set = true, unset = true, complete = true, error = true, immediate = true, once = false } = config;
115
- const stateObservable = state$
116
- .pipe(immediate ? noopOperator() : skip(1), (set && unset) ? noopOperator() : set ? filter((state) => state) : unset ? filter((state) => !state) : filter(() => false), once ? take(1) : noopOperator());
165
+ let stateObservable = source$;
166
+ if (!immediate) {
167
+ stateObservable = stateObservable.pipe(skip(1));
168
+ }
169
+ if (!set || !unset) {
170
+ if (set) {
171
+ stateObservable = stateObservable.pipe(filter((state) => state));
172
+ }
173
+ else if (unset) {
174
+ stateObservable = stateObservable.pipe(filter((state) => !state));
175
+ }
176
+ else {
177
+ stateObservable = stateObservable.pipe(filter(() => false));
178
+ }
179
+ }
180
+ if (once) {
181
+ stateObservable = stateObservable.pipe(take(1));
182
+ }
117
183
  const subscription = stateObservable.subscribe({
118
184
  next: (state) => target.setState(state),
119
- error: error ? ((errorValue) => target.error(errorValue)) : noop,
120
- complete: complete ? (() => target.complete()) : noop,
185
+ error: error ? (errorValue) => target.error(errorValue) : noop,
186
+ complete: complete ? () => target.complete() : noop,
121
187
  });
122
- target.#stateSubject.subscribe({
188
+ // Ensure the connection is torn down if the target is completed or errors.
189
+ target._stateSubject.subscribe({
123
190
  error: () => subscription.unsubscribe(),
124
191
  complete: () => subscription.unsubscribe(),
125
192
  });
126
193
  }
127
194
  /**
128
- * Become a child of the provided parent. Events from the parent are propagated to this token. Events from this token are *not* propagated to the parent.
195
+ * Makes this token a child of a parent token.
196
+ * State changes from the parent will propagate to this token.
197
+ * @param parent The token to inherit state from.
198
+ * @param config Configuration for the connection.
129
199
  */
130
200
  inherit(parent, config) {
131
- const { state$ } = (parent instanceof CancellationToken) ? parent.signal : parent;
132
- CancellationToken.connect(state$, this, config);
201
+ CancellationToken.connect(parent.state$, this, config);
133
202
  return this;
134
203
  }
135
204
  /**
136
- * Set this token.
205
+ * Sets the token's state to `true`.
206
+ * This signals cancellation or completion of the associated operation.
137
207
  */
138
208
  set() {
139
209
  this.setState(true);
140
210
  }
141
211
  /**
142
- * Unset this token.
212
+ * Sets the token's state to `false`.
213
+ * This can be used to reset the token.
143
214
  */
144
215
  unset() {
145
216
  this.setState(false);
146
217
  }
147
218
  /**
148
- * Set the state.
219
+ * Explicitly sets the state of the token.
220
+ * @param state `true` for set, `false` for unset.
149
221
  */
150
222
  setState(state) {
151
- this.#stateSubject.next(state);
223
+ this._stateSubject.next(state);
152
224
  }
153
225
  /**
154
- * Errors the token.
226
+ * Puts the token into an errored state.
227
+ * All current and future subscribers will receive this error.
155
228
  */
156
229
  error(error) {
157
- this.#stateSubject.error(error);
230
+ this._stateSubject.error(error);
158
231
  }
159
232
  /**
160
- * Clean up subscriptions.
161
- *
162
- * Keep in mind that *active* awaits (promise) on this token will throw.
233
+ * Completes the token's lifecycle.
234
+ * No further state changes can occur. Active awaits may throw an error.
163
235
  */
164
236
  complete() {
165
- this.#stateSubject.complete();
237
+ this._stateSubject.complete();
166
238
  }
167
239
  }
168
- // export { CancellationSignal as ReadonlyCancellationToken };
package/core.d.ts CHANGED
@@ -1,11 +1,7 @@
1
- import type { CancellationSignal } from './cancellation/token.js';
2
- import { Injector } from './injector/injector.js';
3
- import { type InjectionToken } from './injector/token.js';
4
- import { LogLevel, Logger, type LoggerArgument } from './logger/index.js';
1
+ import { Injector } from './injector/index.js';
5
2
  declare global {
6
3
  var tstdlLoaded: boolean | undefined;
7
4
  }
8
- export declare const CORE_LOGGER: InjectionToken<Logger, never>;
9
5
  /**
10
6
  * @deprecated Usage of `getGlobalInjector` should be avoided. Use `Application` scoped injector instead.
11
7
  */
@@ -13,11 +9,3 @@ export declare function getGlobalInjector(): Injector;
13
9
  export declare function isDevMode(): boolean;
14
10
  export declare function isProdMode(): boolean;
15
11
  export declare function enableProdMode(): void;
16
- export declare function connect(name: string, connectFunction: (() => Promise<any>), logger: Logger, cancellationSignal: CancellationSignal, maxTries?: number): Promise<void>;
17
- export type CoreConfiguration = {
18
- production?: boolean;
19
- logger?: InjectionToken<Logger, LoggerArgument>;
20
- logLevel?: LogLevel;
21
- coreLogPrefix?: string;
22
- };
23
- export declare function configureTstdl(config?: CoreConfiguration): void;
package/core.js CHANGED
@@ -1,16 +1,8 @@
1
- import { Injector } from './injector/injector.js';
2
- import { injectionToken } from './injector/token.js';
3
- import { ConsoleLogger } from './logger/console/logger.js';
4
- import { LogLevel, Logger } from './logger/index.js';
5
- import { LOG_LEVEL } from './logger/tokens.js';
6
- import { initializeSignals, setProcessShutdownLogger } from './process-shutdown.js';
7
- import { timeout } from './utils/timing.js';
8
- import { assertDefinedPass, isDefined } from './utils/type-guards.js';
1
+ import { Injector } from './injector/index.js';
9
2
  if (globalThis.tstdlLoaded == true) {
10
3
  console.error(new Error('tstdl seems to be loaded multiple times. This is likely an error as some modules won\'t work as intended this way.'));
11
4
  }
12
5
  globalThis.tstdlLoaded = true;
13
- export const CORE_LOGGER = injectionToken('core logger');
14
6
  let globalInjector;
15
7
  let _isDevMode = true;
16
8
  /**
@@ -28,40 +20,3 @@ export function isProdMode() {
28
20
  export function enableProdMode() {
29
21
  _isDevMode = false;
30
22
  }
31
- export async function connect(name, connectFunction, logger, cancellationSignal, maxTries = 5) {
32
- let triesLeft = maxTries;
33
- let success = false;
34
- while (!success && cancellationSignal.isUnset && triesLeft-- > 0) {
35
- try {
36
- logger.verbose(`connecting to ${name}...`);
37
- await connectFunction();
38
- success = true;
39
- logger.info(`connected to ${name}`);
40
- }
41
- catch (error) {
42
- logger.verbose(`error connecting to ${name}${triesLeft > 0 ? ', trying again...' : ''}`);
43
- logger.error(error);
44
- if (triesLeft == 0) {
45
- throw new Error(`Failed to connect to ${name} - no tries left.`);
46
- }
47
- await timeout(3000);
48
- }
49
- }
50
- }
51
- let coreLogPrefix;
52
- export function configureTstdl(config = {}) {
53
- if (config.production == true) {
54
- enableProdMode();
55
- }
56
- const logger = getGlobalInjector().resolve(CORE_LOGGER);
57
- setProcessShutdownLogger(logger);
58
- initializeSignals();
59
- Injector.register(Logger, { useToken: config.logger ?? ConsoleLogger });
60
- Injector.register(LOG_LEVEL, { useFactory: (level) => assertDefinedPass(level, 'LogLevel argument not provided') }, { defaultArgumentProvider: () => config.logLevel ?? LogLevel.Trace });
61
- if (isDefined(config.coreLogPrefix)) {
62
- coreLogPrefix = config.coreLogPrefix;
63
- }
64
- }
65
- Injector.register(Logger, { useToken: ConsoleLogger });
66
- Injector.register(LOG_LEVEL, { useValue: LogLevel.Trace });
67
- Injector.register(CORE_LOGGER, { useToken: Logger, defaultArgumentProvider: () => coreLogPrefix });
@@ -1,11 +1,3 @@
1
- export declare const dispose: typeof Symbol.dispose;
2
- export declare const disposeAsync: typeof Symbol.asyncDispose;
3
- export interface Disposable {
4
- [Symbol.dispose](): void;
5
- }
6
- export interface AsyncDisposable {
7
- [Symbol.asyncDispose](): PromiseLike<void>;
8
- }
9
1
  export declare function isDisposable(object: any): object is Disposable;
10
2
  export declare function isAsyncDisposable(object: any): object is AsyncDisposable;
11
3
  export declare function isSyncOrAsyncDisposable(object: any): object is Disposable | AsyncDisposable;
@@ -1,6 +1,4 @@
1
1
  import { isFunction } from '../utils/type-guards.js';
2
- export const dispose = Symbol.dispose;
3
- export const disposeAsync = Symbol.asyncDispose;
4
2
  export function isDisposable(object) {
5
3
  return isFunction(object?.[Symbol.dispose]);
6
4
  }
@@ -8,5 +6,5 @@ export function isAsyncDisposable(object) {
8
6
  return isFunction(object?.[Symbol.asyncDispose]);
9
7
  }
10
8
  export function isSyncOrAsyncDisposable(object) {
11
- return isFunction(object?.[Symbol.dispose] ?? object?.[Symbol.asyncDispose]);
9
+ return isDisposable(object) || isAsyncDisposable(object);
12
10
  }
@@ -1,8 +1,2 @@
1
- /**
2
- * Dispose pattern
3
- *
4
- * @module Disposable
5
- */
6
- export * from './async-disposer.js';
7
1
  export * from './disposable.js';
8
2
  export * from './using.js';
@@ -1,8 +1,2 @@
1
- /**
2
- * Dispose pattern
3
- *
4
- * @module Disposable
5
- */
6
- export * from './async-disposer.js';
7
1
  export * from './disposable.js';
8
2
  export * from './using.js';
@@ -1,3 +1,2 @@
1
- import type { AsyncDisposable, Disposable } from './disposable.js';
2
1
  export declare function using<T extends Disposable, U>(disposable: T, user: (disposable: T) => U): U;
3
2
  export declare function usingAsync<T extends AsyncDisposable, U>(disposable: T, user: (disposable: T) => U | Promise<U>): Promise<U>;
@@ -1,10 +1,9 @@
1
- import { dispose, disposeAsync } from './disposable.js';
2
1
  export function using(disposable, user) {
3
2
  try {
4
3
  return user(disposable);
5
4
  }
6
5
  finally {
7
- disposable[dispose]();
6
+ disposable[Symbol.dispose]();
8
7
  }
9
8
  }
10
9
  export async function usingAsync(disposable, user) {
@@ -12,6 +11,6 @@ export async function usingAsync(disposable, user) {
12
11
  return await user(disposable);
13
12
  }
14
13
  finally {
15
- await disposable[disposeAsync]();
14
+ await disposable[Symbol.asyncDispose]();
16
15
  }
17
16
  }
@@ -51,7 +51,7 @@ let DistributedLoop = class DistributedLoop {
51
51
  };
52
52
  const controller = {
53
53
  stop: stopFunction,
54
- $stopped
54
+ $stopped,
55
55
  };
56
56
  void (async () => {
57
57
  const lock = this.lockProvider.get(this.key);
@@ -59,7 +59,7 @@ let DistributedLoop = class DistributedLoop {
59
59
  try {
60
60
  while (!stopToken.isSet) {
61
61
  timer.restart();
62
- await lock.use(undefined, false, async () => {
62
+ await lock.tryUse(undefined, async () => {
63
63
  await func(controller);
64
64
  const timeLeft = interval - timer.milliseconds;
65
65
  const timeoutDuration = timeLeft - (accuracy / 2);
package/errors/utils.js CHANGED
@@ -1,8 +1,11 @@
1
1
  export function unwrapError(error) {
2
2
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
3
3
  const wrappedError = error?.rejection ?? error?.reason ?? error?.error;
4
+ // If the original error is a real Error, prefer it unless it's a generic
5
+ // "Uncaught" wrapper around another, more specific Error.
4
6
  if ((error instanceof Error) && !(error.message.startsWith('Uncaught') && (wrappedError instanceof Error))) {
5
7
  return error;
6
8
  }
7
- return wrappedError;
9
+ // Fall back to the original error if no wrapped error was found.
10
+ return wrappedError ?? error;
8
11
  }
@@ -2,6 +2,7 @@
2
2
  import '../../polyfills.js';
3
3
  import { configureApiServer } from '../../api/server/index.js';
4
4
  import { Application } from '../../application/application.js';
5
+ import { provideInitializer, provideModules, provideSignalHandler } from '../../application/index.js';
5
6
  import { AuthenticationApiClient } from '../../authentication/client/api.client.js';
6
7
  import { AuthenticationClientService, configureAuthenticationClient } from '../../authentication/client/index.js';
7
8
  import { AuthenticationApiController, AuthenticationService as AuthenticationServerService, configureAuthenticationServer } from '../../authentication/server/index.js';
@@ -28,24 +29,29 @@ async function clientTest() {
28
29
  authenticationService.token$.subscribe((token) => console.log({ token }));
29
30
  }
30
31
  async function test() {
32
+ const application = inject(Application);
31
33
  await Promise.all([
32
34
  serverTest(),
33
- clientTest()
35
+ clientTest(),
34
36
  ]);
35
- await Application.shutdown();
37
+ await application.shutdown();
36
38
  }
37
39
  function bootstrap() {
38
40
  configureDefaultSignalsImplementation();
39
41
  configureAuthenticationServer({
40
- serviceOptions: { secret: 'djp0fq23576aq' }
42
+ serviceOptions: { secret: 'djp0fq23576aq' },
41
43
  });
42
44
  configureLocalMessageBus();
43
45
  configureAuthenticationClient({
44
- authenticationApiClient: AuthenticationApiClient
46
+ authenticationApiClient: AuthenticationApiClient,
45
47
  });
46
48
  configureNodeHttpServer();
47
49
  configureApiServer({ controllers: [AuthenticationApiController] });
48
50
  configureUndiciHttpClientAdapter({ dispatcher: new Agent({ keepAliveMaxTimeout: 1 }) });
49
51
  configureHttpClient({ baseUrl: 'http://localhost:8000' });
50
52
  }
51
- Application.run({ bootstrap }, WebServerModule, test);
53
+ Application.run('Test', [
54
+ provideModules(WebServerModule, test),
55
+ provideInitializer(bootstrap),
56
+ provideSignalHandler(),
57
+ ]);
@@ -13,6 +13,7 @@ import { compileClient } from '../../api/client/index.js';
13
13
  import { defineApi } from '../../api/index.js';
14
14
  import { apiController, configureApiServer } from '../../api/server/index.js';
15
15
  import { Application } from '../../application/application.js';
16
+ import { provideInitializer, provideModules, provideSignalHandler } from '../../application/index.js';
16
17
  import { configureUndiciHttpClientAdapter } from '../../http/client/adapters/undici.adapter.js';
17
18
  import { configureHttpClient } from '../../http/client/module.js';
18
19
  import { configureNodeHttpServer } from '../../http/server/node/module.js';
@@ -35,7 +36,7 @@ __decorate([
35
36
  ], User.prototype, "name", void 0);
36
37
  const users = [
37
38
  { id: 1, name: 'Alice' },
38
- { id: 3, name: 'Bob' }
39
+ { id: 3, name: 'Bob' },
39
40
  ];
40
41
  const usersApiDefinition = defineApi({
41
42
  resource: 'users', // /api/:version/users
@@ -45,22 +46,22 @@ const usersApiDefinition = defineApi({
45
46
  resource: ':id', // => /api/v1/users/:id
46
47
  version: 1,
47
48
  parameters: object({
48
- id: number({ coerce: true })
49
+ id: number({ coerce: true }),
49
50
  }),
50
- result: User
51
+ result: User,
51
52
  },
52
53
  loadAll: {
53
- result: array(User)
54
+ result: array(User),
54
55
  },
55
56
  delete: {
56
57
  method: 'DELETE',
57
58
  resource: ':id', // => /api/v1/users/:id
58
59
  parameters: object({
59
- id: number({ coerce: true })
60
+ id: number({ coerce: true }),
60
61
  }),
61
- result: boolean()
62
- }
63
- }
62
+ result: boolean(),
63
+ },
64
+ },
64
65
  });
65
66
  let UserApi = class UserApi {
66
67
  load({ parameters }) {
@@ -83,6 +84,7 @@ UserApi = __decorate([
83
84
  ], UserApi);
84
85
  const UserApiClient = compileClient(usersApiDefinition);
85
86
  async function clientTest() {
87
+ const application = inject(Application);
86
88
  const userApiClient = inject(UserApiClient);
87
89
  await timeout(250); // allow server to start
88
90
  const allUsers = await userApiClient.loadAll();
@@ -90,13 +92,16 @@ async function clientTest() {
90
92
  await userApiClient.delete({ id: allUsers[0].id });
91
93
  const allUsersAfterDelete = await userApiClient.loadAll();
92
94
  console.log(allUsersAfterDelete);
93
- Application.requestShutdown();
95
+ application.requestShutdown();
94
96
  }
95
- function main() {
97
+ function bootstrap() {
96
98
  configureNodeHttpServer();
97
99
  configureApiServer({ controllers: [UserApi] });
98
100
  configureUndiciHttpClientAdapter({ dispatcher: new Agent({ keepAliveMaxTimeout: 1 }) });
99
101
  configureHttpClient({ baseUrl: 'http://localhost:8000' });
100
- Application.run(WebServerModule, clientTest);
101
102
  }
102
- main();
103
+ Application.run('Test', [
104
+ provideInitializer(bootstrap),
105
+ provideModules(WebServerModule, clientTest),
106
+ provideSignalHandler(),
107
+ ]);
@@ -12,6 +12,7 @@ import '../../polyfills.js';
12
12
  import { Agent } from 'undici';
13
13
  import { configureApiServer } from '../../api/server/index.js';
14
14
  import { Application } from '../../application/application.js';
15
+ import { provideInitializer, provideModules, provideSignalHandler } from '../../application/index.js';
15
16
  import { AuthenticationClientService, configureAuthenticationClient, getAuthenticationApiClient } from '../../authentication/index.js';
16
17
  import { AuthenticationAncillaryService, AuthenticationApiController, AuthenticationService as AuthenticationServerService, configureAuthenticationServer } from '../../authentication/server/index.js';
17
18
  import { configureUndiciHttpClientAdapter } from '../../http/client/adapters/undici.adapter.js';
@@ -84,35 +85,40 @@ async function serverTest() {
84
85
  const authenticationService = await injectAsync(AuthenticationServerService);
85
86
  await authenticationService.setCredentials('foobar', 'supersecret-dupidupudoo9275');
86
87
  }
87
- async function clientTest() {
88
+ async function clientTest(application) {
88
89
  const authenticationService = inject(AuthenticationClientService);
89
90
  await timeout(1500); // allow server to initialize
90
91
  authenticationService.initialize();
91
92
  await authenticationService.login('foobar', 'supersecret-dupidupudoo9275');
92
93
  authenticationService.token$.subscribe((token) => console.log({ token }));
93
- Application.requestShutdown();
94
+ application.requestShutdown();
94
95
  }
95
96
  async function test() {
97
+ const application = inject(Application);
96
98
  await Promise.all([
97
99
  serverTest(),
98
- clientTest()
100
+ clientTest(application),
99
101
  ]);
100
- await Application.shutdown();
102
+ await application.shutdown();
101
103
  }
102
104
  function bootstrap() {
103
105
  configureDefaultSignalsImplementation();
104
106
  configureAuthenticationServer({
105
107
  serviceOptions: { secret: 'djp0fq23576aq' },
106
- authenticationAncillaryService: CustomAuthenticationAncillaryService
108
+ authenticationAncillaryService: CustomAuthenticationAncillaryService,
107
109
  });
108
110
  configureLocalMessageBus();
109
111
  configureAuthenticationClient({
110
112
  authenticationApiClient: CustomAuthenticationApiClient,
111
- initialAuthenticationData: ({ deviceId: 'my-device' })
113
+ initialAuthenticationData: ({ deviceId: 'my-device' }),
112
114
  });
113
115
  configureNodeHttpServer();
114
116
  configureApiServer({ controllers: [AuthenticationApiController] });
115
117
  configureUndiciHttpClientAdapter({ dispatcher: new Agent({ keepAliveMaxTimeout: 1 }) });
116
118
  configureHttpClient({ baseUrl: 'http://localhost:8000' });
117
119
  }
118
- Application.run({ bootstrap }, WebServerModule, test);
120
+ Application.run('Test', [
121
+ provideInitializer(bootstrap),
122
+ provideModules(WebServerModule, test),
123
+ provideSignalHandler(),
124
+ ]);