@routier/core 0.0.1-alpha.1
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/CHANGELOG.md +8 -0
- package/package.json +91 -0
- package/rspack.config.mjs +65 -0
- package/src/assertions/index.ts +37 -0
- package/src/codegen/SlotPath.ts +20 -0
- package/src/codegen/blocks.ts +578 -0
- package/src/codegen/handlers/CloneHandlerBuilder.ts +13 -0
- package/src/codegen/handlers/CompareHandlerBuilder.ts +13 -0
- package/src/codegen/handlers/DeserializeHandlerBuilder.ts +20 -0
- package/src/codegen/handlers/EnableChangeTrackingHandlerBuilder.ts +13 -0
- package/src/codegen/handlers/EnrichmentHandlerBuilder.ts +28 -0
- package/src/codegen/handlers/FreezeHandlerBuilder.ts +13 -0
- package/src/codegen/handlers/HashHandlerBuilder.ts +25 -0
- package/src/codegen/handlers/HashTypeHandlerBuilder.ts +11 -0
- package/src/codegen/handlers/IdSelectorHandlerBuilder.ts +10 -0
- package/src/codegen/handlers/MergeHandlerBuilder.ts +19 -0
- package/src/codegen/handlers/PrepareHandlerBuilder.ts +23 -0
- package/src/codegen/handlers/SerializeHandlerBuilder.ts +15 -0
- package/src/codegen/handlers/StripHandlerBuilder.ts +18 -0
- package/src/codegen/handlers/clone/CloneObjectHandler.ts +29 -0
- package/src/codegen/handlers/clone/CloneValueHandler.ts +33 -0
- package/src/codegen/handlers/compare/CompareObjectHandler.ts +15 -0
- package/src/codegen/handlers/compare/CompareValueHandler.ts +27 -0
- package/src/codegen/handlers/deserialize/DeserializeComputedValueHandler.ts +16 -0
- package/src/codegen/handlers/deserialize/DeserializeDateHandler.ts +45 -0
- package/src/codegen/handlers/deserialize/DeserializeFunctionHandler.ts +16 -0
- package/src/codegen/handlers/deserialize/DeserializeObjectHandler.ts +29 -0
- package/src/codegen/handlers/deserialize/DeserializeValueHandler.ts +33 -0
- package/src/codegen/handlers/enableChangeTracking/EnableChangeTrackingObjectHandler.ts +20 -0
- package/src/codegen/handlers/enableChangeTracking/EnableChangeTrackingPrimitiveValueHandler.ts +15 -0
- package/src/codegen/handlers/enrichment/EnrichmentComputedValueHandler.ts +37 -0
- package/src/codegen/handlers/enrichment/EnrichmentDefaultFunctionHandler.ts +50 -0
- package/src/codegen/handlers/enrichment/EnrichmentDefaultValueHandler.ts +18 -0
- package/src/codegen/handlers/enrichment/EnrichmentFunctionHandler.ts +38 -0
- package/src/codegen/handlers/enrichment/EnrichmentNullableObjectHandler.ts +44 -0
- package/src/codegen/handlers/enrichment/EnrichmentObjectHandler.ts +29 -0
- package/src/codegen/handlers/enrichment/EnrichmentObjectIdentityHandler.ts +16 -0
- package/src/codegen/handlers/enrichment/EnrichmentPrimitiveHandler.ts +13 -0
- package/src/codegen/handlers/enrichment/EnrichmentPrimitiveIdentityHandler.ts +21 -0
- package/src/codegen/handlers/freeze/FreezeObjectHandler.ts +20 -0
- package/src/codegen/handlers/freeze/FreezePrimitiveValueHandler.ts +15 -0
- package/src/codegen/handlers/hash/HashComputedValueHandler.ts +15 -0
- package/src/codegen/handlers/hash/HashDateHandler.ts +26 -0
- package/src/codegen/handlers/hash/HashFunctionHandler.ts +16 -0
- package/src/codegen/handlers/hash/HashIdentityHandler.ts +15 -0
- package/src/codegen/handlers/hash/HashKeyHandler.ts +26 -0
- package/src/codegen/handlers/hash/HashValueHandler.ts +26 -0
- package/src/codegen/handlers/hashType/HashTypeValueHandler.ts +20 -0
- package/src/codegen/handlers/idSelector/IdSelectorValueHandler.ts +28 -0
- package/src/codegen/handlers/index.ts +13 -0
- package/src/codegen/handlers/merge/MergeComputedValueHandler.ts +37 -0
- package/src/codegen/handlers/merge/MergeDefaultFunctionHandler.ts +40 -0
- package/src/codegen/handlers/merge/MergeDefaultValueHandler.ts +32 -0
- package/src/codegen/handlers/merge/MergeFunctionHandler.ts +16 -0
- package/src/codegen/handlers/merge/MergePrimitiveHandler.ts +21 -0
- package/src/codegen/handlers/prepare/PrepareComputedValueHandler.ts +16 -0
- package/src/codegen/handlers/prepare/PrepareFunctionHandler.ts +16 -0
- package/src/codegen/handlers/prepare/PrepareIdentityHandler.ts +21 -0
- package/src/codegen/handlers/prepare/PrepareKeyHandler.ts +21 -0
- package/src/codegen/handlers/prepare/PrepareObjectHandler.ts +38 -0
- package/src/codegen/handlers/prepare/PrepareValueHandler.ts +36 -0
- package/src/codegen/handlers/serialize/SerializeDateHandler.ts +45 -0
- package/src/codegen/handlers/serialize/SerializeObjectHandler.ts +28 -0
- package/src/codegen/handlers/serialize/SerializeValueHandler.ts +33 -0
- package/src/codegen/handlers/strip/StripIdentityHandler.ts +15 -0
- package/src/codegen/handlers/strip/StripKeyHandler.ts +15 -0
- package/src/codegen/handlers/strip/StripObjectHandler.ts +35 -0
- package/src/codegen/handlers/strip/StripValueHandler.ts +36 -0
- package/src/codegen/handlers/types.ts +119 -0
- package/src/codegen/index.ts +2 -0
- package/src/codegen/types.ts +2 -0
- package/src/codegen/utils.ts +74 -0
- package/src/collections/Changes.test.ts +337 -0
- package/src/collections/Changes.ts +177 -0
- package/src/collections/IdSet.ts +28 -0
- package/src/collections/MemoryDataCollection.test.ts +424 -0
- package/src/collections/MemoryDataCollection.ts +134 -0
- package/src/collections/SchemaCollection.ts +22 -0
- package/src/collections/TagCollection.test.ts +443 -0
- package/src/collections/TagCollection.ts +62 -0
- package/src/collections/index.ts +5 -0
- package/src/errors/SchemaError.ts +6 -0
- package/src/errors/index.ts +1 -0
- package/src/expressions/index.ts +3 -0
- package/src/expressions/parser.test.ts +913 -0
- package/src/expressions/parser.ts +661 -0
- package/src/expressions/types.ts +184 -0
- package/src/expressions/utils.test.ts +346 -0
- package/src/expressions/utils.ts +59 -0
- package/src/index.ts +12 -0
- package/src/performance/index.ts +26 -0
- package/src/pipeline/SyncronousQueue.test.ts +269 -0
- package/src/pipeline/SyncronousQueue.ts +30 -0
- package/src/pipeline/TrampolinePipeline.test.ts +374 -0
- package/src/pipeline/TrampolinePipeline.ts +437 -0
- package/src/pipeline/index.ts +2 -0
- package/src/plugins/EphemeralDataPlugin.ts +132 -0
- package/src/plugins/capabilities/DbPluginCapability.ts +111 -0
- package/src/plugins/capabilities/index.ts +2 -0
- package/src/plugins/capabilities/logging/DbPluginLoggingCapability.ts +261 -0
- package/src/plugins/capabilities/logging/index.ts +1 -0
- package/src/plugins/index.ts +6 -0
- package/src/plugins/query/Query.ts +67 -0
- package/src/plugins/query/QueryOptionsCollection.test.ts +86 -0
- package/src/plugins/query/QueryOptionsCollection.ts +154 -0
- package/src/plugins/query/index.ts +3 -0
- package/src/plugins/query/types.ts +46 -0
- package/src/plugins/replication/OptimisticReplicationDbPlugin.ts +202 -0
- package/src/plugins/replication/ReplicationDbPlugin.ts +137 -0
- package/src/plugins/replication/index.ts +3 -0
- package/src/plugins/replication/types.ts +5 -0
- package/src/plugins/translators/DataTranslator.ts +46 -0
- package/src/plugins/translators/JsonTranslator.test.ts +618 -0
- package/src/plugins/translators/JsonTranslator.ts +211 -0
- package/src/plugins/translators/SqlTranslator.ts +45 -0
- package/src/plugins/translators/index.ts +3 -0
- package/src/plugins/types.ts +114 -0
- package/src/results/Result.ts +91 -0
- package/src/results/index.ts +3 -0
- package/src/results/types.ts +17 -0
- package/src/results/utils.ts +15 -0
- package/src/schema/PropertyInfo.test.ts +479 -0
- package/src/schema/PropertyInfo.ts +374 -0
- package/src/schema/SchemaDefinition.ts +626 -0
- package/src/schema/builder.ts +18 -0
- package/src/schema/index.ts +7 -0
- package/src/schema/property/base/SchemaBase.ts +49 -0
- package/src/schema/property/base/index.ts +1 -0
- package/src/schema/property/modifiers/SchemaDefault.ts +29 -0
- package/src/schema/property/modifiers/SchemaDeserialize.ts +23 -0
- package/src/schema/property/modifiers/SchemaDistinct.ts +14 -0
- package/src/schema/property/modifiers/SchemaFrom.ts +54 -0
- package/src/schema/property/modifiers/SchemaIdentity.ts +13 -0
- package/src/schema/property/modifiers/SchemaIndex.ts +60 -0
- package/src/schema/property/modifiers/SchemaKey.ts +28 -0
- package/src/schema/property/modifiers/SchemaNullable.ts +18 -0
- package/src/schema/property/modifiers/SchemaOptional.ts +19 -0
- package/src/schema/property/modifiers/SchemaReadonly.ts +34 -0
- package/src/schema/property/modifiers/SchemaSerialize.ts +18 -0
- package/src/schema/property/modifiers/SchemaTracked.ts +14 -0
- package/src/schema/property/modifiers/index.ts +12 -0
- package/src/schema/property/types/SchemaArray.ts +50 -0
- package/src/schema/property/types/SchemaBoolean.ts +59 -0
- package/src/schema/property/types/SchemaDate.ts +58 -0
- package/src/schema/property/types/SchemaNumber.ts +69 -0
- package/src/schema/property/types/SchemaObject.ts +44 -0
- package/src/schema/property/types/SchemaString.ts +69 -0
- package/src/schema/property/types/index.ts +6 -0
- package/src/schema/table/SchemaComputed.ts +20 -0
- package/src/schema/table/SchemaFunction.ts +15 -0
- package/src/schema/table/index.ts +2 -0
- package/src/schema/types.ts +238 -0
- package/src/types/index.ts +5 -0
- package/src/utilities/arrays.test.ts +312 -0
- package/src/utilities/arrays.ts +12 -0
- package/src/utilities/dates.test.ts +388 -0
- package/src/utilities/dates.ts +11 -0
- package/src/utilities/dbPluginEventUtils.ts +44 -0
- package/src/utilities/index.ts +10 -0
- package/src/utilities/objects.ts +7 -0
- package/src/utilities/queryOptionsCollection.ts +16 -0
- package/src/utilities/replication.ts +23 -0
- package/src/utilities/runtime.ts +3 -0
- package/src/utilities/strings.ts +18 -0
- package/src/utilities/types.ts +1 -0
- package/src/utilities/uuid.ts +56 -0
- package/tsconfig.json +28 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { DataTranslator } from "./DataTranslator";
|
|
2
|
+
import { QueryOption } from "../query/types";
|
|
3
|
+
import { assertIsArray } from "../../assertions";
|
|
4
|
+
import { ParamsFilter } from "../../expressions";
|
|
5
|
+
import { isDate } from "../../utilities";
|
|
6
|
+
|
|
7
|
+
export class JsonTranslator<TRoot extends {}, TShape> extends DataTranslator<TRoot, TShape> {
|
|
8
|
+
|
|
9
|
+
override filter<TResult>(data: unknown, option: QueryOption<TShape, "filter">): TResult {
|
|
10
|
+
|
|
11
|
+
assertIsArray(data);
|
|
12
|
+
|
|
13
|
+
if (option.value.filter) {
|
|
14
|
+
|
|
15
|
+
if (option.value.params == null) {
|
|
16
|
+
// standard filtering
|
|
17
|
+
return data.filter(option.value.filter) as TResult;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// params filtering
|
|
21
|
+
const selector = option.value.filter as ParamsFilter<unknown, {}>
|
|
22
|
+
return data.filter(w => selector([w, option.value.params])) as TResult;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return data as TResult;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override map<T>(data: unknown, option: QueryOption<T, "map">): T {
|
|
29
|
+
|
|
30
|
+
if (Array.isArray(data) == false) {
|
|
31
|
+
throw new Error("Can only map an array of data");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const response = [];
|
|
35
|
+
|
|
36
|
+
// We want deserialization to flow through mappings
|
|
37
|
+
// TODO: Speed this up!
|
|
38
|
+
// Generate a function on the fly?
|
|
39
|
+
for (let i = 0, length = data.length; i < length; i++) {
|
|
40
|
+
|
|
41
|
+
for (let j = 0, l = option.value.fields.length; j < l; j++) {
|
|
42
|
+
const field = option.value.fields[j];
|
|
43
|
+
|
|
44
|
+
if (field.property != null) {
|
|
45
|
+
const value = field.property.getValue(data[i]);
|
|
46
|
+
|
|
47
|
+
if (value != null) {
|
|
48
|
+
field.property.setValue(data[i], field.property.deserialize(value));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
response.push(option.value.selector(data[i]));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return response as T;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override count<TResult extends number>(data: unknown, _: QueryOption<TShape, "count">): TResult {
|
|
60
|
+
|
|
61
|
+
if (Array.isArray(data)) {
|
|
62
|
+
return data.length as TResult;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
throw new Error("Cannot count resulting data, it must be an array. Please return array of data for function: count()");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
override min<TResult extends string | number | Date>(data: unknown, _: QueryOption<TShape, "min">): TResult {
|
|
69
|
+
return this._minMax(data, "min", (a: any, b: any) => a - b);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override max<TResult extends string | number | Date>(data: unknown, _: QueryOption<TShape, "max">): TResult {
|
|
73
|
+
return this._minMax(data, "max", (a: any, b: any) => b - a);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override sort<TResult>(data: unknown, option: QueryOption<TShape, "sort">): TResult {
|
|
77
|
+
|
|
78
|
+
if (Array.isArray(data)) {
|
|
79
|
+
|
|
80
|
+
data.sort((a, b) => {
|
|
81
|
+
if (option.value.direction === "asc") {
|
|
82
|
+
return (option.value.selector(a) as any) - (option.value.selector(b) as any);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (option.value.selector(b) as any) - (option.value.selector(a) as any);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return data as TResult;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
override sum<TResult extends number>(data: unknown, _: QueryOption<TShape, "sum">): TResult {
|
|
93
|
+
|
|
94
|
+
assertIsArray(data, this._formatDataNotArrayError("sum"));
|
|
95
|
+
|
|
96
|
+
const map = this.query.options.getLast("map");
|
|
97
|
+
|
|
98
|
+
let sum = 0;
|
|
99
|
+
const field = this._getSelectionField("sum", map);
|
|
100
|
+
|
|
101
|
+
for (let i = 0, length = data.length; i < length; i++) {
|
|
102
|
+
const value = data[i];
|
|
103
|
+
|
|
104
|
+
if (typeof value !== "number") {
|
|
105
|
+
throw new Error(`Cannot sum, property is not a number. Property: ${field.sourceName}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
sum += value;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return sum as TResult;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override distinct<TResult>(data: unknown, _: QueryOption<TShape, "distinct">): TResult {
|
|
115
|
+
|
|
116
|
+
assertIsArray(data, this._formatDataNotArrayError("distinct"));
|
|
117
|
+
|
|
118
|
+
const result = new Set<string | number | Date>();
|
|
119
|
+
|
|
120
|
+
// would be nice to have property info here for type detection
|
|
121
|
+
let needsDateConversion = false;
|
|
122
|
+
|
|
123
|
+
for (let i = 0, length = data.length; i < length; i++) {
|
|
124
|
+
const value = data[i];
|
|
125
|
+
|
|
126
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
127
|
+
result.add(value);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (isDate(value)) {
|
|
132
|
+
needsDateConversion = true;
|
|
133
|
+
result.add(value.toISOString());
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (needsDateConversion) {
|
|
140
|
+
return [...result].map(w => new Date(w)) as TResult;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return [...result] as TResult
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override skip<TResult>(data: unknown, option: QueryOption<TShape, "skip">): TResult {
|
|
147
|
+
|
|
148
|
+
if (Array.isArray(data)) {
|
|
149
|
+
|
|
150
|
+
if (option.value > 0) {
|
|
151
|
+
|
|
152
|
+
if (data.length < option.value) {
|
|
153
|
+
// We don't have enough data to skip, return an empty array
|
|
154
|
+
return [] as TResult;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return data.slice(option.value) as TResult;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return data as TResult;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return data as TResult;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
override take<TResult>(data: unknown, option: QueryOption<TShape, "take">): TResult {
|
|
167
|
+
if (Array.isArray(data)) {
|
|
168
|
+
|
|
169
|
+
if (option.value > 0) {
|
|
170
|
+
|
|
171
|
+
if (data.length < option.value) {
|
|
172
|
+
return data as TResult;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return data.slice(0, option.value) as TResult;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return data as TResult;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return data as TResult;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private _getSelectionField(name: string, mapOption: QueryOption<TShape, "map"> | null) {
|
|
185
|
+
|
|
186
|
+
if (mapOption == null ||
|
|
187
|
+
mapOption.value.fields.length === 0 ||
|
|
188
|
+
mapOption.value.fields.length > 1) {
|
|
189
|
+
throw new Error(`${name}() operation can only be performed when one field is mapped for a result. Ex. myset.map(x => x.someNumberOrDateOrString).${name}()`)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return mapOption.value.fields[0];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private _minMax<T extends string | number | Date>(data: unknown, name: string, sort: (a: any, b: any) => any): T {
|
|
196
|
+
|
|
197
|
+
assertIsArray(data, this._formatDataNotArrayError(name));
|
|
198
|
+
|
|
199
|
+
data.sort(sort);
|
|
200
|
+
|
|
201
|
+
if (data.length === 0) {
|
|
202
|
+
throw new Error("Cannot perform operation on empty array, result query contains no data")
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return data[0] as T;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private _formatDataNotArrayError(functionName: string) {
|
|
209
|
+
return `Cannot sum resulting data, it must be an array. Please return array of data for function: ${functionName}()`
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { QueryOption } from "../query/types";
|
|
2
|
+
import { DataTranslator } from "./DataTranslator";
|
|
3
|
+
|
|
4
|
+
export class SqlTranslator<TRoot extends {}, TShape> extends DataTranslator<TRoot, TShape> {
|
|
5
|
+
|
|
6
|
+
count<TResult extends number>(data: unknown, _: QueryOption<TShape, "count">): TResult {
|
|
7
|
+
return data as TResult;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
min<TResult extends string | number | Date>(data: unknown, _: QueryOption<TShape, "min">): TResult {
|
|
11
|
+
return data as TResult;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
max<TResult extends string | number | Date>(data: unknown, _: QueryOption<TShape, "max">): TResult {
|
|
15
|
+
return data as TResult;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
sum<TResult extends number>(data: unknown, _: QueryOption<TShape, "sum">): TResult {
|
|
19
|
+
return data as TResult;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
distinct<TResult>(data: unknown, _: QueryOption<TShape, "distinct">): TResult {
|
|
23
|
+
return data as TResult;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
filter<TResult>(data: unknown, _: QueryOption<TShape, "filter">): TResult {
|
|
27
|
+
return data as TResult;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
skip(data: unknown, _: QueryOption<TShape, "skip">): TShape {
|
|
31
|
+
return data as TShape;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
take(data: unknown, _: QueryOption<TShape, "take">): TShape {
|
|
35
|
+
return data as TShape;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
sort(data: unknown, _: QueryOption<TShape, "sort">): TShape {
|
|
39
|
+
return data as TShape;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
map(data: unknown, _: QueryOption<TShape, "map">): TShape {
|
|
43
|
+
return data as TShape;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { PluginEventCallbackPartialResult, PluginEventCallbackResult } from "../results";
|
|
2
|
+
import { QueryOptionsCollection } from "./query/QueryOptionsCollection";
|
|
3
|
+
import { CompiledSchema, InferType } from '../schema';
|
|
4
|
+
import { BulkPersistChanges, BulkPersistResult, SchemaCollection } from "../collections";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Interface for a database plugin, which provides query, destroy, and bulk operations.
|
|
8
|
+
*/
|
|
9
|
+
export interface IDbPlugin {
|
|
10
|
+
/**
|
|
11
|
+
* Executes a query operation on the database.
|
|
12
|
+
* @param event The query event containing schema, parent, and query operation.
|
|
13
|
+
* @param done Callback with the result or error.
|
|
14
|
+
*/
|
|
15
|
+
query<TRoot extends {}, TShape extends any = TRoot>(event: DbPluginQueryEvent<TRoot, TShape>, done: PluginEventCallbackResult<TShape>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Destroys or cleans up the plugin, closing connections or freeing resources.
|
|
18
|
+
* @param done Callback with an optional error.
|
|
19
|
+
*/
|
|
20
|
+
destroy(event: DbPluginEvent, done: PluginEventCallbackResult<never>): void;
|
|
21
|
+
/**
|
|
22
|
+
* Executes bulk operations (add, update, remove) on the database.
|
|
23
|
+
* @param event The bulk operations event containing schema, parent, and changes.
|
|
24
|
+
* @param done Callback with the result or error.
|
|
25
|
+
*/
|
|
26
|
+
bulkPersist(event: DbPluginBulkPersistEvent, done: PluginEventCallbackPartialResult<BulkPersistResult>): void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Event for a query operation, including schema, parent, and the query operation.
|
|
31
|
+
*/
|
|
32
|
+
export type DbPluginQueryEvent<TRoot extends {}, TShape> = DbPluginOperationEvent<IQuery<TRoot, TShape>>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Event for bulk operations, including schema, parent, and the entity changes.
|
|
36
|
+
*/
|
|
37
|
+
export type DbPluginBulkPersistEvent = DbPluginOperationEvent<BulkPersistChanges>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Base event for all plugin operations, containing the schema and parent.
|
|
41
|
+
*/
|
|
42
|
+
export type DbPluginEvent = {
|
|
43
|
+
/** The compiled schema for the entity. */
|
|
44
|
+
schemas: SchemaCollection;
|
|
45
|
+
|
|
46
|
+
/** Unique id of the event. */
|
|
47
|
+
id: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Event for a specific plugin operation, extending the base event with an operation payload.
|
|
52
|
+
*/
|
|
53
|
+
export type DbPluginOperationEvent<TOperation> = DbPluginEvent & {
|
|
54
|
+
/** The operation payload (query, changes, etc.). */
|
|
55
|
+
operation: TOperation;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Represents a collection of database plugins with a primary source and optional replicas.
|
|
60
|
+
* Used for implementing read/write separation and high availability.
|
|
61
|
+
*/
|
|
62
|
+
export type ReplicationPluginOptions = {
|
|
63
|
+
/** The primary database plugin that handles all write operations, do not include in the list of replicas. */
|
|
64
|
+
source: IDbPlugin;
|
|
65
|
+
/** Array of replica database plugins that can be used for read operations. */
|
|
66
|
+
replicas: IDbPlugin[];
|
|
67
|
+
/**
|
|
68
|
+
* The primary database plugin that handles all read operations, do not include in the list of replicas.
|
|
69
|
+
* Used when the source plugin should generate the identity properties, but the read replica will only
|
|
70
|
+
* read data. Typically this is a MemoryPlugin. Should not be included in the list of replicas.
|
|
71
|
+
*/
|
|
72
|
+
read?: IDbPlugin;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type OptimisticReplicationPluginOptions = {
|
|
76
|
+
/** The primary database plugin that handles all write operations, do not include in the list of replicas. */
|
|
77
|
+
source: IDbPlugin;
|
|
78
|
+
|
|
79
|
+
/** Array of replica database plugins that can be used for read operations. */
|
|
80
|
+
replicas: IDbPlugin[];
|
|
81
|
+
|
|
82
|
+
/** Must be a MemoryPlugin */
|
|
83
|
+
read: IDbPlugin;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
export type EntityUpdateInfo<T extends {}> = {
|
|
88
|
+
entity: InferType<T>,
|
|
89
|
+
changeType: EntityChangeType;
|
|
90
|
+
delta: { [key: string]: string | number | Date }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type TaggedEntity<T> = {
|
|
94
|
+
entity: T;
|
|
95
|
+
tag?: unknown
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Interface for a query operation, including expression, options, filters, and change tracking.
|
|
100
|
+
*/
|
|
101
|
+
export type IQuery<TRoot extends {}, TShape> = {
|
|
102
|
+
|
|
103
|
+
/** Query options (sort, skip, take, etc.). */
|
|
104
|
+
options: QueryOptionsCollection<TShape>;
|
|
105
|
+
|
|
106
|
+
schema: CompiledSchema<TRoot>;
|
|
107
|
+
/**
|
|
108
|
+
* Whether change tracking is enabled for the query result.
|
|
109
|
+
* Only enabled when the response is not reduced/aggregated/mapped.
|
|
110
|
+
*/
|
|
111
|
+
get changeTracking(): boolean;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export type EntityChangeType = "propertiesChanged" | "markedDirty" | "notModified";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { PartialResultType, PluginEventPartialResultType, PluginEventResultType, ResultType } from "./types";
|
|
2
|
+
|
|
3
|
+
abstract class BaseResult {
|
|
4
|
+
static ERROR = "error" as const;
|
|
5
|
+
static SUCCESS = "success" as const;
|
|
6
|
+
static PARTIAL = "partial" as const;
|
|
7
|
+
|
|
8
|
+
static resolve<T>(result: ResultType<T> | PartialResultType<T>, resolve: (data: T) => void, reject: (error?: any) => void) {
|
|
9
|
+
if (result.ok === BaseResult.SUCCESS) {
|
|
10
|
+
resolve(result.data);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (result.ok === BaseResult.PARTIAL) {
|
|
15
|
+
reject({
|
|
16
|
+
partial: result.data,
|
|
17
|
+
error: result.error
|
|
18
|
+
});
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
reject(result.error);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static assertSuccess<T>(result: any): asserts result is { ok: "success"; data: T } {
|
|
26
|
+
if (result.ok !== BaseResult.SUCCESS) {
|
|
27
|
+
throw new Error(`Expected success result, but got ${result.ok}: ${result.error}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class Result extends BaseResult {
|
|
33
|
+
static success<T>(data: T): ResultType<T>;
|
|
34
|
+
static success<T>(): ResultType<never>;
|
|
35
|
+
static success<T>(data?: T): ResultType<T> {
|
|
36
|
+
return {
|
|
37
|
+
ok: Result.SUCCESS,
|
|
38
|
+
data
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static error<T>(error: any): ResultType<T> {
|
|
43
|
+
return {
|
|
44
|
+
ok: Result.ERROR,
|
|
45
|
+
error
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static partial<T>(data: T, error: any): PartialResultType<T> {
|
|
50
|
+
return {
|
|
51
|
+
ok: Result.PARTIAL,
|
|
52
|
+
data,
|
|
53
|
+
error
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class PluginEventResult extends BaseResult {
|
|
59
|
+
static success<T>(id: string, data: T): PluginEventResultType<T>;
|
|
60
|
+
static success<T>(id: string): PluginEventResultType<never>;
|
|
61
|
+
static success<T>(id: string, data?: T): PluginEventResultType<T> {
|
|
62
|
+
return {
|
|
63
|
+
id,
|
|
64
|
+
ok: Result.SUCCESS,
|
|
65
|
+
data
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static error<T>(id: string, error: any): PluginEventResultType<T> {
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
ok: Result.ERROR,
|
|
73
|
+
error
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static partial<T>(id: string, data: T, error: any): PluginEventPartialResultType<T> {
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
ok: Result.PARTIAL,
|
|
81
|
+
data,
|
|
82
|
+
error
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static assertSuccess<T>(result: PluginEventResultType<T>): asserts result is { ok: "success"; data: T; id: string } {
|
|
87
|
+
if (result.ok !== Result.SUCCESS) {
|
|
88
|
+
throw new Error(`Expected success result, but got ${result.ok}: ${result.error}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ErrorType<Extra extends {} = {}> = { error: any, ok: "error" } & Extra;
|
|
2
|
+
export type SuccessType<T, Extra extends {} = {}> = { data: T, ok: "success" } & Extra;
|
|
3
|
+
export type PartialType<T, Extra extends {} = {}> = { data: T, ok: "partial", error: any } & Extra;
|
|
4
|
+
export type ResultType<T, Extra extends {} = {}> = ErrorType<Extra> | SuccessType<T, Extra>;
|
|
5
|
+
export type PartialResultType<T, Extra extends {} = {}> = ErrorType<Extra> | SuccessType<T, Extra> | PartialType<T, Extra>;
|
|
6
|
+
export type CallbackResult<TData, TCallbackResult = void> = (result: ResultType<TData>) => TCallbackResult;
|
|
7
|
+
export type CallbackPartialResult<TData, TCallbackResult = void> = (result: PartialResultType<TData>) => TCallbackResult;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
type IdentifiedType = { id: string }
|
|
11
|
+
export type PluginEventErrorType = ErrorType<IdentifiedType>;
|
|
12
|
+
export type PluginEventSuccessType<T> = SuccessType<T, IdentifiedType>;
|
|
13
|
+
export type PluginEventPartialType<T> = PartialType<T, IdentifiedType>;
|
|
14
|
+
export type PluginEventResultType<T> = PluginEventErrorType | PluginEventSuccessType<T>;
|
|
15
|
+
export type PluginEventPartialResultType<T> = PluginEventErrorType | PluginEventSuccessType<T> | PluginEventPartialType<T>;
|
|
16
|
+
export type PluginEventCallbackResult<TData, TCallbackResult = void> = (result: PluginEventResultType<TData>) => TCallbackResult;
|
|
17
|
+
export type PluginEventCallbackPartialResult<TData, TCallbackResult = void> = (result: PluginEventPartialResultType<TData>) => TCallbackResult;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Result } from "./Result";
|
|
2
|
+
import { CallbackResult } from "./types";
|
|
3
|
+
|
|
4
|
+
export function toPromise<T>(fn: (callback: CallbackResult<T>) => void) {
|
|
5
|
+
return new Promise<T>((resolve, reject) => {
|
|
6
|
+
fn((r) => {
|
|
7
|
+
if (r.ok === Result.ERROR) {
|
|
8
|
+
reject(r.error);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
resolve(r.data);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|