@spinajs/orm 2.0.481 → 2.0.482

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 +115 -11
  5. package/lib/cjs/builders.d.ts.map +1 -1
  6. package/lib/cjs/builders.js +342 -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 +104 -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 +295 -9
  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 +115 -11
  117. package/lib/mjs/builders.d.ts.map +1 -1
  118. package/lib/mjs/builders.js +344 -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 +100 -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 +295 -9
  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 +9 -7
@@ -0,0 +1,100 @@
1
+ import { IModelDescriptor, IRelationDescriptor, OrphanPolicy } from './interfaces.js';
2
+ import type { ModelBase } from './model.js';
3
+ /**
4
+ * What `save()` will do with one model instance.
5
+ *
6
+ * There is no `delete` member: every row `save()` removes is removed because it was detached
7
+ * from a relation, and that is carried by `IOrphanDelta` keyed by primary key rather than by
8
+ * a subject over a model instance the caller no longer holds.
9
+ */
10
+ export declare enum SubjectOperation {
11
+ Insert = "insert",
12
+ Update = "update",
13
+ None = "none"
14
+ }
15
+ /**
16
+ * A foreign-key column whose value is another model's primary key — which may not exist yet
17
+ * when the subject is built. Resolved by the executor immediately before the statement that
18
+ * needs it.
19
+ */
20
+ export interface IPendingForeignKey {
21
+ /** Column on this subject's own row that receives the key. */
22
+ Column: string;
23
+ /** Model whose primary key is the value. */
24
+ Target: ModelBase;
25
+ }
26
+ /**
27
+ * The membership change of one hasMany relation on one owner, as of the snapshot diff.
28
+ *
29
+ * `Added` are members with no snapshot ( never in the database ). `Kept` are members that
30
+ * were already there or were re-parented in from elsewhere. `RemovedKeys` are primary keys
31
+ * that were in the snapshot and are not in the array any more.
32
+ */
33
+ export interface IRelationDelta {
34
+ Descriptor: IRelationDescriptor;
35
+ Added: ModelBase[];
36
+ Kept: ModelBase[];
37
+ RemovedKeys: unknown[];
38
+ }
39
+ /**
40
+ * Junction rows to create and destroy for one manyToMany relation on one owner.
41
+ * `Added` holds target models because their keys may not exist yet; `RemovedKeys` holds
42
+ * plain keys because those models are gone from the array.
43
+ */
44
+ export interface IJunctionDelta {
45
+ Descriptor: IRelationDescriptor;
46
+ JunctionDescriptor: IModelDescriptor;
47
+ Owner: ModelBase;
48
+ Added: ModelBase[];
49
+ RemovedKeys: unknown[];
50
+ }
51
+ /**
52
+ * Rows detached from a relation and the policy that decides their fate.
53
+ */
54
+ export interface IOrphanDelta {
55
+ Descriptor: IRelationDescriptor;
56
+ TargetDescriptor: IModelDescriptor;
57
+ Policy: OrphanPolicy;
58
+ PrimaryKeys: unknown[];
59
+ }
60
+ /**
61
+ * One model instance and everything `save()` needs to know about it.
62
+ */
63
+ export declare class Subject {
64
+ readonly Model: ModelBase;
65
+ readonly Descriptor: IModelDescriptor;
66
+ Operation: SubjectOperation;
67
+ /** Columns that differ from the snapshot. Empty for an insert, which writes everything. */
68
+ ChangedColumns: string[];
69
+ /** Foreign keys resolved just before this subject's own statement runs. */
70
+ PendingForeignKeys: IPendingForeignKey[];
71
+ /**
72
+ * Foreign keys that cannot be resolved before this subject's INSERT — a self-referencing
73
+ * cycle — and are applied by a follow-up UPDATE in the update phase instead.
74
+ */
75
+ DeferredForeignKeys: IPendingForeignKey[];
76
+ /** hasMany membership changes owned by this subject. Read by the orphan resolver. */
77
+ RelationDeltas: IRelationDelta[];
78
+ /** `Model#key`, or `Model#<new>` before the key exists. Diagnostics only — never a map key. */
79
+ get Identity(): string;
80
+ constructor(Model: ModelBase, Descriptor: IModelDescriptor, Operation: SubjectOperation);
81
+ }
82
+ /**
83
+ * Everything one `save()` will do, before ordering.
84
+ */
85
+ export declare class SubjectSet {
86
+ readonly Subjects: Subject[];
87
+ readonly Junctions: IJunctionDelta[];
88
+ readonly Orphans: IOrphanDelta[];
89
+ private _byModel;
90
+ /**
91
+ * Registers `subject`, or returns the one already registered for the same model instance.
92
+ * Instance identity is the key — canonicalizing two instances of one row is the identity
93
+ * map's job, and it runs first.
94
+ */
95
+ add(subject: Subject): Subject;
96
+ find(model: ModelBase): Subject | undefined;
97
+ /** True when this set would emit no statements at all. */
98
+ get IsEmpty(): boolean;
99
+ }
100
+ //# sourceMappingURL=subject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../../src/subject.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;GAMG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,MAAM,EAAE,SAAS,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,WAAW,EAAE,OAAO,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,kBAAkB,EAAE,gBAAgB,CAAC;IACrC,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,WAAW,EAAE,OAAO,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,mBAAmB,CAAC;IAChC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,OAAO,EAAE,CAAC;CACxB;AAkBD;;GAEG;AACH,qBAAa,OAAO;aAqBU,KAAK,EAAE,SAAS;aAAkB,UAAU,EAAE,gBAAgB;IAAS,SAAS,EAAE,gBAAgB;IApB9H,2FAA2F;IACpF,cAAc,EAAE,MAAM,EAAE,CAAM;IAErC,2EAA2E;IACpE,kBAAkB,EAAE,kBAAkB,EAAE,CAAM;IAErD;;;OAGG;IACI,mBAAmB,EAAE,kBAAkB,EAAE,CAAM;IAEtD,qFAAqF;IAC9E,cAAc,EAAE,cAAc,EAAE,CAAM;IAE7C,+FAA+F;IAC/F,IAAW,QAAQ,IAAI,MAAM,CAE5B;gBAE2B,KAAK,EAAE,SAAS,EAAkB,UAAU,EAAE,gBAAgB,EAAS,SAAS,EAAE,gBAAgB;CAC/H;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,SAAgB,QAAQ,EAAE,OAAO,EAAE,CAAM;IACzC,SAAgB,SAAS,EAAE,cAAc,EAAE,CAAM;IACjD,SAAgB,OAAO,EAAE,YAAY,EAAE,CAAM;IAE7C,OAAO,CAAC,QAAQ,CAAiC;IAEjD;;;;OAIG;IACI,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAY9B,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS;IAIlD,0DAA0D;IAC1D,IAAW,OAAO,IAAI,OAAO,CAE5B;CACF"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * What `save()` will do with one model instance.
3
+ *
4
+ * There is no `delete` member: every row `save()` removes is removed because it was detached
5
+ * from a relation, and that is carried by `IOrphanDelta` keyed by primary key rather than by
6
+ * a subject over a model instance the caller no longer holds.
7
+ */
8
+ export var SubjectOperation;
9
+ (function (SubjectOperation) {
10
+ SubjectOperation["Insert"] = "insert";
11
+ SubjectOperation["Update"] = "update";
12
+ SubjectOperation["None"] = "none";
13
+ })(SubjectOperation || (SubjectOperation = {}));
14
+ /**
15
+ * Renders a primary key for a diagnostic message. A composite key arrives as a tuple; a key
16
+ * with any part missing is not a key at all and reads as `<new>`, the same as an absent one.
17
+ */
18
+ function describeKey(pk) {
19
+ if (pk === null || pk === undefined) {
20
+ return '<new>';
21
+ }
22
+ if (Array.isArray(pk)) {
23
+ return pk.some((p) => p === null || p === undefined) ? '<new>' : pk.map((p) => String(p)).join(',');
24
+ }
25
+ return String(pk);
26
+ }
27
+ /**
28
+ * One model instance and everything `save()` needs to know about it.
29
+ */
30
+ export class Subject {
31
+ /** `Model#key`, or `Model#<new>` before the key exists. Diagnostics only — never a map key. */
32
+ get Identity() {
33
+ return `${this.Descriptor.Name}#${describeKey(this.Model.PrimaryKeyValue)}`;
34
+ }
35
+ constructor(Model, Descriptor, Operation) {
36
+ this.Model = Model;
37
+ this.Descriptor = Descriptor;
38
+ this.Operation = Operation;
39
+ /** Columns that differ from the snapshot. Empty for an insert, which writes everything. */
40
+ this.ChangedColumns = [];
41
+ /** Foreign keys resolved just before this subject's own statement runs. */
42
+ this.PendingForeignKeys = [];
43
+ /**
44
+ * Foreign keys that cannot be resolved before this subject's INSERT — a self-referencing
45
+ * cycle — and are applied by a follow-up UPDATE in the update phase instead.
46
+ */
47
+ this.DeferredForeignKeys = [];
48
+ /** hasMany membership changes owned by this subject. Read by the orphan resolver. */
49
+ this.RelationDeltas = [];
50
+ }
51
+ }
52
+ /**
53
+ * Everything one `save()` will do, before ordering.
54
+ */
55
+ export class SubjectSet {
56
+ constructor() {
57
+ this.Subjects = [];
58
+ this.Junctions = [];
59
+ this.Orphans = [];
60
+ this._byModel = new Map();
61
+ }
62
+ /**
63
+ * Registers `subject`, or returns the one already registered for the same model instance.
64
+ * Instance identity is the key — canonicalizing two instances of one row is the identity
65
+ * map's job, and it runs first.
66
+ */
67
+ add(subject) {
68
+ const existing = this._byModel.get(subject.Model);
69
+ if (existing) {
70
+ return existing;
71
+ }
72
+ this._byModel.set(subject.Model, subject);
73
+ this.Subjects.push(subject);
74
+ return subject;
75
+ }
76
+ find(model) {
77
+ return this._byModel.get(model);
78
+ }
79
+ /** True when this set would emit no statements at all. */
80
+ get IsEmpty() {
81
+ return this.Junctions.length === 0 && this.Orphans.length === 0 && this.Subjects.every((s) => s.Operation === SubjectOperation.None);
82
+ }
83
+ }
84
+ //# sourceMappingURL=subject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject.js","sourceRoot":"","sources":["../../src/subject.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;IACjB,iCAAa,CAAA;AACf,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAmDD;;;GAGG;AACH,SAAS,WAAW,CAAC,EAAW;IAC9B,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtG,CAAC;IAED,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,OAAO;IAgBlB,+FAA+F;IAC/F,IAAW,QAAQ;QACjB,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;IAC9E,CAAC;IAED,YAA4B,KAAgB,EAAkB,UAA4B,EAAS,SAA2B;QAAlG,UAAK,GAAL,KAAK,CAAW;QAAkB,eAAU,GAAV,UAAU,CAAkB;QAAS,cAAS,GAAT,SAAS,CAAkB;QApB9H,2FAA2F;QACpF,mBAAc,GAAa,EAAE,CAAC;QAErC,2EAA2E;QACpE,uBAAkB,GAAyB,EAAE,CAAC;QAErD;;;WAGG;QACI,wBAAmB,GAAyB,EAAE,CAAC;QAEtD,qFAAqF;QAC9E,mBAAc,GAAqB,EAAE,CAAC;IAOoF,CAAC;CACnI;AAED;;GAEG;AACH,MAAM,OAAO,UAAU;IAAvB;QACkB,aAAQ,GAAc,EAAE,CAAC;QACzB,cAAS,GAAqB,EAAE,CAAC;QACjC,YAAO,GAAmB,EAAE,CAAC;QAErC,aAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;IA2BnD,CAAC;IAzBC;;;;OAIG;IACI,GAAG,CAAC,OAAgB;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,IAAI,CAAC,KAAgB;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,0DAA0D;IAC1D,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvI,CAAC;CACF"}
@@ -0,0 +1,52 @@
1
+ import { OrmDriver } from './driver.js';
2
+ import { IIdentityMap, IModelDescriptor, ISaveOptions, ISaveResult } from './interfaces.js';
3
+ import type { ModelBase } from './model.js';
4
+ /**
5
+ * The `save()` entry point: one transaction, one identity map, one ordered plan.
6
+ */
7
+ export declare class UnitOfWork {
8
+ /**
9
+ * Persists everything reachable from `root` atomically.
10
+ *
11
+ * @param root - the model `save()` was called on
12
+ * @param options - `reload` to diff against current database state; `chunk` to bound the row
13
+ * count of the statements that ARE batched — junction inserts and the key lists of
14
+ * orphan statements. It does not apply to model inserts: those run one statement per
15
+ * row so each generated key can be read back exactly. See {@link ISaveOptions}.
16
+ */
17
+ static save(root: ModelBase, options?: ISaveOptions): Promise<ISaveResult>;
18
+ /**
19
+ * The identity map for this save. Reused across saves inside one transaction so a row
20
+ * touched by two of them is still one object; created fresh otherwise. Nothing survives
21
+ * the transaction ( decision D7 ).
22
+ */
23
+ protected static identityMapFor(driver: OrmDriver): IIdentityMap;
24
+ /**
25
+ * A graph spanning two connections cannot be persisted atomically — the transaction only
26
+ * covers one of them. Fail loudly rather than commit half of it.
27
+ */
28
+ protected static assertSingleConnection(models: ModelBase[], root: IModelDescriptor): void;
29
+ /**
30
+ * Re-reads every already-persisted model's row and rebases it on the database's current
31
+ * values, batched one SELECT per model class.
32
+ *
33
+ * This is a three-way merge between the hydration baseline, the model, and the row as it
34
+ * stands now. A column the caller edited keeps the caller's value and is rebased so it is
35
+ * written; a column the caller did not touch is reset to the current database value on the
36
+ * model *and* in the baseline, so it drops out of the diff and is not written at all.
37
+ *
38
+ * Moving only the baseline would do the exact opposite of the intent: the model would still
39
+ * hold the stale hydration value, the diff would report `current -> stale`, and the UPDATE
40
+ * would clobber whatever another process wrote. The model has to move too.
41
+ *
42
+ * This is a last-write-wins rebase, not conflict detection: two callers editing the same
43
+ * column still race, and neither is told.
44
+ */
45
+ protected static reloadSnapshots(models: ModelBase[]): Promise<void>;
46
+ /**
47
+ * Re-records every populated relation's member keys after a successful save, so a second
48
+ * `save()` on the same graph sees no membership change and emits nothing.
49
+ */
50
+ protected static resnapshotRelations(models: ModelBase[]): void;
51
+ }
52
+ //# sourceMappingURL=unit-of-work.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-of-work.d.ts","sourceRoot":"","sources":["../../src/unit-of-work.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAgB,MAAM,iBAAiB,CAAC;AAC1G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO5C;;GAEG;AACH,qBAAa,UAAU;IACrB;;;;;;;;OAQG;WACiB,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAkCvF;;;;OAIG;IACH,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,YAAY;IAchE;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAU1F;;;;;;;;;;;;;;;OAeG;qBACoB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAgE1E;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI;CAqBhE"}
@@ -0,0 +1,166 @@
1
+ /* eslint-disable prettier/prettier */
2
+ import { DI } from '@spinajs/di';
3
+ import { createQuery, SelectQueryBuilder } from './builders.js';
4
+ import { extractModelDescriptor } from './descriptor.js';
5
+ import { OrmException } from './exceptions.js';
6
+ import { IdentityMap } from './identity-map.js';
7
+ import { RelationType } from './interfaces.js';
8
+ import { pkKeyString, whereAnyPk } from './primary-keys.js';
9
+ import { snapshotEquals, snapshotFromRow } from './snapshot.js';
10
+ import { SubjectBuilder } from './subject-builder.js';
11
+ import { SubjectExecutor } from './subject-executor.js';
12
+ import { SubjectSorter } from './subject-sorter.js';
13
+ /**
14
+ * The `save()` entry point: one transaction, one identity map, one ordered plan.
15
+ */
16
+ export class UnitOfWork {
17
+ /**
18
+ * Persists everything reachable from `root` atomically.
19
+ *
20
+ * @param root - the model `save()` was called on
21
+ * @param options - `reload` to diff against current database state; `chunk` to bound the row
22
+ * count of the statements that ARE batched — junction inserts and the key lists of
23
+ * orphan statements. It does not apply to model inserts: those run one statement per
24
+ * row so each generated key can be read back exactly. See {@link ISaveOptions}.
25
+ */
26
+ static async save(root, options) {
27
+ const descriptor = extractModelDescriptor(root.constructor);
28
+ if (!descriptor) {
29
+ throw new OrmException(`model ${root.constructor.name} has no descriptor, use the @Model decorator`);
30
+ }
31
+ const driver = DI.resolve('OrmConnection', [descriptor.Connection]);
32
+ if (!driver) {
33
+ throw new OrmException(`model ${descriptor.Name} has invalid connection ${descriptor.Connection}`);
34
+ }
35
+ return await driver.transaction(async () => {
36
+ const identityMap = UnitOfWork.identityMapFor(driver);
37
+ const builder = new SubjectBuilder(identityMap);
38
+ const models = builder.collect(root);
39
+ UnitOfWork.assertSingleConnection(models, descriptor);
40
+ if (options?.reload) {
41
+ await UnitOfWork.reloadSnapshots(models);
42
+ }
43
+ const set = builder.buildFrom(models);
44
+ const plan = new SubjectSorter().sort(set);
45
+ const result = await new SubjectExecutor(options ?? {}).execute(plan);
46
+ UnitOfWork.resnapshotRelations(models);
47
+ return result;
48
+ });
49
+ }
50
+ /**
51
+ * The identity map for this save. Reused across saves inside one transaction so a row
52
+ * touched by two of them is still one object; created fresh otherwise. Nothing survives
53
+ * the transaction ( decision D7 ).
54
+ */
55
+ static identityMapFor(driver) {
56
+ const ctx = driver.CurrentTransaction;
57
+ if (!ctx) {
58
+ return new IdentityMap();
59
+ }
60
+ if (!ctx.IdentityMap) {
61
+ ctx.IdentityMap = new IdentityMap();
62
+ }
63
+ return ctx.IdentityMap;
64
+ }
65
+ /**
66
+ * A graph spanning two connections cannot be persisted atomically — the transaction only
67
+ * covers one of them. Fail loudly rather than commit half of it.
68
+ */
69
+ static assertSingleConnection(models, root) {
70
+ for (const model of models) {
71
+ const descriptor = extractModelDescriptor(model.constructor);
72
+ if (descriptor && descriptor.Connection !== root.Connection) {
73
+ throw new OrmException(`save() cannot span connections: ${root.Name} is on connection ${root.Connection} but ${descriptor.Name} is on ${descriptor.Connection}. Save each connection's graph separately.`);
74
+ }
75
+ }
76
+ }
77
+ /**
78
+ * Re-reads every already-persisted model's row and rebases it on the database's current
79
+ * values, batched one SELECT per model class.
80
+ *
81
+ * This is a three-way merge between the hydration baseline, the model, and the row as it
82
+ * stands now. A column the caller edited keeps the caller's value and is rebased so it is
83
+ * written; a column the caller did not touch is reset to the current database value on the
84
+ * model *and* in the baseline, so it drops out of the diff and is not written at all.
85
+ *
86
+ * Moving only the baseline would do the exact opposite of the intent: the model would still
87
+ * hold the stale hydration value, the diff would report `current -> stale`, and the UPDATE
88
+ * would clobber whatever another process wrote. The model has to move too.
89
+ *
90
+ * This is a last-write-wins rebase, not conflict detection: two callers editing the same
91
+ * column still race, and neither is told.
92
+ */
93
+ static async reloadSnapshots(models) {
94
+ const byConstructor = new Map();
95
+ for (const model of models) {
96
+ // A composite key is a tuple, and a tuple is ALWAYS truthy — check every part.
97
+ const pk = model.PrimaryKeyValue;
98
+ const missing = Array.isArray(pk) ? pk.some((v) => v === null || v === undefined) : pk === null || pk === undefined;
99
+ if (model.Snapshot === null || missing) {
100
+ continue;
101
+ }
102
+ const ctor = model.constructor;
103
+ const list = byConstructor.get(ctor) ?? [];
104
+ list.push(model);
105
+ byConstructor.set(ctor, list);
106
+ }
107
+ for (const [ctor, group] of byConstructor) {
108
+ const descriptor = extractModelDescriptor(ctor);
109
+ const { query } = createQuery(ctor, SelectQueryBuilder);
110
+ const select = query.select('*');
111
+ whereAnyPk(select, descriptor, group.map((m) => m.PrimaryKeyValue));
112
+ const fresh = (await select.asRaw());
113
+ // Index by the flattened key so a composite key matches without a nested scan.
114
+ const byKey = new Map();
115
+ for (const row of fresh) {
116
+ byKey.set(pkKeyString(row, descriptor), row);
117
+ }
118
+ for (const model of group) {
119
+ const row = byKey.get(pkKeyString(model, descriptor));
120
+ if (!row) {
121
+ // The row is gone. Clearing the snapshot reclassifies the model as an INSERT,
122
+ // which re-creates it rather than emitting an UPDATE that matches nothing.
123
+ model.clearSnapshot();
124
+ continue;
125
+ }
126
+ const baseline = model.Snapshot.Columns;
127
+ const current = snapshotFromRow(descriptor, row);
128
+ const converterOf = new Map((descriptor.Columns ?? []).map((c) => [c.Name, c.Converter]));
129
+ for (const [name, value] of current) {
130
+ // eslint-disable-next-line security/detect-object-injection
131
+ const callerEdited = !snapshotEquals(baseline.get(name), model[name], converterOf.get(name));
132
+ if (!callerEdited) {
133
+ // Untouched by this caller: adopt the database's value so it is neither written
134
+ // back stale nor reported as a change.
135
+ // eslint-disable-next-line security/detect-object-injection
136
+ model[name] = value;
137
+ }
138
+ baseline.set(name, value);
139
+ }
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Re-records every populated relation's member keys after a successful save, so a second
145
+ * `save()` on the same graph sees no membership change and emits nothing.
146
+ */
147
+ static resnapshotRelations(models) {
148
+ for (const model of models) {
149
+ const descriptor = extractModelDescriptor(model.constructor);
150
+ if (!descriptor) {
151
+ continue;
152
+ }
153
+ for (const [name, relation] of descriptor.Relations) {
154
+ if (relation.Type === RelationType.Query || relation.Type === RelationType.Virtual) {
155
+ continue;
156
+ }
157
+ // eslint-disable-next-line security/detect-object-injection
158
+ const rel = model[name];
159
+ if (rel?.Populated === true || (relation.Type === RelationType.One && rel?.Value)) {
160
+ model.snapshotRelation(name);
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ //# sourceMappingURL=unit-of-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-of-work.js","sourceRoot":"","sources":["../../src/unit-of-work.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAe,EAAE,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAA6D,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE1G,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;GAEG;AACH,MAAM,OAAO,UAAU;IACrB;;;;;;;;OAQG;IACI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAe,EAAE,OAAsB;QAC9D,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE5D,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,YAAY,CAAC,SAAS,IAAI,CAAC,WAAW,CAAC,IAAI,8CAA8C,CAAC,CAAC;QACvG,CAAC;QAED,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAY,eAAe,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QAE/E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,YAAY,CAAC,SAAS,UAAU,CAAC,IAAI,2BAA2B,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;QACrG,CAAC;QAED,OAAO,MAAM,MAAM,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;YACzC,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,WAAW,CAAC,CAAC;YAEhD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,UAAU,CAAC,sBAAsB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAEtD,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;gBACpB,MAAM,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3C,CAAC;YAED,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,aAAa,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,eAAe,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEtE,UAAU,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAEvC,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACO,MAAM,CAAC,cAAc,CAAC,MAAiB;QAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAEtC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,IAAI,WAAW,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;QACtC,CAAC;QAED,OAAO,GAAG,CAAC,WAAW,CAAC;IACzB,CAAC;IAED;;;OAGG;IACO,MAAM,CAAC,sBAAsB,CAAC,MAAmB,EAAE,IAAsB;QACjF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAE7D,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC5D,MAAM,IAAI,YAAY,CAAC,mCAAmC,IAAI,CAAC,IAAI,qBAAqB,IAAI,CAAC,UAAU,QAAQ,UAAU,CAAC,IAAI,UAAU,UAAU,CAAC,UAAU,4CAA4C,CAAC,CAAC;YAC7M,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACO,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,MAAmB;QACxD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuC,CAAC;QAErE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,+EAA+E;YAC/E,MAAM,EAAE,GAAG,KAAK,CAAC,eAAe,CAAC;YACjC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,CAAC;YAEpH,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,EAAE,CAAC;gBACvC,SAAS;YACX,CAAC;YAED,MAAM,IAAI,GAAG,KAAK,CAAC,WAAqC,CAAC;YACzD,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjB,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,aAAa,EAAE,CAAC;YAC1C,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,CAAE,CAAC;YACjD,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;YAExD,MAAM,MAAM,GAAI,KAAqC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClE,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;YAEpE,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,KAAK,EAA6B,CAA8B,CAAC;YAE7F,+EAA+E;YAC/E,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmC,CAAC;YACzD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;gBACxB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;YAC/C,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;gBAEtD,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,8EAA8E;oBAC9E,2EAA2E;oBAC3E,KAAK,CAAC,aAAa,EAAE,CAAC;oBACtB,SAAS;gBACX,CAAC;gBAED,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAS,CAAC,OAAO,CAAC;gBACzC,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBACjD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAE1F,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;oBACpC,4DAA4D;oBAC5D,MAAM,YAAY,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAG,KAAa,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;oBAEtG,IAAI,CAAC,YAAY,EAAE,CAAC;wBAClB,gFAAgF;wBAChF,uCAAuC;wBACvC,4DAA4D;wBAC3D,KAAa,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;oBAC/B,CAAC;oBAED,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,MAAM,CAAC,mBAAmB,CAAC,MAAmB;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC7D,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,SAAS;YACX,CAAC;YAED,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;gBACpD,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;oBACnF,SAAS;gBACX,CAAC;gBAED,4DAA4D;gBAC5D,MAAM,GAAG,GAAI,KAAa,CAAC,IAAI,CAAC,CAAC;gBAEjC,IAAI,GAAG,EAAE,SAAS,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,GAAG,IAAI,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;oBAClF,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF"}