@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.
Files changed (209) hide show
  1. package/package.json +16 -4
  2. package/src/ArrayReader.ts +32 -0
  3. package/src/BatchCommandIBulkWriteStrategy.ts +228 -0
  4. package/src/BuiltRepository.ts +17 -0
  5. package/src/BulkCRUDRepository.ts +84 -0
  6. package/src/BulkCommand.ts +6 -0
  7. package/src/BulkWriteEnrichment.ts +19 -0
  8. package/src/CRUDRepository.ts +264 -0
  9. package/src/CRUDRepositoryBuilder.ts +53 -0
  10. package/src/CRUDRepositoryOptions.ts +8 -0
  11. package/src/CRUDRepositoryStatements.ts +43 -0
  12. package/src/CascadeDeleteEnrichmentStrategy.ts +51 -0
  13. package/src/CascadeDeleteUpdateEnrichmentStrategy.ts +28 -0
  14. package/src/CommandMiddlewareHost.ts +113 -0
  15. package/src/ConsoleCommandMiddleware.ts +64 -0
  16. package/src/CreateEnrichmentStrategy.ts +82 -0
  17. package/src/Datasource.ts +152 -0
  18. package/src/DatasourceError.ts +6 -0
  19. package/src/DatasourceFactory.ts +86 -0
  20. package/src/DatasourceOptions.ts +1 -0
  21. package/src/DatasourceUrl.ts +37 -0
  22. package/src/DatasourceUrlParser.ts +188 -0
  23. package/src/DefaultCreateEnrichmentStrategy.ts +21 -0
  24. package/src/DefaultReadonlyEnrichmentStrategy.ts +164 -0
  25. package/src/DefaultUpdateEnrichmentStrategy.ts +40 -0
  26. package/src/DefaultWriteEnrichmentStrategy.ts +151 -0
  27. package/src/DeleteEnrichmentStrategy.ts +56 -0
  28. package/src/DriverLoader.ts +97 -0
  29. package/src/Enrichment.ts +15 -0
  30. package/src/EnrichmentPropertyType.ts +9 -0
  31. package/src/ExpectConsoleMiddleware.ts +47 -0
  32. package/src/FirstResultReader.ts +49 -0
  33. package/src/HashsetOptimizedReadonlyEnrichmentStrategy.ts +80 -0
  34. package/src/IBulkWriteStrategy.ts +13 -0
  35. package/src/ICRUDRepository.ts +13 -0
  36. package/src/ICRUDRepositoryFactory.ts +8 -0
  37. package/src/ICommand.ts +45 -0
  38. package/src/ICommandMiddleware.ts +20 -0
  39. package/src/IConnection.ts +13 -0
  40. package/src/IDatasource.ts +27 -0
  41. package/src/IDatasourceFactory.ts +6 -0
  42. package/src/IDriver.ts +24 -0
  43. package/src/IEnriched.ts +11 -0
  44. package/src/IReader.ts +8 -0
  45. package/src/IReadonlyEnrichmentStrategy.ts +19 -0
  46. package/src/IReadonlyRepository.ts +21 -0
  47. package/src/IRepository.ts +5 -0
  48. package/src/IRepositoryFactory.ts +8 -0
  49. package/src/IRepositoryTree.ts +5 -0
  50. package/src/IRepositoryTreeNode.ts +8 -0
  51. package/src/ITransaction.ts +9 -0
  52. package/src/IUnitOfWork.ts +5 -0
  53. package/src/IWriteEnrichmentStrategy.ts +8 -0
  54. package/src/Information.ts +5 -0
  55. package/src/IsolationLevel.ts +8 -0
  56. package/src/LazyWriteEnrichmentStrategy.ts +5 -0
  57. package/src/NestedToObjectEnrichmentStrategy.ts +33 -0
  58. package/src/Parameter.ts +8 -0
  59. package/src/ParameterDirection.ts +9 -0
  60. package/src/ProviderCatalog.ts +21 -0
  61. package/src/ProviderNotImplementedError.ts +9 -0
  62. package/src/ProviderNotInstalledError.ts +9 -0
  63. package/src/ReadonlyRepository.ts +276 -0
  64. package/src/ReadonlyRepositoryBuilder.ts +53 -0
  65. package/src/ReadonlyRepositoryMappingOptions.ts +15 -0
  66. package/src/ReadonlyRepositoryStatements.ts +13 -0
  67. package/src/RepositoryAccess.ts +14 -0
  68. package/src/RepositoryFactory.ts +115 -0
  69. package/src/RepositoryNotRegisteredError.ts +9 -0
  70. package/src/RepositoryTree.ts +6 -0
  71. package/src/RepositoryTreeNode.ts +11 -0
  72. package/src/Response.ts +15 -0
  73. package/src/Row.ts +3 -0
  74. package/src/SingleCommandIBulkWriteStrategy.ts +35 -0
  75. package/src/StatementMappers.ts +110 -0
  76. package/src/StoredEnrichment.ts +25 -0
  77. package/src/StoredProcedureBulkWriteStrategy.ts +164 -0
  78. package/src/StreamingReader.ts +64 -0
  79. package/src/UnitOfWorkTransaction.ts +50 -0
  80. package/src/UpdateEnrichmentStrategy.ts +97 -0
  81. package/src/WriteMode.ts +1 -0
  82. package/src/builders/Field.ts +6 -0
  83. package/src/builders/Scalar.ts +1 -0
  84. package/src/builders/index.ts +2 -0
  85. package/src/collectAsync.ts +7 -0
  86. package/src/converters/Cell.ts +10 -0
  87. package/src/converters/ChangeCasingConverter.ts +59 -0
  88. package/src/converters/Constructable.ts +1 -0
  89. package/src/converters/MetaDataRowTypeConverter.ts +80 -0
  90. package/src/converters/PluralizerConverter.ts +67 -0
  91. package/src/converters/RegexConverter.ts +14 -0
  92. package/src/converters/ReplaceConverter.ts +6 -0
  93. package/src/converters/RowTypeConverter.ts +33 -0
  94. package/src/converters/ToLowerCaseConverter.ts +4 -0
  95. package/src/converters/ToUpperCaseConverter.ts +4 -0
  96. package/src/converters/TypeConverter.ts +6 -0
  97. package/src/createCRUDRepositoryOptions.ts +21 -0
  98. package/src/createReadonlyRepositoryMappingOptions.ts +26 -0
  99. package/src/dotEnv.ts +16 -0
  100. package/src/index.ts +222 -0
  101. package/src/mappers/ChangeCasingMapper.ts +15 -0
  102. package/src/mappers/DictionaryMapper.ts +16 -0
  103. package/src/mappers/FlatToNestedMapper.ts +127 -0
  104. package/src/mappers/IFlatToNestedMapper.ts +7 -0
  105. package/src/mappers/IMapper.ts +4 -0
  106. package/src/mappers/IdentityMapper.ts +6 -0
  107. package/src/mappers/PluralizerMapper.ts +9 -0
  108. package/src/mappers/RowTypeMapper.ts +13 -0
  109. package/src/mappers/TransformConverterMapper.ts +11 -0
  110. package/src/mappers/TransformMapper.ts +8 -0
  111. package/src/mappers/TypeMap.ts +10 -0
  112. package/src/mappers/TypeMapGroup.ts +6 -0
  113. package/src/mocks/index.ts +9 -0
  114. package/src/mocks/mock-command.ts +66 -0
  115. package/src/mocks/mock-connection.ts +57 -0
  116. package/src/mocks/mock-datasource.ts +65 -0
  117. package/src/mocks/mock-driver.ts +27 -0
  118. package/src/mocks/mock-reader.ts +38 -0
  119. package/src/mocks/mock-repository.ts +91 -0
  120. package/src/mocks/mock-select-statement.ts +17 -0
  121. package/src/mocks/mock-transaction.ts +31 -0
  122. package/src/mocks/mock-where.ts +13 -0
  123. package/src/parametersToRecord.ts +11 -0
  124. package/src/readerToAsyncIterable.ts +11 -0
  125. package/src/splitStatements.ts +99 -0
  126. package/src/statementParameters.ts +22 -0
  127. package/src/statementUsesParameter.ts +4 -0
  128. package/src/statements/Aggregate.ts +9 -0
  129. package/src/statements/ArrayExpression.ts +5 -0
  130. package/src/statements/BulkDeleteStatement.ts +18 -0
  131. package/src/statements/BulkDeleteStatementTextRenderer.ts +16 -0
  132. package/src/statements/BulkInsertStatement.ts +37 -0
  133. package/src/statements/BulkInsertStatementTextRenderer.ts +10 -0
  134. package/src/statements/BulkUpdateStatement.ts +24 -0
  135. package/src/statements/BulkUpdateStatementTextRenderer.ts +29 -0
  136. package/src/statements/CheckConstraint.ts +9 -0
  137. package/src/statements/Cmp.ts +12 -0
  138. package/src/statements/Column.ts +10 -0
  139. package/src/statements/ColumnDefault.ts +6 -0
  140. package/src/statements/Condition.ts +3 -0
  141. package/src/statements/ConditionRenderer.ts +17 -0
  142. package/src/statements/CreateIndexStatement.ts +18 -0
  143. package/src/statements/CreateIndexStatementTextRenderer.ts +11 -0
  144. package/src/statements/CreateTableStatement.ts +18 -0
  145. package/src/statements/CreateTableStatementTextRenderer.ts +92 -0
  146. package/src/statements/DefaultStatementTextRenderer.ts +9 -0
  147. package/src/statements/DeleteStatement.ts +15 -0
  148. package/src/statements/DeleteStatementTextRenderer.ts +12 -0
  149. package/src/statements/ExecuteStoredProcedureStatement.ts +15 -0
  150. package/src/statements/ExecuteStoredProcedureStatementTextRenderer.ts +15 -0
  151. package/src/statements/ExpressionEvaluator.ts +166 -0
  152. package/src/statements/ExpressionRenderer.ts +161 -0
  153. package/src/statements/ForeignKey.ts +23 -0
  154. package/src/statements/IBulkDeleteStatement.ts +3 -0
  155. package/src/statements/IBulkInsertStatement.ts +3 -0
  156. package/src/statements/IBulkUpdateStatement.ts +3 -0
  157. package/src/statements/ICondition.ts +5 -0
  158. package/src/statements/IConditionVisitor.ts +7 -0
  159. package/src/statements/ICreateIndexStatement.ts +3 -0
  160. package/src/statements/ICreateTableStatement.ts +3 -0
  161. package/src/statements/IDeleteStatement.ts +6 -0
  162. package/src/statements/IExecuteStoredProcedureStatement.ts +3 -0
  163. package/src/statements/IExpression.ts +1 -0
  164. package/src/statements/IInsertStatement.ts +3 -0
  165. package/src/statements/IReturnStatement.ts +3 -0
  166. package/src/statements/ISelectStatement.ts +6 -0
  167. package/src/statements/IStatement.ts +5 -0
  168. package/src/statements/IStatementVisitor.ts +27 -0
  169. package/src/statements/ITableConstraint.ts +6 -0
  170. package/src/statements/IUpdateStatement.ts +6 -0
  171. package/src/statements/IWhere.ts +7 -0
  172. package/src/statements/Identifier.ts +5 -0
  173. package/src/statements/InsertStatement.ts +15 -0
  174. package/src/statements/InsertStatementTextRenderer.ts +7 -0
  175. package/src/statements/Join.ts +26 -0
  176. package/src/statements/Literal.ts +6 -0
  177. package/src/statements/Native.ts +5 -0
  178. package/src/statements/NotNull.ts +3 -0
  179. package/src/statements/Operator.ts +234 -0
  180. package/src/statements/OrderBy.ts +19 -0
  181. package/src/statements/PrimaryKey.ts +9 -0
  182. package/src/statements/ReturnStatement.ts +15 -0
  183. package/src/statements/ReturnStatementTextRenderer.ts +15 -0
  184. package/src/statements/SelectInsertedIdStatement.ts +11 -0
  185. package/src/statements/SelectInsertedIdStatementTextRenderer.ts +7 -0
  186. package/src/statements/SelectStatement.ts +34 -0
  187. package/src/statements/SelectStatementOptions.ts +16 -0
  188. package/src/statements/SelectStatementTextRenderer.ts +71 -0
  189. package/src/statements/StatementEvaluator.ts +5 -0
  190. package/src/statements/StatementParser.ts +461 -0
  191. package/src/statements/StatementRenderer.ts +120 -0
  192. package/src/statements/StatementTextRenderer.ts +60 -0
  193. package/src/statements/Subquery.ts +6 -0
  194. package/src/statements/UniqueConstraint.ts +9 -0
  195. package/src/statements/UpdateStatement.ts +34 -0
  196. package/src/statements/UpdateStatementTextRenderer.ts +63 -0
  197. package/src/statements/Where.ts +250 -0
  198. package/src/statements/WhereText.ts +10 -0
  199. package/src/statements/index.ts +75 -0
  200. package/src/stubs/StubCommand.ts +30 -0
  201. package/src/stubs/StubConnection.ts +21 -0
  202. package/src/stubs/StubDatasource.ts +60 -0
  203. package/src/stubs/StubReader.ts +25 -0
  204. package/src/stubs/StubRepository.ts +42 -0
  205. package/src/stubs/StubTransaction.ts +17 -0
  206. package/src/stubs/createStubDatasource.ts +4 -0
  207. package/src/stubs/index.ts +7 -0
  208. package/src/stubs/notImplemented.ts +5 -0
  209. package/README.md +0 -3
