@deterministic-code/datasources 0.1.14 → 0.1.15

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.
@@ -83,7 +83,7 @@ export class BatchCommandIBulkWriteStrategy {
83
83
  return { result: null, rowsAffected };
84
84
  };
85
85
  mappedInsert = (item) => {
86
- const record = this.reverse(item);
86
+ const record = this.repo.fillCreateZeros(this.reverse(item));
87
87
  const statement = this.statements().insert(this.fields(record, (col) => listed(this.options.createProperties, col, !this.ids.includes(col) || assigned(record[col] ?? null))));
88
88
  return { table: statement.table, fields: statement.fields };
89
89
  };
@@ -14,6 +14,7 @@ export declare class CRUDRepository<T = Cells> extends ReadonlyRepository<T> imp
14
14
  readonly ids: readonly string[];
15
15
  private readonly createProperties?;
16
16
  private readonly updateProperties?;
17
+ protected createZeros?: Cells;
17
18
  private readonly crudStatements;
18
19
  private readonly tree;
19
20
  private readonly write;
@@ -36,6 +37,7 @@ export declare class CRUDRepository<T = Cells> extends ReadonlyRepository<T> imp
36
37
  private save;
37
38
  private remove;
38
39
  private byId;
40
+ fillCreateZeros: (record: Cells) => Cells;
39
41
  private reverseConvert;
40
42
  private idWhere;
41
43
  protected enrichmentInto: (name: string) => boolean;
