@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,202 @@
|
|
|
1
|
+
import { PluginEventCallbackPartialResult, PluginEventCallbackResult, PluginEventResult, Result } from '../../results';
|
|
2
|
+
import { DbPluginBulkPersistEvent, DbPluginEvent, DbPluginQueryEvent, IDbPlugin, OptimisticReplicationPluginOptions } from '../types';
|
|
3
|
+
import { WorkPipeline } from '../../pipeline'; 7
|
|
4
|
+
import { CompiledSchema } from '../../schema';
|
|
5
|
+
import { Query } from '../query';
|
|
6
|
+
import { resolveBulkPersistChanges, uuid } from '../../utilities';
|
|
7
|
+
import { BulkPersistChanges, BulkPersistResult } from '../../collections';
|
|
8
|
+
|
|
9
|
+
const getMemoryPluginCollectionSize = <T extends {}>(plugin: IDbPlugin, schema: CompiledSchema<T>): number => {
|
|
10
|
+
|
|
11
|
+
if ("getCollectionSize" in plugin && typeof plugin.getCollectionSize === "function") {
|
|
12
|
+
return plugin.getCollectionSize(schema.collectionName) as number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
throw new Error("Cannot get size of collection for MemoryPlugin, not an instance of MemoryPlugin")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class OptimisticReplicationDbPlugin implements IDbPlugin {
|
|
19
|
+
|
|
20
|
+
protected plugins: OptimisticReplicationPluginOptions;
|
|
21
|
+
|
|
22
|
+
protected constructor(plugins: OptimisticReplicationPluginOptions) {
|
|
23
|
+
this.plugins = plugins;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new OptimisticDbPluginReplicator that coordinates operations between a source database and its replicas.
|
|
28
|
+
*
|
|
29
|
+
* @param source The primary database plugin that will receive all operations first
|
|
30
|
+
* @param replicas Additional database plugins that will replicate operations from the source
|
|
31
|
+
* @returns A new DbPluginReplicator instance that manages the source-replica relationship
|
|
32
|
+
*/
|
|
33
|
+
static create(plugins: OptimisticReplicationPluginOptions) {
|
|
34
|
+
return new OptimisticReplicationDbPlugin(plugins);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Will query the read plugin if there is one, otherwise the source plugin will be queried
|
|
39
|
+
*/
|
|
40
|
+
query<TEntity extends {}, TShape extends any = TEntity>(event: DbPluginQueryEvent<TEntity, TShape>, done: PluginEventCallbackResult<TShape>): void {
|
|
41
|
+
try {
|
|
42
|
+
|
|
43
|
+
const readPlugin = this.plugins.read;
|
|
44
|
+
const sourcePlugin = this.plugins.source;
|
|
45
|
+
const collectionSize = getMemoryPluginCollectionSize(this.plugins.read, event.operation.schema);
|
|
46
|
+
|
|
47
|
+
if (collectionSize === 0) {
|
|
48
|
+
// nothing is hydrated, let's try and hydrate before querying
|
|
49
|
+
// Memory plugin might not be hydrated, lets hydrate it for the targeted schema only,
|
|
50
|
+
// Other queries will do the same and hydrate if needed
|
|
51
|
+
// We want to select all data here
|
|
52
|
+
sourcePlugin.query<TEntity, TShape>({
|
|
53
|
+
id: uuid(8),
|
|
54
|
+
schemas: event.schemas,
|
|
55
|
+
|
|
56
|
+
// Select All Data
|
|
57
|
+
operation: Query.EMPTY<TEntity, TShape>(event.operation.schema)
|
|
58
|
+
}, (sourceResult) => {
|
|
59
|
+
|
|
60
|
+
if (sourceResult.ok === Result.ERROR) {
|
|
61
|
+
done(sourceResult);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (sourceResult == null || (Array.isArray(sourceResult.data) && sourceResult.data.length === 0)) {
|
|
66
|
+
done(sourceResult);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (Array.isArray(sourceResult.data) === false) {
|
|
71
|
+
done(PluginEventResult.error(event.id, "Query result is not an array"));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const changesCollection = new BulkPersistChanges();
|
|
76
|
+
const schemaChanges = changesCollection.resolve(event.operation.schema.id);
|
|
77
|
+
|
|
78
|
+
// Add the existing items into the persist payload as adds
|
|
79
|
+
schemaChanges.adds = sourceResult.data;
|
|
80
|
+
|
|
81
|
+
readPlugin.bulkPersist({
|
|
82
|
+
id: uuid(8),
|
|
83
|
+
schemas: event.schemas,
|
|
84
|
+
operation: changesCollection
|
|
85
|
+
}, (readPersistResult) => {
|
|
86
|
+
|
|
87
|
+
if (readPersistResult.ok === Result.ERROR) {
|
|
88
|
+
done(readPersistResult);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// requery the read plugin
|
|
93
|
+
readPlugin.query(event, done);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Collection is hydrated for the targeted collection and should be in sync
|
|
100
|
+
readPlugin.query(event, (readResult) => {
|
|
101
|
+
|
|
102
|
+
if (readResult.ok === Result.ERROR) {
|
|
103
|
+
done(readResult);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
done(readResult);
|
|
108
|
+
return;
|
|
109
|
+
|
|
110
|
+
});
|
|
111
|
+
} catch (e: any) {
|
|
112
|
+
done(PluginEventResult.error(event.id, e));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
destroy(event: DbPluginEvent, done: PluginEventCallbackResult<never>): void {
|
|
117
|
+
try {
|
|
118
|
+
|
|
119
|
+
const workPipeline = new WorkPipeline();
|
|
120
|
+
const plugins = [this.plugins.source, ...this.plugins.replicas];
|
|
121
|
+
|
|
122
|
+
for (let i = 0, length = plugins.length; i < length; i++) {
|
|
123
|
+
workPipeline.pipe((done) => plugins[i].destroy(event, done));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
workPipeline.filter((result) => {
|
|
127
|
+
|
|
128
|
+
if (result.ok === Result.ERROR) {
|
|
129
|
+
done(PluginEventResult.error(event.id, result.error));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
done(PluginEventResult.success(event.id));
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
} catch (e: any) {
|
|
137
|
+
done(PluginEventResult.error(event.id, e));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
bulkPersist(event: DbPluginBulkPersistEvent, done: PluginEventCallbackPartialResult<BulkPersistResult>): void {
|
|
142
|
+
try {
|
|
143
|
+
|
|
144
|
+
const workPipeline = new WorkPipeline();
|
|
145
|
+
const deferredPlugins = [this.plugins.source, ... this.plugins.replicas];
|
|
146
|
+
|
|
147
|
+
// Since we are doing optimistic, we insert into the read plugin first and assume later plugins will succeed
|
|
148
|
+
// This means the read plugin will generate ids for the source plugin
|
|
149
|
+
this.plugins.read.bulkPersist({
|
|
150
|
+
id: uuid(8),
|
|
151
|
+
operation: event.operation,
|
|
152
|
+
schemas: event.schemas
|
|
153
|
+
}, (r) => {
|
|
154
|
+
|
|
155
|
+
if (r.ok !== Result.SUCCESS) {
|
|
156
|
+
done(r);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// optimistically call done and still continue saving the rest of the data. We read from the memory
|
|
161
|
+
// db anyways
|
|
162
|
+
done(r);
|
|
163
|
+
|
|
164
|
+
const optimisticBulkPersistChanges = new BulkPersistChanges();
|
|
165
|
+
|
|
166
|
+
// make sure we swap the adds here, that way we can make sure other persist events
|
|
167
|
+
// don't take their additions and try to change subsequent calls
|
|
168
|
+
resolveBulkPersistChanges(event, r.data, optimisticBulkPersistChanges);
|
|
169
|
+
|
|
170
|
+
for (let i = 0, length = deferredPlugins.length; i < length; i++) {
|
|
171
|
+
workPipeline.pipe((d) => {
|
|
172
|
+
|
|
173
|
+
const plugin = deferredPlugins[i];
|
|
174
|
+
|
|
175
|
+
plugin.bulkPersist({
|
|
176
|
+
id: uuid(8),
|
|
177
|
+
operation: optimisticBulkPersistChanges,
|
|
178
|
+
schemas: event.schemas
|
|
179
|
+
}, (r) => {
|
|
180
|
+
|
|
181
|
+
if (r.ok === Result.ERROR) {
|
|
182
|
+
d(r);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
d(Result.success());
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
setTimeout(() => {
|
|
192
|
+
workPipeline.filter((_) => {
|
|
193
|
+
// no-op for now, maybe implement retries?
|
|
194
|
+
});
|
|
195
|
+
}, 5);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
} catch (e: any) {
|
|
199
|
+
done(PluginEventResult.error(event.id, e));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { PluginEventCallbackPartialResult, PluginEventCallbackResult, PluginEventResult, Result } from '../../results';
|
|
2
|
+
import { DbPluginBulkPersistEvent, DbPluginEvent, DbPluginQueryEvent, IDbPlugin, ReplicationPluginOptions } from '../types';
|
|
3
|
+
import { AsyncPipeline, WorkPipeline } from '../../pipeline';
|
|
4
|
+
import { BulkPersistResult } from '../../collections';
|
|
5
|
+
import { resolveBulkPersistChanges } from '../../utilities';
|
|
6
|
+
|
|
7
|
+
export class ReplicationDbPlugin implements IDbPlugin {
|
|
8
|
+
|
|
9
|
+
plugins: ReplicationPluginOptions;
|
|
10
|
+
|
|
11
|
+
protected constructor(plugins: ReplicationPluginOptions) {
|
|
12
|
+
this.plugins = plugins;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new DbPluginReplicator that coordinates operations between a source database and its replicas.
|
|
17
|
+
*
|
|
18
|
+
* @param source The primary database plugin that will receive all operations first
|
|
19
|
+
* @param replicas Additional database plugins that will replicate operations from the source
|
|
20
|
+
* @returns A new DbPluginReplicator instance that manages the source-replica relationship
|
|
21
|
+
*/
|
|
22
|
+
static create(plugins: ReplicationPluginOptions) {
|
|
23
|
+
return new ReplicationDbPlugin(plugins);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Will query the read plugin if there is one, otherwise the source plugin will be queried
|
|
28
|
+
*/
|
|
29
|
+
query<TEntity extends {}, TShape extends any = TEntity>(event: DbPluginQueryEvent<TEntity, TShape>, done: PluginEventCallbackResult<TShape>): void {
|
|
30
|
+
try {
|
|
31
|
+
|
|
32
|
+
const plugin = this.plugins.read != null ? this.plugins.read : this.plugins.source;
|
|
33
|
+
|
|
34
|
+
plugin.query(event, done);
|
|
35
|
+
} catch (e: any) {
|
|
36
|
+
done(PluginEventResult.error(event.id, e));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
destroy(event: DbPluginEvent, done: PluginEventCallbackResult<never>): void {
|
|
41
|
+
try {
|
|
42
|
+
|
|
43
|
+
const pipeline = new AsyncPipeline<IDbPlugin, never>();
|
|
44
|
+
const plugins = [this.plugins.source, ...this.plugins.replicas];
|
|
45
|
+
|
|
46
|
+
for (let i = 0, length = plugins.length; i < length; i++) {
|
|
47
|
+
pipeline.pipe(plugins[i], (plugin, done) => plugin.destroy(event, done));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pipeline.filter((result) => {
|
|
51
|
+
|
|
52
|
+
if (result.ok === Result.ERROR) {
|
|
53
|
+
done(PluginEventResult.error(event.id, result.error));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
done(PluginEventResult.success(event.id));
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
} catch (e: any) {
|
|
61
|
+
done(PluginEventResult.error(event.id, e));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
bulkPersist(event: DbPluginBulkPersistEvent, done: PluginEventCallbackPartialResult<BulkPersistResult>): void {
|
|
67
|
+
try {
|
|
68
|
+
// insert into the source first to generate any ids, then take the result and persist that into the replicas
|
|
69
|
+
const pipeline = new WorkPipeline();
|
|
70
|
+
const plugins = [this.plugins.source, ...this.plugins.replicas];
|
|
71
|
+
|
|
72
|
+
if (this.plugins.read != null) {
|
|
73
|
+
plugins.push(this.plugins.read);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const result = new BulkPersistResult();
|
|
77
|
+
|
|
78
|
+
for (let i = 0, length = plugins.length; i < length; i++) {
|
|
79
|
+
pipeline.pipe((d) => {
|
|
80
|
+
|
|
81
|
+
const plugin = plugins[i];
|
|
82
|
+
|
|
83
|
+
// source is first
|
|
84
|
+
if (i === 0) {
|
|
85
|
+
plugin.bulkPersist(event, (r) => {
|
|
86
|
+
|
|
87
|
+
if (r.ok === Result.ERROR) {
|
|
88
|
+
d(r)
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// make sure we swap the adds here, that way we can make sure other persist events
|
|
93
|
+
// don't take their additions and try to change subsequent calls
|
|
94
|
+
resolveBulkPersistChanges(event, r.data, event.operation);
|
|
95
|
+
|
|
96
|
+
d(Result.success());
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
plugin.bulkPersist(event, (r) => {
|
|
102
|
+
|
|
103
|
+
if (r.ok === Result.ERROR) {
|
|
104
|
+
d(r)
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
d(Result.success());
|
|
109
|
+
});
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let successCount = 0;
|
|
114
|
+
|
|
115
|
+
pipeline.filter((r) => {
|
|
116
|
+
|
|
117
|
+
if (r.ok === Result.ERROR) {
|
|
118
|
+
|
|
119
|
+
if (successCount > 0) {
|
|
120
|
+
done(PluginEventResult.partial(event.id, result, r.error));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
done(PluginEventResult.error(event.id, r.error));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
successCount++;
|
|
129
|
+
|
|
130
|
+
done(PluginEventResult.success(event.id, result));
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
} catch (e: any) {
|
|
134
|
+
done(PluginEventResult.error(event.id, e));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { QueryOption, QueryOptionName } from "../query/types";
|
|
2
|
+
import { IQuery } from "../types";
|
|
3
|
+
|
|
4
|
+
export abstract class DataTranslator<TRoot extends {}, TShape> {
|
|
5
|
+
|
|
6
|
+
protected query: IQuery<TRoot, TShape>;
|
|
7
|
+
private functionMap: Record<QueryOptionName, (data: unknown, option: QueryOption<any, any>) => TShape> = {
|
|
8
|
+
count: (data: unknown, option: QueryOption<TShape, "count">) => this.count<any>(data, option),
|
|
9
|
+
distinct: (data: unknown, option: QueryOption<TShape, "distinct">) => this.distinct(data, option),
|
|
10
|
+
filter: (data: unknown, option: QueryOption<TShape, "filter">) => this.filter(data, option),
|
|
11
|
+
map: (data: unknown, option: QueryOption<TShape, "map">) => this.map(data, option),
|
|
12
|
+
max: (data: unknown, option: QueryOption<TShape, "max">) => this.max<any>(data, option),
|
|
13
|
+
min: (data: unknown, option: QueryOption<TShape, "min">) => this.min<any>(data, option),
|
|
14
|
+
skip: (data: unknown, option: QueryOption<TShape, "skip">) => this.skip(data, option),
|
|
15
|
+
sort: (data: unknown, option: QueryOption<TShape, "sort">) => this.sort(data, option),
|
|
16
|
+
sum: (data: unknown, option: QueryOption<TShape, "sum">) => this.sum<any>(data, option),
|
|
17
|
+
take: (data: unknown, option: QueryOption<TShape, "take">) => this.take(data, option)
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
constructor(query: IQuery<TRoot, TShape>) {
|
|
21
|
+
this.query = query;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Terminators
|
|
25
|
+
abstract count<TResult extends number>(data: unknown, option: QueryOption<TShape, "count">): TResult;
|
|
26
|
+
abstract min<TResult extends string | number | Date>(data: unknown, option: QueryOption<TShape, "min">): TResult;
|
|
27
|
+
abstract max<TResult extends string | number | Date>(data: unknown, option: QueryOption<TShape, "max">): TResult;
|
|
28
|
+
abstract sum<TResult extends number>(data: unknown, option: QueryOption<TShape, "sum">): TResult;
|
|
29
|
+
abstract distinct<TResult>(data: unknown, option: QueryOption<TShape, "distinct">): TResult;
|
|
30
|
+
|
|
31
|
+
// Shapers
|
|
32
|
+
abstract filter<TResult>(data: unknown, option: QueryOption<TShape, "filter">): TResult;
|
|
33
|
+
abstract skip(data: unknown, option: QueryOption<TShape, "skip">): TShape;
|
|
34
|
+
abstract take(data: unknown, option: QueryOption<TShape, "take">): TShape;
|
|
35
|
+
abstract sort(data: unknown, option: QueryOption<TShape, "sort">): TShape;
|
|
36
|
+
abstract map(data: unknown, option: QueryOption<TShape, "map">): TShape;
|
|
37
|
+
|
|
38
|
+
translate(data: unknown): TShape {
|
|
39
|
+
|
|
40
|
+
this.query.options.forEach(item => {
|
|
41
|
+
data = this.functionMap[item.name](data, item);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return data as TShape;
|
|
45
|
+
}
|
|
46
|
+
}
|