@deterministic-code/datasources 0.0.0-stage → 0.1.0
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/package.json +16 -4
- package/src/ArrayReader.ts +32 -0
- package/src/BatchCommandIBulkWriteStrategy.ts +228 -0
- package/src/BuiltRepository.ts +17 -0
- package/src/BulkCRUDRepository.ts +84 -0
- package/src/BulkCommand.ts +6 -0
- package/src/BulkWriteEnrichment.ts +19 -0
- package/src/CRUDRepository.ts +264 -0
- package/src/CRUDRepositoryBuilder.ts +53 -0
- package/src/CRUDRepositoryOptions.ts +8 -0
- package/src/CRUDRepositoryStatements.ts +43 -0
- package/src/CascadeDeleteEnrichmentStrategy.ts +51 -0
- package/src/CascadeDeleteUpdateEnrichmentStrategy.ts +28 -0
- package/src/CommandMiddlewareHost.ts +113 -0
- package/src/ConsoleCommandMiddleware.ts +64 -0
- package/src/CreateEnrichmentStrategy.ts +82 -0
- package/src/Datasource.ts +152 -0
- package/src/DatasourceError.ts +6 -0
- package/src/DatasourceFactory.ts +86 -0
- package/src/DatasourceOptions.ts +1 -0
- package/src/DatasourceUrl.ts +37 -0
- package/src/DatasourceUrlParser.ts +188 -0
- package/src/DefaultCreateEnrichmentStrategy.ts +21 -0
- package/src/DefaultReadonlyEnrichmentStrategy.ts +164 -0
- package/src/DefaultUpdateEnrichmentStrategy.ts +40 -0
- package/src/DefaultWriteEnrichmentStrategy.ts +151 -0
- package/src/DeleteEnrichmentStrategy.ts +56 -0
- package/src/DriverLoader.ts +97 -0
- package/src/Enrichment.ts +15 -0
- package/src/EnrichmentPropertyType.ts +9 -0
- package/src/ExpectConsoleMiddleware.ts +47 -0
- package/src/FirstResultReader.ts +49 -0
- package/src/HashsetOptimizedReadonlyEnrichmentStrategy.ts +80 -0
- package/src/IBulkWriteStrategy.ts +13 -0
- package/src/ICRUDRepository.ts +13 -0
- package/src/ICRUDRepositoryFactory.ts +8 -0
- package/src/ICommand.ts +45 -0
- package/src/ICommandMiddleware.ts +20 -0
- package/src/IConnection.ts +13 -0
- package/src/IDatasource.ts +27 -0
- package/src/IDatasourceFactory.ts +6 -0
- package/src/IDriver.ts +24 -0
- package/src/IEnriched.ts +11 -0
- package/src/IReader.ts +8 -0
- package/src/IReadonlyEnrichmentStrategy.ts +19 -0
- package/src/IReadonlyRepository.ts +21 -0
- package/src/IRepository.ts +5 -0
- package/src/IRepositoryFactory.ts +8 -0
- package/src/IRepositoryTree.ts +5 -0
- package/src/IRepositoryTreeNode.ts +8 -0
- package/src/ITransaction.ts +9 -0
- package/src/IUnitOfWork.ts +5 -0
- package/src/IWriteEnrichmentStrategy.ts +8 -0
- package/src/Information.ts +5 -0
- package/src/IsolationLevel.ts +8 -0
- package/src/LazyWriteEnrichmentStrategy.ts +5 -0
- package/src/NestedToObjectEnrichmentStrategy.ts +33 -0
- package/src/Parameter.ts +8 -0
- package/src/ParameterDirection.ts +9 -0
- package/src/ProviderCatalog.ts +21 -0
- package/src/ProviderNotImplementedError.ts +9 -0
- package/src/ProviderNotInstalledError.ts +9 -0
- package/src/ReadonlyRepository.ts +276 -0
- package/src/ReadonlyRepositoryBuilder.ts +53 -0
- package/src/ReadonlyRepositoryMappingOptions.ts +15 -0
- package/src/ReadonlyRepositoryStatements.ts +13 -0
- package/src/RepositoryAccess.ts +14 -0
- package/src/RepositoryFactory.ts +115 -0
- package/src/RepositoryNotRegisteredError.ts +9 -0
- package/src/RepositoryTree.ts +6 -0
- package/src/RepositoryTreeNode.ts +11 -0
- package/src/Response.ts +15 -0
- package/src/Row.ts +3 -0
- package/src/SingleCommandIBulkWriteStrategy.ts +35 -0
- package/src/StatementMappers.ts +110 -0
- package/src/StoredEnrichment.ts +25 -0
- package/src/StoredProcedureBulkWriteStrategy.ts +164 -0
- package/src/StreamingReader.ts +64 -0
- package/src/UnitOfWorkTransaction.ts +50 -0
- package/src/UpdateEnrichmentStrategy.ts +97 -0
- package/src/WriteMode.ts +1 -0
- package/src/builders/Field.ts +6 -0
- package/src/builders/Scalar.ts +1 -0
- package/src/builders/index.ts +2 -0
- package/src/collectAsync.ts +7 -0
- package/src/converters/Cell.ts +10 -0
- package/src/converters/ChangeCasingConverter.ts +59 -0
- package/src/converters/Constructable.ts +1 -0
- package/src/converters/MetaDataRowTypeConverter.ts +80 -0
- package/src/converters/PluralizerConverter.ts +67 -0
- package/src/converters/RegexConverter.ts +14 -0
- package/src/converters/ReplaceConverter.ts +6 -0
- package/src/converters/RowTypeConverter.ts +33 -0
- package/src/converters/ToLowerCaseConverter.ts +4 -0
- package/src/converters/ToUpperCaseConverter.ts +4 -0
- package/src/converters/TypeConverter.ts +6 -0
- package/src/createCRUDRepositoryOptions.ts +21 -0
- package/src/createReadonlyRepositoryMappingOptions.ts +26 -0
- package/src/dotEnv.ts +16 -0
- package/src/index.ts +222 -0
- package/src/mappers/ChangeCasingMapper.ts +15 -0
- package/src/mappers/DictionaryMapper.ts +16 -0
- package/src/mappers/FlatToNestedMapper.ts +127 -0
- package/src/mappers/IFlatToNestedMapper.ts +7 -0
- package/src/mappers/IMapper.ts +4 -0
- package/src/mappers/IdentityMapper.ts +6 -0
- package/src/mappers/PluralizerMapper.ts +9 -0
- package/src/mappers/RowTypeMapper.ts +13 -0
- package/src/mappers/TransformConverterMapper.ts +11 -0
- package/src/mappers/TransformMapper.ts +8 -0
- package/src/mappers/TypeMap.ts +10 -0
- package/src/mappers/TypeMapGroup.ts +6 -0
- package/src/mocks/index.ts +9 -0
- package/src/mocks/mock-command.ts +66 -0
- package/src/mocks/mock-connection.ts +57 -0
- package/src/mocks/mock-datasource.ts +65 -0
- package/src/mocks/mock-driver.ts +27 -0
- package/src/mocks/mock-reader.ts +38 -0
- package/src/mocks/mock-repository.ts +91 -0
- package/src/mocks/mock-select-statement.ts +17 -0
- package/src/mocks/mock-transaction.ts +31 -0
- package/src/mocks/mock-where.ts +13 -0
- package/src/parametersToRecord.ts +11 -0
- package/src/readerToAsyncIterable.ts +11 -0
- package/src/splitStatements.ts +99 -0
- package/src/statementParameters.ts +22 -0
- package/src/statementUsesParameter.ts +4 -0
- package/src/statements/Aggregate.ts +9 -0
- package/src/statements/ArrayExpression.ts +5 -0
- package/src/statements/BulkDeleteStatement.ts +18 -0
- package/src/statements/BulkDeleteStatementTextRenderer.ts +16 -0
- package/src/statements/BulkInsertStatement.ts +37 -0
- package/src/statements/BulkInsertStatementTextRenderer.ts +10 -0
- package/src/statements/BulkUpdateStatement.ts +24 -0
- package/src/statements/BulkUpdateStatementTextRenderer.ts +29 -0
- package/src/statements/CheckConstraint.ts +9 -0
- package/src/statements/Cmp.ts +12 -0
- package/src/statements/Column.ts +10 -0
- package/src/statements/ColumnDefault.ts +6 -0
- package/src/statements/Condition.ts +3 -0
- package/src/statements/ConditionRenderer.ts +17 -0
- package/src/statements/CreateIndexStatement.ts +18 -0
- package/src/statements/CreateIndexStatementTextRenderer.ts +11 -0
- package/src/statements/CreateTableStatement.ts +18 -0
- package/src/statements/CreateTableStatementTextRenderer.ts +92 -0
- package/src/statements/DefaultStatementTextRenderer.ts +9 -0
- package/src/statements/DeleteStatement.ts +15 -0
- package/src/statements/DeleteStatementTextRenderer.ts +12 -0
- package/src/statements/ExecuteStoredProcedureStatement.ts +15 -0
- package/src/statements/ExecuteStoredProcedureStatementTextRenderer.ts +15 -0
- package/src/statements/ExpressionEvaluator.ts +166 -0
- package/src/statements/ExpressionRenderer.ts +161 -0
- package/src/statements/ForeignKey.ts +23 -0
- package/src/statements/IBulkDeleteStatement.ts +3 -0
- package/src/statements/IBulkInsertStatement.ts +3 -0
- package/src/statements/IBulkUpdateStatement.ts +3 -0
- package/src/statements/ICondition.ts +5 -0
- package/src/statements/IConditionVisitor.ts +7 -0
- package/src/statements/ICreateIndexStatement.ts +3 -0
- package/src/statements/ICreateTableStatement.ts +3 -0
- package/src/statements/IDeleteStatement.ts +6 -0
- package/src/statements/IExecuteStoredProcedureStatement.ts +3 -0
- package/src/statements/IExpression.ts +1 -0
- package/src/statements/IInsertStatement.ts +3 -0
- package/src/statements/IReturnStatement.ts +3 -0
- package/src/statements/ISelectStatement.ts +6 -0
- package/src/statements/IStatement.ts +5 -0
- package/src/statements/IStatementVisitor.ts +27 -0
- package/src/statements/ITableConstraint.ts +6 -0
- package/src/statements/IUpdateStatement.ts +6 -0
- package/src/statements/IWhere.ts +7 -0
- package/src/statements/Identifier.ts +5 -0
- package/src/statements/InsertStatement.ts +15 -0
- package/src/statements/InsertStatementTextRenderer.ts +7 -0
- package/src/statements/Join.ts +26 -0
- package/src/statements/Literal.ts +6 -0
- package/src/statements/Native.ts +5 -0
- package/src/statements/NotNull.ts +3 -0
- package/src/statements/Operator.ts +234 -0
- package/src/statements/OrderBy.ts +19 -0
- package/src/statements/PrimaryKey.ts +9 -0
- package/src/statements/ReturnStatement.ts +15 -0
- package/src/statements/ReturnStatementTextRenderer.ts +15 -0
- package/src/statements/SelectInsertedIdStatement.ts +11 -0
- package/src/statements/SelectInsertedIdStatementTextRenderer.ts +7 -0
- package/src/statements/SelectStatement.ts +34 -0
- package/src/statements/SelectStatementOptions.ts +16 -0
- package/src/statements/SelectStatementTextRenderer.ts +71 -0
- package/src/statements/StatementEvaluator.ts +5 -0
- package/src/statements/StatementParser.ts +461 -0
- package/src/statements/StatementRenderer.ts +120 -0
- package/src/statements/StatementTextRenderer.ts +60 -0
- package/src/statements/Subquery.ts +6 -0
- package/src/statements/UniqueConstraint.ts +9 -0
- package/src/statements/UpdateStatement.ts +34 -0
- package/src/statements/UpdateStatementTextRenderer.ts +63 -0
- package/src/statements/Where.ts +250 -0
- package/src/statements/WhereText.ts +10 -0
- package/src/statements/index.ts +75 -0
- package/src/stubs/StubCommand.ts +30 -0
- package/src/stubs/StubConnection.ts +21 -0
- package/src/stubs/StubDatasource.ts +60 -0
- package/src/stubs/StubReader.ts +25 -0
- package/src/stubs/StubRepository.ts +42 -0
- package/src/stubs/StubTransaction.ts +17 -0
- package/src/stubs/createStubDatasource.ts +4 -0
- package/src/stubs/index.ts +7 -0
- package/src/stubs/notImplemented.ts +5 -0
- package/README.md +0 -3
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { CascadeDeleteEnrichmentStrategy } from "./CascadeDeleteEnrichmentStrategy.ts";
|
|
2
|
+
import type { CreateEnrichmentStrategy } from "./CreateEnrichmentStrategy.ts";
|
|
3
|
+
import { DatasourceError } from "./DatasourceError.ts";
|
|
4
|
+
import { DefaultCreateEnrichmentStrategy } from "./DefaultCreateEnrichmentStrategy.ts";
|
|
5
|
+
import { EnrichmentPropertyType } from "./EnrichmentPropertyType.ts";
|
|
6
|
+
import { DefaultUpdateEnrichmentStrategy } from "./DefaultUpdateEnrichmentStrategy.ts";
|
|
7
|
+
import type { ICRUDRepository } from "./ICRUDRepository.ts";
|
|
8
|
+
import { enrichmentsOf } from "./ReadonlyRepository.ts";
|
|
9
|
+
import type { IRepositoryTree } from "./IRepositoryTree.ts";
|
|
10
|
+
import type { IWriteEnrichmentStrategy } from "./IWriteEnrichmentStrategy.ts";
|
|
11
|
+
import type { StoredEnrichment } from "./StoredEnrichment.ts";
|
|
12
|
+
import type { Scalar } from "./builders/Scalar.ts";
|
|
13
|
+
import type { DeleteEnrichmentStrategy } from "./DeleteEnrichmentStrategy.ts";
|
|
14
|
+
import type { UpdateEnrichmentStrategy } from "./UpdateEnrichmentStrategy.ts";
|
|
15
|
+
import type { WriteMode } from "./WriteMode.ts";
|
|
16
|
+
|
|
17
|
+
const unloaded = <TParent>(parent: TParent, into: string): boolean => {
|
|
18
|
+
const value = (parent as never as Record<string, Scalar | object>)[into];
|
|
19
|
+
return value === undefined || value === null;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const childWriter = (entry: StoredEnrichment, into: string): ICRUDRepository<object> => {
|
|
23
|
+
if (entry.persist) return entry.persist;
|
|
24
|
+
throw new DatasourceError(`Deep write requires a CRUD repository for "${into}"`);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const linkWriter = (entry: StoredEnrichment, into: string): ICRUDRepository<object> => {
|
|
28
|
+
if (entry.link) return entry.link;
|
|
29
|
+
throw new DatasourceError(`Deep write requires a CRUD repository for "${into}"`);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const dispatch = (mode: string, runs: Record<WriteMode, () => Promise<void>>): Promise<void> =>
|
|
33
|
+
(runs[mode as WriteMode] ??
|
|
34
|
+
(() => {
|
|
35
|
+
throw new DatasourceError("Unknown persist mode");
|
|
36
|
+
}))();
|
|
37
|
+
|
|
38
|
+
export class DefaultWriteEnrichmentStrategy<T> implements IWriteEnrichmentStrategy<T> {
|
|
39
|
+
protected skipUnloaded = false;
|
|
40
|
+
readonly useTransaction: boolean;
|
|
41
|
+
private readonly createStrategy: CreateEnrichmentStrategy<T>;
|
|
42
|
+
private readonly deleteStrategy: DeleteEnrichmentStrategy<T>;
|
|
43
|
+
private readonly updateStrategy: UpdateEnrichmentStrategy<T>;
|
|
44
|
+
|
|
45
|
+
constructor(
|
|
46
|
+
deleteStrategy: DeleteEnrichmentStrategy<T> = new CascadeDeleteEnrichmentStrategy<T>(),
|
|
47
|
+
updateStrategy: UpdateEnrichmentStrategy<T> = new DefaultUpdateEnrichmentStrategy<T>(),
|
|
48
|
+
createStrategy: CreateEnrichmentStrategy<T> = new DefaultCreateEnrichmentStrategy<T>(),
|
|
49
|
+
useTransaction = false,
|
|
50
|
+
) {
|
|
51
|
+
this.deleteStrategy = deleteStrategy;
|
|
52
|
+
this.updateStrategy = updateStrategy;
|
|
53
|
+
this.createStrategy = createStrategy;
|
|
54
|
+
this.useTransaction = useTransaction;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
persist = async (tree: IRepositoryTree, items: T[], mode: WriteMode): Promise<void> => {
|
|
58
|
+
await this.walk(tree.parent.value, items, mode);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
persistBulk = async (tree: IRepositoryTree, items: T[], mode: WriteMode): Promise<void> => {
|
|
62
|
+
if (mode === "delete") return this.persist(tree, items, mode);
|
|
63
|
+
await this.walkBulk(tree.parent.value, items, mode);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
private walk = async (host: object, parents: T[], mode: WriteMode): Promise<void> => {
|
|
67
|
+
const entries = enrichmentsOf(host);
|
|
68
|
+
if (!entries) return;
|
|
69
|
+
for (const entry of entries) await this.persistEntry(entry, parents, mode);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
private walkBulk = async (host: object, parents: T[], mode: WriteMode): Promise<void> => {
|
|
73
|
+
const entries = enrichmentsOf(host);
|
|
74
|
+
if (!entries) return;
|
|
75
|
+
for (const entry of entries) await this.persistEntryBulk(entry, parents, mode);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
private persistEntryBulk = async (
|
|
79
|
+
entry: StoredEnrichment,
|
|
80
|
+
parents: T[],
|
|
81
|
+
mode: WriteMode,
|
|
82
|
+
): Promise<void> => {
|
|
83
|
+
const enrichment = entry.enrichment;
|
|
84
|
+
const type = enrichment.type ?? EnrichmentPropertyType.Object;
|
|
85
|
+
if (type === EnrichmentPropertyType.Custom)
|
|
86
|
+
throw new DatasourceError(`Unsupported enrichment type "${type}"`);
|
|
87
|
+
if (enrichment.association) {
|
|
88
|
+
const writer = linkWriter(entry, enrichment.destinationProperty);
|
|
89
|
+
for (const parent of parents) {
|
|
90
|
+
if (this.skip(parent, enrichment.destinationProperty, mode)) continue;
|
|
91
|
+
await dispatch(mode, {
|
|
92
|
+
create: () => this.createStrategy.createLinked(writer, enrichment, parent),
|
|
93
|
+
update: () => this.updateStrategy.updateLinked(writer, enrichment, parent),
|
|
94
|
+
delete: () => this.deleteStrategy.deleteLinked(writer, enrichment, parent),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (type === EnrichmentPropertyType.List && enrichment.relatedProperty) return;
|
|
100
|
+
if (type !== EnrichmentPropertyType.List && type !== EnrichmentPropertyType.Dictionary) return;
|
|
101
|
+
const writer = childWriter(entry, enrichment.destinationProperty);
|
|
102
|
+
const ready = parents.filter((parent) => !this.skip(parent, enrichment.destinationProperty, mode));
|
|
103
|
+
const children = ready.flatMap((parent) => this.createStrategy.collectChildren(writer, enrichment, parent));
|
|
104
|
+
if (children.length === 0) return;
|
|
105
|
+
const bulk = writer as ICRUDRepository<object> & { createBulk?: (items: object[]) => Promise<object[]>; updateBulk?: (items: object[]) => Promise<unknown> };
|
|
106
|
+
if (mode === "create") {
|
|
107
|
+
if (bulk.createBulk) await bulk.createBulk(children);
|
|
108
|
+
else for (const child of children) await writer.create(child);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (bulk.updateBulk) await bulk.updateBulk(children);
|
|
112
|
+
else for (const child of children) await writer.update(child);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
private persistEntry = async (
|
|
116
|
+
entry: StoredEnrichment,
|
|
117
|
+
parents: T[],
|
|
118
|
+
mode: WriteMode,
|
|
119
|
+
): Promise<void> => {
|
|
120
|
+
const enrichment = entry.enrichment;
|
|
121
|
+
const type = enrichment.type ?? EnrichmentPropertyType.Object;
|
|
122
|
+
if (type === EnrichmentPropertyType.Custom)
|
|
123
|
+
throw new DatasourceError(`Unsupported enrichment type "${type}"`);
|
|
124
|
+
if (enrichment.association) {
|
|
125
|
+
const writer = linkWriter(entry, enrichment.destinationProperty);
|
|
126
|
+
for (const parent of parents) {
|
|
127
|
+
if (this.skip(parent, enrichment.destinationProperty, mode)) continue;
|
|
128
|
+
await dispatch(mode, {
|
|
129
|
+
create: () => this.createStrategy.createLinked(writer, enrichment, parent),
|
|
130
|
+
update: () => this.updateStrategy.updateLinked(writer, enrichment, parent),
|
|
131
|
+
delete: () => this.deleteStrategy.deleteLinked(writer, enrichment, parent),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (type === EnrichmentPropertyType.List && enrichment.relatedProperty) return;
|
|
137
|
+
if (type !== EnrichmentPropertyType.List && type !== EnrichmentPropertyType.Dictionary) return;
|
|
138
|
+
const writer = childWriter(entry, enrichment.destinationProperty);
|
|
139
|
+
for (const parent of parents) {
|
|
140
|
+
if (this.skip(parent, enrichment.destinationProperty, mode)) continue;
|
|
141
|
+
await dispatch(mode, {
|
|
142
|
+
create: () => this.createStrategy.createChildren(writer, enrichment, parent),
|
|
143
|
+
update: () => this.updateStrategy.updateChildren(writer, enrichment, parent),
|
|
144
|
+
delete: () => this.deleteStrategy.deleteChildren(writer, enrichment, parent, async () => {}),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
private skip = (parent: T, into: string, mode: string): boolean =>
|
|
150
|
+
this.skipUnloaded && mode !== "delete" && unloaded(parent, into);
|
|
151
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Enrichment } from "./Enrichment.ts";
|
|
2
|
+
import type { ICRUDRepository } from "./ICRUDRepository.ts";
|
|
3
|
+
import type { Scalar } from "./builders/Scalar.ts";
|
|
4
|
+
import { Operator, Where } from "./statements/index.ts";
|
|
5
|
+
|
|
6
|
+
type Props = Record<string, Scalar | object>;
|
|
7
|
+
|
|
8
|
+
const get = <TItem>(item: TItem, name: string): Scalar | object | undefined =>
|
|
9
|
+
(item as never as Props)[name];
|
|
10
|
+
|
|
11
|
+
export abstract class DeleteEnrichmentStrategy<T> {
|
|
12
|
+
abstract deleteChildren<TChild extends object>(
|
|
13
|
+
writer: ICRUDRepository<TChild>,
|
|
14
|
+
enrichment: Enrichment,
|
|
15
|
+
parent: T,
|
|
16
|
+
deleteNested: (rows: TChild[]) => Promise<void>,
|
|
17
|
+
): Promise<void>;
|
|
18
|
+
|
|
19
|
+
abstract deleteLinked<TChild extends object>(writer: ICRUDRepository<TChild>, enrichment: Enrichment, parent: T): Promise<void>;
|
|
20
|
+
|
|
21
|
+
static load = async <TParent, TChild extends object>(
|
|
22
|
+
writer: ICRUDRepository<TChild>,
|
|
23
|
+
enrichment: Enrichment,
|
|
24
|
+
parent: TParent,
|
|
25
|
+
): Promise<TChild[]> => {
|
|
26
|
+
const key = get(parent, enrichment.sourceProperty);
|
|
27
|
+
if (key === undefined || key === null || typeof key === "object") return [];
|
|
28
|
+
const items: TChild[] = [];
|
|
29
|
+
for await (const item of writer.read(new Where(new Operator.Equals(enrichment.relatedKey, key))))
|
|
30
|
+
items.push(item);
|
|
31
|
+
return items;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
static childrenWhere = <TParent, TChild extends object>(
|
|
35
|
+
writer: ICRUDRepository<TChild>,
|
|
36
|
+
enrichment: Enrichment,
|
|
37
|
+
parent: TParent,
|
|
38
|
+
): Where | undefined => {
|
|
39
|
+
if (writer.ids.length > 0) return undefined;
|
|
40
|
+
const key = get(parent, enrichment.sourceProperty);
|
|
41
|
+
return key === undefined || key === null || typeof key === "object"
|
|
42
|
+
? undefined
|
|
43
|
+
: new Where(new Operator.Equals(enrichment.relatedKey, key));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
static loadLinks = async <TChild extends object>(
|
|
47
|
+
writer: ICRUDRepository<TChild>,
|
|
48
|
+
column: string,
|
|
49
|
+
key: Scalar,
|
|
50
|
+
): Promise<TChild[]> => {
|
|
51
|
+
const items: TChild[] = [];
|
|
52
|
+
for await (const item of writer.read(new Where(new Operator.Equals(column, key))))
|
|
53
|
+
items.push(item);
|
|
54
|
+
return items;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire, registerHooks } from "node:module";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import type { IDriver } from "./IDriver.ts";
|
|
6
|
+
import type { ProviderCatalog } from "./ProviderCatalog.ts";
|
|
7
|
+
import { ProviderNotInstalledError } from "./ProviderNotInstalledError.ts";
|
|
8
|
+
|
|
9
|
+
type DriverCtor = new () => IDriver;
|
|
10
|
+
type DriverModule = Record<string, DriverCtor>;
|
|
11
|
+
type TypeScript = {
|
|
12
|
+
transpileModule: (
|
|
13
|
+
source: string,
|
|
14
|
+
options: {
|
|
15
|
+
compilerOptions: { module: number; target: number };
|
|
16
|
+
fileName: string;
|
|
17
|
+
},
|
|
18
|
+
) => { outputText: string };
|
|
19
|
+
ModuleKind: { ESNext: number };
|
|
20
|
+
ScriptTarget: { ES2022: number };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const require = createRequire(import.meta.url);
|
|
24
|
+
const virtual = new Map<string, string>();
|
|
25
|
+
const virtualBySource = new Map<string, string>();
|
|
26
|
+
let typeScriptHook = false;
|
|
27
|
+
let compiling = false;
|
|
28
|
+
let nextVirtual = 0;
|
|
29
|
+
|
|
30
|
+
const installTypeScriptHook = (): void => {
|
|
31
|
+
if (typeScriptHook) return;
|
|
32
|
+
const typescript = require("typescript") as TypeScript;
|
|
33
|
+
/* v8 ignore start */
|
|
34
|
+
registerHooks({
|
|
35
|
+
resolve: (specifier, context, nextResolve) => {
|
|
36
|
+
const parentURL = context.parentURL ? virtual.get(context.parentURL) ?? context.parentURL : undefined;
|
|
37
|
+
const resolved = nextResolve(specifier, parentURL ? { ...context, parentURL } : context);
|
|
38
|
+
/* v8 ignore next */
|
|
39
|
+
if (!compiling || !resolved.url.endsWith(".ts")) return resolved;
|
|
40
|
+
const existing = virtualBySource.get(resolved.url);
|
|
41
|
+
/* v8 ignore next */
|
|
42
|
+
if (existing) return { url: existing, shortCircuit: true };
|
|
43
|
+
const url = pathToFileURL(`${tmpdir()}/datasources-plugin-${nextVirtual++}.mjs`).href;
|
|
44
|
+
virtual.set(url, resolved.url);
|
|
45
|
+
virtualBySource.set(resolved.url, url);
|
|
46
|
+
return { url, shortCircuit: true };
|
|
47
|
+
},
|
|
48
|
+
load: (url, context, nextLoad) => {
|
|
49
|
+
const original = virtual.get(url) ?? (compiling && url.endsWith(".ts") ? url : undefined);
|
|
50
|
+
/* v8 ignore next */
|
|
51
|
+
if (!original) return nextLoad(url, context);
|
|
52
|
+
const filename = fileURLToPath(original);
|
|
53
|
+
const source = typescript.transpileModule(readFileSync(filename, "utf8"), {
|
|
54
|
+
compilerOptions: {
|
|
55
|
+
module: typescript.ModuleKind.ESNext,
|
|
56
|
+
target: typescript.ScriptTarget.ES2022,
|
|
57
|
+
},
|
|
58
|
+
fileName: filename,
|
|
59
|
+
}).outputText;
|
|
60
|
+
return { format: "module", source, shortCircuit: true };
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
/* v8 ignore stop */
|
|
64
|
+
typeScriptHook = true;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const instantiate = (catalog: ProviderCatalog): IDriver => {
|
|
68
|
+
compiling = true;
|
|
69
|
+
try {
|
|
70
|
+
return instantiateLoaded(catalog);
|
|
71
|
+
} finally {
|
|
72
|
+
compiling = false;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const instantiateLoaded = (catalog: ProviderCatalog): IDriver => {
|
|
77
|
+
const loaded = require(catalog.location) as DriverModule;
|
|
78
|
+
const Type = loaded[catalog.module];
|
|
79
|
+
if (typeof Type !== "function") throw new ProviderNotInstalledError(catalog.name);
|
|
80
|
+
return new Type();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export class DriverLoader {
|
|
84
|
+
static load = (catalog: ProviderCatalog): IDriver => {
|
|
85
|
+
try {
|
|
86
|
+
return instantiate(catalog);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (error instanceof ProviderNotInstalledError) throw error;
|
|
89
|
+
try {
|
|
90
|
+
installTypeScriptHook();
|
|
91
|
+
return instantiate(catalog);
|
|
92
|
+
} catch {
|
|
93
|
+
throw new ProviderNotInstalledError(catalog.name);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EnrichmentPropertyType } from "./EnrichmentPropertyType.ts";
|
|
2
|
+
|
|
3
|
+
export type Association = {
|
|
4
|
+
parent: string;
|
|
5
|
+
related: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type Enrichment = {
|
|
9
|
+
destinationProperty: string;
|
|
10
|
+
sourceProperty: string;
|
|
11
|
+
relatedKey: string;
|
|
12
|
+
relatedProperty?: string;
|
|
13
|
+
type?: EnrichmentPropertyType;
|
|
14
|
+
association?: Association;
|
|
15
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ConsoleCommandMiddleware } from "./ConsoleCommandMiddleware.ts";
|
|
2
|
+
import type { ICommandMiddleware } from "./ICommandMiddleware.ts";
|
|
3
|
+
import type { Parameter } from "./Parameter.ts";
|
|
4
|
+
import type { Row } from "./Row.ts";
|
|
5
|
+
|
|
6
|
+
export const consoleSignature = (line: string): string => {
|
|
7
|
+
const duration = line.lastIndexOf("] ");
|
|
8
|
+
return duration >= 0 && (line.endsWith("ms") || line.endsWith("μs"))
|
|
9
|
+
? line.slice(0, duration + 1)
|
|
10
|
+
: line;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class ExpectConsoleMiddleware implements ICommandMiddleware {
|
|
14
|
+
private readonly inner: ConsoleCommandMiddleware;
|
|
15
|
+
private index = 0;
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly expected: readonly string[],
|
|
19
|
+
now: () => Date,
|
|
20
|
+
private readonly normalize: (line: string) => string = consoleSignature,
|
|
21
|
+
) {
|
|
22
|
+
this.inner = new ConsoleCommandMiddleware((line) => this.check(line), now, { isVerbose: "true" });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
beforeCommand = (text: string, params?: ReadonlyArray<Parameter>) =>
|
|
26
|
+
this.inner.beforeCommand(text, params);
|
|
27
|
+
|
|
28
|
+
afterCommand = (
|
|
29
|
+
text: string,
|
|
30
|
+
params: ReadonlyArray<Parameter> | undefined,
|
|
31
|
+
results: ReadonlyArray<Row>,
|
|
32
|
+
elapsedMs: number,
|
|
33
|
+
error?: Error,
|
|
34
|
+
) => this.inner.afterCommand(text, params, results, elapsedMs, error);
|
|
35
|
+
|
|
36
|
+
complete = (): void => {
|
|
37
|
+
if (this.index !== this.expected.length)
|
|
38
|
+
throw new Error(`console mismatch at ${this.index}\nexpected: ${this.expected[this.index]}\nactual: <missing>`);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
private check = (line: string): void => {
|
|
42
|
+
const actual = this.normalize(line);
|
|
43
|
+
if (this.index >= this.expected.length || actual !== this.expected[this.index])
|
|
44
|
+
throw new Error(`console mismatch at ${this.index}\nexpected: ${this.index < this.expected.length ? this.expected[this.index] : "<missing>"}\nactual: ${actual}`);
|
|
45
|
+
this.index++;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Cells } from "./converters/Cell.ts";
|
|
2
|
+
import type { IReader } from "./IReader.ts";
|
|
3
|
+
import { readerToAsyncIterable } from "./readerToAsyncIterable.ts";
|
|
4
|
+
|
|
5
|
+
export class FirstResultReader implements IReader<Cells> {
|
|
6
|
+
current: Cells | undefined = undefined;
|
|
7
|
+
private index = -1;
|
|
8
|
+
private firstSet = true;
|
|
9
|
+
|
|
10
|
+
private constructor(
|
|
11
|
+
private readonly first: readonly Cells[],
|
|
12
|
+
private readonly live: IReader<Cells>,
|
|
13
|
+
) {}
|
|
14
|
+
|
|
15
|
+
static async capture(live: IReader<Cells>): Promise<{ value: IReader<Cells>; rows: Cells[] }> {
|
|
16
|
+
const rows: Cells[] = [];
|
|
17
|
+
while (await live.next()) if (live.current != null) rows.push(live.current);
|
|
18
|
+
return { value: new FirstResultReader(rows, live), rows };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async next(): Promise<boolean> {
|
|
22
|
+
if (!this.firstSet) {
|
|
23
|
+
const moved = await this.live.next();
|
|
24
|
+
this.current = this.live.current;
|
|
25
|
+
return moved;
|
|
26
|
+
}
|
|
27
|
+
this.index += 1;
|
|
28
|
+
if (this.index < this.first.length) {
|
|
29
|
+
this.current = this.first[this.index];
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
this.current = undefined;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async nextResult(): Promise<boolean> {
|
|
37
|
+
this.firstSet = false;
|
|
38
|
+
this.current = undefined;
|
|
39
|
+
return this.live.nextResult();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
read(): AsyncIterable<Cells> {
|
|
43
|
+
return readerToAsyncIterable(this);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
dispose = (): Promise<void> => this.live.dispose();
|
|
47
|
+
|
|
48
|
+
[Symbol.asyncDispose] = (): Promise<void> => this.dispose();
|
|
49
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Scalar } from "./builders/Scalar.ts";
|
|
2
|
+
import { Operator, Where } from "./statements/index.ts";
|
|
3
|
+
import type { Enrichment } from "./Enrichment.ts";
|
|
4
|
+
import type { IReadonlyRepository } from "./IReadonlyRepository.ts";
|
|
5
|
+
import type { Row } from "./Row.ts";
|
|
6
|
+
import { DefaultReadonlyEnrichmentStrategy } from "./DefaultReadonlyEnrichmentStrategy.ts";
|
|
7
|
+
|
|
8
|
+
const hasKey = (value: Scalar | object | undefined): value is Scalar =>
|
|
9
|
+
value !== undefined && value !== null;
|
|
10
|
+
|
|
11
|
+
export class HashsetOptimizedReadonlyEnrichmentStrategy<T extends object>
|
|
12
|
+
extends DefaultReadonlyEnrichmentStrategy<T>
|
|
13
|
+
{
|
|
14
|
+
protected override async applyObject<TRelated extends object>(
|
|
15
|
+
via: IReadonlyRepository<TRelated>,
|
|
16
|
+
enrichment: Enrichment,
|
|
17
|
+
parents: T[],
|
|
18
|
+
sources?: (Row | undefined)[],
|
|
19
|
+
): Promise<void> {
|
|
20
|
+
const keys = this.keysOf(parents, sources, enrichment.sourceProperty);
|
|
21
|
+
if (keys.size === 0) return;
|
|
22
|
+
const index = new Map<string, TRelated>();
|
|
23
|
+
for await (const item of via.read(
|
|
24
|
+
new Where(new Operator.In(enrichment.relatedKey, [...keys.values()])),
|
|
25
|
+
)) {
|
|
26
|
+
const by = this.props(item)[enrichment.relatedKey];
|
|
27
|
+
if (hasKey(by)) index.set(this.keyOf(by), item);
|
|
28
|
+
}
|
|
29
|
+
for (const [indexOfParent, parent] of parents.entries()) {
|
|
30
|
+
const key = this.sourceKey(parent, enrichment.sourceProperty, sources, indexOfParent);
|
|
31
|
+
if (key === undefined || key === null) continue;
|
|
32
|
+
const related = index.get(this.keyOf(key));
|
|
33
|
+
if (!related) continue;
|
|
34
|
+
Object.assign(parent, {
|
|
35
|
+
[enrichment.destinationProperty]: enrichment.relatedProperty ? this.props(related)[enrichment.relatedProperty] : related,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
protected override async applyList<TRelated extends object>(
|
|
41
|
+
via: IReadonlyRepository<TRelated>,
|
|
42
|
+
enrichment: Enrichment,
|
|
43
|
+
parents: T[],
|
|
44
|
+
sources?: (Row | undefined)[],
|
|
45
|
+
): Promise<void> {
|
|
46
|
+
const keys = this.keysOf(parents, sources, enrichment.sourceProperty);
|
|
47
|
+
if (keys.size === 0) return;
|
|
48
|
+
const index = new Map<string, TRelated[]>();
|
|
49
|
+
for await (const item of via.read(
|
|
50
|
+
new Where(new Operator.In(enrichment.relatedKey, [...keys.values()])),
|
|
51
|
+
)) {
|
|
52
|
+
const by = this.props(item)[enrichment.relatedKey];
|
|
53
|
+
if (hasKey(by)) {
|
|
54
|
+
const cacheKey = this.keyOf(by);
|
|
55
|
+
const list = index.get(cacheKey) ?? [];
|
|
56
|
+
list.push(item);
|
|
57
|
+
index.set(cacheKey, list);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
for (const [indexOfParent, parent] of parents.entries()) {
|
|
61
|
+
const key = this.sourceKey(parent, enrichment.sourceProperty, sources, indexOfParent);
|
|
62
|
+
if (key === undefined || key === null) continue;
|
|
63
|
+
Object.assign(parent, { [enrichment.destinationProperty]: index.get(this.keyOf(key)) ?? [] });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private keysOf(
|
|
68
|
+
parents: T[],
|
|
69
|
+
sources: (Row | undefined)[] | undefined,
|
|
70
|
+
from: string,
|
|
71
|
+
): Map<string, Scalar> {
|
|
72
|
+
const keys = new Map<string, Scalar>();
|
|
73
|
+
for (const [index, parent] of parents.entries()) {
|
|
74
|
+
const key = this.sourceKey(parent, from, sources, index);
|
|
75
|
+
if (key === undefined || key === null) continue;
|
|
76
|
+
keys.set(this.keyOf(key), this.scalar(key));
|
|
77
|
+
}
|
|
78
|
+
return keys;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CRUDRepository } from "./CRUDRepository.ts";
|
|
2
|
+
import type { CRUDRepositoryOptions } from "./CRUDRepositoryOptions.ts";
|
|
3
|
+
import type { ICommand } from "./ICommand.ts";
|
|
4
|
+
import type { Response } from "./Response.ts";
|
|
5
|
+
import type { IWhere } from "./statements/IWhere.ts";
|
|
6
|
+
|
|
7
|
+
export interface IBulkWriteStrategy<T extends object> {
|
|
8
|
+
repo: CRUDRepository<T>;
|
|
9
|
+
attach(command: ICommand, options: CRUDRepositoryOptions<T>): void;
|
|
10
|
+
create(items: T[]): Promise<Response>;
|
|
11
|
+
update(items: T[], byWhere: IWhere | undefined): Promise<Response>;
|
|
12
|
+
delete(items: T[], byWhere: IWhere | undefined): Promise<Response>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Scalar } from "./builders/Scalar.ts";
|
|
2
|
+
import type { Cells } from "./converters/Cell.ts";
|
|
3
|
+
import type { IReadonlyRepository } from "./IReadonlyRepository.ts";
|
|
4
|
+
import type { IWhere } from "./statements/IWhere.ts";
|
|
5
|
+
import type { Response } from "./Response.ts";
|
|
6
|
+
|
|
7
|
+
export interface ICRUDRepository<T = unknown> extends IReadonlyRepository<T> {
|
|
8
|
+
readonly ids: readonly string[];
|
|
9
|
+
create(item: T): Promise<T>;
|
|
10
|
+
update(item: T, byWhere?: IWhere): Promise<Response>;
|
|
11
|
+
delete(item: T, byWhere?: IWhere): Promise<Response>;
|
|
12
|
+
readSingleById(id: Scalar | Cells): Promise<T | undefined>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Constructable } from "./converters/Constructable.ts";
|
|
2
|
+
import type { ICRUDRepository } from "./ICRUDRepository.ts";
|
|
3
|
+
import type { IRepository } from "./IRepository.ts";
|
|
4
|
+
|
|
5
|
+
export interface ICRUDRepositoryFactory {
|
|
6
|
+
register(repository: IRepository): void;
|
|
7
|
+
create<T>(type: Constructable<T>): ICRUDRepository<T>;
|
|
8
|
+
}
|
package/src/ICommand.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { IStatement } from "./statements/IStatement.ts";
|
|
2
|
+
import { DefaultStatementTextRenderer } from "./statements/DefaultStatementTextRenderer.ts";
|
|
3
|
+
import { Native } from "./statements/Native.ts";
|
|
4
|
+
import type { ICommandMiddleware } from "./ICommandMiddleware.ts";
|
|
5
|
+
import type { IConnection } from "./IConnection.ts";
|
|
6
|
+
import type { Cells } from "./converters/Cell.ts";
|
|
7
|
+
import type { IReader } from "./IReader.ts";
|
|
8
|
+
import type { Response } from "./Response.ts";
|
|
9
|
+
import type { Parameter } from "./Parameter.ts";
|
|
10
|
+
|
|
11
|
+
export interface ICommand {
|
|
12
|
+
readonly connection: IConnection;
|
|
13
|
+
addMiddleware(middleware: ICommandMiddleware): this;
|
|
14
|
+
executeReader(text: string, parameters?: Parameter[]): Promise<IReader<Cells>>;
|
|
15
|
+
execute(text: string, parameters?: Parameter[]): Promise<Response>;
|
|
16
|
+
executeNative(text: Native, parameters?: Parameter[]): Promise<Response>;
|
|
17
|
+
executeReaderNative(text: Native, parameters?: Parameter[]): Promise<IReader<Cells>>;
|
|
18
|
+
executeStatement?(statement: IStatement, parameters?: Parameter[]): Promise<Response>;
|
|
19
|
+
executeReaderStatement?(
|
|
20
|
+
statement: IStatement,
|
|
21
|
+
parameters?: Parameter[],
|
|
22
|
+
): Promise<IReader<Cells>>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const execute = (
|
|
26
|
+
command: ICommand,
|
|
27
|
+
statement: IStatement,
|
|
28
|
+
parameters?: Parameter[],
|
|
29
|
+
): Promise<Response> =>
|
|
30
|
+
command.executeStatement?.(statement, parameters) ??
|
|
31
|
+
command.executeNative(
|
|
32
|
+
new Native(DefaultStatementTextRenderer.instance.render(statement)),
|
|
33
|
+
parameters,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const executeReader = (
|
|
37
|
+
command: ICommand,
|
|
38
|
+
statement: IStatement,
|
|
39
|
+
parameters?: Parameter[],
|
|
40
|
+
): Promise<IReader<Cells>> =>
|
|
41
|
+
command.executeReaderStatement?.(statement, parameters) ??
|
|
42
|
+
command.executeReaderNative(
|
|
43
|
+
new Native(DefaultStatementTextRenderer.instance.render(statement)),
|
|
44
|
+
parameters,
|
|
45
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Parameter } from "./Parameter.ts";
|
|
2
|
+
import type { Row } from "./Row.ts";
|
|
3
|
+
|
|
4
|
+
export interface ICommandMiddleware {
|
|
5
|
+
beforeCommand(
|
|
6
|
+
text: string,
|
|
7
|
+
params?: ReadonlyArray<Parameter>,
|
|
8
|
+
):
|
|
9
|
+
| void
|
|
10
|
+
| { text: string; params?: ReadonlyArray<Parameter> }
|
|
11
|
+
| Promise<void | { text: string; params?: ReadonlyArray<Parameter> }>;
|
|
12
|
+
|
|
13
|
+
afterCommand(
|
|
14
|
+
text: string,
|
|
15
|
+
params: ReadonlyArray<Parameter> | undefined,
|
|
16
|
+
results: ReadonlyArray<Row>,
|
|
17
|
+
elapsedMs: number,
|
|
18
|
+
error?: Error,
|
|
19
|
+
): void | Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ICommand } from "./ICommand.ts";
|
|
2
|
+
import type { ITransaction } from "./ITransaction.ts";
|
|
3
|
+
import type { IsolationLevel } from "./IsolationLevel.ts";
|
|
4
|
+
|
|
5
|
+
export interface IConnection {
|
|
6
|
+
readonly provider: string;
|
|
7
|
+
readonly isOpen: boolean;
|
|
8
|
+
createCommand(): ICommand;
|
|
9
|
+
open(): Promise<void>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
startTransaction(isolation?: IsolationLevel): Promise<ITransaction>;
|
|
12
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Constructable } from "./converters/Constructable.ts";
|
|
2
|
+
import type { CRUDRepositoryOptions } from "./CRUDRepositoryOptions.ts";
|
|
3
|
+
import type { ICommand } from "./ICommand.ts";
|
|
4
|
+
import type { IConnection } from "./IConnection.ts";
|
|
5
|
+
import type { IReadonlyRepository } from "./IReadonlyRepository.ts";
|
|
6
|
+
import type { ICRUDRepository } from "./ICRUDRepository.ts";
|
|
7
|
+
import type { ReadonlyRepositoryMappingOptions } from "./ReadonlyRepositoryMappingOptions.ts";
|
|
8
|
+
import type { RepositoryFactory } from "./RepositoryFactory.ts";
|
|
9
|
+
|
|
10
|
+
export interface IDatasource {
|
|
11
|
+
readonly provider: string;
|
|
12
|
+
readonly repositories: RepositoryFactory;
|
|
13
|
+
createConnection(): Promise<IConnection>;
|
|
14
|
+
createCommand(connection?: IConnection): Promise<ICommand>;
|
|
15
|
+
createRepository<T>(
|
|
16
|
+
type: Constructable<T>,
|
|
17
|
+
connection?: IConnection,
|
|
18
|
+
options?: CRUDRepositoryOptions<T>,
|
|
19
|
+
): ICRUDRepository<T>;
|
|
20
|
+
createRepository(typeName: string, connection?: IConnection): ICRUDRepository;
|
|
21
|
+
createReadonlyRepository<T>(
|
|
22
|
+
type: Constructable<T>,
|
|
23
|
+
connection?: IConnection,
|
|
24
|
+
options?: ReadonlyRepositoryMappingOptions<T>,
|
|
25
|
+
): IReadonlyRepository<T>;
|
|
26
|
+
createReadonlyRepository(typeName: string, connection?: IConnection): IReadonlyRepository;
|
|
27
|
+
}
|