@spinajs/orm 2.0.481 → 2.0.484

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 (228) hide show
  1. package/README.md +72 -3
  2. package/lib/cjs/bootstrap.js +10 -0
  3. package/lib/cjs/bootstrap.js.map +1 -1
  4. package/lib/cjs/builders.d.ts +127 -11
  5. package/lib/cjs/builders.d.ts.map +1 -1
  6. package/lib/cjs/builders.js +368 -283
  7. package/lib/cjs/builders.js.map +1 -1
  8. package/lib/cjs/converters.d.ts +9 -2
  9. package/lib/cjs/converters.d.ts.map +1 -1
  10. package/lib/cjs/converters.js +48 -8
  11. package/lib/cjs/converters.js.map +1 -1
  12. package/lib/cjs/decorators.d.ts +26 -3
  13. package/lib/cjs/decorators.d.ts.map +1 -1
  14. package/lib/cjs/decorators.js +95 -42
  15. package/lib/cjs/decorators.js.map +1 -1
  16. package/lib/cjs/dehydrators.js +1 -1
  17. package/lib/cjs/dehydrators.js.map +1 -1
  18. package/lib/cjs/descriptor.d.ts +1 -0
  19. package/lib/cjs/descriptor.d.ts.map +1 -1
  20. package/lib/cjs/descriptor.js +16 -40
  21. package/lib/cjs/descriptor.js.map +1 -1
  22. package/lib/cjs/driver.d.ts +136 -7
  23. package/lib/cjs/driver.d.ts.map +1 -1
  24. package/lib/cjs/driver.js +279 -0
  25. package/lib/cjs/driver.js.map +1 -1
  26. package/lib/cjs/existsRelationHandlers.d.ts +29 -0
  27. package/lib/cjs/existsRelationHandlers.d.ts.map +1 -0
  28. package/lib/cjs/existsRelationHandlers.js +138 -0
  29. package/lib/cjs/existsRelationHandlers.js.map +1 -0
  30. package/lib/cjs/fp.d.ts.map +1 -1
  31. package/lib/cjs/fp.js +10 -15
  32. package/lib/cjs/fp.js.map +1 -1
  33. package/lib/cjs/hydrators.d.ts.map +1 -1
  34. package/lib/cjs/hydrators.js +29 -2
  35. package/lib/cjs/hydrators.js.map +1 -1
  36. package/lib/cjs/identity-map.d.ts +60 -0
  37. package/lib/cjs/identity-map.d.ts.map +1 -0
  38. package/lib/cjs/identity-map.js +135 -0
  39. package/lib/cjs/identity-map.js.map +1 -0
  40. package/lib/cjs/index.d.ts +12 -0
  41. package/lib/cjs/index.d.ts.map +1 -1
  42. package/lib/cjs/index.js +12 -0
  43. package/lib/cjs/index.js.map +1 -1
  44. package/lib/cjs/interfaces.d.ts +300 -10
  45. package/lib/cjs/interfaces.d.ts.map +1 -1
  46. package/lib/cjs/interfaces.js +54 -1
  47. package/lib/cjs/interfaces.js.map +1 -1
  48. package/lib/cjs/metadata.d.ts.map +1 -1
  49. package/lib/cjs/metadata.js +4 -1
  50. package/lib/cjs/metadata.js.map +1 -1
  51. package/lib/cjs/metrics.d.ts +53 -0
  52. package/lib/cjs/metrics.d.ts.map +1 -0
  53. package/lib/cjs/metrics.js +82 -0
  54. package/lib/cjs/metrics.js.map +1 -0
  55. package/lib/cjs/middlewares.d.ts +13 -1
  56. package/lib/cjs/middlewares.d.ts.map +1 -1
  57. package/lib/cjs/middlewares.js +55 -15
  58. package/lib/cjs/middlewares.js.map +1 -1
  59. package/lib/cjs/model.d.ts +129 -13
  60. package/lib/cjs/model.d.ts.map +1 -1
  61. package/lib/cjs/model.js +449 -93
  62. package/lib/cjs/model.js.map +1 -1
  63. package/lib/cjs/orm.d.ts.map +1 -1
  64. package/lib/cjs/orm.js +12 -3
  65. package/lib/cjs/orm.js.map +1 -1
  66. package/lib/cjs/orphan.d.ts +27 -0
  67. package/lib/cjs/orphan.d.ts.map +1 -0
  68. package/lib/cjs/orphan.js +55 -0
  69. package/lib/cjs/orphan.js.map +1 -0
  70. package/lib/cjs/primary-keys.d.ts +60 -0
  71. package/lib/cjs/primary-keys.d.ts.map +1 -0
  72. package/lib/cjs/primary-keys.js +243 -0
  73. package/lib/cjs/primary-keys.js.map +1 -0
  74. package/lib/cjs/relation-objects.d.ts +101 -9
  75. package/lib/cjs/relation-objects.d.ts.map +1 -1
  76. package/lib/cjs/relation-objects.js +194 -43
  77. package/lib/cjs/relation-objects.js.map +1 -1
  78. package/lib/cjs/relations.d.ts +7 -1
  79. package/lib/cjs/relations.d.ts.map +1 -1
  80. package/lib/cjs/relations.js +16 -1
  81. package/lib/cjs/relations.js.map +1 -1
  82. package/lib/cjs/resilience.d.ts +50 -0
  83. package/lib/cjs/resilience.d.ts.map +1 -0
  84. package/lib/cjs/resilience.js +70 -0
  85. package/lib/cjs/resilience.js.map +1 -0
  86. package/lib/cjs/snapshot.d.ts +58 -0
  87. package/lib/cjs/snapshot.d.ts.map +1 -0
  88. package/lib/cjs/snapshot.js +125 -0
  89. package/lib/cjs/snapshot.js.map +1 -0
  90. package/lib/cjs/statements.d.ts +11 -1
  91. package/lib/cjs/statements.d.ts.map +1 -1
  92. package/lib/cjs/statements.js +13 -2
  93. package/lib/cjs/statements.js.map +1 -1
  94. package/lib/cjs/subject-builder.d.ts +79 -0
  95. package/lib/cjs/subject-builder.d.ts.map +1 -0
  96. package/lib/cjs/subject-builder.js +296 -0
  97. package/lib/cjs/subject-builder.js.map +1 -0
  98. package/lib/cjs/subject-executor.d.ts +122 -0
  99. package/lib/cjs/subject-executor.d.ts.map +1 -0
  100. package/lib/cjs/subject-executor.js +319 -0
  101. package/lib/cjs/subject-executor.js.map +1 -0
  102. package/lib/cjs/subject-sorter.d.ts +70 -0
  103. package/lib/cjs/subject-sorter.d.ts.map +1 -0
  104. package/lib/cjs/subject-sorter.js +173 -0
  105. package/lib/cjs/subject-sorter.js.map +1 -0
  106. package/lib/cjs/subject.d.ts +100 -0
  107. package/lib/cjs/subject.d.ts.map +1 -0
  108. package/lib/cjs/subject.js +89 -0
  109. package/lib/cjs/subject.js.map +1 -0
  110. package/lib/cjs/unit-of-work.d.ts +52 -0
  111. package/lib/cjs/unit-of-work.d.ts.map +1 -0
  112. package/lib/cjs/unit-of-work.js +170 -0
  113. package/lib/cjs/unit-of-work.js.map +1 -0
  114. package/lib/mjs/bootstrap.js +10 -0
  115. package/lib/mjs/bootstrap.js.map +1 -1
  116. package/lib/mjs/builders.d.ts +127 -11
  117. package/lib/mjs/builders.d.ts.map +1 -1
  118. package/lib/mjs/builders.js +370 -285
  119. package/lib/mjs/builders.js.map +1 -1
  120. package/lib/mjs/converters.d.ts +9 -2
  121. package/lib/mjs/converters.d.ts.map +1 -1
  122. package/lib/mjs/converters.js +48 -8
  123. package/lib/mjs/converters.js.map +1 -1
  124. package/lib/mjs/decorators.d.ts +26 -3
  125. package/lib/mjs/decorators.d.ts.map +1 -1
  126. package/lib/mjs/decorators.js +96 -44
  127. package/lib/mjs/decorators.js.map +1 -1
  128. package/lib/mjs/dehydrators.js +1 -1
  129. package/lib/mjs/dehydrators.js.map +1 -1
  130. package/lib/mjs/descriptor.d.ts +1 -0
  131. package/lib/mjs/descriptor.d.ts.map +1 -1
  132. package/lib/mjs/descriptor.js +17 -39
  133. package/lib/mjs/descriptor.js.map +1 -1
  134. package/lib/mjs/driver.d.ts +136 -7
  135. package/lib/mjs/driver.d.ts.map +1 -1
  136. package/lib/mjs/driver.js +279 -0
  137. package/lib/mjs/driver.js.map +1 -1
  138. package/lib/mjs/existsRelationHandlers.d.ts +29 -0
  139. package/lib/mjs/existsRelationHandlers.d.ts.map +1 -0
  140. package/lib/mjs/existsRelationHandlers.js +134 -0
  141. package/lib/mjs/existsRelationHandlers.js.map +1 -0
  142. package/lib/mjs/fp.d.ts.map +1 -1
  143. package/lib/mjs/fp.js +10 -15
  144. package/lib/mjs/fp.js.map +1 -1
  145. package/lib/mjs/hydrators.d.ts.map +1 -1
  146. package/lib/mjs/hydrators.js +29 -2
  147. package/lib/mjs/hydrators.js.map +1 -1
  148. package/lib/mjs/identity-map.d.ts +60 -0
  149. package/lib/mjs/identity-map.d.ts.map +1 -0
  150. package/lib/mjs/identity-map.js +130 -0
  151. package/lib/mjs/identity-map.js.map +1 -0
  152. package/lib/mjs/index.d.ts +12 -0
  153. package/lib/mjs/index.d.ts.map +1 -1
  154. package/lib/mjs/index.js +12 -0
  155. package/lib/mjs/index.js.map +1 -1
  156. package/lib/mjs/interfaces.d.ts +300 -10
  157. package/lib/mjs/interfaces.d.ts.map +1 -1
  158. package/lib/mjs/interfaces.js +53 -0
  159. package/lib/mjs/interfaces.js.map +1 -1
  160. package/lib/mjs/metadata.d.ts.map +1 -1
  161. package/lib/mjs/metadata.js +4 -1
  162. package/lib/mjs/metadata.js.map +1 -1
  163. package/lib/mjs/metrics.d.ts +53 -0
  164. package/lib/mjs/metrics.d.ts.map +1 -0
  165. package/lib/mjs/metrics.js +76 -0
  166. package/lib/mjs/metrics.js.map +1 -0
  167. package/lib/mjs/middlewares.d.ts +13 -1
  168. package/lib/mjs/middlewares.d.ts.map +1 -1
  169. package/lib/mjs/middlewares.js +55 -15
  170. package/lib/mjs/middlewares.js.map +1 -1
  171. package/lib/mjs/model.d.ts +129 -13
  172. package/lib/mjs/model.d.ts.map +1 -1
  173. package/lib/mjs/model.js +451 -95
  174. package/lib/mjs/model.js.map +1 -1
  175. package/lib/mjs/orm.d.ts.map +1 -1
  176. package/lib/mjs/orm.js +12 -3
  177. package/lib/mjs/orm.js.map +1 -1
  178. package/lib/mjs/orphan.d.ts +27 -0
  179. package/lib/mjs/orphan.d.ts.map +1 -0
  180. package/lib/mjs/orphan.js +52 -0
  181. package/lib/mjs/orphan.js.map +1 -0
  182. package/lib/mjs/primary-keys.d.ts +60 -0
  183. package/lib/mjs/primary-keys.d.ts.map +1 -0
  184. package/lib/mjs/primary-keys.js +223 -0
  185. package/lib/mjs/primary-keys.js.map +1 -0
  186. package/lib/mjs/relation-objects.d.ts +101 -9
  187. package/lib/mjs/relation-objects.d.ts.map +1 -1
  188. package/lib/mjs/relation-objects.js +194 -43
  189. package/lib/mjs/relation-objects.js.map +1 -1
  190. package/lib/mjs/relations.d.ts +7 -1
  191. package/lib/mjs/relations.d.ts.map +1 -1
  192. package/lib/mjs/relations.js +16 -1
  193. package/lib/mjs/relations.js.map +1 -1
  194. package/lib/mjs/resilience.d.ts +50 -0
  195. package/lib/mjs/resilience.d.ts.map +1 -0
  196. package/lib/mjs/resilience.js +64 -0
  197. package/lib/mjs/resilience.js.map +1 -0
  198. package/lib/mjs/snapshot.d.ts +58 -0
  199. package/lib/mjs/snapshot.d.ts.map +1 -0
  200. package/lib/mjs/snapshot.js +115 -0
  201. package/lib/mjs/snapshot.js.map +1 -0
  202. package/lib/mjs/statements.d.ts +11 -1
  203. package/lib/mjs/statements.d.ts.map +1 -1
  204. package/lib/mjs/statements.js +14 -3
  205. package/lib/mjs/statements.js.map +1 -1
  206. package/lib/mjs/subject-builder.d.ts +79 -0
  207. package/lib/mjs/subject-builder.d.ts.map +1 -0
  208. package/lib/mjs/subject-builder.js +292 -0
  209. package/lib/mjs/subject-builder.js.map +1 -0
  210. package/lib/mjs/subject-executor.d.ts +122 -0
  211. package/lib/mjs/subject-executor.d.ts.map +1 -0
  212. package/lib/mjs/subject-executor.js +312 -0
  213. package/lib/mjs/subject-executor.js.map +1 -0
  214. package/lib/mjs/subject-sorter.d.ts +70 -0
  215. package/lib/mjs/subject-sorter.d.ts.map +1 -0
  216. package/lib/mjs/subject-sorter.js +168 -0
  217. package/lib/mjs/subject-sorter.js.map +1 -0
  218. package/lib/mjs/subject.d.ts +100 -0
  219. package/lib/mjs/subject.d.ts.map +1 -0
  220. package/lib/mjs/subject.js +84 -0
  221. package/lib/mjs/subject.js.map +1 -0
  222. package/lib/mjs/unit-of-work.d.ts +52 -0
  223. package/lib/mjs/unit-of-work.d.ts.map +1 -0
  224. package/lib/mjs/unit-of-work.js +166 -0
  225. package/lib/mjs/unit-of-work.js.map +1 -0
  226. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  227. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  228. package/package.json +10 -7
