@deterministic-code/datasources 0.1.10 → 0.1.11

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.
@@ -27,6 +27,7 @@ export declare class BatchCommandIBulkWriteStrategy<T extends object> implements
27
27
  private statements;
28
28
  private get ids();
29
29
  private reverse;
30
+ private writable;
30
31
  private fields;
31
32
  private cell;
32
33
  private idsWhere;
@@ -9,6 +9,7 @@ const empty = () => ({ result: null, rowsAffected: 0 });
9
9
  const budget = 8000;
10
10
  const maxRows = 250;
11
11
  const assigned = (value) => value !== null && value !== "" && value !== 0 && value !== 0n;
12
+ const listed = (list, col, fallback) => list === undefined ? fallback : list.includes(col);
12
13
  const columnsOf = (rows) => {
13
14
  const seen = new Set();
14
15
  const columns = [];
@@ -83,12 +84,12 @@ export class BatchCommandIBulkWriteStrategy {
83
84
  };
84
85
  mappedInsert = (item) => {
85
86
  const record = this.reverse(item);
86
- const statement = this.statements().insert(this.fields(record, (col) => !this.ids.includes(col) || assigned(record[col] ?? null)));
87
+ const statement = this.statements().insert(this.fields(record, (col) => listed(this.options.createProperties, col, !this.ids.includes(col) || assigned(record[col] ?? null))));
87
88
  return { table: statement.table, fields: statement.fields };
88
89
  };
89
90
  mappedUpdate = (item) => {
90
91
  const record = this.reverse(item);
91
- const fields = this.fields(record, (col) => !this.ids.includes(col));
92
+ const fields = this.fields(record, (col) => listed(this.options.updateProperties, col, !this.ids.includes(col)));
92
93
  if (fields.length === 0)
93
94
  throw new DatasourceError("Update requires at least one non-Id field");
94
95
  const statement = this.statements().update(fields, this.idsWhere(record), (name, value) => this.cell(name, value, true));
@@ -101,7 +102,7 @@ export class BatchCommandIBulkWriteStrategy {
101
102
  };
102
103
  updateCommand = (item, byWhere) => {
103
104
  const record = this.reverse(item);
104
- const fields = this.fields(record, (col) => !this.ids.includes(col));
105
+ const fields = this.fields(record, (col) => listed(this.options.updateProperties, col, !this.ids.includes(col)));
105
106
  if (fields.length === 0)
106
107
  throw new DatasourceError("Update requires at least one non-Id field");
107
108
  const statement = this.statements().update(fields, byWhere ?? this.idsWhere(record), (name, value) => this.cell(name, value, byWhere === undefined));
@@ -127,8 +128,15 @@ export class BatchCommandIBulkWriteStrategy {
127
128
  const row = objects.reverseConvert(item);
128
129
  return this.options.rowConverter ? this.options.rowConverter.reverseConvert(row) : row;
129
130
  };
131
+ writable = (key) => {
132
+ const columns = this.statements().readColumns;
133
+ const map = this.options.propertyMappings;
134
+ return (columns.length === 0 ||
135
+ columns.includes(key) ||
136
+ (map !== undefined && columns.some((name) => map.map(name) === key)));
137
+ };
130
138
  fields = (record, include) => Object.entries(record)
131
- .filter(([key, value]) => include(key) && value !== null && value !== undefined)
139
+ .filter(([key, value]) => include(key) && this.writable(key) && value !== null && value !== undefined)
132
140
  .sort(([left], [right]) => left.localeCompare(right))
133
141
  .map(([name, value]) => ({ name, value: this.cell(name, value, true) }));
134
142
  cell = (property, value, fieldsApplied) => fieldsApplied
@@ -12,6 +12,8 @@ import type { IReadonlyEnrichmentStrategy } from "./IReadonlyEnrichmentStrategy.
12
12
  import type { IReadonlyRepository } from "./IReadonlyRepository.js";
13
13
  export declare class CRUDRepository<T = Cells> extends ReadonlyRepository<T> implements ICRUDRepository<T> {
14
14
  readonly ids: readonly string[];
15
+ private readonly createProperties?;
16
+ private readonly updateProperties?;
15
17
  private readonly crudStatements;
16
18
  private readonly tree;
17
19
  private readonly write;
@@ -11,8 +11,14 @@ import { UnitOfWorkTransaction } from "./UnitOfWorkTransaction.js";
11
11
  import { RepositoryTree } from "./RepositoryTree.js";
12
12
  import { RepositoryTreeNode } from "./RepositoryTreeNode.js";
13
13
  const assigned = (value) => value !== null && value !== "" && value !== 0 && value !== 0n;
14
- const fieldsOf = (record, include, cell, enrichmentInto) => Object.entries(record)
15
- .filter(([key, value]) => include(key) && !enrichmentInto(key) && value !== null && value !== undefined)
14
+ const listed = (list, col, fallback) => list === undefined ? fallback : list.includes(col);
15
+ const writable = (key, columns, column) => columns.length === 0 || columns.includes(key) || columns.some((name) => column(name) === key);
16
+ const fieldsOf = (record, include, cell, enrichmentInto, columns, column) => Object.entries(record)
17
+ .filter(([key, value]) => include(key) &&
18
+ writable(key, columns, column) &&
19
+ !enrichmentInto(key) &&
20
+ value !== null &&
21
+ value !== undefined)
16
22
  .sort(([left], [right]) => left.localeCompare(right))
17
23
  .map(([name, value]) => ({ name, value: cell(name, value, true) }));
18
24
  const isCells = (id) => typeof id === "object" && id !== null;
@@ -29,6 +35,8 @@ const identified = (row, column) => {
29
35
  const scalarOf = (value) => value === undefined || value === null || typeof value === "object" ? undefined : value;
30
36
  export class CRUDRepository extends ReadonlyRepository {
31
37
  ids;
38
+ createProperties;
39
+ updateProperties;
32
40
  crudStatements;
33
41
  tree;
34
42
  write;
@@ -40,6 +48,8 @@ export class CRUDRepository extends ReadonlyRepository {
40
48
  const opened = repositoryParts(typeOrConnection, options);
41
49
  super(opened.built);
42
50
  this.ids = opened.built.ids;
51
+ this.createProperties = options.createProperties;
52
+ this.updateProperties = options.updateProperties;
43
53
  this.crudStatements = opened.statements;
44
54
  this.tree = new RepositoryTree(new RepositoryTreeNode(this, ""));
45
55
  this.write = options.write ?? new DefaultWriteEnrichmentStrategy();
@@ -101,7 +111,7 @@ export class CRUDRepository extends ReadonlyRepository {
101
111
  readSingleById = async (id) => this.readSingle(this.byId(id));
102
112
  insert = async (item) => {
103
113
  const record = this.reverseConvert(item);
104
- const fields = fieldsOf(record, (col) => !this.ids.includes(col) || assigned(record[col] ?? null), this.cell, this.enrichmentInto);
114
+ const fields = fieldsOf(record, (col) => listed(this.createProperties, col, !this.ids.includes(col) || assigned(record[col] ?? null)), this.cell, this.enrichmentInto, this.crudStatements.readColumns, this.column);
105
115
  const statement = this.crudStatements.insert(fields);
106
116
  const response = await execute(this.command(), statement, statement.fields);
107
117
  if (this.ids.length === 1 && !fields.some((field) => field.name === this.ids[0]))
@@ -136,7 +146,7 @@ export class CRUDRepository extends ReadonlyRepository {
136
146
  idValue = (item) => scalarOf(item[this.ids[0]]);
137
147
  save = async (item, byWhere) => {
138
148
  const record = this.reverseConvert(item);
139
- const fields = fieldsOf(record, (col) => !this.ids.includes(col), this.cell, this.enrichmentInto);
149
+ const fields = fieldsOf(record, (col) => listed(this.updateProperties, col, !this.ids.includes(col)), this.cell, this.enrichmentInto, this.crudStatements.readColumns, this.column);
140
150
  if (fields.length === 0)
141
151
  throw new DatasourceError("Update requires at least one non-Id field");
142
152
  const statement = this.crudStatements.update(fields, byWhere ?? this.idWhere(record), (name, value) => this.cell(name, value, byWhere === undefined));
@@ -149,7 +159,7 @@ export class CRUDRepository extends ReadonlyRepository {
149
159
  const parameters = listed.length
150
160
  ? listed
151
161
  : DefaultStatementTextRenderer.instance.render(statement).includes("$")
152
- ? fieldsOf(record, () => true, this.cell, this.enrichmentInto)
162
+ ? fieldsOf(record, () => true, this.cell, this.enrichmentInto, this.crudStatements.readColumns, this.column)
153
163
  : [];
154
164
  return execute(this.command(), statement, parameters);
155
165
  };
@@ -3,5 +3,7 @@ import type { Cells } from "./converters/Cell.js";
3
3
  import type { IWriteEnrichmentStrategy } from "./IWriteEnrichmentStrategy.js";
4
4
  export type CRUDRepositoryOptions<T = Cells> = ReadonlyRepositoryMappingOptions<T> & {
5
5
  ids?: string[];
6
+ createProperties?: string[];
7
+ updateProperties?: string[];
6
8
  write?: IWriteEnrichmentStrategy<T>;
7
9
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deterministic-code/datasources",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",