@@ -0,0 +1,63 @@
1
+ import type { Field } from "../builders/Field.ts";
2
+ import type { Scalar } from "../builders/Scalar.ts";
3
+ import type { Parameter } from "../Parameter.ts";
4
+ import type { IWhere } from "./IWhere.ts";
5
+ import type { StatementTextRenderer } from "./StatementTextRenderer.ts";
6
+ import type { UpdateStatement } from "./UpdateStatement.ts";
7
+
8
+ const rename = (text: string, name: string, alias: string): string => {
9
+ const token = `$${name}`;
10
+ const next = `$${alias}`;
11
+ let index = 0;
12
+ let result = "";
13
+ while (text.indexOf(token, index) >= 0) {
14
+ const at = text.indexOf(token, index);
15
+ const end = at + token.length;
16
+ const nextChar = text.charAt(end);
17
+ const boundary = nextChar === "" || !/[A-Za-z0-9_]/.test(nextChar);
18
+ result += text.slice(index, at) + (boundary ? next : token);
19
+ index = end;
20
+ }
21
+ return result + text.slice(index);
22
+ };
23
+
24
+ const setClause = (fields: Field[]): string =>
25
+ fields.map((field) => `${field.name} = $${field.name}`).join(", ");
26
+
27
+ export class UpdateStatementTextRenderer {
28
+ constructor(private readonly text: StatementTextRenderer) {}
29
+
30
+ render(statement: UpdateStatement): string {
31
+ return this.compose(
32
+ `UPDATE ${statement.table} SET ${setClause(statement.fields)}`,
33
+ statement.where,
34
+ statement.fields,
35
+ ).text;
36
+ }
37
+
38
+ compose(
39
+ sql: string,
40
+ where: IWhere | undefined,
41
+ fields: Field[],
42
+ ): { text: string; parameters: Parameter[] } {
43
+ if (!where) return { text: sql, parameters: fields };
44
+ const rendered = `${sql} WHERE ${this.text.render(where)}`;
45
+ const split = rendered.lastIndexOf(" WHERE ");
46
+ /* v8 ignore next 2 */
47
+ const head = split < 0 ? rendered : rendered.slice(0, split);
48
+ let tail = split < 0 ? "" : rendered.slice(split);
49
+ const parameters: Parameter[] = [...fields];
50
+ const values = new Map<string, Scalar>();
51
+ for (const field of fields) values.set(field.name, field.value);
52
+ for (const parameter of where.parameters ?? []) {
53
+ if (parameter.value === undefined) continue;
54
+ const current = values.get(parameter.name);
55
+ if (values.has(parameter.name) && current !== parameter.value) {
56
+ const alias = `${parameter.name}__where`;
57
+ tail = rename(tail, parameter.name, alias);
58
+ parameters.push({ name: alias, value: parameter.value });
59
+ } else parameters.push({ name: parameter.name, value: parameter.value });
60
+ }
61
+ return { text: head + tail, parameters };
62
+ }
63
+ }
@@ -0,0 +1,250 @@
1
+ import type { Parameter } from "../Parameter.ts";
2
+ import type { Cell } from "../converters/Cell.ts";
3
+ import { ArrayExpression } from "./ArrayExpression.ts";
4
+ import { Identifier } from "./Identifier.ts";
5
+ import type { IConditionVisitor } from "./IConditionVisitor.ts";
6
+ import type { IExpression } from "./IExpression.ts";
7
+ import type { IWhere } from "./IWhere.ts";
8
+ import { Literal } from "./Literal.ts";
9
+ import { Operator } from "./Operator.ts";
10
+ import type { Comparison } from "./Cmp.ts";
11
+ import { eq } from "./Cmp.ts";
12
+ import { SelectStatement } from "./SelectStatement.ts";
13
+ import { Subquery } from "./Subquery.ts";
14
+
15
+ const pair = (
16
+ expression: Operator,
17
+ ): { left: IExpression; right: IExpression } | undefined =>
18
+ expression instanceof Operator.Equals ||
19
+ expression instanceof Operator.NotEquals ||
20
+ expression instanceof Operator.GreaterThan ||
21
+ expression instanceof Operator.LessThan ||
22
+ expression instanceof Operator.GreaterThanOrEqual ||
23
+ expression instanceof Operator.LessThanOrEqual ||
24
+ expression instanceof Operator.And ||
25
+ expression instanceof Operator.Or ||
26
+ expression instanceof Operator.In ||
27
+ expression instanceof Operator.Like ||
28
+ expression instanceof Operator.NotLike
29
+ ? expression
30
+ : undefined;
31
+
32
+ const parameterName = (name: string): string =>
33
+ parts(name)
34
+ .map((part) =>
35
+ part.length >= 2 && part.startsWith('"') && part.endsWith('"')
36
+ ? part.slice(1, -1).replace(/""/g, '"')
37
+ : part,
38
+ )
39
+ .join(".");
40
+
41
+ const parts = (name: string): string[] => {
42
+ const found: string[] = [];
43
+ let start = 0;
44
+ let quoted = false;
45
+ for (let i = 0; i < name.length; i++) {
46
+ if (name[i] === '"') quoted = !quoted;
47
+ if (name[i] !== "." || quoted) continue;
48
+ found.push(name.slice(start, i));
49
+ start = i + 1;
50
+ }
51
+ found.push(name.slice(start));
52
+ return found;
53
+ };
54
+
55
+ const side = (
56
+ expression: IExpression,
57
+ other: IExpression,
58
+ column: (name: string) => string,
59
+ value: (name: string, cell: Cell) => Cell,
60
+ ): IExpression =>
61
+ expression instanceof Literal && other instanceof Identifier
62
+ ? new Literal(value(other.name, expression.value))
63
+ : rewrite(expression, column, value);
64
+
65
+ const inRight = (
66
+ left: IExpression,
67
+ right: IExpression,
68
+ column: (name: string) => string,
69
+ value: (name: string, cell: Cell) => Cell,
70
+ ): IExpression =>
71
+ left instanceof Identifier && right instanceof ArrayExpression
72
+ ? new ArrayExpression(
73
+ right.elements.map((element) =>
74
+ element instanceof Literal
75
+ ? new Literal(value(left.name, element.value))
76
+ : rewrite(element, column, value),
77
+ ),
78
+ )
79
+ : rewrite(right, column, value);
80
+
81
+ const bound = (
82
+ subject: IExpression,
83
+ edge: IExpression,
84
+ column: (name: string) => string,
85
+ value: (name: string, cell: Cell) => Cell,
86
+ ): IExpression =>
87
+ subject instanceof Identifier && edge instanceof Literal
88
+ ? new Literal(value(subject.name, edge.value))
89
+ : rewrite(edge, column, value);
90
+
91
+ const rewriteWhere = (
92
+ where: IWhere | undefined,
93
+ column: (name: string) => string,
94
+ value: (name: string, cell: Cell) => Cell,
95
+ ): IWhere | undefined =>
96
+ where instanceof Where ? new Where(rewrite(where.condition, column, value)) : where;
97
+
98
+ const rewriteQuery = (
99
+ query: SelectStatement,
100
+ column: (name: string) => string,
101
+ value: (name: string, cell: Cell) => Cell,
102
+ ): SelectStatement =>
103
+ query.table === undefined
104
+ ? query
105
+ : new SelectStatement({
106
+ distinct: query.distinct,
107
+ table: query.table,
108
+ fields: query.fields,
109
+ where: rewriteWhere(query.where, column, value),
110
+ joins: query.joins.map((join) =>
111
+ join.on ? { ...join, on: rewrite(join.on, column, value) } : join,
112
+ ),
113
+ groupBy: query.groupBy,
114
+ having: rewriteWhere(query.having, column, value),
115
+ orderBy: query.orderBy,
116
+ limit: query.limit,
117
+ offset: query.offset,
118
+ });
119
+
120
+ const rewrite = (
121
+ expression: IExpression,
122
+ column: (name: string) => string,
123
+ value: (name: string, cell: Cell) => Cell,
124
+ ): IExpression =>
125
+ expression instanceof Where
126
+ ? rewrite(expression.condition, column, value)
127
+ : expression instanceof Identifier
128
+ ? new Identifier(column(expression.name))
129
+ : expression instanceof Literal
130
+ ? expression
131
+ : expression instanceof ArrayExpression
132
+ ? new ArrayExpression(expression.elements.map((element) => rewrite(element, column, value)))
133
+ : expression instanceof Subquery
134
+ ? new Subquery(rewriteQuery(expression.query, column, value))
135
+ : expression instanceof Operator.Not
136
+ ? new Operator.Not(rewrite(expression.argument, column, value))
137
+ : expression instanceof Operator.IsNull
138
+ ? new Operator.IsNull(rewrite(expression.argument, column, value))
139
+ : expression instanceof Operator.IsNotNull
140
+ ? new Operator.IsNotNull(rewrite(expression.argument, column, value))
141
+ : expression instanceof Operator.Exists
142
+ ? new Operator.Exists(rewrite(expression.argument, column, value))
143
+ : expression instanceof Operator.And
144
+ ? new Operator.And(rewrite(expression.left, column, value), rewrite(expression.right, column, value))
145
+ : expression instanceof Operator.Or
146
+ ? new Operator.Or(rewrite(expression.left, column, value), rewrite(expression.right, column, value))
147
+ : expression instanceof Operator.In
148
+ ? new Operator.In(rewrite(expression.left, column, value), inRight(expression.left, expression.right, column, value))
149
+ : expression instanceof Operator.NotIn
150
+ ? new Operator.NotIn(rewrite(expression.left, column, value), inRight(expression.left, expression.right, column, value))
151
+ : expression instanceof Operator.Like
152
+ ? new Operator.Like(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
153
+ : expression instanceof Operator.NotLike
154
+ ? new Operator.NotLike(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
155
+ : expression instanceof Operator.Between
156
+ ? new Operator.Between(rewrite(expression.value, column, value), bound(expression.value, expression.low, column, value), bound(expression.value, expression.high, column, value))
157
+ : expression instanceof Operator.NotBetween
158
+ ? new Operator.NotBetween(rewrite(expression.value, column, value), bound(expression.value, expression.low, column, value), bound(expression.value, expression.high, column, value))
159
+ : expression instanceof Operator.Equals
160
+ ? new Operator.Equals(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
161
+ : expression instanceof Operator.NotEquals
162
+ ? new Operator.NotEquals(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
163
+ : expression instanceof Operator.GreaterThan
164
+ ? new Operator.GreaterThan(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
165
+ : expression instanceof Operator.LessThan
166
+ ? new Operator.LessThan(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
167
+ : expression instanceof Operator.GreaterThanOrEqual
168
+ ? new Operator.GreaterThanOrEqual(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
169
+ : expression instanceof Operator.LessThanOrEqual
170
+ ? new Operator.LessThanOrEqual(side(expression.left, expression.right, column, value), side(expression.right, expression.left, column, value))
171
+ : (() => {
172
+ throw new Error("empty expression");
173
+ })();
174
+
175
+ const listed = (name: string, elements: IExpression[]): Parameter<Cell>[] =>
176
+ elements.map((element, i) =>
177
+ element instanceof Literal
178
+ ? { name: `${parameterName(name)}_${i}`, value: element.value }
179
+ : (() => {
180
+ throw new Error("empty in");
181
+ })(),
182
+ );
183
+
184
+ const collect = (expression: IExpression): Parameter<Cell>[] => {
185
+ if (expression instanceof Where) return collect(expression.condition);
186
+ if (expression instanceof Literal || expression instanceof Identifier) return [];
187
+ if (expression instanceof Operator.Not || expression instanceof Operator.IsNull || expression instanceof Operator.IsNotNull)
188
+ return collect(expression.argument);
189
+ if (expression instanceof Operator.Exists) return collect(expression.argument);
190
+ if (expression instanceof Subquery)
191
+ return [
192
+ ...(expression.query.where ? collect(expression.query.where) : []),
193
+ ...(expression.query.having ? collect(expression.query.having) : []),
194
+ ...expression.query.joins.flatMap((join) => (join.on ? collect(join.on) : [])),
195
+ ];
196
+ if (expression instanceof Operator.In && expression.left instanceof Identifier && expression.right instanceof ArrayExpression)
197
+ return listed(expression.left.name, expression.right.elements);
198
+ if (expression instanceof Operator.NotIn && expression.left instanceof Identifier && expression.right instanceof ArrayExpression)
199
+ return listed(expression.left.name, expression.right.elements);
200
+ if (expression instanceof Operator.In || expression instanceof Operator.NotIn)
201
+ return [...collect(expression.left), ...collect(expression.right)];
202
+ if (
203
+ (expression instanceof Operator.Between || expression instanceof Operator.NotBetween) &&
204
+ expression.value instanceof Identifier &&
205
+ expression.low instanceof Literal &&
206
+ expression.high instanceof Literal
207
+ )
208
+ return [
209
+ { name: `${parameterName(expression.value.name)}_0`, value: expression.low.value },
210
+ { name: `${parameterName(expression.value.name)}_1`, value: expression.high.value },
211
+ ];
212
+ if (expression instanceof Operator.Between || expression instanceof Operator.NotBetween)
213
+ return [...collect(expression.value), ...collect(expression.low), ...collect(expression.high)];
214
+ const operands = expression instanceof Operator ? pair(expression) : undefined;
215
+ if (operands && operands.left instanceof Identifier && operands.right instanceof Literal)
216
+ return [{ name: parameterName(operands.left.name), value: operands.right.value }];
217
+ if (operands && operands.left instanceof Literal && operands.right instanceof Literal) return [];
218
+ if (operands) return [...collect(operands.left), ...collect(operands.right)];
219
+ if (expression instanceof ArrayExpression) return expression.elements.flatMap(collect);
220
+ throw new Error("empty expression");
221
+ };
222
+
223
+ export class Where implements IWhere {
224
+ readonly condition: IExpression;
225
+
226
+ constructor(condition: IExpression);
227
+ constructor(column: string, op: Comparison, value: Cell);
228
+ constructor(columnOrCondition: IExpression | string, op: Comparison = eq, value: Cell = null) {
229
+ this.condition =
230
+ typeof columnOrCondition === "string" ? op(columnOrCondition, value) : columnOrCondition;
231
+ }
232
+
233
+ and(column: string, op: Comparison, value: Cell): Where {
234
+ return new Where(new Operator.And(this.condition, op(column, value)));
235
+ }
236
+
237
+ or(column: string, op: Comparison, value: Cell): Where {
238
+ return new Where(new Operator.Or(this.condition, op(column, value)));
239
+ }
240
+
241
+ map(column: (name: string) => string, value: (name: string, cell: Cell) => Cell): Where {
242
+ return new Where(rewrite(this.condition, column, value));
243
+ }
244
+
245
+ accept = (visitor: IConditionVisitor): string => visitor.visit(this);
246
+
247
+ get parameters(): Parameter[] {
248
+ return collect(this.condition) as Parameter[];
249
+ }
250
+ }
@@ -0,0 +1,10 @@
1
+ import type { IConditionVisitor } from "./IConditionVisitor.ts";
2
+ import type { IWhere } from "./IWhere.ts";
3
+
4
+ export class WhereText implements IWhere {
5
+ constructor(private readonly text: string) {}
6
+ get rawText(): string {
7
+ return this.text;
8
+ }
9
+ accept = (visitor: IConditionVisitor): string => visitor.visit(this);
10
+ }
@@ -0,0 +1,75 @@
1
+ export type { IExpression } from "./IExpression.ts";
2
+ export type { IStatement } from "./IStatement.ts";
3
+ export type { IStatementVisitor } from "./IStatementVisitor.ts";
4
+ export type { ICondition } from "./ICondition.ts";
5
+ export type { IConditionVisitor } from "./IConditionVisitor.ts";
6
+ export type { IWhere } from "./IWhere.ts";
7
+ export type { ISelectStatement } from "./ISelectStatement.ts";
8
+ export type { IInsertStatement } from "./IInsertStatement.ts";
9
+ export type { IUpdateStatement } from "./IUpdateStatement.ts";
10
+ export type { IDeleteStatement } from "./IDeleteStatement.ts";
11
+ export type { IBulkInsertStatement } from "./IBulkInsertStatement.ts";
12
+ export type { IBulkUpdateStatement } from "./IBulkUpdateStatement.ts";
13
+ export type { IBulkDeleteStatement } from "./IBulkDeleteStatement.ts";
14
+ export type { ICreateTableStatement } from "./ICreateTableStatement.ts";
15
+ export type { ICreateIndexStatement } from "./ICreateIndexStatement.ts";
16
+ export type { IExecuteStoredProcedureStatement } from "./IExecuteStoredProcedureStatement.ts";
17
+ export type { IReturnStatement } from "./IReturnStatement.ts";
18
+ export type { Column } from "./Column.ts";
19
+ export type { ITableConstraint, TableConstraintKind } from "./ITableConstraint.ts";
20
+ export type { Join, JoinKind } from "./Join.ts";
21
+ export { Join } from "./Join.ts";
22
+ export { Aggregate } from "./Aggregate.ts";
23
+ export type { SortDirection } from "./OrderBy.ts";
24
+ export { OrderBy } from "./OrderBy.ts";
25
+ export type { SelectStatementOptions } from "./SelectStatementOptions.ts";
26
+ export { Condition } from "./Condition.ts";
27
+ export { Operator } from "./Operator.ts";
28
+ export { eq, ne, gt, lt, ge, le } from "./Cmp.ts";
29
+ export type { Comparison } from "./Cmp.ts";
30
+ export { Identifier } from "./Identifier.ts";
31
+ export { Literal } from "./Literal.ts";
32
+ export { ArrayExpression } from "./ArrayExpression.ts";
33
+ export { Where } from "./Where.ts";
34
+ export { ExpressionEvaluator } from "./ExpressionEvaluator.ts";
35
+ export { StatementEvaluator } from "./StatementEvaluator.ts";
36
+ export { WhereText } from "./WhereText.ts";
37
+ export { SelectStatement } from "./SelectStatement.ts";
38
+ export { StatementParser } from "./StatementParser.ts";
39
+ export { StatementTextRenderer } from "./StatementTextRenderer.ts";
40
+ export { DefaultStatementTextRenderer } from "./DefaultStatementTextRenderer.ts";
41
+ export { StatementRenderer } from "./StatementRenderer.ts";
42
+ export { ExpressionRenderer } from "./ExpressionRenderer.ts";
43
+ export { ConditionRenderer } from "./ConditionRenderer.ts";
44
+ export { Native, n } from "./Native.ts";
45
+ export { Subquery } from "./Subquery.ts";
46
+ export { InsertStatement } from "./InsertStatement.ts";
47
+ export { UpdateStatement } from "./UpdateStatement.ts";
48
+ export { DeleteStatement } from "./DeleteStatement.ts";
49
+ export { BulkInsertStatement } from "./BulkInsertStatement.ts";
50
+ export { BulkUpdateStatement } from "./BulkUpdateStatement.ts";
51
+ export { BulkDeleteStatement } from "./BulkDeleteStatement.ts";
52
+ export { BulkInsertStatementTextRenderer } from "./BulkInsertStatementTextRenderer.ts";
53
+ export { BulkUpdateStatementTextRenderer } from "./BulkUpdateStatementTextRenderer.ts";
54
+ export { BulkDeleteStatementTextRenderer } from "./BulkDeleteStatementTextRenderer.ts";
55
+ export { CreateTableStatement } from "./CreateTableStatement.ts";
56
+ export { CreateTableStatementTextRenderer } from "./CreateTableStatementTextRenderer.ts";
57
+ export { CreateIndexStatement } from "./CreateIndexStatement.ts";
58
+ export { CreateIndexStatementTextRenderer } from "./CreateIndexStatementTextRenderer.ts";
59
+ export { SelectStatementTextRenderer } from "./SelectStatementTextRenderer.ts";
60
+ export { InsertStatementTextRenderer } from "./InsertStatementTextRenderer.ts";
61
+ export { UpdateStatementTextRenderer } from "./UpdateStatementTextRenderer.ts";
62
+ export { DeleteStatementTextRenderer } from "./DeleteStatementTextRenderer.ts";
63
+ export { ExecuteStoredProcedureStatementTextRenderer } from "./ExecuteStoredProcedureStatementTextRenderer.ts";
64
+ export { ReturnStatementTextRenderer } from "./ReturnStatementTextRenderer.ts";
65
+ export { SelectInsertedIdStatementTextRenderer } from "./SelectInsertedIdStatementTextRenderer.ts";
66
+ export { ColumnDefault } from "./ColumnDefault.ts";
67
+ export { NotNull } from "./NotNull.ts";
68
+ export { PrimaryKey } from "./PrimaryKey.ts";
69
+ export { ForeignKey, ReferentialAction } from "./ForeignKey.ts";
70
+ export type { ReferentialAction as ReferentialActionName } from "./ForeignKey.ts";
71
+ export { UniqueConstraint } from "./UniqueConstraint.ts";
72
+ export { CheckConstraint } from "./CheckConstraint.ts";
73
+ export { ExecuteStoredProcedureStatement } from "./ExecuteStoredProcedureStatement.ts";
74
+ export { SelectInsertedIdStatement } from "./SelectInsertedIdStatement.ts";
75
+ export { ReturnStatement } from "./ReturnStatement.ts";
@@ -0,0 +1,30 @@
1
+ import type { ICommand } from "../ICommand.ts";
2
+ import type { IConnection } from "../IConnection.ts";
3
+ import type { Cells } from "../converters/Cell.ts";
4
+ import type { IReader } from "../IReader.ts";
5
+ import type { Response } from "../Response.ts";
6
+ import type { Parameter } from "../Parameter.ts";
7
+ import { CommandMiddlewareHost } from "../CommandMiddlewareHost.ts";
8
+ import { Native } from "../statements/Native.ts";
9
+ import { notImplemented } from "./notImplemented.ts";
10
+
11
+ export class StubCommand extends CommandMiddlewareHost implements ICommand {
12
+ constructor(
13
+ readonly provider: string,
14
+ readonly connection: IConnection,
15
+ ) {
16
+ super();
17
+ }
18
+
19
+ executeReaderNative = (
20
+ text: Native,
21
+ parameters?: Parameter[],
22
+ ): Promise<IReader<Cells>> =>
23
+ this.run(text.text, parameters, async () => notImplemented(this.provider));
24
+
25
+ executeNative = (
26
+ text: Native,
27
+ parameters?: Parameter[],
28
+ ): Promise<Response> =>
29
+ this.run(text.text, parameters, async () => notImplemented(this.provider));
30
+ }
@@ -0,0 +1,21 @@
1
+ import type { ICommand } from "../ICommand.ts";
2
+ import type { IConnection } from "../IConnection.ts";
3
+ import type { ITransaction } from "../ITransaction.ts";
4
+ import { StubCommand } from "./StubCommand.ts";
5
+ import { notImplemented } from "./notImplemented.ts";
6
+
7
+ export class StubConnection implements IConnection {
8
+ isOpen = false;
9
+ constructor(readonly provider: string) {}
10
+
11
+ createCommand = (): ICommand => new StubCommand(this.provider, this);
12
+
13
+ open = async (): Promise<void> => notImplemented(this.provider);
14
+
15
+ close = async (): Promise<void> => notImplemented(this.provider);
16
+
17
+ [Symbol.asyncDispose] = (): Promise<void> => this.close();
18
+
19
+ startTransaction = async (): Promise<ITransaction> =>
20
+ notImplemented(this.provider);
21
+ }
@@ -0,0 +1,60 @@
1
+ import type { Constructable } from "../converters/Constructable.ts";
2
+ import type { ICommand } from "../ICommand.ts";
3
+ import type { IConnection } from "../IConnection.ts";
4
+ import type { IDatasource } from "../IDatasource.ts";
5
+ import type { IReadonlyRepository } from "../IReadonlyRepository.ts";
6
+ import type { ICRUDRepository } from "../ICRUDRepository.ts";
7
+ import { DatasourceError } from "../DatasourceError.ts";
8
+ import { RepositoryFactory } from "../RepositoryFactory.ts";
9
+ import { StubCommand } from "./StubCommand.ts";
10
+ import { StubConnection } from "./StubConnection.ts";
11
+ import { StubRepository } from "./StubRepository.ts";
12
+ export class StubDatasource implements IDatasource {
13
+ private connection?: IConnection;
14
+ readonly repositories = new RepositoryFactory();
15
+
16
+ constructor(readonly provider: string) {}
17
+
18
+ private defaultConnection = (): IConnection =>
19
+ (this.connection ??= new StubConnection(this.provider));
20
+
21
+ createConnection = (): Promise<IConnection> =>
22
+ Promise.resolve(this.defaultConnection());
23
+
24
+ createCommand = async (connection?: IConnection): Promise<ICommand> => {
25
+ if (!connection) {
26
+ connection = this.defaultConnection();
27
+ if (connection.isOpen) throw new DatasourceError("Connection is already open");
28
+ await connection.open();
29
+ }
30
+ return new StubCommand(this.provider, connection);
31
+ };
32
+
33
+ createRepository<T>(
34
+ type: Constructable<T>,
35
+ connection?: IConnection,
36
+ ): ICRUDRepository<T>;
37
+ createRepository(typeName: string, connection?: IConnection): ICRUDRepository;
38
+ createRepository<T>(
39
+ typeOrName: Constructable<T> | string,
40
+ connection?: IConnection,
41
+ ): ICRUDRepository<T> {
42
+ if (typeof typeOrName === "string")
43
+ return this.repositories.create(typeOrName, connection ?? this.defaultConnection()) as ICRUDRepository<T>;
44
+ return new StubRepository<T>(this.provider, connection ?? this.defaultConnection(), typeOrName);
45
+ }
46
+
47
+ createReadonlyRepository<T>(
48
+ type: Constructable<T>,
49
+ connection?: IConnection,
50
+ ): IReadonlyRepository<T>;
51
+ createReadonlyRepository(typeName: string, connection?: IConnection): IReadonlyRepository;
52
+ createReadonlyRepository<T>(
53
+ typeOrName: Constructable<T> | string,
54
+ connection?: IConnection,
55
+ ): IReadonlyRepository<T> {
56
+ if (typeof typeOrName === "string")
57
+ return this.repositories.createReadonly(typeOrName, connection ?? this.defaultConnection()) as IReadonlyRepository<T>;
58
+ return this.createRepository(typeOrName, connection);
59
+ }
60
+ }
@@ -0,0 +1,25 @@
1
+ import type { IReader } from "../IReader.ts";
2
+ import { readerToAsyncIterable } from "../readerToAsyncIterable.ts";
3
+ import { notImplemented } from "./notImplemented.ts";
4
+
5
+ export class StubReader<T = unknown> implements IReader<T> {
6
+ current: T | undefined = undefined;
7
+
8
+ constructor(readonly provider: string) {}
9
+
10
+ async next(): Promise<boolean> {
11
+ notImplemented(this.provider);
12
+ }
13
+
14
+ read(): AsyncIterable<T> {
15
+ return readerToAsyncIterable(this);
16
+ }
17
+
18
+ async nextResult(): Promise<boolean> {
19
+ notImplemented(this.provider);
20
+ }
21
+
22
+ async dispose(): Promise<void> {}
23
+
24
+ [Symbol.asyncDispose] = (): Promise<void> => this.dispose();
25
+ }
@@ -0,0 +1,42 @@
1
+ import type { Scalar } from "../builders/Scalar.ts";
2
+ import type { Cells } from "../converters/Cell.ts";
3
+ import type { Constructable } from "../converters/Constructable.ts";
4
+ import type { IConnection } from "../IConnection.ts";
5
+ import type { Parameter } from "../Parameter.ts";
6
+ import type { IExecuteStoredProcedureStatement } from "../statements/IExecuteStoredProcedureStatement.ts";
7
+ import type { ISelectStatement } from "../statements/ISelectStatement.ts";
8
+ import type { ICRUDRepository } from "../ICRUDRepository.ts";
9
+ import { ReadonlyRepository, untyped } from "../ReadonlyRepository.ts";
10
+ import type { ReadonlyRepositoryMappingOptions } from "../ReadonlyRepositoryMappingOptions.ts";
11
+ import type { Response } from "../Response.ts";
12
+ import type { IWhere } from "../statements/IWhere.ts";
13
+ import { notImplemented } from "./notImplemented.ts";
14
+
15
+ export class StubRepository<T = unknown> extends ReadonlyRepository<T> implements ICRUDRepository<T> {
16
+ readonly ids: readonly string[] = [];
17
+ constructor(
18
+ readonly provider: string,
19
+ _connection: IConnection,
20
+ type: Constructable<T> = untyped<T>(),
21
+ ) {
22
+ super(type);
23
+ }
24
+
25
+ async *read(
26
+ _query?: ISelectStatement | IWhere | IExecuteStoredProcedureStatement,
27
+ _parameters?: Parameter[],
28
+ _options?: ReadonlyRepositoryMappingOptions<T>,
29
+ ): AsyncIterable<T> {
30
+ notImplemented(this.provider);
31
+ }
32
+
33
+ create = async (_item: T): Promise<T> => notImplemented(this.provider);
34
+
35
+ update = async (_item: T, _byWhere?: IWhere): Promise<Response> =>
36
+ notImplemented(this.provider);
37
+
38
+ delete = async (_item: T, _byWhere?: IWhere): Promise<Response> =>
39
+ notImplemented(this.provider);
40
+
41
+ readSingleById = (_id: Scalar | Cells): Promise<T | undefined> => notImplemented(this.provider);
42
+ }
@@ -0,0 +1,17 @@
1
+ import type { IConnection } from "../IConnection.ts";
2
+ import type { ITransaction } from "../ITransaction.ts";
3
+ import { IsolationLevel } from "../IsolationLevel.ts";
4
+ import { notImplemented } from "./notImplemented.ts";
5
+
6
+ export class StubTransaction implements ITransaction {
7
+ readonly isolation = IsolationLevel.ReadCommitted;
8
+
9
+ constructor(
10
+ readonly provider: string,
11
+ readonly connection: IConnection,
12
+ ) {}
13
+
14
+ commit = async (): Promise<void> => notImplemented(this.provider);
15
+
16
+ abort = async (): Promise<void> => notImplemented(this.provider);
17
+ }
@@ -0,0 +1,4 @@
1
+ import { StubDatasource } from "./StubDatasource.ts";
2
+
3
+ export const createStubDatasource = (provider: string): StubDatasource =>
4
+ new StubDatasource(provider);
@@ -0,0 +1,7 @@
1
+ export { createStubDatasource } from "./createStubDatasource.ts";
2
+ export { StubCommand } from "./StubCommand.ts";
3
+ export { StubConnection } from "./StubConnection.ts";
4
+ export { StubDatasource } from "./StubDatasource.ts";
5
+ export { StubReader } from "./StubReader.ts";
6
+ export { StubRepository } from "./StubRepository.ts";
7
+ export { StubTransaction } from "./StubTransaction.ts";
@@ -0,0 +1,5 @@
1
+ import { ProviderNotImplementedError } from "../ProviderNotImplementedError.ts";
2
+
3
+ export const notImplemented = (provider: string): never => {
4
+ throw new ProviderNotImplementedError(provider);
5
+ };
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.