@player-ui/player 0.8.0--canary.307.9621 → 0.8.0-next.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 (214) hide show
  1. package/dist/Player.native.js +11630 -0
  2. package/dist/Player.native.js.map +1 -0
  3. package/dist/cjs/index.cjs +5626 -0
  4. package/dist/cjs/index.cjs.map +1 -0
  5. package/dist/{index.esm.js → index.legacy-esm.js} +2044 -1667
  6. package/dist/{index.cjs.js → index.mjs} +2052 -1761
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +29 -63
  9. package/src/__tests__/data.test.ts +498 -0
  10. package/src/__tests__/flow.test.ts +312 -0
  11. package/src/__tests__/helpers/action-exp.plugin.ts +22 -0
  12. package/src/__tests__/helpers/actions.flow.ts +67 -0
  13. package/src/__tests__/helpers/binding.plugin.ts +125 -0
  14. package/src/__tests__/helpers/expression.plugin.ts +88 -0
  15. package/src/__tests__/helpers/transform-plugin.ts +19 -0
  16. package/src/__tests__/helpers/validation.flow.ts +56 -0
  17. package/src/__tests__/player.test.ts +597 -0
  18. package/src/__tests__/string-resolver.test.ts +186 -0
  19. package/src/__tests__/validation.test.ts +3555 -0
  20. package/src/__tests__/view.test.ts +715 -0
  21. package/src/binding/__tests__/binding.test.ts +113 -0
  22. package/src/binding/__tests__/index.test.ts +208 -0
  23. package/src/binding/__tests__/resolver.test.ts +83 -0
  24. package/src/binding/binding.ts +6 -6
  25. package/src/binding/index.ts +34 -34
  26. package/src/binding/resolver.ts +19 -19
  27. package/src/binding/utils.ts +7 -7
  28. package/src/binding-grammar/__tests__/parser.test.ts +64 -0
  29. package/src/binding-grammar/__tests__/test-utils/ast-cases.ts +198 -0
  30. package/src/binding-grammar/__tests__/test-utils/perf-test.ts +66 -0
  31. package/src/binding-grammar/ast.ts +11 -11
  32. package/src/binding-grammar/custom/index.ts +19 -22
  33. package/src/binding-grammar/ebnf/index.ts +20 -21
  34. package/src/binding-grammar/ebnf/types.ts +13 -13
  35. package/src/binding-grammar/index.ts +4 -4
  36. package/src/binding-grammar/parsimmon/index.ts +14 -14
  37. package/src/controllers/constants/__tests__/index.test.ts +106 -0
  38. package/src/controllers/constants/index.ts +3 -3
  39. package/src/controllers/constants/utils.ts +4 -4
  40. package/src/controllers/data/controller.ts +22 -22
  41. package/src/controllers/data/index.ts +1 -1
  42. package/src/controllers/data/utils.ts +7 -7
  43. package/src/controllers/flow/__tests__/controller.test.ts +195 -0
  44. package/src/controllers/flow/__tests__/flow.test.ts +381 -0
  45. package/src/controllers/flow/controller.ts +13 -13
  46. package/src/controllers/flow/flow.ts +23 -23
  47. package/src/controllers/flow/index.ts +2 -2
  48. package/src/controllers/index.ts +5 -5
  49. package/src/controllers/validation/binding-tracker.ts +71 -59
  50. package/src/controllers/validation/controller.ts +104 -104
  51. package/src/controllers/validation/index.ts +2 -2
  52. package/src/controllers/view/asset-transform.ts +20 -20
  53. package/src/controllers/view/controller.ts +27 -27
  54. package/src/controllers/view/index.ts +4 -4
  55. package/src/controllers/view/store.ts +3 -3
  56. package/src/controllers/view/types.ts +7 -7
  57. package/src/data/__tests__/__snapshots__/dependency-tracker.test.ts.snap +64 -0
  58. package/src/data/__tests__/dependency-tracker.test.ts +146 -0
  59. package/src/data/__tests__/local-model.test.ts +46 -0
  60. package/src/data/__tests__/model.test.ts +78 -0
  61. package/src/data/dependency-tracker.ts +16 -16
  62. package/src/data/index.ts +4 -4
  63. package/src/data/local-model.ts +6 -6
  64. package/src/data/model.ts +17 -17
  65. package/src/data/noop-model.ts +1 -1
  66. package/src/expressions/__tests__/__snapshots__/parser.test.ts.snap +854 -0
  67. package/src/expressions/__tests__/evaluator-functions.test.ts +47 -0
  68. package/src/expressions/__tests__/evaluator.test.ts +410 -0
  69. package/src/expressions/__tests__/parser.test.ts +115 -0
  70. package/src/expressions/__tests__/utils.test.ts +44 -0
  71. package/src/expressions/evaluator-functions.ts +6 -6
  72. package/src/expressions/evaluator.ts +71 -67
  73. package/src/expressions/index.ts +4 -4
  74. package/src/expressions/parser.ts +102 -105
  75. package/src/expressions/types.ts +29 -21
  76. package/src/expressions/utils.ts +32 -21
  77. package/src/index.ts +13 -13
  78. package/src/logger/__tests__/consoleLogger.test.ts +46 -0
  79. package/src/logger/__tests__/noopLogger.test.ts +13 -0
  80. package/src/logger/__tests__/proxyLogger.test.ts +31 -0
  81. package/src/logger/__tests__/tapableLogger.test.ts +41 -0
  82. package/src/logger/consoleLogger.ts +9 -9
  83. package/src/logger/index.ts +5 -5
  84. package/src/logger/noopLogger.ts +1 -1
  85. package/src/logger/proxyLogger.ts +6 -6
  86. package/src/logger/tapableLogger.ts +7 -7
  87. package/src/logger/types.ts +2 -2
  88. package/src/player.ts +60 -58
  89. package/src/plugins/default-exp-plugin.ts +10 -10
  90. package/src/plugins/default-view-plugin.ts +29 -0
  91. package/src/plugins/flow-exp-plugin.ts +6 -6
  92. package/src/schema/__tests__/schema.test.ts +243 -0
  93. package/src/schema/index.ts +2 -2
  94. package/src/schema/schema.ts +24 -24
  95. package/src/schema/types.ts +4 -4
  96. package/src/string-resolver/__tests__/index.test.ts +361 -0
  97. package/src/string-resolver/index.ts +17 -17
  98. package/src/types.ts +17 -17
  99. package/src/utils/__tests__/replaceParams.test.ts +33 -0
  100. package/src/utils/index.ts +1 -1
  101. package/src/utils/replaceParams.ts +1 -1
  102. package/src/validator/__tests__/binding-map-splice.test.ts +53 -0
  103. package/src/validator/__tests__/validation-middleware.test.ts +127 -0
  104. package/src/validator/binding-map-splice.ts +5 -5
  105. package/src/validator/index.ts +4 -4
  106. package/src/validator/registry.ts +1 -1
  107. package/src/validator/types.ts +13 -13
  108. package/src/validator/validation-middleware.ts +15 -15
  109. package/src/view/__tests__/view.immutable.test.ts +269 -0
  110. package/src/view/__tests__/view.test.ts +959 -0
  111. package/src/view/builder/index.test.ts +69 -0
  112. package/src/view/builder/index.ts +3 -3
  113. package/src/view/index.ts +5 -5
  114. package/src/view/parser/__tests__/__snapshots__/parser.test.ts.snap +394 -0
  115. package/src/view/parser/__tests__/parser.test.ts +264 -0
  116. package/src/view/parser/index.ts +43 -33
  117. package/src/view/parser/types.ts +11 -11
  118. package/src/view/parser/utils.ts +5 -5
  119. package/src/view/plugins/__tests__/__snapshots__/template.test.ts.snap +278 -0
  120. package/src/view/plugins/__tests__/applicability.test.ts +265 -0
  121. package/src/view/plugins/__tests__/string.test.ts +122 -0
  122. package/src/view/plugins/__tests__/template.test.ts +724 -0
  123. package/src/view/plugins/applicability.ts +19 -19
  124. package/src/view/plugins/index.ts +4 -5
  125. package/src/view/plugins/options.ts +1 -1
  126. package/src/view/plugins/string-resolver.ts +22 -22
  127. package/src/view/plugins/switch.ts +22 -23
  128. package/src/view/plugins/template-plugin.ts +26 -27
  129. package/src/view/resolver/__tests__/dependencies.test.ts +321 -0
  130. package/src/view/resolver/__tests__/edgecases.test.ts +626 -0
  131. package/src/view/resolver/index.ts +42 -42
  132. package/src/view/resolver/types.ts +21 -20
  133. package/src/view/resolver/utils.ts +9 -9
  134. package/src/view/view.ts +32 -22
  135. package/types/binding/binding.d.ts +50 -0
  136. package/types/binding/index.d.ts +29 -0
  137. package/types/binding/resolver.d.ts +26 -0
  138. package/types/binding/utils.d.ts +12 -0
  139. package/types/binding-grammar/ast.d.ts +67 -0
  140. package/types/binding-grammar/custom/index.d.ts +4 -0
  141. package/types/binding-grammar/ebnf/index.d.ts +4 -0
  142. package/types/binding-grammar/ebnf/types.d.ts +75 -0
  143. package/types/binding-grammar/index.d.ts +5 -0
  144. package/types/binding-grammar/parsimmon/index.d.ts +4 -0
  145. package/types/controllers/constants/index.d.ts +45 -0
  146. package/types/controllers/constants/utils.d.ts +6 -0
  147. package/types/controllers/data/controller.d.ts +45 -0
  148. package/types/controllers/data/index.d.ts +2 -0
  149. package/types/controllers/data/utils.d.ts +14 -0
  150. package/types/controllers/flow/controller.d.ts +25 -0
  151. package/types/controllers/flow/flow.d.ts +50 -0
  152. package/types/controllers/flow/index.d.ts +3 -0
  153. package/types/controllers/index.d.ts +6 -0
  154. package/types/controllers/validation/binding-tracker.d.ts +32 -0
  155. package/types/controllers/validation/controller.d.ts +151 -0
  156. package/types/controllers/validation/index.d.ts +3 -0
  157. package/types/controllers/view/asset-transform.d.ts +19 -0
  158. package/types/controllers/view/controller.d.ts +37 -0
  159. package/types/controllers/view/index.d.ts +5 -0
  160. package/types/controllers/view/store.d.ts +20 -0
  161. package/types/controllers/view/types.d.ts +16 -0
  162. package/types/data/dependency-tracker.d.ts +49 -0
  163. package/types/data/index.d.ts +5 -0
  164. package/types/data/local-model.d.ts +16 -0
  165. package/types/data/model.d.ts +86 -0
  166. package/types/data/noop-model.d.ts +13 -0
  167. package/types/expressions/evaluator-functions.d.ts +15 -0
  168. package/types/expressions/evaluator.d.ts +52 -0
  169. package/types/expressions/index.d.ts +5 -0
  170. package/types/expressions/parser.d.ts +10 -0
  171. package/types/expressions/types.d.ts +144 -0
  172. package/types/expressions/utils.d.ts +12 -0
  173. package/types/index.d.ts +14 -0
  174. package/types/logger/consoleLogger.d.ts +17 -0
  175. package/types/logger/index.d.ts +6 -0
  176. package/types/logger/noopLogger.d.ts +10 -0
  177. package/types/logger/proxyLogger.d.ts +15 -0
  178. package/types/logger/tapableLogger.d.ts +23 -0
  179. package/types/logger/types.d.ts +6 -0
  180. package/types/player.d.ts +101 -0
  181. package/types/plugins/default-exp-plugin.d.ts +9 -0
  182. package/types/plugins/default-view-plugin.d.ts +9 -0
  183. package/types/plugins/flow-exp-plugin.d.ts +11 -0
  184. package/types/schema/index.d.ts +3 -0
  185. package/types/schema/schema.d.ts +36 -0
  186. package/types/schema/types.d.ts +38 -0
  187. package/types/string-resolver/index.d.ts +30 -0
  188. package/types/types.d.ts +73 -0
  189. package/types/utils/index.d.ts +2 -0
  190. package/types/utils/replaceParams.d.ts +9 -0
  191. package/types/validator/binding-map-splice.d.ts +10 -0
  192. package/types/validator/index.d.ts +5 -0
  193. package/types/validator/registry.d.ts +11 -0
  194. package/types/validator/types.d.ts +53 -0
  195. package/types/validator/validation-middleware.d.ts +36 -0
  196. package/types/view/builder/index.d.ts +35 -0
  197. package/types/view/index.d.ts +6 -0
  198. package/types/view/parser/index.d.ts +52 -0
  199. package/types/view/parser/types.d.ts +109 -0
  200. package/types/view/parser/utils.d.ts +6 -0
  201. package/types/view/plugins/applicability.d.ts +10 -0
  202. package/types/view/plugins/index.d.ts +5 -0
  203. package/types/view/plugins/options.d.ts +4 -0
  204. package/types/view/plugins/string-resolver.d.ts +13 -0
  205. package/types/view/plugins/switch.d.ts +14 -0
  206. package/types/view/plugins/template-plugin.d.ts +33 -0
  207. package/types/view/resolver/index.d.ts +73 -0
  208. package/types/view/resolver/types.d.ts +129 -0
  209. package/types/view/resolver/utils.d.ts +11 -0
  210. package/types/view/view.d.ts +37 -0
  211. package/dist/index.d.ts +0 -1814
  212. package/dist/player.dev.js +0 -11472
  213. package/dist/player.prod.js +0 -2
  214. package/src/view/plugins/plugin.ts +0 -21
