@tstdl/base 0.93.139 → 0.93.141

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 (218) hide show
  1. package/README.md +166 -0
  2. package/ai/genkit/multi-region.plugin.js +5 -3
  3. package/ai/genkit/tests/multi-region.test.d.ts +1 -0
  4. package/ai/genkit/tests/multi-region.test.js +5 -2
  5. package/ai/parser/parser.js +2 -2
  6. package/ai/prompts/build.js +1 -0
  7. package/ai/prompts/instructions-formatter.d.ts +15 -2
  8. package/ai/prompts/instructions-formatter.js +36 -31
  9. package/ai/prompts/prompt-builder.js +5 -5
  10. package/ai/prompts/steering.d.ts +3 -2
  11. package/ai/prompts/steering.js +3 -1
  12. package/ai/tests/instructions-formatter.test.js +1 -0
  13. package/api/README.md +403 -0
  14. package/api/client/client.js +7 -13
  15. package/api/client/tests/api-client.test.js +10 -10
  16. package/api/default-error-handlers.js +1 -1
  17. package/api/response.d.ts +2 -2
  18. package/api/response.js +22 -33
  19. package/api/server/api-controller.d.ts +1 -1
  20. package/api/server/api-controller.js +3 -3
  21. package/api/server/api-request-token.provider.d.ts +1 -0
  22. package/api/server/api-request-token.provider.js +1 -0
  23. package/api/server/middlewares/allowed-methods.middleware.js +2 -1
  24. package/api/server/middlewares/content-type.middleware.js +2 -1
  25. package/api/types.d.ts +3 -2
  26. package/application/README.md +240 -0
  27. package/application/application.d.ts +1 -1
  28. package/application/application.js +3 -3
  29. package/application/providers.d.ts +20 -2
  30. package/application/providers.js +34 -7
  31. package/audit/README.md +267 -0
  32. package/audit/module.d.ts +5 -0
  33. package/audit/module.js +9 -1
  34. package/authentication/README.md +288 -0
  35. package/authentication/client/authentication.service.d.ts +12 -11
  36. package/authentication/client/authentication.service.js +21 -21
  37. package/authentication/client/http-client.middleware.js +2 -2
  38. package/authentication/server/module.d.ts +5 -0
  39. package/authentication/server/module.js +9 -1
  40. package/authentication/tests/authentication.api-controller.test.js +1 -1
  41. package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
  42. package/authentication/tests/authentication.client-error-handling.test.js +2 -1
  43. package/authentication/tests/authentication.client-service-refresh.test.js +5 -3
  44. package/authentication/tests/authentication.client-service.test.js +1 -1
  45. package/browser/README.md +401 -0
  46. package/cancellation/README.md +156 -0
  47. package/cancellation/tests/coverage.test.d.ts +1 -0
  48. package/cancellation/tests/coverage.test.js +49 -0
  49. package/cancellation/tests/leak.test.js +24 -29
  50. package/cancellation/tests/token.test.d.ts +1 -0
  51. package/cancellation/tests/token.test.js +136 -0
  52. package/cancellation/token.d.ts +53 -177
  53. package/cancellation/token.js +132 -208
  54. package/circuit-breaker/postgres/module.d.ts +1 -0
  55. package/circuit-breaker/postgres/module.js +5 -1
  56. package/context/README.md +174 -0
  57. package/cookie/README.md +161 -0
  58. package/css/README.md +157 -0
  59. package/data-structures/README.md +320 -0
  60. package/decorators/README.md +140 -0
  61. package/distributed-loop/README.md +231 -0
  62. package/distributed-loop/distributed-loop.js +1 -1
  63. package/document-management/README.md +403 -0
  64. package/document-management/server/configure.js +5 -1
  65. package/document-management/server/module.d.ts +1 -1
  66. package/document-management/server/module.js +1 -1
  67. package/document-management/server/services/document-management-ancillary.service.js +1 -1
  68. package/document-management/server/services/document-management.service.js +9 -7
  69. package/document-management/tests/ai-config-hierarchy.test.js +0 -5
  70. package/document-management/tests/document-management-ai-overrides.test.js +0 -1
  71. package/document-management/tests/document-management-core.test.js +2 -7
  72. package/document-management/tests/document-management.api.test.js +6 -7
  73. package/document-management/tests/document-statistics.service.test.js +11 -12
  74. package/document-management/tests/document-validation-ai-overrides.test.js +0 -1
  75. package/document-management/tests/document.service.test.js +3 -3
  76. package/document-management/tests/enum-helpers.test.js +2 -3
  77. package/dom/README.md +213 -0
  78. package/enumerable/README.md +259 -0
  79. package/enumeration/README.md +121 -0
  80. package/errors/README.md +267 -0
  81. package/examples/document-management/main.d.ts +1 -0
  82. package/examples/document-management/main.js +14 -11
  83. package/file/README.md +191 -0
  84. package/formats/README.md +210 -0
  85. package/function/README.md +144 -0
  86. package/http/README.md +318 -0
  87. package/http/client/adapters/undici.adapter.js +1 -1
  88. package/http/client/http-client-request.d.ts +6 -5
  89. package/http/client/http-client-request.js +8 -9
  90. package/http/server/node/node-http-server.js +1 -2
  91. package/image-service/README.md +137 -0
  92. package/injector/README.md +491 -0
  93. package/intl/README.md +113 -0
  94. package/json-path/README.md +182 -0
  95. package/jsx/README.md +154 -0
  96. package/key-value-store/README.md +191 -0
  97. package/key-value-store/postgres/module.d.ts +1 -0
  98. package/key-value-store/postgres/module.js +5 -1
  99. package/lock/README.md +249 -0
  100. package/lock/postgres/module.d.ts +1 -0
  101. package/lock/postgres/module.js +5 -1
  102. package/lock/web/web-lock.js +119 -47
  103. package/logger/README.md +287 -0
  104. package/mail/README.md +256 -0
  105. package/mail/module.d.ts +5 -1
  106. package/mail/module.js +11 -6
  107. package/memory/README.md +144 -0
  108. package/message-bus/README.md +244 -0
  109. package/message-bus/message-bus-base.js +1 -1
  110. package/module/README.md +182 -0
  111. package/module/module.d.ts +1 -1
  112. package/module/module.js +77 -17
  113. package/module/modules/web-server.module.js +3 -4
  114. package/notification/server/module.d.ts +1 -0
  115. package/notification/server/module.js +5 -1
  116. package/notification/tests/notification-flow.test.js +2 -2
  117. package/notification/tests/notification-type.service.test.js +24 -15
  118. package/object-storage/README.md +300 -0
  119. package/openid-connect/README.md +274 -0
  120. package/orm/README.md +423 -0
  121. package/orm/decorators.d.ts +5 -1
  122. package/orm/decorators.js +1 -1
  123. package/orm/server/drizzle/schema-converter.js +17 -30
  124. package/orm/server/encryption.d.ts +0 -1
  125. package/orm/server/encryption.js +1 -4
  126. package/orm/server/index.d.ts +1 -6
  127. package/orm/server/index.js +1 -6
  128. package/orm/server/migration.d.ts +19 -0
  129. package/orm/server/migration.js +72 -0
  130. package/orm/server/repository.d.ts +1 -1
  131. package/orm/server/transaction.d.ts +5 -10
  132. package/orm/server/transaction.js +22 -26
  133. package/orm/server/transactional.js +3 -3
  134. package/orm/tests/database-migration.test.d.ts +1 -0
  135. package/orm/tests/database-migration.test.js +82 -0
  136. package/orm/tests/encryption.test.js +3 -4
  137. package/orm/utils.d.ts +17 -2
  138. package/orm/utils.js +49 -1
  139. package/package.json +9 -6
  140. package/password/README.md +164 -0
  141. package/pdf/README.md +246 -0
  142. package/polyfills.js +1 -0
  143. package/pool/README.md +198 -0
  144. package/process/README.md +237 -0
  145. package/promise/README.md +252 -0
  146. package/promise/cancelable-promise.js +1 -1
  147. package/random/README.md +193 -0
  148. package/rate-limit/postgres/module.d.ts +1 -0
  149. package/rate-limit/postgres/module.js +5 -1
  150. package/reflection/README.md +305 -0
  151. package/reflection/decorator-data.js +11 -12
  152. package/rpc/README.md +386 -0
  153. package/rxjs-utils/README.md +262 -0
  154. package/schema/README.md +342 -0
  155. package/serializer/README.md +342 -0
  156. package/signals/implementation/README.md +134 -0
  157. package/sse/README.md +278 -0
  158. package/task-queue/README.md +293 -0
  159. package/task-queue/postgres/drizzle/{0000_simple_invisible_woman.sql → 0000_wakeful_sunspot.sql} +22 -14
  160. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +160 -82
  161. package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
  162. package/task-queue/postgres/module.d.ts +1 -0
  163. package/task-queue/postgres/module.js +5 -1
  164. package/task-queue/postgres/schemas.d.ts +9 -6
  165. package/task-queue/postgres/schemas.js +4 -3
  166. package/task-queue/postgres/task-queue.d.ts +4 -13
  167. package/task-queue/postgres/task-queue.js +462 -355
  168. package/task-queue/postgres/task.model.d.ts +12 -5
  169. package/task-queue/postgres/task.model.js +51 -25
  170. package/task-queue/task-context.d.ts +2 -2
  171. package/task-queue/task-context.js +8 -8
  172. package/task-queue/task-queue.d.ts +53 -19
  173. package/task-queue/task-queue.js +121 -55
  174. package/task-queue/tests/cascading-cancellations.test.d.ts +1 -0
  175. package/task-queue/tests/cascading-cancellations.test.js +38 -0
  176. package/task-queue/tests/complex.test.js +45 -229
  177. package/task-queue/tests/coverage-branch.test.d.ts +1 -0
  178. package/task-queue/tests/coverage-branch.test.js +407 -0
  179. package/task-queue/tests/coverage-enhancement.test.d.ts +1 -0
  180. package/task-queue/tests/coverage-enhancement.test.js +144 -0
  181. package/task-queue/tests/dag-dependencies.test.d.ts +1 -0
  182. package/task-queue/tests/dag-dependencies.test.js +41 -0
  183. package/task-queue/tests/dependencies.test.js +28 -26
  184. package/task-queue/tests/extensive-dependencies.test.js +64 -139
  185. package/task-queue/tests/fan-out-spawning.test.d.ts +1 -0
  186. package/task-queue/tests/fan-out-spawning.test.js +53 -0
  187. package/task-queue/tests/idempotent-replacement.test.d.ts +1 -0
  188. package/task-queue/tests/idempotent-replacement.test.js +61 -0
  189. package/task-queue/tests/missing-idempotent-tasks.test.d.ts +1 -0
  190. package/task-queue/tests/missing-idempotent-tasks.test.js +38 -0
  191. package/task-queue/tests/queue.test.js +128 -8
  192. package/task-queue/tests/worker.test.js +39 -16
  193. package/task-queue/tests/zombie-parent.test.d.ts +1 -0
  194. package/task-queue/tests/zombie-parent.test.js +45 -0
  195. package/task-queue/tests/zombie-recovery.test.d.ts +1 -0
  196. package/task-queue/tests/zombie-recovery.test.js +51 -0
  197. package/templates/README.md +287 -0
  198. package/test5.js +5 -5
  199. package/testing/README.md +157 -0
  200. package/testing/integration-setup.d.ts +4 -4
  201. package/testing/integration-setup.js +54 -29
  202. package/text/README.md +346 -0
  203. package/text/localization.service.js +2 -2
  204. package/threading/README.md +238 -0
  205. package/types/README.md +311 -0
  206. package/utils/README.md +322 -0
  207. package/utils/async-iterable-helpers/observable-iterable.d.ts +1 -1
  208. package/utils/async-iterable-helpers/observable-iterable.js +4 -8
  209. package/utils/async-iterable-helpers/take-until.js +4 -4
  210. package/utils/backoff.js +89 -30
  211. package/utils/file-reader.js +1 -2
  212. package/utils/retry-with-backoff.js +1 -1
  213. package/utils/timer.d.ts +1 -1
  214. package/utils/timer.js +5 -7
  215. package/utils/timing.d.ts +1 -1
  216. package/utils/timing.js +2 -4
  217. package/utils/z-base32.d.ts +1 -0
  218. package/utils/z-base32.js +1 -0
