j-templates 8.0.14 → 8.0.16

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.
@@ -39,7 +39,7 @@ export interface IDiffTreeConstructor {
39
39
  * positionally in the same order, so each parameter can be typed at the call site instead of
40
40
  * cast out of a generic read.
41
41
  */
42
- export type DiffTreeProjectionFunc = (...values: any[]) => any;
42
+ export type DiffTreeProjectionFunc = (keys: string[], ...values: any[]) => any;
43
43
  /**
44
44
  * A projection's declaration: the dot-separated paths it reads (a plain tree path, an
45
45
  * entity's key, or another projection's `$projection_<id>` key for chaining) and the
@@ -160,7 +160,14 @@ function BuildProjectionOrder(projections) {
160
160
  throw new Error(`DiffTree projection "${id}" is not defined`);
161
161
  state.set(id, "visiting");
162
162
  for (let x = 0; x < def.reads.length; x++) {
163
- const root = def.reads[x].split(".", 1)[0];
163
+ const read = def.reads[x];
164
+ const root = read.split(".", 1)[0];
165
+ if (root.endsWith("*") && x !== def.reads.length - 1)
166
+ throw `Wildcard reads only supported as the final read: ${root}`;
167
+ if (root.endsWith("*") && root.includes("."))
168
+ throw `Wildcard reads do not support dot nesting: ${root}`;
169
+ if (root.startsWith(PROJECTION_PREFIX) && read.endsWith("*"))
170
+ throw `Projection keys do not support wildcard reads: ${root}`;
164
171
  if (root.startsWith(PROJECTION_PREFIX))
165
172
  Visit(root.slice(PROJECTION_PREFIX.length), stack.concat(id));
166
173
  }
@@ -203,17 +210,31 @@ function RunProjections(source, keyFunc, projections, memo) {
203
210
  const diffResult = [];
204
211
  for (let x = 0; x < projections.length; x++) {
205
212
  const { id, reads, projection } = projections[x];
206
- const values = new Array(reads.length);
213
+ const values = [];
214
+ const keys = [];
207
215
  let allPathsExist = true;
208
- for (let y = 0; allPathsExist && y < reads.length; y++) {
209
- const [value, found] = GetPathValue(source, reads[y]);
216
+ let y = 0;
217
+ for (; allPathsExist && y < reads.length && !reads[y].endsWith("*"); y++) {
218
+ const read = reads[y];
219
+ const [value, found] = GetPathValue(source, read);
210
220
  allPathsExist = found;
211
- values[y] = (found && CreateSnapshot(source, keyFunc, value)) || value;
221
+ keys.push(read);
222
+ values.push((found && CreateSnapshot(source, keyFunc, value)) || value);
223
+ }
224
+ if (y < reads.length && reads[y].endsWith("*")) {
225
+ const prefix = reads[y].slice(0, reads[y].length - 1);
226
+ const matchedKeys = Object.keys(source).filter(key => key.startsWith(prefix));
227
+ for (let z = 0; z < matchedKeys.length; z++) {
228
+ const [value, found] = GetPathValue(source, matchedKeys[z]);
229
+ allPathsExist = allPathsExist && found;
230
+ keys.push(matchedKeys[z]);
231
+ values.push((found && CreateSnapshot(source, keyFunc, value)) || value);
232
+ }
212
233
  }
213
234
  if (allPathsExist) {
214
235
  const priorValues = memo.get(id);
215
236
  if (!ArraysEqual(priorValues, values)) {
216
- const result = projection(...values);
237
+ const result = projection(keys, ...values);
217
238
  memo.set(id, values);
218
239
  // The same diff-and-apply UpdateSource uses for any other write, so a keyed entity
219
240
  // embedded in a projection's result is flattened to its own root like any other write,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "j-templates",
3
- "version": "8.0.14",
3
+ "version": "8.0.16",
4
4
  "description": "j-templates",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/TypesInCode/jTemplates",