@@ -1,27 +1,27 @@
1
- import { SyncWaterfallHook, SyncHook } from 'tapable-ts';
2
- import { setIn, addLast, clone } from 'timm';
3
- import dlv from 'dlv';
4
- import { dequal } from 'dequal';
5
- import type { BindingInstance, BindingLike } from '../../binding';
1
+ import { SyncWaterfallHook, SyncHook } from "tapable-ts";
2
+ import { setIn, addLast, clone } from "timm";
3
+ import dlv from "dlv";
4
+ import { dequal } from "dequal";
5
+ import type { BindingInstance, BindingLike } from "../../binding";
6
6
  import type {
7
7
  DataModelOptions,
8
8
  DataModelWithParser,
9
9
  Updates,
10
- } from '../../data';
11
- import { DependencyModel, withParser } from '../../data';
12
- import type { Logger } from '../../logger';
13
- import type { Node } from '../parser';
14
- import { NodeType } from '../parser';
10
+ } from "../../data";
11
+ import { DependencyModel, withParser } from "../../data";
12
+ import type { Logger } from "../../logger";
13
+ import type { Node } from "../parser";
14
+ import { NodeType } from "../parser";
15
15
  import {
16
16
  caresAboutDataChanges,
17
17
  toNodeResolveOptions,
18
18
  unpackAndPush,
19
- } from './utils';
20
- import type { Resolve } from './types';
21
- import { getNodeID } from '../parser/utils';
19
+ } from "./utils";
20
+ import type { Resolve } from "./types";
21
+ import { getNodeID } from "../parser/utils";
22
22
 