package/lib/mjs/driver.js CHANGED
@@ -13,9 +13,20 @@ import { ModelToSqlConverter, ObjectToSqlConverter } from './interfaces.js';
13
13
  import { SyncService, DI, Container, Autoinject } from '@spinajs/di';
14
14
  import { UpdateQueryBuilder, SelectQueryBuilder, IndexQueryBuilder, DeleteQueryBuilder, InsertQueryBuilder, SchemaQueryBuilder, TruncateTableQueryBuilder } from './builders.js';
15
15
  import { JsonValueConverter, StandardModelToSqlConverter, StandardObjectToSqlConverter, UniversalValueConverter, UuidConverter } from './converters.js';
16
+ import { OrmException } from './exceptions.js';
17
+ import { AsyncLocalStorage } from 'async_hooks';
18
+ import { backoffDelay, ConnectionState, delay, isRetryableErrorCode } from './resilience.js';
19
+ import { ORM_METRIC_KEY_ACQUIRE_SECONDS, ORM_METRIC_KEY_CONNECTION_STATE, ORM_METRIC_KEY_POOL_IN_USE, ORM_METRIC_KEY_POOL_SIZE, ORM_METRIC_KEY_POOL_WAITING, ormGauge, ormHistogram, ormMetrics } from './metrics.js';
16
20
  import './hydrators.js';