@@ -37,6 +37,7 @@ export class CRUDRepository extends ReadonlyRepository {
37
37
  ids;
38
38
  createProperties;
39
39
  updateProperties;
40
+ createZeros;
40
41
  crudStatements;
41
42
  tree;
42
43
  write;
@@ -118,7 +119,7 @@ export class CRUDRepository extends ReadonlyRepository {
118
119
  readSingleById = async (id) => this.readSingle(this.byId(id));
119
120
  insert = async (item) => {
120
121
  const extras = lookupKeys(item);
121
- const record = this.reverseConvert(item);
122
+ const record = this.fillCreateZeros(this.reverseConvert(item));
122
123
  const fields = fieldsOf(record, (col) => extras.has(col) || listed(this.createProperties, col, !this.ids.includes(col) || assigned(record[col] ?? null)), extras, this.cell, this.enrichmentInto, this.crudStatements.readColumns, this.column);
123
124
  const statement = this.crudStatements.insert(fields);
124
125
  const response = await execute(this.command(), statement, statement.fields);
@@ -181,6 +182,7 @@ export class CRUDRepository extends ReadonlyRepository {
181
182
  throw new DatasourceError("Composite id requires a row keyed by each Id column");
182
183
  return this.idWhere({ [this.ids[0]]: id });
183
184
  };
185
+ fillCreateZeros = (record) => this.createZeros === undefined ? record : { ...this.createZeros, ...record };
184
186
  reverseConvert = (item) => {
185
187
  const row = this.objectConverter.reverseConvert(item);
186
188
  const converted = this.rowConverter ? this.rowConverter.reverseConvert(row) : row;
@@ -6,6 +6,8 @@ export class ConditionRenderer {
6
6
  }
7
7
  render = (condition) => condition.accept(this);
8
8
  visit(where) {
9
- return where instanceof Where ? this.expressions.render(where.condition) : where.rawText;
9
+ return where instanceof Where || where.constructor.name === "Where"
10
+ ? this.expressions.render(where.condition)
11
+ : where.rawText;
10
12
  }
11
13
  }
@@ -4,69 +4,70 @@ import { Literal } from "./Literal.js";
4
4
  import { Operator } from "./Operator.js";
5
5
  import { Subquery } from "./Subquery.js";
6
6
  import { Where } from "./Where.js";
7
+ const is = (value, type, name) => value instanceof type || value.constructor.name === name;
7
8
  export class ExpressionRenderer {
8
9
  text;
9
10
  constructor(text) {
10
11
  this.text = text;
11
12
  }
12
13
  render = (expression) => {
13
- if (expression instanceof Where)
14
+ if (is(expression, Where, "Where"))
14
15
  return this.render(expression.condition);
15
- if (expression instanceof Identifier)
16
+ if (is(expression, Identifier, "Identifier"))
16
17
  return expression.name;
17
- if (expression instanceof Literal)
18
+ if (is(expression, Literal, "Literal"))
18
19
  return inline(expression.value);
19
- if (expression instanceof ArrayExpression)
20
+ if (is(expression, ArrayExpression, "ArrayExpression"))
20
21
  return expression.elements.map((e) => this.render(e)).join(", ");
21
- if (expression instanceof Operator.Not)
22
+ if (is(expression, Operator.Not, "Not"))
22
23
  return `NOT (${this.render(expression.argument)})`;
23
- if (expression instanceof Operator.IsNull)
24
+ if (is(expression, Operator.IsNull, "IsNull"))
24
25
  return `${this.render(expression.argument)} IS NULL`;
25
- if (expression instanceof Operator.IsNotNull)
26
+ if (is(expression, Operator.IsNotNull, "IsNotNull"))
26
27
  return `${this.render(expression.argument)} IS NOT NULL`;
27
- if (expression instanceof Operator.Exists)
28
+ if (is(expression, Operator.Exists, "Exists"))
28
29
  return `EXISTS ${this.render(expression.argument)}`;
29
- if (expression instanceof Subquery)
30
+ if (is(expression, Subquery, "Subquery"))
30
31
  return `(${this.text.render(expression.query)})`;
31
- if (expression instanceof Operator.In &&
32
- expression.left instanceof Identifier &&
33
- expression.right instanceof ArrayExpression)
32
+ if (is(expression, Operator.In, "In") &&
33
+ is(expression.left, Identifier, "Identifier") &&
34
+ is(expression.right, ArrayExpression, "ArrayExpression"))
34
35
  return expression.right.elements.length === 0
35
36
  ? "1 = 0"
36
37
  : `${expression.left.name} IN (${slots(expression.left.name, expression.right.elements.length)})`;
37
- if (expression instanceof Operator.In &&
38
- expression.left instanceof Identifier &&
39
- expression.right instanceof Subquery)
38
+ if (is(expression, Operator.In, "In") &&
39
+ is(expression.left, Identifier, "Identifier") &&
40
+ is(expression.right, Subquery, "Subquery"))
40
41
  return `${expression.left.name} IN ${this.render(expression.right)}`;
41
- if (expression instanceof Operator.NotIn &&
42
- expression.left instanceof Identifier &&
43
- expression.right instanceof ArrayExpression)
42
+ if (is(expression, Operator.NotIn, "NotIn") &&
43
+ is(expression.left, Identifier, "Identifier") &&
44
+ is(expression.right, ArrayExpression, "ArrayExpression"))
44
45
  return expression.right.elements.length === 0
45
46
  ? "1 = 1"
46
47
  : `${expression.left.name} NOT IN (${slots(expression.left.name, expression.right.elements.length)})`;
47
- if (expression instanceof Operator.NotIn &&
48
- expression.left instanceof Identifier &&
49
- expression.right instanceof Subquery)
48
+ if (is(expression, Operator.NotIn, "NotIn") &&
49
+ is(expression.left, Identifier, "Identifier") &&
50
+ is(expression.right, Subquery, "Subquery"))
50
51
  return `${expression.left.name} NOT IN ${this.render(expression.right)}`;
51
- if ((expression instanceof Operator.Between || expression instanceof Operator.NotBetween) &&
52
- expression.value instanceof Identifier &&
53
- expression.low instanceof Literal &&
54
- expression.high instanceof Literal) {
55
- const word = expression instanceof Operator.NotBetween ? "NOT BETWEEN" : "BETWEEN";
52
+ if ((is(expression, Operator.Between, "Between") || is(expression, Operator.NotBetween, "NotBetween")) &&
53
+ is(expression.value, Identifier, "Identifier") &&
54
+ is(expression.low, Literal, "Literal") &&
55
+ is(expression.high, Literal, "Literal")) {
56
+ const word = is(expression, Operator.NotBetween, "NotBetween") ? "NOT BETWEEN" : "BETWEEN";
56
57
  return `${expression.value.name} ${word} $${parameterName(expression.value.name)}_0 AND $${parameterName(expression.value.name)}_1`;
57
58
  }
58
- if (expression instanceof Operator.Between)
59
+ if (is(expression, Operator.Between, "Between"))
59
60
  return `${this.render(expression.value)} BETWEEN ${this.render(expression.low)} AND ${this.render(expression.high)}`;
60
- if (expression instanceof Operator.NotBetween)
61
+ if (is(expression, Operator.NotBetween, "NotBetween"))
61
62
  return `${this.render(expression.value)} NOT BETWEEN ${this.render(expression.low)} AND ${this.render(expression.high)}`;
62
- if (expression instanceof Operator.And)
63
+ if (is(expression, Operator.And, "And"))
63
64
  return `${this.wrap(expression.left, true)} AND ${this.wrap(expression.right, true)}`;
64
- if (expression instanceof Operator.Or)
65
+ if (is(expression, Operator.Or, "Or"))
65
66
  return `${this.wrap(expression.left, false)} OR ${this.wrap(expression.right, false)}`;
66
- const operands = expression instanceof Operator ? pair(expression) : undefined;
67
- if (operands && operands.left instanceof Identifier && operands.right instanceof Literal)
67
+ const operands = pair(expression);
68
+ if (operands && is(operands.left, Identifier, "Identifier") && is(operands.right, Literal, "Literal"))
68
69
  return `${operands.left.name} ${symbol(expression)} $${parameterName(operands.left.name)}`;
69
- if (operands && operands.left instanceof Literal && operands.right instanceof Literal)
70
+ if (operands && is(operands.left, Literal, "Literal") && is(operands.right, Literal, "Literal"))
70
71
  return `${inline(operands.left.value)} ${symbol(expression)} ${inline(operands.right.value)}`;
71
72
  if (operands)
72
73
  return `${this.render(operands.left)} ${symbol(expression)} ${this.render(operands.right)}`;
@@ -74,23 +75,34 @@ export class ExpressionRenderer {
74
75
  };
75
76
  wrap = (child, and) => needsParens(child, and) ? `(${this.render(child)})` : this.render(child);
76
77
  }
77
- const symbol = (op) => op instanceof Operator.Equals
78
- ? "="
79
- : op instanceof Operator.NotEquals
80
- ? "<>"
81
- : op instanceof Operator.GreaterThan
82
- ? ">"
83
- : op instanceof Operator.LessThan
84
- ? "<"
85
- : op instanceof Operator.GreaterThanOrEqual
86
- ? ">="
87
- : op instanceof Operator.LessThanOrEqual
88
- ? "<="
89
- : op instanceof Operator.Like
90
- ? "LIKE"
91
- : op instanceof Operator.NotLike
92
- ? "NOT LIKE"
93
- : "IN";
78
+ const symbols = {
79
+ Equals: "=",
80
+ NotEquals: "<>",
81
+ GreaterThan: ">",
82
+ LessThan: "<",
83
+ GreaterThanOrEqual: ">=",
84
+ LessThanOrEqual: "<=",
85
+ Like: "LIKE",
86
+ NotLike: "NOT LIKE",
87
+ };
88
+ const symbol = (op) => symbols[op.constructor.name] ??
89
+ (is(op, Operator.Equals, "Equals")
90
+ ? "="
91
+ : is(op, Operator.NotEquals, "NotEquals")
92
+ ? "<>"
93
+ : is(op, Operator.GreaterThan, "GreaterThan")
94
+ ? ">"
95
+ : is(op, Operator.LessThan, "LessThan")
96
+ ? "<"
97
+ : is(op, Operator.GreaterThanOrEqual, "GreaterThanOrEqual")
98
+ ? ">="
99
+ : is(op, Operator.LessThanOrEqual, "LessThanOrEqual")
100
+ ? "<="
101
+ : is(op, Operator.Like, "Like")
102
+ ? "LIKE"
103
+ : is(op, Operator.NotLike, "NotLike")
104
+ ? "NOT LIKE"
105
+ : "IN");
94
106
  const inline = (value) => value === null
95
107
  ? "null"
96
108
  : typeof value === "boolean"
@@ -98,24 +110,24 @@ const inline = (value) => value === null
98
110
  : typeof value === "string"
99
111
  ? `'${value.replace(/'/g, "''")}'`
100
112
  : String(value);
101
- const needsParens = (child, and) => child instanceof Where
113
+ const needsParens = (child, and) => is(child, Where, "Where")
102
114
  ? needsParens(child.condition, and)
103
- : child instanceof Operator.Not ||
104
- child instanceof Operator.In ||
105
- child instanceof Operator.NotIn ||
106
- (child instanceof Operator.And && !and) ||
107
- (child instanceof Operator.Or && and);
108
- const pair = (expression) => expression instanceof Operator.Equals ||
109
- expression instanceof Operator.NotEquals ||
110
- expression instanceof Operator.GreaterThan ||
111
- expression instanceof Operator.LessThan ||
112
- expression instanceof Operator.GreaterThanOrEqual ||
113
- expression instanceof Operator.LessThanOrEqual ||
114
- expression instanceof Operator.And ||
115
- expression instanceof Operator.Or ||
116
- expression instanceof Operator.In ||
117
- expression instanceof Operator.Like ||
118
- expression instanceof Operator.NotLike
115
+ : is(child, Operator.Not, "Not") ||
116
+ is(child, Operator.In, "In") ||
117
+ is(child, Operator.NotIn, "NotIn") ||
118
+ (is(child, Operator.And, "And") && !and) ||
119
+ (is(child, Operator.Or, "Or") && and);
120
+ const pair = (expression) => is(expression, Operator.Equals, "Equals") ||
121
+ is(expression, Operator.NotEquals, "NotEquals") ||
122
+ is(expression, Operator.GreaterThan, "GreaterThan") ||
123
+ is(expression, Operator.LessThan, "LessThan") ||
124
+ is(expression, Operator.GreaterThanOrEqual, "GreaterThanOrEqual") ||
125
+ is(expression, Operator.LessThanOrEqual, "LessThanOrEqual") ||
126
+ is(expression, Operator.And, "And") ||
127
+ is(expression, Operator.Or, "Or") ||
128
+ is(expression, Operator.In, "In") ||
129
+ is(expression, Operator.Like, "Like") ||
130
+ is(expression, Operator.NotLike, "NotLike")
119
131
  ? expression
120
132
  : undefined;
121
133
  const parameterName = (name) => parts(name)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deterministic-code/datasources",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",