23
- export * from './types';
24
- export * from './utils';
23
+ export * from "./types";
24
+ export * from "./utils";
25
25
 
26
26
  interface NodeUpdate extends Resolve.ResolvedNode {
27
27
  /** A flag to track if a node has changed since the last resolution */
@@ -40,7 +40,7 @@ const withContext = (model: DataModelWithParser): DataModelWithParser => {
40
40
 
41
41
  set: (
42
42
  transaction: [BindingLike, any][],
43
- options?: DataModelOptions
43
+ options?: DataModelOptions,
44
44
  ): Updates => {
45
45
  return model.set(transaction, {
46
46
  context: { model },
@@ -163,7 +163,7 @@ export class Resolver {
163
163
  resolveCache,
164
164
  toNodeResolveOptions(this.options),
165
165
  undefined,
166
- prevASTMap
166
+ prevASTMap,
167
167
  );
168
168
  this.resolveCache = resolveCache;
169
169
  this.hooks.afterUpdate.call(updated.value);
@@ -190,11 +190,11 @@ export class Resolver {
190
190
  if (isFirstUpdate) {
191
191
  if (node.type === NodeType.Asset || node.type === NodeType.View) {
192
192
  this.logger?.error(
193
- `Cache conflict: Found Asset/View nodes that have conflicting ids: ${id}, may cause cache issues.`
193
+ `Cache conflict: Found Asset/View nodes that have conflicting ids: ${id}, may cause cache issues.`,
194
194
  );
195
195
  } else if (node.type === NodeType.Value) {
196
196
  this.logger?.info(
197
- `Cache conflict: Found Value nodes that have conflicting ids: ${id}, may cause cache issues. To improve performance make value node IDs globally unique.`
197
+ `Cache conflict: Found Value nodes that have conflicting ids: ${id}, may cause cache issues. To improve performance make value node IDs globally unique.`,
198
198
  );
199
199
  }
200
200
  }
@@ -213,10 +213,10 @@ export class Resolver {
213
213
  const clonedNode = clone(node);
214
214
 
215
215
  Object.keys(clonedNode).forEach((key) => {
216
- if (key === 'parent') return;
216
+ if (key === "parent") return;
217
217
 
218
218
  const value = clonedNode[key];
219
- if (typeof value === 'object' && value !== null) {
219
+ if (typeof value === "object" && value !== null) {
220
220
  clonedNode[key] = Array.isArray(value) ? [...value] : { ...value };
221
221
  }
222
222
  });
@@ -231,13 +231,13 @@ export class Resolver {
231
231
  cacheUpdate: Map<Node.Node, Resolve.ResolvedNode>,
232
232
  options: Resolve.NodeResolveOptions,
233
233
  partiallyResolvedParent: Node.Node | undefined,
234
- prevASTMap: Map<Node.Node, Node.Node>
234
+ prevASTMap: Map<Node.Node, Node.Node>,
235
235
  ): NodeUpdate {
236
236
  const dependencyModel = new DependencyModel(options.data.model);
237
237
 
238
- dependencyModel.trackSubset('core');
238
+ dependencyModel.trackSubset("core");
239
239
  const depModelWithParser = withContext(
240
- withParser(dependencyModel, this.options.parseBinding)
240
+ withParser(dependencyModel, this.options.parseBinding),
241
241
  );
242
242
 
243
243
  const resolveOptions = this.hooks.resolveOptions.call(
@@ -251,7 +251,7 @@ export class Resolver {
251
251
  this.options.evaluator.evaluate(exp, { model: depModelWithParser }),
252
252
  node,
253
253
  },
254
- node
254
+ node,
255
255
  );
256
256
 
257
257
  const previousResult = this.getPreviousResult(node);
@@ -261,7 +261,7 @@ export class Resolver {
261
261
  const shouldUseLastValue = this.hooks.skipResolve.call(
262
262
  !dataChanged,
263
263
  node,
264
- resolveOptions
264
+ resolveOptions,
265
265
  );
266
266
 
267
267
  // Shallow clone the node so that changes to it during the resolve steps don't impact the original.
@@ -272,7 +272,7 @@ export class Resolver {
272
272
  };
273
273
  const resolvedAST = this.hooks.beforeResolve.call(
274
274
  clonedNode,
275
- resolveOptions
275
+ resolveOptions,
276
276
  ) ?? {
277
277
  type: NodeType.Empty,
278
278
  };
@@ -292,7 +292,7 @@ export class Resolver {
292
292
  const repopulateASTMapFromCache = (
293
293
  resolvedNode: Resolve.ResolvedNode,
294
294
  AST: Node.Node,
295
- ASTParent: Node.Node | undefined
295
+ ASTParent: Node.Node | undefined,
296
296
  ) => {
297
297
  const { node: resolvedASTLocal } = resolvedNode;
298
298
  this.ASTMap.set(resolvedASTLocal, AST);
@@ -312,13 +312,13 @@ export class Resolver {
312
312
  repopulateASTMapFromCache(
313
313
  previousChildResult,
314
314
  originalChildNode,
315
- AST
315
+ AST,
316
316
  );
317
317
  };
318
318
 
319
- if ('children' in resolvedASTLocal) {
319
+ if ("children" in resolvedASTLocal) {
320
320
  resolvedASTLocal.children?.forEach(({ value: childAST }) =>
321
- handleChildNode(childAST)
321
+ handleChildNode(childAST),
322
322
  );
323
323
  } else if (resolvedASTLocal.type === NodeType.MultiNode) {
324
324
  resolvedASTLocal.values.forEach(handleChildNode);
@@ -344,7 +344,7 @@ export class Resolver {
344
344
  let resolved = this.hooks.resolve.call(
345
345
  undefined,
346
346
  resolvedAST,
347
- resolveOptions
347
+ resolveOptions,
348
348
  );
349
349
 
350
350
  let updated = !dequal(previousResult?.value, resolved);
@@ -354,9 +354,9 @@ export class Resolver {
354
354
  }
355
355
 
356
356
  const childDependencies = new Set<BindingInstance>();
357
- dependencyModel.trackSubset('children');
357
+ dependencyModel.trackSubset("children");
358
358
 
359
- if ('children' in resolvedAST) {
359
+ if ("children" in resolvedAST) {
360
360
  const newChildren = resolvedAST.children?.map((child) => {
361
361
  const computedChildTree = this.computeTree(
362
362
  child.value,
@@ -365,7 +365,7 @@ export class Resolver {
365
365
  cacheUpdate,
366
366
  resolveOptions,
367
367
  resolvedAST,
368
- prevASTMap
368
+ prevASTMap,
369
369
  );
370
370
  const {
371
371
  dependencies: childTreeDeps,
@@ -380,7 +380,7 @@ export class Resolver {
380
380
  if (childNode.type === NodeType.MultiNode && !childNode.override) {
381
381
  const arr = addLast(
382
382
  dlv(resolved, child.path as any[], []),
383
- childValue
383
+ childValue,
384
384
  );
385
385
  resolved = setIn(resolved, child.path, arr);
386
386
  } else {
@@ -408,7 +408,7 @@ export class Resolver {
408
408
  cacheUpdate,
409
409
  resolveOptions,
410
410
  resolvedAST,
411
- prevASTMap
411
+ prevASTMap,
412
412
  );
413
413
 
414
414
  if (mTree.value !== undefined && mTree.value !== null) {
@@ -425,7 +425,7 @@ export class Resolver {
425
425
  }
426
426
 
427
427
  mTree.dependencies.forEach((bindingDep) =>
428
- childDependencies.add(bindingDep)
428
+ childDependencies.add(bindingDep),
429
429
  );
430
430
 
431
431
  updated = updated || mTree.updated;
@@ -438,17 +438,17 @@ export class Resolver {
438
438
  }
439
439
 
440
440
  childDependencies.forEach((bindingDep) =>
441
- dependencyModel.addChildReadDep(bindingDep)
441
+ dependencyModel.addChildReadDep(bindingDep),
442
442
  );
443
443
 
444
- dependencyModel.trackSubset('core');
444
+ dependencyModel.trackSubset("core");
445
445
  if (previousResult && !updated) {
446
446
  resolved = previousResult?.value;
447
447
  }
448
448
 
449
449
  resolved = this.hooks.afterResolve.call(resolved, resolvedAST, {
450
450
  ...resolveOptions,
451
- getDependencies: (scope?: 'core' | 'children') =>
451
+ getDependencies: (scope?: "core" | "children") =>
452
452
  dependencyModel.getDependencies(scope),
453
453
  });
454
454
 
@@ -465,7 +465,7 @@ export class Resolver {
465
465
  this.hooks.afterNodeUpdate.call(
466
466
  node,
467
467
  isNestedMultiNode ? partiallyResolvedParent?.parent : rawParent,
468
- update
468
+ update,
469
469
  );
470
470
  cacheUpdate.set(node, update);
471
471
 
@@ -2,24 +2,24 @@ import type {
2
2
  Schema,
3
3
  Formatting,
4
4
  Validation as ValidationTypes,
5
- } from '@player-ui/types';
5
+ } from "@player-ui/types";
6
6
  import type {
7
7
  BindingInstance,
8
8
  BindingLike,
9
9
  BindingFactory,
10
- } from '../../binding';
10
+ } from "../../binding";
11
11
  import type {
12
12
  DataModelWithParser,
13
13
  DataModelImpl,
14
14
  DataModelOptions,
15
- } from '../../data';
16
- import type { ConstantsProvider } from '../../controllers/constants';
17
- import type { TransitionFunction } from '../../controllers';
18
- import type { ExpressionEvaluator, ExpressionType } from '../../expressions';
19
- import type { ValidationResponse } from '../../validator';
20
- import type { Logger } from '../../logger';
21
- import type { SchemaController } from '../../schema';
22
- import type { Node } from '../parser';
15
+ } from "../../data";
16
+ import type { ConstantsProvider } from "../../controllers/constants";
17
+ import type { TransitionFunction } from "../../controllers";
18
+ import type { ExpressionEvaluator, ExpressionType } from "../../expressions";
19
+ import type { ValidationResponse } from "../../validator";
20
+ import type { Logger } from "../../logger";
21
+ import type { SchemaController } from "../../schema";
22
+ import type { Node } from "../parser";
23
23
 
24
24
  export interface ValidationGetResolveOptions {
25
25
  /**
@@ -33,6 +33,7 @@ export interface PlayerUtils {
33
33
  findPlugin<Plugin = unknown>(symbol: symbol): Plugin | undefined;
34
34
  }
35
35
 
36
+ // eslint-disable-next-line @typescript-eslint/no-namespace
36
37
  export declare namespace Resolve {
37
38
  export interface Validation {
38
39
  /** Fetch the data-type for the given binding */
@@ -40,7 +41,7 @@ export declare namespace Resolve {
40
41
 
41
42
  /** Get all currently applicable validation errors */
42
43
  getAll(
43
- options?: ValidationGetResolveOptions
44
+ options?: ValidationGetResolveOptions,
44
45
  ): Map<BindingInstance, ValidationResponse> | undefined;
45
46
 
46
47
  /** Internal Method to lookup if there is a validation for the given binding */
@@ -48,12 +49,12 @@ export declare namespace Resolve {
48
49
  | {
49
50
  /** Get the validation for the given binding */
50
51
  get: (
51
- options?: ValidationGetResolveOptions
52
+ options?: ValidationGetResolveOptions,
52
53
  ) => ValidationResponse | undefined;
53
54
 
54
55
  /** Get all validations for the given binding */
55
56
  getAll: (
56
- options?: ValidationGetResolveOptions
57
+ options?: ValidationGetResolveOptions,
57
58
  ) => Array<ValidationResponse>;
58
59
  }
59
60
  | undefined;
@@ -64,7 +65,7 @@ export declare namespace Resolve {
64
65
  options?: {
65
66
  /** If this binding should also be tracked for validations */
66
67
  track?: boolean;
67
- } & ValidationGetResolveOptions
68
+ } & ValidationGetResolveOptions,
68
69
  ): ValidationResponse | undefined;
69
70
 
70
71
  getValidationsForBinding(
@@ -72,12 +73,12 @@ export declare namespace Resolve {
72
73
  options?: {
73
74
  /** If this binding should also be tracked for validations */
74
75
  track?: boolean;
75
- } & ValidationGetResolveOptions
76
+ } & ValidationGetResolveOptions,
76
77
  ): Array<ValidationResponse>;
77
78
 
78
79
  /** Get errors for all children regardless of section */
79
80
  getChildren(
80
- type?: ValidationTypes.DisplayTarget
81
+ type?: ValidationTypes.DisplayTarget,
81
82
  ): Array<ValidationResponse>;
82
83
 
83
84
  /** Get errors for all children solely in this section */
@@ -89,7 +90,7 @@ export declare namespace Resolve {
89
90
  /** Register node as a section */
90
91
  register: (options?: {
91
92
  /** While type of Display Target group it should register as */
92
- type: Exclude<ValidationTypes.DisplayTarget, 'field'>;
93
+ type: Exclude<ValidationTypes.DisplayTarget, "field">;
93
94
  }) => void;
94
95
  }
95
96
 
@@ -141,7 +142,7 @@ export declare namespace Resolve {
141
142
  data: NodeDataOptions;
142
143
 
143
144
  /** The data dependencies that were requested during the resolution */
144
- getDependencies?(scope?: 'core' | 'children'): Set<BindingInstance>;
145
+ getDependencies?(scope?: "core" | "children"): Set<BindingInstance>;
145
146
 
146
147
  /** original node */
147
148
  node?: Node.Node;
@@ -180,13 +181,13 @@ export declare namespace Resolve {
180
181
 
181
182
  export type NodeTransformFunction = (
182
183
  node: Node.Node,
183
- options: NodeResolveOptions
184
+ options: NodeResolveOptions,
184
185
  ) => Node.Node | null;
185
186
 
186
187
  export type NodeResolveFunction = (
187
188
  value: any,
188
189
  node: Node.Node,
189
- options: NodeResolveOptions
190
+ options: NodeResolveOptions,
190
191
  ) => any;
191
192
 
192
193
  export interface Plugin {
@@ -1,12 +1,12 @@
1
- import type { BindingInstance, BindingLike } from '../../binding';
2
- import { isBinding } from '../../binding';
3
- import type { ExpressionType } from '../../expressions';
4
- import type { Resolve } from './types';
1
+ import type { BindingInstance, BindingLike } from "../../binding";
2
+ import { isBinding } from "../../binding";
3
+ import type { ExpressionType } from "../../expressions";
4
+ import type { Resolve } from "./types";
5
5
 
6
6
  /** Check to see if and of the data-changes affect the given dependencies */
7
7
  export function caresAboutDataChanges(
8
8
  dataChanges?: Set<BindingInstance>,
9
- dependencies?: Set<BindingInstance>
9
+ dependencies?: Set<BindingInstance>,
10
10
  ) {
11
11
  if (!dataChanges || !dependencies) {
12
12
  return true;
@@ -20,15 +20,15 @@ export function caresAboutDataChanges(
20
20
  (dep) =>
21
21
  !!dataChangeArray.find(
22
22
  (change) =>
23
- change === dep || change.contains(dep) || dep.contains(change)
24
- )
23
+ change === dep || change.contains(dep) || dep.contains(change),
24
+ ),
25
25
  ) !== undefined
26
26
  );
27
27
  }
28
28
 
29
29
  /** Convert the options object for a resolver to one for a node */
30
30
  export function toNodeResolveOptions(
31
- resolverOptions: Resolve.ResolverOptions
31
+ resolverOptions: Resolve.ResolverOptions,
32
32
  ): Resolve.NodeResolveOptions {
33
33
  return {
34
34
  ...resolverOptions,
@@ -47,7 +47,7 @@ export function toNodeResolveOptions(
47
47
  isBinding(bindingLike)
48
48
  ? bindingLike
49
49
  : resolverOptions.parseBinding(bindingLike),
50
- value
50
+ value,
51
51
  )
52
52
  : value,
53
53
  },
package/src/view/view.ts CHANGED
@@ -1,18 +1,18 @@
1
- import { SyncHook } from 'tapable-ts';
2
- import type { View as ViewType } from '@player-ui/types';
3
- import type { BindingInstance, BindingFactory } from '../binding';
4
- import type { ValidationProvider, ValidationObject } from '../validator';
5
- import type { Logger } from '../logger';
6
- import type { Resolve } from './resolver';
7
- import { Resolver, toNodeResolveOptions } from './resolver';
8
- import type { Node } from './parser';
9
- import { Parser } from './parser';
1
+ import { SyncHook } from "tapable-ts";
2
+ import type { View as ViewType } from "@player-ui/types";
3
+ import type { BindingInstance, BindingFactory } from "../binding";
4
+ import type { ValidationProvider, ValidationObject } from "../validator";
5
+ import type { Logger } from "../logger";
6
+ import type { Resolve } from "./resolver";
7
+ import { Resolver, toNodeResolveOptions } from "./resolver";
8
+ import type { Node } from "./parser";
9
+ import { Parser } from "./parser";
10
10
  import {
11
11
  TemplatePlugin,
12
12
  StringResolverPlugin,
13
13
  ApplicabilityPlugin,
14
14
  SwitchPlugin,
15
- } from './plugins';
15
+ } from "./plugins";
16
16
 
17
17
  /**
18
18
  * Manages the view level validations
@@ -36,7 +36,7 @@ class CrossfieldProvider implements ValidationProvider {
36
36
 
37
37
  if (!Array.isArray(xfieldRefs)) {
38
38
  this.logger?.warn(
39
- `Unable to register view validations for id: ${contentView.id}. 'validation' property must be an Array.`
39
+ `Unable to register view validations for id: ${contentView.id}. 'validation' property must be an Array.`,
40
40
  );
41
41
 
42
42
  return;
@@ -49,8 +49,8 @@ class CrossfieldProvider implements ValidationProvider {
49
49
  // x-field validations by default are triggered by navigating away from the page
50
50
  // the reference can also override that _or_ the severity
51
51
  const withDefaults: ValidationObject = {
52
- trigger: 'navigation',
53
- severity: 'error',
52
+ trigger: "navigation",
53
+ severity: "error",
54
54
  ...vRef,
55
55
  };
56
56
 
@@ -83,6 +83,7 @@ export class ViewInstance implements ValidationProvider {
83
83
  onUpdate: new SyncHook<[ViewType]>(),
84
84
  parser: new SyncHook<[Parser]>(),
85
85
  resolver: new SyncHook<[Resolver]>(),
86
+ onTemplatePluginCreated: new SyncHook<[TemplatePlugin]>(),
86
87
  templatePlugin: new SyncHook<[TemplatePlugin]>(),
87
88
  };
88
89
 
@@ -93,7 +94,7 @@ export class ViewInstance implements ValidationProvider {
93
94
 
94
95
  private validationProvider?: CrossfieldProvider;
95
96
 
96
- private templatePlugin: TemplatePlugin;
97
+ private templatePlugin: TemplatePlugin | undefined;
97
98
 
98
99
  // TODO might want to add a version/timestamp to this to compare updates
99
100
  public lastUpdate: Record<string, any> | undefined;
@@ -101,12 +102,9 @@ export class ViewInstance implements ValidationProvider {
101
102
  constructor(initialView: ViewType, resolverOptions: Resolve.ResolverOptions) {
102
103
  this.initialView = initialView;
103
104
  this.resolverOptions = resolverOptions;
104
- const pluginOptions = toNodeResolveOptions(resolverOptions);
105
- new SwitchPlugin(pluginOptions).apply(this);
106
- new ApplicabilityPlugin().apply(this);
107
- new StringResolverPlugin().apply(this);
108
- this.templatePlugin = new TemplatePlugin(pluginOptions);
109
- this.templatePlugin.apply(this);
105
+ this.hooks.onTemplatePluginCreated.tap("view", (templatePlugin) => {
106
+ this.templatePlugin = templatePlugin;
107
+ });
110
108
  }
111
109
 
112
110
  public updateAsync() {
@@ -121,10 +119,16 @@ export class ViewInstance implements ValidationProvider {
121
119
  this.validationProvider = new CrossfieldProvider(
122
120
  this.initialView,
123
121
  this.resolverOptions.parseBinding,
124
- this.resolverOptions.logger
122
+ this.resolverOptions.logger,
125
123
  );
126
124
 
127
- this.hooks.templatePlugin.call(this.templatePlugin);
125
+ if (this.templatePlugin) {
126
+ this.hooks.templatePlugin.call(this.templatePlugin);
127
+ } else {
128
+ this.resolverOptions.logger?.warn(
129
+ "templatePlugin not set for View, legacy templates may not work",
130
+ );
131
+ }
128
132
 
129
133
  const parser = new Parser();
130
134
  this.hooks.parser.call(parser);
@@ -153,3 +157,9 @@ export class ViewInstance implements ValidationProvider {
153
157
  return this.validationProvider?.getValidationsForBinding(binding);
154
158
  }
155
159
  }
160
+
161
+ /** A plugin for a view */
162
+ export interface ViewPlugin {
163
+ /** Called with a view instance */
164
+ apply(view: ViewInstance): void;
165
+ }
@@ -0,0 +1,50 @@
1
+ export interface BindingParserOptions {
2
+ /** Get the value for a specific binding */
3
+ get: (binding: BindingInstance) => any;
4
+ /**
5
+ * Set the values for bindings.
6
+ * This is used when the query syntax needs to modify an object
7
+ */
8
+ set: (transaction: Array<[BindingInstance, any]>) => void;
9
+ /**
10
+ * Get the result of evaluating an expression
11
+ */
12
+ evaluate: (exp: string) => any;
13
+ /**
14
+ * Without readOnly, if a binding such as this is used: arr[key='does not exist'],
15
+ * then an object with that key will be created.
16
+ * This is done to make assignment such as arr[key='abc'].val = 'foo' work smoothly.
17
+ * Setting readOnly to true will prevent this behavior, avoiding unintended data changes.
18
+ */
19
+ readOnly?: boolean;
20
+ }
21
+ export type Getter = (path: BindingInstance) => any;
22
+ export type RawBindingSegment = number | string;
23
+ export type RawBinding = string | RawBindingSegment[];
24
+ export type BindingLike = RawBinding | BindingInstance;
25
+ export type BindingFactory = (raw: RawBinding, options?: Partial<BindingParserOptions>) => BindingInstance;
26
+ /**
27
+ * A path in the data model
28
+ */
29
+ export declare class BindingInstance {
30
+ private split;
31
+ private joined;
32
+ private factory;
33
+ constructor(raw: RawBinding, factory?: (rawBinding: RawBinding) => BindingInstance);
34
+ asArray(): RawBindingSegment[];
35
+ asString(): string;
36
+ /**
37
+ * Check to see if the given binding is a sub-path of the current one
38
+ */
39
+ contains(binding: BindingInstance): boolean;
40
+ relative(binding: BindingInstance): RawBindingSegment[];
41
+ parent(): BindingInstance;
42
+ key(): RawBindingSegment;
43
+ /**
44
+ * This is a utility method to get a binding that is a descendent of this binding
45
+ *
46
+ * @param relative - The relative path to descend to
47
+ */
48
+ descendent(relative: BindingLike): BindingInstance;
49
+ }
50
+ //# sourceMappingURL=binding.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { SyncBailHook, SyncWaterfallHook } from "tapable-ts";
2
+ import type { AnyNode } from "../binding-grammar/index";
3
+ import type { BindingParserOptions, BindingLike } from "./binding";
4
+ import { BindingInstance } from "./binding";
5
+ import type { NormalizedResult, ResolveBindingASTOptions } from "./resolver";
6
+ export * from "./utils";
7
+ export * from "./binding";
8
+ export declare const SIMPLE_BINDING_REGEX: RegExp;
9
+ export declare const BINDING_BRACKETS_REGEX: RegExp;
10
+ type BeforeResolveNodeContext = Required<NormalizedResult> & ResolveBindingASTOptions;
11
+ /** A parser for creating bindings from a string */
12
+ export declare class BindingParser {
13
+ private cache;
14
+ private parseCache;
15
+ private parserOptions;
16
+ hooks: {
17
+ skipOptimization: SyncBailHook<[string], boolean, Record<string, any>>;
18
+ beforeResolveNode: SyncWaterfallHook<[AnyNode, BeforeResolveNodeContext], Record<string, any>>;
19
+ };
20
+ constructor(options?: Partial<BindingParserOptions>);
21
+ /**
22
+ * Takes a binding path, parses it, and returns an equivalent, normalized
23
+ * representation of that path.
24
+ */
25
+ private normalizePath;
26
+ private getBindingForNormalizedResult;
27
+ parse(rawBinding: BindingLike, overrides?: Partial<BindingParserOptions>): BindingInstance;
28
+ }
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,26 @@
1
+ import type { SyncWaterfallHook } from "tapable-ts";
2
+ import type { PathNode, AnyNode } from "../binding-grammar";
3
+ export interface NormalizedResult {
4
+ /** The normalized path */
5
+ path: Array<string | number>;
6
+ /** Any new updates that need to happen for this binding to be resolved */
7
+ updates?: Record<string, any>;
8
+ }
9
+ export interface ResolveBindingASTOptions {
10
+ /** Get the value of the model at the given path */
11
+ getValue: (path: Array<string | number>) => any;
12
+ /** Convert the value into valid path segments */
13
+ convertToPath: (value: any) => string;
14
+ /** Convert the value into valid path segments */
15
+ evaluate: (exp: string) => any;
16
+ }
17
+ export interface ResolveBindingASTHooks {
18
+ /** A hook for transforming a node before fully resolving it */
19
+ beforeResolveNode: SyncWaterfallHook<[
20
+ AnyNode,
21
+ Required<NormalizedResult> & ResolveBindingASTOptions
22
+ ]>;
23
+ }
24
+ /** Given a binding AST, resolve it */
25
+ export declare function resolveBindingAST(bindingPathNode: PathNode, options: ResolveBindingASTOptions, hooks?: ResolveBindingASTHooks): NormalizedResult;
26
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1,12 @@
1
+ import type { BindingLike, BindingInstance } from "./binding";
2
+ /** Check if the parameter representing a binding is already of the Binding class */
3
+ export declare function isBinding(binding: BindingLike): binding is BindingInstance;
4
+ /** Convert the string to an int if you can, otherwise just return the original string */
5
+ export declare function maybeConvertToNum(i: string): string | number;
6
+ /**
7
+ * utility to convert binding into binding segments.
8
+ */
9
+ export declare function getBindingSegments(binding: BindingLike): Array<string | number>;
10
+ /** Like _.findIndex, but ignores types */
11
+ export declare function findInArray<T extends Record<string | number, object>>(array: Array<T>, key: string | number, value: T): number | undefined;
12
+ //# sourceMappingURL=utils.d.ts.map