17
21
  import './dehydrators.js';
18
22
  export class OrmDriver extends SyncService {
23
+ /**
24
+ * The transaction currently in scope on this async execution path, or `undefined` outside
25
+ * a transaction.
26
+ */
27
+ get CurrentTransaction() {
28
+ return this.TransactionStorage.getStore();
29
+ }
19
30
  constructor(options) {
20
31
  super();
21
32
  /**
@@ -27,6 +38,22 @@ export class OrmDriver extends SyncService {
27
38
  Name: 'orm-driver',
28
39
  DefaultConnection: false,
29
40
  };
41
+ /**
42
+ * Ambient transaction context.
43
+ *
44
+ * Statements executed inside a `transaction()` callback must run on that transaction's
45
+ * connection. This lives on the abstract driver — rather than being a MySQL implementation
46
+ * detail, as it used to be — so the guarantee is part of the contract and every driver
47
+ * inherits it.
48
+ */
49
+ this.TransactionStorage = new AsyncLocalStorage();
50
+ /**
51
+ * Isolation levels this driver honours. Empty by default: a driver that declares nothing
52
+ * rejects every explicitly requested isolation level rather than quietly ignoring it.
53
+ */
54
+ this.SupportedIsolationLevels = [];
55
+ this._state = ConnectionState.Disconnected;
56
+ this._healthCheckTimer = null;
30
57
  this.Options = Object.assign(this.Options, options);
31
58
  }
32
59
  resolve() {
@@ -41,6 +68,207 @@ export class OrmDriver extends SyncService {
41
68
  this.Container.register(UuidConverter).as(UuidConverter);
42
69
  this.Container.register(UniversalValueConverter).as(UniversalValueConverter);
43
70
  }
71
+ /**
72
+ * Effective pool settings: `Pool.*` when given, then the deprecated `PoolLimit` for `Max`,
73
+ * then the defaults. Resolved in one place so every driver agrees on what "unset" means.
74
+ */
75
+ resolvedPoolOptions() {
76
+ const pool = this.Options.Pool ?? {};
77
+ return {
78
+ Min: pool.Min ?? 0,
79
+ Max: pool.Max ?? this.Options.PoolLimit ?? 10,
80
+ IdleTimeout: pool.IdleTimeout ?? 30000,
81
+ AcquireTimeout: pool.AcquireTimeout ?? 10000,
82
+ };
83
+ }
84
+ /**
85
+ * Current connection lifecycle state.
86
+ */
87
+ get State() {
88
+ return this._state;
89
+ }
90
+ /**
91
+ * Records a state transition and logs it. Repeat transitions to the same state are ignored.
92
+ */
93
+ setState(state) {
94
+ if (this._state === state) {
95
+ return;
96
+ }
97
+ const previous = this._state;
98
+ this._state = state;
99
+ if (state === ConnectionState.Connected) {
100
+ this.Log.info(`connection ${this.Options.Name} is ${state} (was ${previous})`);
101
+ }
102
+ else if (state === ConnectionState.Degraded || state === ConnectionState.Disconnected) {
103
+ this.Log.warn(`connection ${this.Options.Name} is ${state} (was ${previous})`);
104
+ }
105
+ else {
106
+ this.Log.trace(`connection ${this.Options.Name} is ${state} (was ${previous})`);
107
+ }
108
+ }
109
+ /**
110
+ * Effective resilience settings with defaults applied.
111
+ */
112
+ resolvedResilienceOptions() {
113
+ const r = this.Options.Resilience ?? {};
114
+ return {
115
+ HealthCheckInterval: r.HealthCheckInterval ?? 30000,
116
+ MaxRetries: r.MaxRetries ?? 5,
117
+ RetryDelay: r.RetryDelay ?? 200,
118
+ MaxRetryDelay: r.MaxRetryDelay ?? 5000,
119
+ };
120
+ }
121
+ /**
122
+ * True when the error means the transport died rather than the statement being wrong.
123
+ * Drivers override to add dialect-specific codes.
124
+ */
125
+ isRetryableError(err) {
126
+ return isRetryableErrorCode(err);
127
+ }
128
+ /**
129
+ * Runs `operation`, and on a retryable transport failure reconnects and retries with bounded
130
+ * exponential backoff. Query errors propagate on the first attempt untouched.
131
+ */
132
+ async withReconnect(operation) {
133
+ const { MaxRetries, RetryDelay, MaxRetryDelay } = this.resolvedResilienceOptions();
134
+ let lastError;
135
+ for (let attempt = 0; attempt <= MaxRetries; attempt++) {
136
+ try {
137
+ const result = await operation();
138
+ this.setState(ConnectionState.Connected);
139
+ return result;
140
+ }
141
+ catch (err) {
142
+ if (!this.isRetryableError(err)) {
143
+ throw err;
144
+ }
145
+ lastError = err;
146
+ this.setState(ConnectionState.Degraded);
147
+ if (attempt === MaxRetries) {
148
+ break;
149
+ }
150
+ const wait = backoffDelay(attempt, RetryDelay, MaxRetryDelay);
151
+ this.Log.warn(`connection ${this.Options.Name} lost (${err.message}); reconnect attempt ${attempt + 1}/${MaxRetries} in ${wait}ms`);
152
+ await delay(wait);
153
+ try {
154
+ this.setState(ConnectionState.Connecting);
155
+ await this.connect();
156
+ }
157
+ catch (reconnectErr) {
158
+ this.Log.warn(`reconnect attempt ${attempt + 1} for ${this.Options.Name} failed: ${reconnectErr.message}`);
159
+ this.setState(ConnectionState.Degraded);
160
+ }
161
+ }
162
+ }
163
+ this.setState(ConnectionState.Disconnected);
164
+ throw lastError;
165
+ }
166
+ /**
167
+ * Starts the periodic health probe. Replaces the single startup `ping()` — a connection that
168
+ * was healthy at boot tells you nothing about a pool holding sockets to a database that has
169
+ * since restarted. No-op when `Resilience.HealthCheckInterval` is 0. Idempotent.
170
+ */
171
+ startHealthCheck() {
172
+ const { HealthCheckInterval } = this.resolvedResilienceOptions();
173
+ if (HealthCheckInterval <= 0 || this._healthCheckTimer !== null) {
174
+ return;
175
+ }
176
+ this._healthCheckTimer = setInterval(() => {
177
+ void this.runHealthCheck();
178
+ }, HealthCheckInterval);
179
+ // Never hold the process open just to probe a database.
180
+ if (typeof this._healthCheckTimer.unref === 'function') {
181
+ this._healthCheckTimer.unref();
182
+ }
183
+ }
184
+ /**
185
+ * Stops the periodic health probe. Idempotent.
186
+ */
187
+ stopHealthCheck() {
188
+ if (this._healthCheckTimer !== null) {
189
+ clearInterval(this._healthCheckTimer);
190
+ this._healthCheckTimer = null;
191
+ }
192
+ }
193
+ /**
194
+ * One health probe. A failed probe degrades the driver and attempts a single reconnect; it
195
+ * never throws, because it runs on a timer with no caller to receive the error.
196
+ */
197
+ async runHealthCheck() {
198
+ this.publishPoolMetrics();
199
+ let alive = false;
200
+ try {
201
+ alive = await this.ping();
202
+ }
203
+ catch {
204
+ alive = false;
205
+ }
206
+ if (alive) {
207
+ this.setState(ConnectionState.Connected);
208
+ return;
209
+ }
210
+ this.setState(ConnectionState.Degraded);
211
+ try {
212
+ // The driver stays DEGRADED even when reconnecting succeeds: a fresh handle is not
213
+ // evidence that queries work. Only the next successful probe promotes it back to
214
+ // Connected — drivers whose own connect() verifies the link ( mysql takes and releases
215
+ // a real connection ) set the state themselves.
216
+ await this.connect();
217
+ }
218
+ catch (err) {
219
+ this.Log.warn(`health check reconnect for ${this.Options.Name} failed: ${err.message}`);
220
+ }
221
+ }
222
+ /**
223
+ * Point-in-time pool state. The base implementation reports an empty pool; drivers that own a
224
+ * real pool override it. Must never throw — it runs on the health-check timer.
225
+ */
226
+ poolMetrics() {
227
+ return { Size: 0, InUse: 0, Waiting: 0 };
228
+ }
229
+ /**
230
+ * Pushes the current pool state and connection state to the shared `Metrics` registry from
231
+ * `@spinajs/telemetry-common`. Nothing has to be wired for this to work — `Metrics` owns a
232
+ * private registry and `@spinajs/telemetry`'s `/metrics` endpoint renders that same singleton.
233
+ */
234
+ publishPoolMetrics() {
235
+ try {
236
+ const metrics = ormMetrics();
237
+ if (!metrics) {
238
+ return;
239
+ }
240
+ const labels = { connection: this.Options.Name };
241
+ const pool = this.poolMetrics();
242
+ ormGauge(metrics, ORM_METRIC_KEY_POOL_SIZE).set(labels, pool.Size);
243
+ ormGauge(metrics, ORM_METRIC_KEY_POOL_IN_USE).set(labels, pool.InUse);
244
+ ormGauge(metrics, ORM_METRIC_KEY_POOL_WAITING).set(labels, pool.Waiting);
245
+ ormGauge(metrics, ORM_METRIC_KEY_CONNECTION_STATE).set(labels, this.State === ConnectionState.Connected ? 1 : 0);
246
+ }
247
+ catch (err) {
248
+ // Telemetry must never break a connection. This runs first on every health tick, so a
249
+ // registry that throws — or a driver built outside DI, as tooling and tests do — would
250
+ // otherwise stop the probe that follows it from ever running.
251
+ this.Log?.trace(`publishing pool metrics for ${this.Options.Name} failed: ${err.message}`);
252
+ }
253
+ }
254
+ /**
255
+ * Records one pool-acquire wait, in SECONDS ( prometheus convention ). Drivers that own a real
256
+ * pool call this from the acquire callback; keeping the prom-client objects behind this method
257
+ * is what stops every driver from needing to know about `@spinajs/telemetry-common`. Never
258
+ * throws, for the same reason `publishPoolMetrics` never throws.
259
+ */
260
+ observeAcquireSeconds(seconds) {
261
+ try {
262
+ const metrics = ormMetrics();
263
+ if (!metrics) {
264
+ return;
265
+ }
266
+ ormHistogram(metrics, ORM_METRIC_KEY_ACQUIRE_SECONDS).observe({ connection: this.Options.Name }, seconds);
267
+ }
268
+ catch (err) {
269
+ this.Log?.trace(`observing pool acquire time for ${this.Options.Name} failed: ${err.message}`);
270
+ }
271
+ }
44
272
  /**
45
273
  * Creates select query builder associated with this connection.
46
274
  * This can be used to execute raw queries to db without orm model layer
@@ -91,6 +319,57 @@ export class OrmDriver extends SyncService {
91
319
  index() {
92
320
  return this.Container.resolve(IndexQueryBuilder, [this]);
93
321
  }
322
+ /**
323
+ * Runs `cb` inside a transaction and owns its whole lifecycle: commits when the callback
324
+ * resolves, rolls back when it throws, and releases the connection exactly once either way.
325
+ * Resolves with whatever the callback returned.
326
+ *
327
+ * Statements issued inside the callback run on this transaction's connection automatically —
328
+ * the context is carried through `AsyncLocalStorage`, so nothing has to be threaded through
329
+ * by hand.
330
+ *
331
+ * Calling it again while a transaction is already in scope on this async path does **not**
332
+ * open a second, independent transaction: it takes a savepoint, so a failing nested block
333
+ * rolls back only its own work.
334
+ *
335
+ * @param cb - the transaction body
336
+ * @param options - optional isolation level, validated against {@link SupportedIsolationLevels}
337
+ */
338
+ async transaction(cb, options) {
339
+ if (options?.isolation && !this.SupportedIsolationLevels.includes(options.isolation)) {
340
+ throw new OrmException(`isolation level ${options.isolation} not supported by driver ${this.Options.Driver}`);
341
+ }
342
+ const active = this.TransactionStorage.getStore();
343
+ // already inside a transaction — nest with a savepoint rather than opening a second one
344
+ if (active) {
345
+ const name = `sp_${++active.depth}`;
346
+ await this._savepoint(active, name);
347
+ try {
348
+ const result = await cb(this);
349
+ await this._releaseSavepoint(active, name);
350
+ return result;
351
+ }
352
+ catch (err) {
353
+ await this._rollbackToSavepoint(active, name);
354
+ throw err;
355
+ }
356
+ }
357
+ const ctx = await this._begin(options);
358
+ ctx.depth = 0;
359
+ try {
360
+ const result = await this.TransactionStorage.run(ctx, () => cb(this));
361
+ await this._commit(ctx);
362
+ return result;
363
+ }
364
+ catch (err) {
365
+ // swallow a rollback failure so it cannot mask whatever actually went wrong
366
+ await this._rollback(ctx).catch(() => undefined);
367
+ throw err;
368
+ }
369
+ finally {
370
+ await this._dispose(ctx);
371
+ }
372
+ }
94
373
  }
95
374
  __decorate([
96
375
  Autoinject(),
@@ -1 +1 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/driver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { IRelationDescriptor, ISelectQueryBuilder, RelationType } from './interfaces.js';
2
+ import type { WhereBuilder } from './builders.js';
3
+ import { WhereFunction } from './types.js';
4
+ /**
5
+ * Strategy that builds the EXISTS / NOT EXISTS clause for one relation type.
6
+ *
7
+ * Resolved via `Array.ofType(ExistsRelationHandler)` and dispatched by `rel.Type` from
8
+ * `WhereBuilder.buildExistsClause`. Implementations either:
9
+ * - mutate the outer builder directly and return `undefined` (eg. {@link RelationType.One}
10
+ * adds `WHERE FK IS NOT NULL` plus a right-join, no EXISTS sub-query is generated), or
11
+ * - return a correlated sub-query that the caller wraps in EXISTS/NOT EXISTS.
12
+ */
13
+ export declare abstract class ExistsRelationHandler {
14
+ abstract get Type(): RelationType;
15
+ abstract apply<R>(builder: WhereBuilder<any>, rel: IRelationDescriptor, relationName: string, callback?: WhereFunction<R>): ISelectQueryBuilder | undefined;
16
+ }
17
+ export declare class OneExistsRelationHandler extends ExistsRelationHandler {
18
+ get Type(): RelationType;
19
+ apply<R>(builder: WhereBuilder<any>, rel: IRelationDescriptor, _relationName: string, callback?: WhereFunction<R>): ISelectQueryBuilder | undefined;
20
+ }
21
+ export declare class ManyExistsRelationHandler extends ExistsRelationHandler {
22
+ get Type(): RelationType;
23
+ apply<R>(builder: WhereBuilder<any>, rel: IRelationDescriptor, _relationName: string, callback?: WhereFunction<R>): ISelectQueryBuilder;
24
+ }
25
+ export declare class ManyToManyExistsRelationHandler extends ExistsRelationHandler {
26
+ get Type(): RelationType;
27
+ apply<R>(builder: WhereBuilder<any>, rel: IRelationDescriptor, _relationName: string, callback?: WhereFunction<R>): ISelectQueryBuilder;
28
+ }
29
+ //# sourceMappingURL=existsRelationHandlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"existsRelationHandlers.d.ts","sourceRoot":"","sources":["../../src/existsRelationHandlers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAgB,mBAAmB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEvG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;GAQG;AACH,8BAAsB,qBAAqB;IACzC,aAAoB,IAAI,IAAI,YAAY,CAAC;aAEzB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,GAAG,SAAS;CACnK;AAuBD,qBACa,wBAAyB,SAAQ,qBAAqB;IACjE,IAAW,IAAI,IAAI,YAAY,CAE9B;IAEM,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,GAAG,SAAS;CAyC3J;AAED,qBACa,yBAA0B,SAAQ,qBAAqB;IAClE,IAAW,IAAI,IAAI,YAAY,CAE9B;IAEM,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB;CAmB/I;AAED,qBACa,+BAAgC,SAAQ,qBAAqB;IACxE,IAAW,IAAI,IAAI,YAAY,CAE9B;IAEM,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB;CAuB/I"}
@@ -0,0 +1,134 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /* eslint-disable prettier/prettier */
8
+ import { Injectable } from '@spinajs/di';
9
+ import { Lazy } from '@spinajs/util';
10
+ import { RelationType } from './interfaces.js';
11
+ import { RawQuery } from './builders.js';
12
+ /**
13
+ * Strategy that builds the EXISTS / NOT EXISTS clause for one relation type.
14
+ *
15
+ * Resolved via `Array.ofType(ExistsRelationHandler)` and dispatched by `rel.Type` from
16
+ * `WhereBuilder.buildExistsClause`. Implementations either:
17
+ * - mutate the outer builder directly and return `undefined` (eg. {@link RelationType.One}
18
+ * adds `WHERE FK IS NOT NULL` plus a right-join, no EXISTS sub-query is generated), or
19
+ * - return a correlated sub-query that the caller wraps in EXISTS/NOT EXISTS.
20
+ */
21
+ export class ExistsRelationHandler {
22
+ }
23
+ /**
24
+ * Resolves the correlated source primary key column reference, eg. `` `users`.`Id` ``.
25
+ * Falls back to the source descriptor's `TableName` when neither the builder nor its parent
26
+ * has an alias set, matching the legacy behaviour of `whereExist` / `whereNotExists`.
27
+ */
28
+ function sourcePKeyRef(builder, tDesc) {
29
+ return sourceColumnRef(builder, tDesc, tDesc.PrimaryKey[0]);
30
+ }
31
+ /**
32
+ * Resolves an arbitrary correlated column on the source side, eg. `` `entries`.`group_id` ``.
33
+ *
34
+ * {@link RelationType.One} correlates on the source's FOREIGN key rather than its primary
35
+ * key, so it cannot reuse {@link sourcePKeyRef}. Both share the alias resolution: the
36
+ * builder's alias, its parent's, or the source table name.
37
+ */
38
+ function sourceColumnRef(builder, tDesc, column) {
39
+ const sourceAlias = builder.TableAlias ?? tDesc.TableName;
40
+ return `\`${sourceAlias}\`.\`${column}\``;
41
+ }
42
+ let OneExistsRelationHandler = class OneExistsRelationHandler extends ExistsRelationHandler {
43
+ get Type() {
44
+ return RelationType.One;
45
+ }
46
+ apply(builder, rel, _relationName, callback) {
47
+ builder.whereNotNull(rel.ForeignKey);
48
+ // A belongsTo with a non-null FK always has its parent row, so an unconditional check
49
+ // needs no sub-query at all.
50
+ if (!callback) {
51
+ return undefined;
52
+ }
53
+ /**
54
+ * Correlated EXISTS, NOT a join.
55
+ *
56
+ * This ran as `builder.rightJoin(...)` on the OUTER builder, which only ever worked on
57
+ * selects: `UpdateQueryBuilder` mixes in `WhereBuilder` alone and `DeleteQueryBuilder`
58
+ * adds only `LimitBuilder`, so neither defines `rightJoin`. The rbac middleware runs
59
+ * `afterQueryCreation` on all three builder types, so any model reaching ownership
60
+ * through a belongsTo threw a TypeError the moment it was updated or deleted, and had
61
+ * to hand-roll the correlation in raw SQL instead.
62
+ *
63
+ * EXISTS is also the semantics the method name promises: the join form leaked the
64
+ * joined table's columns into the outer result and turned an existence test into a
65
+ * row-multiplying join.
66
+ */
67
+ const tDesc = builder.Model.getModelDescriptor();
68
+ const alias = `${rel.TargetModel.getModelDescriptor().TableName}_exists`;
69
+ const relQuery = rel.TargetModel.query().setAlias(alias);
70
+ // lazy, so the outer alias is resolved at compile time - it may be assigned after this
71
+ // handler runs. Both sides stay alias-qualified so a callback that joins further tables
72
+ // cannot make the correlation column ambiguous.
73
+ relQuery.where(Lazy.oF(function () {
74
+ relQuery.where(new RawQuery(`\`${alias}\`.\`${rel.PrimaryKey}\` = ${sourceColumnRef(builder, tDesc, rel.ForeignKey)}`));
75
+ }));
76
+ callback.apply(relQuery);
77
+ return relQuery;
78
+ }
79
+ };
80
+ OneExistsRelationHandler = __decorate([
81
+ Injectable(ExistsRelationHandler)
82
+ ], OneExistsRelationHandler);
83
+ export { OneExistsRelationHandler };
84
+ let ManyExistsRelationHandler = class ManyExistsRelationHandler extends ExistsRelationHandler {
85
+ get Type() {
86
+ return RelationType.Many;
87
+ }
88
+ apply(builder, rel, _relationName, callback) {
89
+ const tDesc = builder.Model.getModelDescriptor();
90
+ const tableName = rel.TargetModel.getModelDescriptor().TableName;
91
+ // set alias to avoid conflicts in case of multiple relations to same model and to make
92
+ // sure that relation query is correct even if source query has alias
93
+ const relQuery = rel.TargetModel.query().setAlias(`${tableName}_exists`);
94
+ relQuery.where(Lazy.oF(function () {
95
+ relQuery.where(new RawQuery(`${rel.ForeignKey} = ${sourcePKeyRef(builder, tDesc)}`));
96
+ }));
97
+ if (callback) {
98
+ callback.apply(relQuery);
99
+ }
100
+ return relQuery;
101
+ }
102
+ };
103
+ ManyExistsRelationHandler = __decorate([
104
+ Injectable(ExistsRelationHandler)
105
+ ], ManyExistsRelationHandler);
106
+ export { ManyExistsRelationHandler };
107
+ let ManyToManyExistsRelationHandler = class ManyToManyExistsRelationHandler extends ExistsRelationHandler {
108
+ get Type() {
109
+ return RelationType.ManyToMany;
110
+ }
111
+ apply(builder, rel, _relationName, callback) {
112
+ const tDesc = builder.Model.getModelDescriptor();
113
+ const junctionModel = rel.JunctionModel;
114
+ const junctionTableName = junctionModel.getModelDescriptor().TableName;
115
+ const relQuery = junctionModel.query().setAlias(`${junctionTableName}_exists`);
116
+ relQuery.where(Lazy.oF(function () {
117
+ relQuery.where(new RawQuery(`${rel.JunctionModelSourceModelFKey_Name} = ${sourcePKeyRef(builder, tDesc)}`));
118
+ }));
119
+ if (callback) {
120
+ relQuery.rightJoin({
121
+ joinModel: rel.TargetModel,
122
+ joinTableForeignKey: rel.PrimaryKey,
123
+ sourceTablePrimaryKey: rel.JunctionModelTargetModelFKey_Name,
124
+ callback: callback,
125
+ });
126
+ }
127
+ return relQuery;
128
+ }
129
+ };
130
+ ManyToManyExistsRelationHandler = __decorate([
131
+ Injectable(ExistsRelationHandler)
132
+ ], ManyToManyExistsRelationHandler);
133
+ export { ManyToManyExistsRelationHandler };
134
+ //# sourceMappingURL=existsRelationHandlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"existsRelationHandlers.js","sourceRoot":"","sources":["../../src/existsRelationHandlers.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fp.d.ts","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAiB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,oBAAY,WAAW;IACrB,kBAAkB,IAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,sBAY1G;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAUvF;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAuB9G;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAU/E;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAUvE"}
1
+ {"version":3,"file":"fp.d.ts","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAiB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,oBAAY,WAAW;IACrB,kBAAkB,IAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,sBAY1G;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAMvF;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAyB9G;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAK/E;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAUvE"}
package/lib/mjs/fp.js CHANGED
@@ -32,12 +32,9 @@ export function _get_entity(idOrEntity, c, fresh) {
32
32
  */
33
33
  export function _update(data) {
34
34
  return (model) => {
35
- return model.update(data).then((res) => {
36
- if (res.LastInsertId <= 0 || res.RowsAffected <= 0) {
37
- return Promise.reject(new ErrorCode(E_ORM_CODES.E_NO_ROWS_AFFECTED));
38
- }
39
- return model;
40
- });
35
+ // A clean model short-circuits to { RowsAffected: 0 } - that is a no-op success,
36
+ // not a failure, so we always resolve the model.
37
+ return model.update(data).then(() => model);
41
38
  };
42
39
  }
43
40
  /**
@@ -53,14 +50,16 @@ export function _insert(behaviour) {
53
50
  return Promise.resolve(model);
54
51
  }
55
52
  return model[0].constructor.insert(model, behaviour).then((res) => {
56
- if (res.LastInsertId <= 0 || res.RowsAffected <= 0) {
53
+ // `uuid` and `assigned` primary keys report LastInsertId 0 on a successful insert, so
54
+ // only RowsAffected signals failure. See @Primary({ generated }) in the ORM docs.
55
+ if (res.RowsAffected <= 0) {
57
56
  return Promise.reject(new ErrorCode(E_ORM_CODES.E_NO_ROWS_AFFECTED));
58
57
  }
59
58
  return model;
60
59
  });
61
60
  }
62
61
  return model.insert(behaviour).then((res) => {
63
- if (res.LastInsertId <= 0 || res.RowsAffected <= 0) {
62
+ if (res.RowsAffected <= 0) {
64
63
  return Promise.reject(new ErrorCode(E_ORM_CODES.E_NO_ROWS_AFFECTED));
65
64
  }
66
65
  return model;
@@ -69,12 +68,8 @@ export function _insert(behaviour) {
69
68
  }
70
69
  export function _insertOrUpdate() {
71
70
  return (model) => {
72
- return model.insertOrUpdate().then((res) => {
73
- if (res.LastInsertId <= 0 || res.RowsAffected <= 0) {
74
- return Promise.reject(new ErrorCode(E_ORM_CODES.E_NO_ROWS_AFFECTED));
75
- }
76
- return model;
77
- });
71
+ // insertOrUpdate on a clean model is a no-op success (RowsAffected 0) - resolve the model.
72
+ return model.insertOrUpdate().then(() => model);
78
73
  };
79
74
  }
80
75
  /**
@@ -86,7 +81,7 @@ export function _insertOrUpdate() {
86
81
  export function _delete() {
87
82
  return (model) => {
88
83
  return model.destroy().then((res) => {
89
- if (res.LastInsertId <= 0 || res.RowsAffected <= 0) {
84
+ if (res.RowsAffected <= 0) {
90
85
  return Promise.reject(new ErrorCode(E_ORM_CODES.E_NO_ROWS_AFFECTED));
91
86
  }
92
87
  return model;
package/lib/mjs/fp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fp.js","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,CAAN,IAAY,WAEX;AAFD,WAAY,WAAW;IACrB,yEAAkB,CAAA;AACpB,CAAC,EAFW,WAAW,KAAX,WAAW,QAEtB;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAsB,UAAsB,EAAE,CAAiB,EAAE,KAAe;IACzG,OAAO,KAAK,IAAI,EAAE;QAChB,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAQ,CAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,UAAU,CAAC,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAsB,IAAiB;IAC5D,OAAO,CAAC,KAAQ,EAAE,EAAE;QAClB,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAkB,EAAE,EAAE;YACpD,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;gBACnD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACvE,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAsB,SAA2B;IACtE,OAAO,CAAC,KAAc,EAAE,EAAE;QACxB,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YACD,OAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,WAAgC,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAkB,EAAE,EAAE;gBACrG,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;oBACnD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;gBACvE,CAAC;gBAED,OAAO,KAAK,CAAC;YACf,CAAC,CAAiB,CAAC;QACrB,CAAC;QAED,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAkB,EAAE,EAAE;YACzD,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;gBACnD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACvE,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,KAAQ,EAAE,EAAE;QAClB,OAAO,KAAK,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,GAAkB,EAAE,EAAE;YACxD,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;gBACnD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACvE,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,KAAQ,EAAE,EAAE;QAClB,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,GAAkB,EAAE,EAAE;YACjD,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;gBACnD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACvE,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"fp.js","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hydrators.d.ts","sourceRoot":"","sources":["../../src/hydrators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,8BAAsB,aAAa;aACjB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CACxD;AAED,qBACa,kBAAmB,SAAQ,aAAa;IAC5C,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAuBrD;AAED,qBACa,qBAAsB,SAAQ,aAAa;IAC/C,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAYrD;AAED,qBACa,yBAA0B,SAAQ,aAAa;IACnD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CA2BrD;AAED,qBACa,wBAAyB,SAAQ,aAAa;IAClD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAyBrD;AAED,qBACa,6BAA8B,SAAQ,aAAa;IACvD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAarD"}
1
+ {"version":3,"file":"hydrators.d.ts","sourceRoot":"","sources":["../../src/hydrators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,8BAAsB,aAAa;aACjB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CACxD;AAED,qBACa,kBAAmB,SAAQ,aAAa;IAC5C,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAiCrD;AAED,qBACa,qBAAsB,SAAQ,aAAa;IAC/C,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAYrD;AAED,qBACa,yBAA0B,SAAQ,aAAa;IACnD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CA+BrD;AAED,qBACa,wBAAyB,SAAQ,aAAa;IAClD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAuCrD;AAED,qBACa,6BAA8B,SAAQ,aAAa;IACvD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;CAarD"}