@@ -0,0 +1,252 @@
1
+ # Promise
2
+
3
+ This module provides advanced Promise implementations to handle complex asynchronous patterns such as cancellation, deferred resolution, and lazy execution. It extends standard Promise capabilities to offer more control over asynchronous flows.
4
+
5
+ ## Table of Contents
6
+
7
+ - [✨ Features](#-features)
8
+ - [Core Concepts](#core-concepts)
9
+ - [CustomPromise](#custompromise)
10
+ - [DeferredPromise](#deferredpromise)
11
+ - [CancelablePromise](#cancelablepromise)
12
+ - [LazyPromise](#lazypromise)
13
+ - [🚀 Basic Usage](#-basic-usage)
14
+ - [Using DeferredPromise](#using-deferredpromise)
15
+ - [Using CancelablePromise](#using-cancelablepromise)
16
+ - [Using LazyPromise](#using-lazypromise)
17
+ - [🔧 Advanced Topics](#-advanced-topics)
18
+ - [Resetting a DeferredPromise](#resetting-a-deferredpromise)
19
+ - [Handling Cancellation Signals](#handling-cancellation-signals)
20
+ - [📚 API](#-api)
21
+
22
+ ## ✨ Features
23
+
24
+ - **Deferred Resolution**: Control the resolution or rejection of a promise from outside its executor scope.
25
+ - **Cancellation Support**: Create promises that can be explicitly canceled, returning a specific result state.
26
+ - **Lazy Execution**: Define asynchronous logic that only executes when the promise is actually awaited or subscribed to.
27
+ - **State Inspection**: Synchronously check if a promise is pending, resolved, or rejected (specifically for `DeferredPromise`).
28
+
29
+ ## Core Concepts
30
+
31
+ ### CustomPromise
32
+
33
+ `CustomPromise` is a base class that extends the native `Promise`. It simplifies creating custom promise implementations by exposing the `resolve` and `reject` functions as protected fields to its subclasses. It also ensures that chained promises (via `then`, `catch`, etc.) return a standard `Promise` by overriding `Symbol.species`.
34
+
35
+ ### DeferredPromise
36
+
37
+ A `DeferredPromise` is a Promise where the `resolve` and `reject` functions are exposed as public methods on the instance. This allows you to create a promise in one part of your application and settle it from another, effectively acting as a one-time signal or latch. It also supports being `reset()` to a pending state, allowing the same instance to be reused for sequential events.
38
+
39
+ ### CancelablePromise
40
+
41
+ A `CancelablePromise` wraps an asynchronous operation that might need to be aborted. Unlike standard promises, it resolves to a result object that indicates whether the operation finished successfully or was canceled. It provides a `cancellationSignal` to the executor, which can be passed down to other cancelable operations (like `fetch` or timers).
42
+
43
+ ### LazyPromise
44
+
45
+ A `LazyPromise` holds an executor function but does not run it immediately upon instantiation. The executor is only invoked when `then`, `catch`, or `finally` is called on the promise (usually when it is `await`ed). This is useful for defining expensive operations or network requests that should only occur if their result is strictly needed.
46
+
47
+ ## 🚀 Basic Usage
48
+
49
+ ### Using DeferredPromise
50
+
51
+ Use `DeferredPromise` when you need to wait for an event that happens elsewhere.
52
+
53
+ ```ts
54
+ import { DeferredPromise } from '@tstdl/base/promise';
55
+ import { timeout } from '@tstdl/base/utils';
56
+
57
+ async function main() {
58
+ const signal = new DeferredPromise<string>();
59
+
60
+ // Simulate an async process that will trigger the signal
61
+ void (async () => {
62
+ console.log('Process started...');
63
+ await timeout(1000);
64
+ console.log('Process finished, resolving signal.');
65
+ signal.resolve('Operation Complete');
66
+ })();
67
+
68
+ console.log('Waiting for signal...');
69
+ const result = await signal;
70
+ console.log('Received:', result);
71
+ }
72
+
73
+ main();
74
+ ```
75
+
76
+ ### Using CancelablePromise
77
+
78
+ Use `CancelablePromise` for operations that users might want to abort, such as a long-running calculation or a network request.
79
+
80
+ ```ts
81
+ import { CancelablePromise } from '@tstdl/base/promise';
82
+ import { cancelableTimeout } from '@tstdl/base/utils';
83
+
84
+ const longOperation = new CancelablePromise<string, string>((resolve, reject, signal) => {
85
+ // Pass the signal to other cancelable utilities
86
+ cancelableTimeout(2000, signal)
87
+ .then(() => resolve('Finished successfully'))
88
+ .catch((error) => reject(error));
89
+ });
90
+
91
+ async function run() {
92
+ // Cancel the operation before it finishes
93
+ setTimeout(() => {
94
+ longOperation.cancel('User aborted');
95
+ }, 500);
96
+
97
+ const result = await longOperation;
98
+
99
+ if (result.canceled) {
100
+ console.log('Operation canceled:', result.reason);
101
+ } else {
102
+ console.log('Operation success:', result.value);
103
+ }
104
+ }
105
+
106
+ run();
107
+ ```
108
+
109
+ ### Using LazyPromise
110
+
111
+ Use `LazyPromise` to define a task without starting it immediately. You can provide either a standard executor or an asynchronous promise provider function.
112
+
113
+ ```ts
114
+ import { LazyPromise } from '@tstdl/base/promise';
115
+
116
+ // Using an executor
117
+ const expensiveTask = new LazyPromise<number>((resolve) => {
118
+ console.log('Expensive task starting now...');
119
+ resolve(42);
120
+ });
121
+
122
+ // Using a promise provider
123
+ const lazyProvider = new LazyPromise(async () => {
124
+ console.log('Lazy provider starting now...');
125
+ return 'result';
126
+ });
127
+
128
+ async function main() {
129
+ console.log('Promises created, but tasks have not started.');
130
+
131
+ // The executor runs here, when we await
132
+ const value = await expensiveTask;
133
+ console.log('Result:', value);
134
+
135
+ const providerValue = await lazyProvider;
136
+ console.log('Provider Result:', providerValue);
137
+ }
138
+
139
+ main();
140
+ ```
141
+
142
+ ## 🔧 Advanced Topics
143
+
144
+ ### Resetting a DeferredPromise
145
+
146
+ A `DeferredPromise` can be reused by calling `reset()`. This puts the promise back into a `Pending` state with a new underlying promise. Note that any previous awaiters will have already resolved with the previous value; `reset()` applies to future awaiters.
147
+
148
+ ```ts
149
+ import { DeferredPromise } from '@tstdl/base/promise';
150
+
151
+ const gate = new DeferredPromise<void>();
152
+
153
+ async function worker(id: number) {
154
+ console.log(`Worker ${id} waiting at gate...`);
155
+ await gate;
156
+ console.log(`Worker ${id} passed.`);
157
+ }
158
+
159
+ async function main() {
160
+ // First batch
161
+ const w1 = worker(1);
162
+ const w2 = worker(2);
163
+
164
+ gate.resolve();
165
+ await Promise.all([w1, w2]);
166
+
167
+ // Reset for next batch
168
+ gate.reset();
169
+
170
+ // Second batch
171
+ const w3 = worker(3);
172
+
173
+ setTimeout(() => {
174
+ console.log('Opening gate again...');
175
+ gate.resolve();
176
+ }, 500);
177
+
178
+ await w3;
179
+ }
180
+
181
+ main();
182
+ ```
183
+
184
+ ### Handling Cancellation Signals
185
+
186
+ When implementing a `CancelablePromise`, it is crucial to respect the `cancellationSignal`. This signal is an instance of `CancellationSignal` from the `@tstdl/base/cancellation` module.
187
+
188
+ ```ts
189
+ import { CancelablePromise } from '@tstdl/base/promise';
190
+ import { CancellationToken } from '@tstdl/base/cancellation';
191
+
192
+ function doWork(token: CancellationToken) {
193
+ return new CancelablePromise<void, string>((resolve, _, signal) => {
194
+ // Link the external token to the internal signal
195
+ const unregister = token.register(() => {
196
+ // If the external token is cancelled, we cancel this promise
197
+ // Note: In a real scenario, you might just pass 'signal' down directly
198
+ });
199
+
200
+ const timer = setTimeout(() => {
201
+ resolve();
202
+ }, 5000);
203
+
204
+ // Listen for cancellation on this specific promise
205
+ signal.register(() => {
206
+ clearTimeout(timer);
207
+ unregister();
208
+ console.log('Cleaned up resources due to cancellation');
209
+ });
210
+ });
211
+ }
212
+ ```
213
+
214
+ ## 📚 API
215
+
216
+ ### Classes
217
+
218
+ | Class | Description |
219
+ | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------- |
220
+ | `CustomPromise<T>` | A base class extending `Promise` that exposes `resolve` and `reject` to subclasses. |
221
+ | `DeferredPromise<T>` | A Promise that can be resolved or rejected externally. Supports state inspection (`pending`, `resolved`, `rejected`) and resetting. |
222
+ | `CancelablePromise<T, R>` | A Promise that wraps an operation which can be canceled. Resolves to a `CancelablePromiseResult`. |
223
+ | `LazyPromise<T>` | A Promise that executes its logic only when awaited or when `then`/`catch`/`finally` is called. |
224
+
225
+ ### Types & Interfaces
226
+
227
+ | Type | Description |
228
+ | :------------------------------ | :----------------------------------------------------------------------------------------------------- |
229
+ | `PromiseExecutor<T>` | Standard executor function signature for Promises. |
230
+ | `CancelablePromiseExecutor<T>` | Executor signature for `CancelablePromise`, receiving `resolve`, `reject`, and a `CancellationSignal`. |
231
+ | `CancelablePromiseResult<T, R>` | Discriminated union result: `{ canceled: true, reason: R }` or `{ canceled: false, value: T }`. |
232
+ | `PromiseState` | Enum representing the state of a `DeferredPromise`: `Pending`, `Resolved`, `Rejected`. |
233
+
234
+ ### DeferredPromise Methods
235
+
236
+ | Method | Description |
237
+ | :--------------------------- | :-------------------------------------------------------------------------------- |
238
+ | `resolve(value: T)` | Resolves the promise. Throws if already settled. |
239
+ | `reject(reason?: any)` | Rejects the promise. Throws if already settled. |
240
+ | `resolveIfPending(value: T)` | Resolves the promise only if it is currently pending. |
241
+ | `resolveAndReset(value: T)` | Resolves the current promise and immediately resets it to pending for future use. |
242
+ | `reset()` | Resets the promise to a pending state. |
243
+ | `pending` | Getter. Returns `true` if the promise is pending. |
244
+ | `resolved` | Getter. Returns `true` if the promise has been resolved. |
245
+ | `rejected` | Getter. Returns `true` if the promise has been rejected. |
246
+ | `settled` | Getter. Returns `true` if the promise is either resolved or rejected. |
247
+
248
+ ### CancelablePromise Methods
249
+
250
+ | Method | Description |
251
+ | :------------------ | :--------------------------------------------------------------------------- |
252
+ | `cancel(reason: R)` | Cancels the promise. The promise resolves with `{ canceled: true, reason }`. |
@@ -20,7 +20,7 @@ export class CancelablePromise extends CustomPromise {
20
20
  this.#pending = false;
21
21
  }
22
22
  };
23
- executor((value) => this.#resolve(Promise.resolve(value).then((result) => ({ canceled: false, value: result }))), this.#reject, this.#cancellationToken.signal);
23
+ executor((value) => this.#resolve(Promise.resolve(value).then((result) => ({ canceled: false, value: result }))), this.#reject, this.#cancellationToken);
24
24
  }
25
25
  cancel(reason) {
26
26
  this.#cancellationToken.set();
@@ -0,0 +1,193 @@
1
+ # Random
2
+
3
+ A comprehensive module for deterministic, seeded random number generation and simulation of random data series. It provides high-performance algorithms like Mulberry32 and SFC32, along with utilities for generating complex, bounded random walks.
4
+
5
+ ## Table of Contents
6
+
7
+ - [✨ Features](#-features)
8
+ - [Core Concepts](#core-concepts)
9
+ - [Seeded Random Number Generators](#seeded-random-number-generators)
10
+ - [Random Series Simulation](#random-series-simulation)
11
+ - [🚀 Basic Usage](#-basic-usage)
12
+ - [Using Mulberry32](#using-mulberry32)
13
+ - [Using SFC32](#using-sfc32)
14
+ - [Generating a Simple Series](#generating-a-simple-series)
15
+ - [🔧 Advanced Topics](#-advanced-topics)
16
+ - [Forking and Cloning Generators](#forking-and-cloning-generators)
17
+ - [Simulating Stock Charts (Complex Series)](#simulating-stock-charts-complex-series)
18
+ - [Cryptographically Secure Seeds](#cryptographically-secure-seeds)
19
+ - [📚 API](#-api)
20
+
21
+ ## ✨ Features
22
+
23
+ - **Seeded RNGs**: Deterministic number generation using seeds, essential for reproducible tests and simulations.
24
+ - **High Performance Algorithms**: Includes implementations of **Mulberry32** (fast, 32-bit state) and **SFC32** (Small Fast Counter, 128-bit state).
25
+ - **State Management**: Capabilities to **fork** (create a new independent stream from current state) and **clone** (duplicate current state) generators.
26
+ - **Random Series Generator**: A powerful iterator for creating random walks, stock market simulations, or sensor data with configurable volatility, bounds, and regression to the mean.
27
+ - **Type Safety**: Fully typed TypeScript implementation.
28
+
29
+ ## Core Concepts
30
+
31
+ ### Seeded Random Number Generators
32
+
33
+ Standard `Math.random()` is not seedable, making it unsuitable for scenarios where you need reproducible results (e.g., procedural generation, testing, simulations). This module provides classes extending `SeededRandomNumberGenerator` that accept initial seeds. If initialized with the same seed, they produce the exact same sequence of numbers.
34
+
35
+ ### Random Series Simulation
36
+
37
+ The `randomSeries` function is a generator that produces a stream of numbers. It models a "random walk" where the next value depends on the previous one, modified by volatility. It supports:
38
+
39
+ - **Bounds**: Keeping values within a specific range.
40
+ - **Regression**: Automatically pulling values back towards the mean when they approach bounds.
41
+ - **Dynamic Volatility**: Changing how erratic the series is over time.
42
+
43
+ ## 🚀 Basic Usage
44
+
45
+ ### Using Mulberry32
46
+
47
+ Mulberry32 is a very fast generator with a 32-bit state. It is excellent for most non-cryptographic use cases.
48
+
49
+ ```ts
50
+ import { mulberry32 } from '@tstdl/base/random';
51
+
52
+ // Initialize with a specific seed for reproducibility
53
+ const rng = mulberry32(12345);
54
+
55
+ console.log(rng.next()); // Returns a float between 0 and 1
56
+ console.log(rng.nextInt()); // Returns a 32-bit integer
57
+ console.log(rng.next()); // Next value in the sequence
58
+ ```
59
+
60
+ ### Using SFC32
61
+
62
+ SFC32 (Small Fast Counter) has a 128-bit state, making it suitable when a longer period is required.
63
+
64
+ ```ts
65
+ import { sfc32 } from '@tstdl/base/random';
66
+
67
+ // Initialize with up to 4 seeds
68
+ const rng = sfc32(0x9e3779b9, 0x243f6a88, 0xb7e15162, 1);
69
+
70
+ console.log(rng.next());
71
+ console.log(rng.nextInt());
72
+ ```
73
+
74
+ ### Generating a Simple Series
75
+
76
+ Generate a random walk starting at 0.
77
+
78
+ ```ts
79
+ import { randomSeries } from '@tstdl/base/random';
80
+
81
+ const series = randomSeries({
82
+ initial: 0,
83
+ volatility: 0.1, // 10% change per step
84
+ });
85
+
86
+ for (let i = 0; i < 5; i++) {
87
+ console.log(series.next().value);
88
+ }
89
+ // Output example: 0, 0.05, 0.048, 0.055, ...
90
+ ```
91
+
92
+ ## 🔧 Advanced Topics
93
+
94
+ ### Forking and Cloning Generators
95
+
96
+ You can branch RNGs to create independent streams or save state to retry a sequence.
97
+
98
+ ```ts
99
+ import { mulberry32 } from '@tstdl/base/random';
100
+
101
+ const rootRng = mulberry32(500);
102
+
103
+ // Fork: Creates a new RNG derived from the current state of rootRng.
104
+ // Useful for creating separate RNGs for different game entities or threads.
105
+ const entityRng = rootRng.fork();
106
+
107
+ // Clone: Creates an exact copy of the current state.
108
+ const savedStateRng = rootRng.clone();
109
+
110
+ console.log(rootRng.next()); // 0.123...
111
+ console.log(savedStateRng.next()); // 0.123... (Same as rootRng)
112
+ console.log(entityRng.next()); // 0.876... (Different sequence)
113
+ ```
114
+
115
+ ### Simulating Stock Charts (Complex Series)
116
+
117
+ You can simulate complex data like stock prices by combining bounds, regression, and dynamic volatility.
118
+
119
+ ```ts
120
+ import { randomSeries } from '@tstdl/base/random';
121
+
122
+ // Create a volatility provider that changes over time (e.g., market becomes more volatile)
123
+ const volatilitySeries = randomSeries({
124
+ bounds: [0.01, 0.05], // Volatility between 1% and 5%
125
+ initial: 0.02,
126
+ regressionExponent: 2,
127
+ });
128
+
129
+ // Create the price series
130
+ const stockPrice = randomSeries({
131
+ initial: 100,
132
+ bounds: [50, 150], // Price stays roughly between 50 and 150
133
+ volatility: volatilitySeries, // Use the dynamic volatility
134
+ relativeTo: 'current', // Changes are relative to the last price
135
+ regressionExponent: 5, // Strong pull back to mean (100) when near bounds
136
+ });
137
+
138
+ // Generate 10 data points
139
+ for (let i = 0; i < 10; i++) {
140
+ console.log(`Price: ${stockPrice.next().value?.toFixed(2)}`);
141
+ }
142
+ ```
143
+
144
+ ### Cryptographically Secure Seeds
145
+
146
+ If you need a random seed that is cryptographically secure to initialize your PRNG (Pseudo-Random Number Generator), use the utility provided.
147
+
148
+ ```ts
149
+ import { mulberry32, random32BitSeedCrypto } from '@tstdl/base/random';
150
+
151
+ // Initialize Mulberry32 with a crypto-secure seed
152
+ const secureSeed = random32BitSeedCrypto();
153
+ const rng = mulberry32(secureSeed);
154
+ ```
155
+
156
+ ## 📚 API
157
+
158
+ ### Classes & Interfaces
159
+
160
+ | Name | Description |
161
+ | :---------------------------- | :------------------------------------------------------------------------------ |
162
+ | `RandomNumberGenerator` | Abstract base class defining `next()` and `nextInt()`. |
163
+ | `SeededRandomNumberGenerator` | Abstract class extending `RandomNumberGenerator` with `fork()` and `clone()`. |
164
+ | `Mulberry32` | Implementation of `SeededRandomNumberGenerator` using the Mulberry32 algorithm. |
165
+ | `Sfc32` | Implementation of `SeededRandomNumberGenerator` using the SFC32 algorithm. |
166
+
167
+ ### Functions
168
+
169
+ | Name | Description |
170
+ | :------------------------------- | :----------------------------------------------------------------------------------- |
171
+ | `mulberry32(seed?)` | Factory function to create a `Mulberry32` instance. |
172
+ | `sfc32(seed1?, seed2?, ...)` | Factory function to create an `Sfc32` instance. |
173
+ | `randomSeries(options?)` | Generator function that yields a sequence of numbers based on simulation parameters. |
174
+ | `random32BitSeed()` | Generates a random 32-bit integer using `Math.random()`. |
175
+ | `random32BitSeedCrypto()` | Generates a random 32-bit integer using the environment's crypto API. |
176
+ | `defaultRandomNumberGeneratorFn` | The default RNG function (uses `Math.random`). |
177
+
178
+ ### Types
179
+
180
+ #### `RandomNumberGeneratorFn`
181
+
182
+ A function that returns a random float in the range $[0, 1)$. Equivalent to `() => number`.
183
+
184
+ #### `RandomSeriesOptions`
185
+
186
+ | Property | Type | Default | Description |
187
+ | :------------------- | :------------------------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- |
188
+ | `initial` | `number \| [number, number]` | `bounds ?? 1` | Initial value or range for the series. If a range is provided, a random value within it is chosen using `generator`. |
189
+ | `bounds` | `[number, number]` | `undefined` | Optional `[min, max]` boundaries. When provided, a regression toward the mean is applied as values approach the edges. |
190
+ | `volatility` | `number \| Iterator<number>` | `0.025` | Change factor per step. Can be a fixed number or an iterator for dynamic volatility (e.g., using another `randomSeries`). |
191
+ | `relativeTo` | `'current' \| 'initial'` | `'initial'` | Determines if `volatility` is applied relative to the current value or the initial value. |
192
+ | `regressionExponent` | `number` | `10` | Controls the strength of the pull back toward the mean of `bounds`. Practical values range from 0.5 to 15. High values have little pull near the mean but exponential pull near the bounds. Values < 1 stay very close to the mean. |
193
+ | `generator` | `RandomNumberGeneratorFn` | `Math.random` | The source of randomness for the series. Use a seeded generator for reproducibility. |
@@ -2,6 +2,7 @@ import { Injector } from '../../injector/injector.js';
2
2
  import { type DatabaseConfig } from '../../orm/server/index.js';
3
3
  export declare class PostgresRateLimiterModuleConfig {
4
4
  database?: DatabaseConfig;
5
+ autoMigrate?: boolean;
5
6
  }
6
7
  /**
7
8
  * configure rate limit module
@@ -1,12 +1,13 @@
1
1
  import { inject } from '../../injector/index.js';
2
2
  import { Injector } from '../../injector/injector.js';
3
- import { Database, migrate } from '../../orm/server/index.js';
3
+ import { Database, migrate, registerDatabaseMigration } from '../../orm/server/index.js';
4
4
  import { RateLimiterProvider } from '../provider.js';
5
5
  import { RateLimiter } from '../rate-limiter.js';
6
6
  import { PostgresRateLimiter } from './postgres-rate-limiter.js';
7
7
  import { PostgresRateLimiterProvider } from './rate-limiter.provider.js';
8
8
  export class PostgresRateLimiterModuleConfig {
9
9
  database;
10
+ autoMigrate;
10
11
  }
11
12
  /**
12
13
  * configure rate limit module
@@ -16,6 +17,9 @@ export function configurePostgresRateLimiter({ injector, ...config } = {}) {
16
17
  targetInjector.register(PostgresRateLimiterModuleConfig, { useValue: config });
17
18
  targetInjector.registerSingleton(RateLimiterProvider, { useToken: PostgresRateLimiterProvider });
18
19
  targetInjector.registerSingleton(RateLimiter, { useToken: PostgresRateLimiter });
20
+ if (config.autoMigrate != false) {
21
+ registerDatabaseMigration('PostgresRateLimiter', migratePostgresRateLimiterSchema, { injector });
22
+ }
19
23
  }
20
24
  export async function migratePostgresRateLimiterSchema() {
21
25
  const connection = inject(PostgresRateLimiterModuleConfig, undefined, { optional: true })?.database?.connection;