@spinajs/orm 2.0.480 → 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.
- package/README.md +72 -3
- package/lib/cjs/bootstrap.js +10 -0
- package/lib/cjs/bootstrap.js.map +1 -1
- package/lib/cjs/builders.d.ts +115 -11
- package/lib/cjs/builders.d.ts.map +1 -1
- package/lib/cjs/builders.js +342 -283
- package/lib/cjs/builders.js.map +1 -1
- package/lib/cjs/converters.d.ts +9 -2
- package/lib/cjs/converters.d.ts.map +1 -1
- package/lib/cjs/converters.js +48 -8
- package/lib/cjs/converters.js.map +1 -1
- package/lib/cjs/decorators.d.ts +26 -3
- package/lib/cjs/decorators.d.ts.map +1 -1
- package/lib/cjs/decorators.js +95 -42
- package/lib/cjs/decorators.js.map +1 -1
- package/lib/cjs/dehydrators.js +1 -1
- package/lib/cjs/dehydrators.js.map +1 -1
- package/lib/cjs/descriptor.d.ts +1 -0
- package/lib/cjs/descriptor.d.ts.map +1 -1
- package/lib/cjs/descriptor.js +16 -40
- package/lib/cjs/descriptor.js.map +1 -1
- package/lib/cjs/driver.d.ts +136 -7
- package/lib/cjs/driver.d.ts.map +1 -1
- package/lib/cjs/driver.js +279 -0
- package/lib/cjs/driver.js.map +1 -1
- package/lib/cjs/existsRelationHandlers.d.ts +29 -0
- package/lib/cjs/existsRelationHandlers.d.ts.map +1 -0
- package/lib/cjs/existsRelationHandlers.js +104 -0
- package/lib/cjs/existsRelationHandlers.js.map +1 -0
- package/lib/cjs/fp.d.ts.map +1 -1
- package/lib/cjs/fp.js +10 -15
- package/lib/cjs/fp.js.map +1 -1
- package/lib/cjs/hydrators.d.ts.map +1 -1
- package/lib/cjs/hydrators.js +29 -2
- package/lib/cjs/hydrators.js.map +1 -1
- package/lib/cjs/identity-map.d.ts +60 -0
- package/lib/cjs/identity-map.d.ts.map +1 -0
- package/lib/cjs/identity-map.js +135 -0
- package/lib/cjs/identity-map.js.map +1 -0
- package/lib/cjs/index.d.ts +12 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +12 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces.d.ts +295 -9
- package/lib/cjs/interfaces.d.ts.map +1 -1
- package/lib/cjs/interfaces.js +54 -1
- package/lib/cjs/interfaces.js.map +1 -1
- package/lib/cjs/metadata.d.ts.map +1 -1
- package/lib/cjs/metadata.js +4 -1
- package/lib/cjs/metadata.js.map +1 -1
- package/lib/cjs/metrics.d.ts +53 -0
- package/lib/cjs/metrics.d.ts.map +1 -0
- package/lib/cjs/metrics.js +82 -0
- package/lib/cjs/metrics.js.map +1 -0
- package/lib/cjs/middlewares.d.ts +13 -1
- package/lib/cjs/middlewares.d.ts.map +1 -1
- package/lib/cjs/middlewares.js +55 -15
- package/lib/cjs/middlewares.js.map +1 -1
- package/lib/cjs/model.d.ts +129 -13
- package/lib/cjs/model.d.ts.map +1 -1
- package/lib/cjs/model.js +449 -93
- package/lib/cjs/model.js.map +1 -1
- package/lib/cjs/orm.d.ts.map +1 -1
- package/lib/cjs/orm.js +12 -3
- package/lib/cjs/orm.js.map +1 -1
- package/lib/cjs/orphan.d.ts +27 -0
- package/lib/cjs/orphan.d.ts.map +1 -0
- package/lib/cjs/orphan.js +55 -0
- package/lib/cjs/orphan.js.map +1 -0
- package/lib/cjs/primary-keys.d.ts +60 -0
- package/lib/cjs/primary-keys.d.ts.map +1 -0
- package/lib/cjs/primary-keys.js +243 -0
- package/lib/cjs/primary-keys.js.map +1 -0
- package/lib/cjs/relation-objects.d.ts +101 -9
- package/lib/cjs/relation-objects.d.ts.map +1 -1
- package/lib/cjs/relation-objects.js +194 -43
- package/lib/cjs/relation-objects.js.map +1 -1
- package/lib/cjs/relations.d.ts +7 -1
- package/lib/cjs/relations.d.ts.map +1 -1
- package/lib/cjs/relations.js +16 -1
- package/lib/cjs/relations.js.map +1 -1
- package/lib/cjs/resilience.d.ts +50 -0
- package/lib/cjs/resilience.d.ts.map +1 -0
- package/lib/cjs/resilience.js +70 -0
- package/lib/cjs/resilience.js.map +1 -0
- package/lib/cjs/snapshot.d.ts +58 -0
- package/lib/cjs/snapshot.d.ts.map +1 -0
- package/lib/cjs/snapshot.js +125 -0
- package/lib/cjs/snapshot.js.map +1 -0
- package/lib/cjs/statements.d.ts +11 -1
- package/lib/cjs/statements.d.ts.map +1 -1
- package/lib/cjs/statements.js +13 -2
- package/lib/cjs/statements.js.map +1 -1
- package/lib/cjs/subject-builder.d.ts +79 -0
- package/lib/cjs/subject-builder.d.ts.map +1 -0
- package/lib/cjs/subject-builder.js +296 -0
- package/lib/cjs/subject-builder.js.map +1 -0
- package/lib/cjs/subject-executor.d.ts +122 -0
- package/lib/cjs/subject-executor.d.ts.map +1 -0
- package/lib/cjs/subject-executor.js +319 -0
- package/lib/cjs/subject-executor.js.map +1 -0
- package/lib/cjs/subject-sorter.d.ts +70 -0
- package/lib/cjs/subject-sorter.d.ts.map +1 -0
- package/lib/cjs/subject-sorter.js +173 -0
- package/lib/cjs/subject-sorter.js.map +1 -0
- package/lib/cjs/subject.d.ts +100 -0
- package/lib/cjs/subject.d.ts.map +1 -0
- package/lib/cjs/subject.js +89 -0
- package/lib/cjs/subject.js.map +1 -0
- package/lib/cjs/unit-of-work.d.ts +52 -0
- package/lib/cjs/unit-of-work.d.ts.map +1 -0
- package/lib/cjs/unit-of-work.js +170 -0
- package/lib/cjs/unit-of-work.js.map +1 -0
- package/lib/mjs/bootstrap.js +10 -0
- package/lib/mjs/bootstrap.js.map +1 -1
- package/lib/mjs/builders.d.ts +115 -11
- package/lib/mjs/builders.d.ts.map +1 -1
- package/lib/mjs/builders.js +344 -285
- package/lib/mjs/builders.js.map +1 -1
- package/lib/mjs/converters.d.ts +9 -2
- package/lib/mjs/converters.d.ts.map +1 -1
- package/lib/mjs/converters.js +48 -8
- package/lib/mjs/converters.js.map +1 -1
- package/lib/mjs/decorators.d.ts +26 -3
- package/lib/mjs/decorators.d.ts.map +1 -1
- package/lib/mjs/decorators.js +96 -44
- package/lib/mjs/decorators.js.map +1 -1
- package/lib/mjs/dehydrators.js +1 -1
- package/lib/mjs/dehydrators.js.map +1 -1
- package/lib/mjs/descriptor.d.ts +1 -0
- package/lib/mjs/descriptor.d.ts.map +1 -1
- package/lib/mjs/descriptor.js +17 -39
- package/lib/mjs/descriptor.js.map +1 -1
- package/lib/mjs/driver.d.ts +136 -7
- package/lib/mjs/driver.d.ts.map +1 -1
- package/lib/mjs/driver.js +279 -0
- package/lib/mjs/driver.js.map +1 -1
- package/lib/mjs/existsRelationHandlers.d.ts +29 -0
- package/lib/mjs/existsRelationHandlers.d.ts.map +1 -0
- package/lib/mjs/existsRelationHandlers.js +100 -0
- package/lib/mjs/existsRelationHandlers.js.map +1 -0
- package/lib/mjs/fp.d.ts.map +1 -1
- package/lib/mjs/fp.js +10 -15
- package/lib/mjs/fp.js.map +1 -1
- package/lib/mjs/hydrators.d.ts.map +1 -1
- package/lib/mjs/hydrators.js +29 -2
- package/lib/mjs/hydrators.js.map +1 -1
- package/lib/mjs/identity-map.d.ts +60 -0
- package/lib/mjs/identity-map.d.ts.map +1 -0
- package/lib/mjs/identity-map.js +130 -0
- package/lib/mjs/identity-map.js.map +1 -0
- package/lib/mjs/index.d.ts +12 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +12 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/interfaces.d.ts +295 -9
- package/lib/mjs/interfaces.d.ts.map +1 -1
- package/lib/mjs/interfaces.js +53 -0
- package/lib/mjs/interfaces.js.map +1 -1
- package/lib/mjs/metadata.d.ts.map +1 -1
- package/lib/mjs/metadata.js +4 -1
- package/lib/mjs/metadata.js.map +1 -1
- package/lib/mjs/metrics.d.ts +53 -0
- package/lib/mjs/metrics.d.ts.map +1 -0
- package/lib/mjs/metrics.js +76 -0
- package/lib/mjs/metrics.js.map +1 -0
- package/lib/mjs/middlewares.d.ts +13 -1
- package/lib/mjs/middlewares.d.ts.map +1 -1
- package/lib/mjs/middlewares.js +55 -15
- package/lib/mjs/middlewares.js.map +1 -1
- package/lib/mjs/model.d.ts +129 -13
- package/lib/mjs/model.d.ts.map +1 -1
- package/lib/mjs/model.js +451 -95
- package/lib/mjs/model.js.map +1 -1
- package/lib/mjs/orm.d.ts.map +1 -1
- package/lib/mjs/orm.js +12 -3
- package/lib/mjs/orm.js.map +1 -1
- package/lib/mjs/orphan.d.ts +27 -0
- package/lib/mjs/orphan.d.ts.map +1 -0
- package/lib/mjs/orphan.js +52 -0
- package/lib/mjs/orphan.js.map +1 -0
- package/lib/mjs/primary-keys.d.ts +60 -0
- package/lib/mjs/primary-keys.d.ts.map +1 -0
- package/lib/mjs/primary-keys.js +223 -0
- package/lib/mjs/primary-keys.js.map +1 -0
- package/lib/mjs/relation-objects.d.ts +101 -9
- package/lib/mjs/relation-objects.d.ts.map +1 -1
- package/lib/mjs/relation-objects.js +194 -43
- package/lib/mjs/relation-objects.js.map +1 -1
- package/lib/mjs/relations.d.ts +7 -1
- package/lib/mjs/relations.d.ts.map +1 -1
- package/lib/mjs/relations.js +16 -1
- package/lib/mjs/relations.js.map +1 -1
- package/lib/mjs/resilience.d.ts +50 -0
- package/lib/mjs/resilience.d.ts.map +1 -0
- package/lib/mjs/resilience.js +64 -0
- package/lib/mjs/resilience.js.map +1 -0
- package/lib/mjs/snapshot.d.ts +58 -0
- package/lib/mjs/snapshot.d.ts.map +1 -0
- package/lib/mjs/snapshot.js +115 -0
- package/lib/mjs/snapshot.js.map +1 -0
- package/lib/mjs/statements.d.ts +11 -1
- package/lib/mjs/statements.d.ts.map +1 -1
- package/lib/mjs/statements.js +14 -3
- package/lib/mjs/statements.js.map +1 -1
- package/lib/mjs/subject-builder.d.ts +79 -0
- package/lib/mjs/subject-builder.d.ts.map +1 -0
- package/lib/mjs/subject-builder.js +292 -0
- package/lib/mjs/subject-builder.js.map +1 -0
- package/lib/mjs/subject-executor.d.ts +122 -0
- package/lib/mjs/subject-executor.d.ts.map +1 -0
- package/lib/mjs/subject-executor.js +312 -0
- package/lib/mjs/subject-executor.js.map +1 -0
- package/lib/mjs/subject-sorter.d.ts +70 -0
- package/lib/mjs/subject-sorter.d.ts.map +1 -0
- package/lib/mjs/subject-sorter.js +168 -0
- package/lib/mjs/subject-sorter.js.map +1 -0
- package/lib/mjs/subject.d.ts +100 -0
- package/lib/mjs/subject.d.ts.map +1 -0
- package/lib/mjs/subject.js +84 -0
- package/lib/mjs/subject.js.map +1 -0
- package/lib/mjs/unit-of-work.d.ts +52 -0
- package/lib/mjs/unit-of-work.d.ts.map +1 -0
- package/lib/mjs/unit-of-work.js +166 -0
- package/lib/mjs/unit-of-work.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- 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":"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"}
|