@player-ui/computed-properties-plugin 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.
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ function _array_like_to_array(arr, len) {
3
+ if (len == null || len > arr.length) len = arr.length;
4
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
5
+ return arr2;
6
+ }
7
+ function _array_without_holes(arr) {
8
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
9
+ }
10
+ function _class_call_check(instance, Constructor) {
11
+ if (!(instance instanceof Constructor)) {
12
+ throw new TypeError("Cannot call a class as a function");
13
+ }
14
+ }
15
+ function _defineProperties(target, props) {
16
+ for(var i = 0; i < props.length; i++){
17
+ var descriptor = props[i];
18
+ descriptor.enumerable = descriptor.enumerable || false;
19
+ descriptor.configurable = true;
20
+ if ("value" in descriptor) descriptor.writable = true;
21
+ Object.defineProperty(target, descriptor.key, descriptor);
22
+ }
23
+ }
24
+ function _create_class(Constructor, protoProps, staticProps) {
25
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
26
+ if (staticProps) _defineProperties(Constructor, staticProps);
27
+ return Constructor;
28
+ }
29
+ function _iterable_to_array(iter) {
30
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
31
+ }
32
+ function _non_iterable_spread() {
33
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
34
+ }
35
+ function _to_consumable_array(arr) {
36
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
37
+ }
38
+ function _unsupported_iterable_to_array(o, minLen) {
39
+ if (!o) return;
40
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
41
+ var n = Object.prototype.toString.call(o).slice(8, -1);
42
+ if (n === "Object" && o.constructor) n = o.constructor.name;
43
+ if (n === "Map" || n === "Set") return Array.from(n);
44
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
45
+ }
46
+ var ComputedPropertiesPlugin = function() {
47
+ var __defProp = Object.defineProperty;
48
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
49
+ var __getOwnPropNames = Object.getOwnPropertyNames;
50
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
51
+ var __export = function(target, all) {
52
+ for(var name in all)__defProp(target, name, {
53
+ get: all[name],
54
+ enumerable: true
55
+ });
56
+ };
57
+ var __copyProps = function(to, from, except, desc) {
58
+ if (from && typeof from === "object" || typeof from === "function") {
59
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
60
+ try {
61
+ var _loop = function() {
62
+ var key = _step.value;
63
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
64
+ get: function() {
65
+ return from[key];
66
+ },
67
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
68
+ });
69
+ };
70
+ for(var _iterator = __getOwnPropNames(from)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_loop();
71
+ } catch (err) {
72
+ _didIteratorError = true;
73
+ _iteratorError = err;
74
+ } finally{
75
+ try {
76
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
77
+ _iterator.return();
78
+ }
79
+ } finally{
80
+ if (_didIteratorError) {
81
+ throw _iteratorError;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ return to;
87
+ };
88
+ var __toCommonJS = function(mod) {
89
+ return __copyProps(__defProp({}, "__esModule", {
90
+ value: true
91
+ }), mod);
92
+ };
93
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts
94
+ var src_exports = {};
95
+ __export(src_exports, {
96
+ ComputedPropertiesPlugin: function() {
97
+ return ComputedPropertiesPlugin;
98
+ }
99
+ });
100
+ var ComputedPropertiesPlugin = /*#__PURE__*/ function() {
101
+ function ComputedPropertiesPlugin() {
102
+ _class_call_check(this, ComputedPropertiesPlugin);
103
+ this.name = "ComputedProperties";
104
+ }
105
+ _create_class(ComputedPropertiesPlugin, [
106
+ {
107
+ key: "apply",
108
+ value: function apply(player) {
109
+ var _this = this;
110
+ var schemaController;
111
+ var expressionEvaluator;
112
+ var getExpressionType = function(binding) {
113
+ var dataType = schemaController === null || schemaController === void 0 ? void 0 : schemaController.getType(binding);
114
+ if ((dataType === null || dataType === void 0 ? void 0 : dataType.type) === "Expression") {
115
+ return dataType;
116
+ }
117
+ };
118
+ var computedPropertyMiddleware = {
119
+ name: this.name,
120
+ get: function get(binding, options, next) {
121
+ var expType = getExpressionType(binding);
122
+ if (expType) {
123
+ var exp = expType.exp;
124
+ var result = exp && (expressionEvaluator === null || expressionEvaluator === void 0 ? void 0 : expressionEvaluator.evaluate(exp, options === null || options === void 0 ? void 0 : options.context));
125
+ return result !== null && result !== void 0 ? result : expType.default;
126
+ }
127
+ return next === null || next === void 0 ? void 0 : next.get(binding, options);
128
+ },
129
+ set: function set(transaction, options, next) {
130
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
131
+ try {
132
+ for(var _iterator = transaction[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
133
+ var setOperation = _step.value;
134
+ if (getExpressionType(setOperation[0])) {
135
+ throw new Error("Invalid 'set' operation on computed property: ".concat(setOperation[0].asString()));
136
+ }
137
+ }
138
+ } catch (err) {
139
+ _didIteratorError = true;
140
+ _iteratorError = err;
141
+ } finally{
142
+ try {
143
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
144
+ _iterator.return();
145
+ }
146
+ } finally{
147
+ if (_didIteratorError) {
148
+ throw _iteratorError;
149
+ }
150
+ }
151
+ }
152
+ var _next_set;
153
+ return (_next_set = next === null || next === void 0 ? void 0 : next.set(transaction, options)) !== null && _next_set !== void 0 ? _next_set : [];
154
+ },
155
+ delete: function _delete(binding, options, next) {
156
+ if (getExpressionType(binding)) {
157
+ throw new Error("Invalid 'delete' operation on computed property: ".concat(binding.asString()));
158
+ }
159
+ return next === null || next === void 0 ? void 0 : next.delete(binding, options);
160
+ }
161
+ };
162
+ player.hooks.dataController.tap(this.name, function(dataController) {
163
+ dataController.hooks.resolveDataStages.tap(_this.name, function(dataPipeline) {
164
+ return _to_consumable_array(dataPipeline).concat([
165
+ computedPropertyMiddleware
166
+ ]);
167
+ });
168
+ });
169
+ player.hooks.schema.tap(this.name, function(schema) {
170
+ schemaController = schema;
171
+ });
172
+ player.hooks.expressionEvaluator.tap(this.name, function(evaluator) {
173
+ expressionEvaluator = evaluator;
174
+ });
175
+ }
176
+ }
177
+ ]);
178
+ return ComputedPropertiesPlugin;
179
+ }();
180
+ return __toCommonJS(src_exports);
181
+ }();
182
+ //# sourceMappingURL=index.global.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAqBO,MAAM,2BAAN,MAAuD;AAAA,IAAvD;AACL,kBAAO;AAAA;AAAA,IAEP,MAAM,QAAgB;AAIpB,UAAI;AACJ,UAAI;AAGJ,YAAM,oBAAoB,CACxB,YACmC;AAEnC,cAAM,WAAW,kBAAkB,QAAQ,OAAO;AAElD,YAAI,UAAU,SAAS,cAAc;AACnC,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,6BAAkD;AAAA,QACtD,MAAM,KAAK;AAAA,QACX,IAAI,SAAS,SAAS,MAAM;AAC1B,gBAAM,UAAU,kBAAkB,OAAO;AAEzC,cAAI,SAAS;AACX,kBAAM,EAAE,IAAI,IAAI;AAChB,kBAAM,SACJ,OAAO,qBAAqB,SAAS,KAAK,SAAS,OAAO;AAE5D,mBAAO,UAAU,QAAQ;AAAA,UAC3B;AAEA,iBAAO,MAAM,IAAI,SAAS,OAAO;AAAA,QACnC;AAAA,QACA,IAAI,aAAa,SAAS,MAAe;AACvC,qBAAW,gBAAgB,aAAa;AACtC,gBAAI,kBAAkB,aAAa,CAAC,CAAC,GAAG;AACtC,oBAAM,IAAI;AAAA,gBACR,iDAAiD,aAAa,CAAC,EAAE,SAAS,CAAC;AAAA,cAC7E;AAAA,YACF;AAAA,UACF;AAEA,iBAAO,MAAM,IAAI,aAAa,OAAO,KAAK,CAAC;AAAA,QAC7C;AAAA,QACA,OAAO,SAAS,SAAS,MAAM;AAC7B,cAAI,kBAAkB,OAAO,GAAG;AAC9B,kBAAM,IAAI;AAAA,cACR,oDAAoD,QAAQ,SAAS,CAAC;AAAA,YACxE;AAAA,UACF;AAEA,iBAAO,MAAM,OAAO,SAAS,OAAO;AAAA,QACtC;AAAA,MACF;AAEA,aAAO,MAAM,eAAe,IAAI,KAAK,MAAM,CAAC,mBAAmB;AAC7D,uBAAe,MAAM,kBAAkB,IAAI,KAAK,MAAM,CAAC,iBAAiB;AACtE,iBAAO,CAAC,GAAG,cAAc,0BAA0B;AAAA,QACrD,CAAC;AAAA,MACH,CAAC;AAED,aAAO,MAAM,OAAO,IAAI,KAAK,MAAM,CAAC,WAAW;AAC7C,2BAAmB;AAAA,MACrB,CAAC;AAED,aAAO,MAAM,oBAAoB,IAAI,KAAK,MAAM,CAAC,cAAc;AAC7D,8BAAsB;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF","sourcesContent":["import type {\n Player,\n PlayerPlugin,\n ExpressionEvaluator,\n Schema,\n Expression,\n DataModelMiddleware,\n Updates,\n SchemaController,\n BindingInstance,\n} from \"@player-ui/player\";\n\nexport interface ExpressionDataType extends Schema.DataType<\"Expression\"> {\n /** The expression to evaluate to compute the value of this node */\n exp?: Expression;\n}\n\n/**\n * A player plugin to manage beacon events.\n * It automatically keeps track of the current user's view, and adds additional metaData to each beacon event.\n */\nexport class ComputedPropertiesPlugin implements PlayerPlugin {\n name = \"ComputedProperties\";\n\n apply(player: Player) {\n // Inject a middleware into the data-model to intercept any calls to an expression type in the schema\n // Calls to `set` throw an error. Calls to `get` compute the value and return if or default\n\n let schemaController: SchemaController | undefined;\n let expressionEvaluator: ExpressionEvaluator | undefined;\n\n /** Look up the data-type of the binding, and check for an Expression type */\n const getExpressionType = (\n binding: BindingInstance,\n ): ExpressionDataType | undefined => {\n // Check to see if the data-type of the binding is an `Expression`\n const dataType = schemaController?.getType(binding);\n\n if (dataType?.type === \"Expression\") {\n return dataType as ExpressionDataType;\n }\n };\n\n const computedPropertyMiddleware: DataModelMiddleware = {\n name: this.name,\n get(binding, options, next) {\n const expType = getExpressionType(binding);\n\n if (expType) {\n const { exp } = expType;\n const result =\n exp && expressionEvaluator?.evaluate(exp, options?.context);\n\n return result ?? expType.default;\n }\n\n return next?.get(binding, options);\n },\n set(transaction, options, next): Updates {\n for (const setOperation of transaction) {\n if (getExpressionType(setOperation[0])) {\n throw new Error(\n `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`,\n );\n }\n }\n\n return next?.set(transaction, options) ?? [];\n },\n delete(binding, options, next) {\n if (getExpressionType(binding)) {\n throw new Error(\n `Invalid 'delete' operation on computed property: ${binding.asString()}`,\n );\n }\n\n return next?.delete(binding, options);\n },\n };\n\n player.hooks.dataController.tap(this.name, (dataController) => {\n dataController.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {\n return [...dataPipeline, computedPropertyMiddleware];\n });\n });\n\n player.hooks.schema.tap(this.name, (schema) => {\n schemaController = schema;\n });\n\n player.hooks.expressionEvaluator.tap(this.name, (evaluator) => {\n expressionEvaluator = evaluator;\n });\n }\n}\n"]}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ ComputedPropertiesPlugin: () => ComputedPropertiesPlugin
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+ var ComputedPropertiesPlugin = class {
27
+ constructor() {
28
+ this.name = "ComputedProperties";
29
+ }
30
+ apply(player) {
31
+ let schemaController;
32
+ let expressionEvaluator;
33
+ const getExpressionType = (binding) => {
34
+ const dataType = schemaController?.getType(binding);
35
+ if (dataType?.type === "Expression") {
36
+ return dataType;
37
+ }
38
+ };
39
+ const computedPropertyMiddleware = {
40
+ name: this.name,
41
+ get(binding, options, next) {
42
+ const expType = getExpressionType(binding);
43
+ if (expType) {
44
+ const { exp } = expType;
45
+ const result = exp && expressionEvaluator?.evaluate(exp, options?.context);
46
+ return result ?? expType.default;
47
+ }
48
+ return next?.get(binding, options);
49
+ },
50
+ set(transaction, options, next) {
51
+ for (const setOperation of transaction) {
52
+ if (getExpressionType(setOperation[0])) {
53
+ throw new Error(
54
+ `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`
55
+ );
56
+ }
57
+ }
58
+ return next?.set(transaction, options) ?? [];
59
+ },
60
+ delete(binding, options, next) {
61
+ if (getExpressionType(binding)) {
62
+ throw new Error(
63
+ `Invalid 'delete' operation on computed property: ${binding.asString()}`
64
+ );
65
+ }
66
+ return next?.delete(binding, options);
67
+ }
68
+ };
69
+ player.hooks.dataController.tap(this.name, (dataController) => {
70
+ dataController.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {
71
+ return [...dataPipeline, computedPropertyMiddleware];
72
+ });
73
+ });
74
+ player.hooks.schema.tap(this.name, (schema) => {
75
+ schemaController = schema;
76
+ });
77
+ player.hooks.expressionEvaluator.tap(this.name, (evaluator) => {
78
+ expressionEvaluator = evaluator;
79
+ });
80
+ }
81
+ };
82
+ // Annotate the CommonJS export names for ESM import in node:
83
+ 0 && (module.exports = {
84
+ ComputedPropertiesPlugin
85
+ });
86
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts"],"sourcesContent":["import type {\n Player,\n PlayerPlugin,\n ExpressionEvaluator,\n Schema,\n Expression,\n DataModelMiddleware,\n Updates,\n SchemaController,\n BindingInstance,\n} from \"@player-ui/player\";\n\nexport interface ExpressionDataType extends Schema.DataType<\"Expression\"> {\n /** The expression to evaluate to compute the value of this node */\n exp?: Expression;\n}\n\n/**\n * A player plugin to manage beacon events.\n * It automatically keeps track of the current user's view, and adds additional metaData to each beacon event.\n */\nexport class ComputedPropertiesPlugin implements PlayerPlugin {\n name = \"ComputedProperties\";\n\n apply(player: Player) {\n // Inject a middleware into the data-model to intercept any calls to an expression type in the schema\n // Calls to `set` throw an error. Calls to `get` compute the value and return if or default\n\n let schemaController: SchemaController | undefined;\n let expressionEvaluator: ExpressionEvaluator | undefined;\n\n /** Look up the data-type of the binding, and check for an Expression type */\n const getExpressionType = (\n binding: BindingInstance,\n ): ExpressionDataType | undefined => {\n // Check to see if the data-type of the binding is an `Expression`\n const dataType = schemaController?.getType(binding);\n\n if (dataType?.type === \"Expression\") {\n return dataType as ExpressionDataType;\n }\n };\n\n const computedPropertyMiddleware: DataModelMiddleware = {\n name: this.name,\n get(binding, options, next) {\n const expType = getExpressionType(binding);\n\n if (expType) {\n const { exp } = expType;\n const result =\n exp && expressionEvaluator?.evaluate(exp, options?.context);\n\n return result ?? expType.default;\n }\n\n return next?.get(binding, options);\n },\n set(transaction, options, next): Updates {\n for (const setOperation of transaction) {\n if (getExpressionType(setOperation[0])) {\n throw new Error(\n `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`,\n );\n }\n }\n\n return next?.set(transaction, options) ?? [];\n },\n delete(binding, options, next) {\n if (getExpressionType(binding)) {\n throw new Error(\n `Invalid 'delete' operation on computed property: ${binding.asString()}`,\n );\n }\n\n return next?.delete(binding, options);\n },\n };\n\n player.hooks.dataController.tap(this.name, (dataController) => {\n dataController.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {\n return [...dataPipeline, computedPropertyMiddleware];\n });\n });\n\n player.hooks.schema.tap(this.name, (schema) => {\n schemaController = schema;\n });\n\n player.hooks.expressionEvaluator.tap(this.name, (evaluator) => {\n expressionEvaluator = evaluator;\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBO,IAAM,2BAAN,MAAuD;AAAA,EAAvD;AACL,gBAAO;AAAA;AAAA,EAEP,MAAM,QAAgB;AAIpB,QAAI;AACJ,QAAI;AAGJ,UAAM,oBAAoB,CACxB,YACmC;AAEnC,YAAM,WAAW,kBAAkB,QAAQ,OAAO;AAElD,UAAI,UAAU,SAAS,cAAc;AACnC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,6BAAkD;AAAA,MACtD,MAAM,KAAK;AAAA,MACX,IAAI,SAAS,SAAS,MAAM;AAC1B,cAAM,UAAU,kBAAkB,OAAO;AAEzC,YAAI,SAAS;AACX,gBAAM,EAAE,IAAI,IAAI;AAChB,gBAAM,SACJ,OAAO,qBAAqB,SAAS,KAAK,SAAS,OAAO;AAE5D,iBAAO,UAAU,QAAQ;AAAA,QAC3B;AAEA,eAAO,MAAM,IAAI,SAAS,OAAO;AAAA,MACnC;AAAA,MACA,IAAI,aAAa,SAAS,MAAe;AACvC,mBAAW,gBAAgB,aAAa;AACtC,cAAI,kBAAkB,aAAa,CAAC,CAAC,GAAG;AACtC,kBAAM,IAAI;AAAA,cACR,iDAAiD,aAAa,CAAC,EAAE,SAAS,CAAC;AAAA,YAC7E;AAAA,UACF;AAAA,QACF;AAEA,eAAO,MAAM,IAAI,aAAa,OAAO,KAAK,CAAC;AAAA,MAC7C;AAAA,MACA,OAAO,SAAS,SAAS,MAAM;AAC7B,YAAI,kBAAkB,OAAO,GAAG;AAC9B,gBAAM,IAAI;AAAA,YACR,oDAAoD,QAAQ,SAAS,CAAC;AAAA,UACxE;AAAA,QACF;AAEA,eAAO,MAAM,OAAO,SAAS,OAAO;AAAA,MACtC;AAAA,IACF;AAEA,WAAO,MAAM,eAAe,IAAI,KAAK,MAAM,CAAC,mBAAmB;AAC7D,qBAAe,MAAM,kBAAkB,IAAI,KAAK,MAAM,CAAC,iBAAiB;AACtE,eAAO,CAAC,GAAG,cAAc,0BAA0B;AAAA,MACrD,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM,OAAO,IAAI,KAAK,MAAM,CAAC,WAAW;AAC7C,yBAAmB;AAAA,IACrB,CAAC;AAED,WAAO,MAAM,oBAAoB,IAAI,KAAK,MAAM,CAAC,cAAc;AAC7D,4BAAsB;AAAA,IACxB,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -1,4 +1,5 @@
1
- class ComputedPropertiesPlugin {
1
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts
2
+ var ComputedPropertiesPlugin = class {
2
3
  constructor() {
3
4
  this.name = "ComputedProperties";
4
5
  }
@@ -6,8 +7,8 @@ class ComputedPropertiesPlugin {
6
7
  let schemaController;
7
8
  let expressionEvaluator;
8
9
  const getExpressionType = (binding) => {
9
- const dataType = schemaController == null ? void 0 : schemaController.getType(binding);
10
- if ((dataType == null ? void 0 : dataType.type) === "Expression") {
10
+ const dataType = schemaController?.getType(binding);
11
+ if (dataType?.type === "Expression") {
11
12
  return dataType;
12
13
  }
13
14
  };
@@ -17,25 +18,28 @@ class ComputedPropertiesPlugin {
17
18
  const expType = getExpressionType(binding);
18
19
  if (expType) {
19
20
  const { exp } = expType;
20
- const result = exp && (expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp, options == null ? void 0 : options.context));
21
- return result != null ? result : expType.default;
21
+ const result = exp && expressionEvaluator?.evaluate(exp, options?.context);
22
+ return result ?? expType.default;
22
23
  }
23
- return next == null ? void 0 : next.get(binding, options);
24
+ return next?.get(binding, options);
24
25
  },
25
26
  set(transaction, options, next) {
26
- var _a;
27
27
  for (const setOperation of transaction) {
28
28
  if (getExpressionType(setOperation[0])) {
29
- throw new Error(`Invalid 'set' operation on computed property: ${setOperation[0].asString()}`);
29
+ throw new Error(
30
+ `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`
31
+ );
30
32
  }
31
33
  }
32
- return (_a = next == null ? void 0 : next.set(transaction, options)) != null ? _a : [];
34
+ return next?.set(transaction, options) ?? [];
33
35
  },
34
36
  delete(binding, options, next) {
35
37
  if (getExpressionType(binding)) {
36
- throw new Error(`Invalid 'delete' operation on computed property: ${binding.asString()}`);
38
+ throw new Error(
39
+ `Invalid 'delete' operation on computed property: ${binding.asString()}`
40
+ );
37
41
  }
38
- return next == null ? void 0 : next.delete(binding, options);
42
+ return next?.delete(binding, options);
39
43
  }
40
44
  };
41
45
  player.hooks.dataController.tap(this.name, (dataController) => {
@@ -50,7 +54,8 @@ class ComputedPropertiesPlugin {
50
54
  expressionEvaluator = evaluator;
51
55
  });
52
56
  }
53
- }
54
-
55
- export { ComputedPropertiesPlugin };
56
- //# sourceMappingURL=index.esm.js.map
57
+ };
58
+ export {
59
+ ComputedPropertiesPlugin
60
+ };
61
+ //# sourceMappingURL=index.mjs.map
@@ -1,8 +1,5 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- class ComputedPropertiesPlugin {
1
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts
2
+ var ComputedPropertiesPlugin = class {
6
3
  constructor() {
7
4
  this.name = "ComputedProperties";
8
5
  }
@@ -10,8 +7,8 @@ class ComputedPropertiesPlugin {
10
7
  let schemaController;
11
8
  let expressionEvaluator;
12
9
  const getExpressionType = (binding) => {
13
- const dataType = schemaController == null ? void 0 : schemaController.getType(binding);
14
- if ((dataType == null ? void 0 : dataType.type) === "Expression") {
10
+ const dataType = schemaController?.getType(binding);
11
+ if (dataType?.type === "Expression") {
15
12
  return dataType;
16
13
  }
17
14
  };
@@ -21,25 +18,28 @@ class ComputedPropertiesPlugin {
21
18
  const expType = getExpressionType(binding);
22
19
  if (expType) {
23
20
  const { exp } = expType;
24
- const result = exp && (expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp, options == null ? void 0 : options.context));
25
- return result != null ? result : expType.default;
21
+ const result = exp && expressionEvaluator?.evaluate(exp, options?.context);
22
+ return result ?? expType.default;
26
23
  }
27
- return next == null ? void 0 : next.get(binding, options);
24
+ return next?.get(binding, options);
28
25
  },
29
26
  set(transaction, options, next) {
30
- var _a;
31
27
  for (const setOperation of transaction) {
32
28
  if (getExpressionType(setOperation[0])) {
33
- throw new Error(`Invalid 'set' operation on computed property: ${setOperation[0].asString()}`);
29
+ throw new Error(
30
+ `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`
31
+ );
34
32
  }
35
33
  }
36
- return (_a = next == null ? void 0 : next.set(transaction, options)) != null ? _a : [];
34
+ return next?.set(transaction, options) ?? [];
37
35
  },
38
36
  delete(binding, options, next) {
39
37
  if (getExpressionType(binding)) {
40
- throw new Error(`Invalid 'delete' operation on computed property: ${binding.asString()}`);
38
+ throw new Error(
39
+ `Invalid 'delete' operation on computed property: ${binding.asString()}`
40
+ );
41
41
  }
42
- return next == null ? void 0 : next.delete(binding, options);
42
+ return next?.delete(binding, options);
43
43
  }
44
44
  };
45
45
  player.hooks.dataController.tap(this.name, (dataController) => {
@@ -54,7 +54,8 @@ class ComputedPropertiesPlugin {
54
54
  expressionEvaluator = evaluator;
55
55
  });
56
56
  }
57
- }
58
-
59
- exports.ComputedPropertiesPlugin = ComputedPropertiesPlugin;
60
- //# sourceMappingURL=index.cjs.js.map
57
+ };
58
+ export {
59
+ ComputedPropertiesPlugin
60
+ };
61
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/src/index.ts"],"sourcesContent":["import type {\n Player,\n PlayerPlugin,\n ExpressionEvaluator,\n Schema,\n Expression,\n DataModelMiddleware,\n Updates,\n SchemaController,\n BindingInstance,\n} from \"@player-ui/player\";\n\nexport interface ExpressionDataType extends Schema.DataType<\"Expression\"> {\n /** The expression to evaluate to compute the value of this node */\n exp?: Expression;\n}\n\n/**\n * A player plugin to manage beacon events.\n * It automatically keeps track of the current user's view, and adds additional metaData to each beacon event.\n */\nexport class ComputedPropertiesPlugin implements PlayerPlugin {\n name = \"ComputedProperties\";\n\n apply(player: Player) {\n // Inject a middleware into the data-model to intercept any calls to an expression type in the schema\n // Calls to `set` throw an error. Calls to `get` compute the value and return if or default\n\n let schemaController: SchemaController | undefined;\n let expressionEvaluator: ExpressionEvaluator | undefined;\n\n /** Look up the data-type of the binding, and check for an Expression type */\n const getExpressionType = (\n binding: BindingInstance,\n ): ExpressionDataType | undefined => {\n // Check to see if the data-type of the binding is an `Expression`\n const dataType = schemaController?.getType(binding);\n\n if (dataType?.type === \"Expression\") {\n return dataType as ExpressionDataType;\n }\n };\n\n const computedPropertyMiddleware: DataModelMiddleware = {\n name: this.name,\n get(binding, options, next) {\n const expType = getExpressionType(binding);\n\n if (expType) {\n const { exp } = expType;\n const result =\n exp && expressionEvaluator?.evaluate(exp, options?.context);\n\n return result ?? expType.default;\n }\n\n return next?.get(binding, options);\n },\n set(transaction, options, next): Updates {\n for (const setOperation of transaction) {\n if (getExpressionType(setOperation[0])) {\n throw new Error(\n `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`,\n );\n }\n }\n\n return next?.set(transaction, options) ?? [];\n },\n delete(binding, options, next) {\n if (getExpressionType(binding)) {\n throw new Error(\n `Invalid 'delete' operation on computed property: ${binding.asString()}`,\n );\n }\n\n return next?.delete(binding, options);\n },\n };\n\n player.hooks.dataController.tap(this.name, (dataController) => {\n dataController.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {\n return [...dataPipeline, computedPropertyMiddleware];\n });\n });\n\n player.hooks.schema.tap(this.name, (schema) => {\n schemaController = schema;\n });\n\n player.hooks.expressionEvaluator.tap(this.name, (evaluator) => {\n expressionEvaluator = evaluator;\n });\n }\n}\n"],"mappings":";AAqBO,IAAM,2BAAN,MAAuD;AAAA,EAAvD;AACL,gBAAO;AAAA;AAAA,EAEP,MAAM,QAAgB;AAIpB,QAAI;AACJ,QAAI;AAGJ,UAAM,oBAAoB,CACxB,YACmC;AAEnC,YAAM,WAAW,kBAAkB,QAAQ,OAAO;AAElD,UAAI,UAAU,SAAS,cAAc;AACnC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,6BAAkD;AAAA,MACtD,MAAM,KAAK;AAAA,MACX,IAAI,SAAS,SAAS,MAAM;AAC1B,cAAM,UAAU,kBAAkB,OAAO;AAEzC,YAAI,SAAS;AACX,gBAAM,EAAE,IAAI,IAAI;AAChB,gBAAM,SACJ,OAAO,qBAAqB,SAAS,KAAK,SAAS,OAAO;AAE5D,iBAAO,UAAU,QAAQ;AAAA,QAC3B;AAEA,eAAO,MAAM,IAAI,SAAS,OAAO;AAAA,MACnC;AAAA,MACA,IAAI,aAAa,SAAS,MAAe;AACvC,mBAAW,gBAAgB,aAAa;AACtC,cAAI,kBAAkB,aAAa,CAAC,CAAC,GAAG;AACtC,kBAAM,IAAI;AAAA,cACR,iDAAiD,aAAa,CAAC,EAAE,SAAS,CAAC;AAAA,YAC7E;AAAA,UACF;AAAA,QACF;AAEA,eAAO,MAAM,IAAI,aAAa,OAAO,KAAK,CAAC;AAAA,MAC7C;AAAA,MACA,OAAO,SAAS,SAAS,MAAM;AAC7B,YAAI,kBAAkB,OAAO,GAAG;AAC9B,gBAAM,IAAI;AAAA,YACR,oDAAoD,QAAQ,SAAS,CAAC;AAAA,UACxE;AAAA,QACF;AAEA,eAAO,MAAM,OAAO,SAAS,OAAO;AAAA,MACtC;AAAA,IACF;AAEA,WAAO,MAAM,eAAe,IAAI,KAAK,MAAM,CAAC,mBAAmB;AAC7D,qBAAe,MAAM,kBAAkB,IAAI,KAAK,MAAM,CAAC,iBAAiB;AACtE,eAAO,CAAC,GAAG,cAAc,0BAA0B;AAAA,MACrD,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM,OAAO,IAAI,KAAK,MAAM,CAAC,WAAW;AAC7C,yBAAmB;AAAA,IACrB,CAAC;AAED,WAAO,MAAM,oBAAoB,IAAI,KAAK,MAAM,CAAC,cAAc;AAC7D,4BAAsB;AAAA,IACxB,CAAC;AAAA,EACH;AACF;","names":[]}
package/package.json CHANGED
@@ -1,67 +1,37 @@
1
1
  {
2
2
  "name": "@player-ui/computed-properties-plugin",
3
- "version": "0.8.0--canary.307.9621",
4
- "private": false,
5
- "publishConfig": {
6
- "registry": "https://registry.npmjs.org"
7
- },
3
+ "version": "0.8.0-next.0",
4
+ "main": "dist/cjs/index.cjs",
8
5
  "peerDependencies": {
9
- "@player-ui/player": "0.8.0--canary.307.9621"
6
+ "@player-ui/player": "0.8.0-next.0"
10
7
  },
11
- "dependencies": {
12
- "tapable-ts": "^0.2.3",
13
- "@babel/runtime": "7.15.4"
8
+ "devDependencies": {
9
+ "@player-ui/asset-transform-plugin": "workspace:*",
10
+ "@player-ui/make-flow": "workspace:*",
11
+ "@player-ui/partial-match-registry": "workspace:*",
12
+ "@player-ui/common-expressions-plugin": "workspace:*",
13
+ "@player-ui/common-types-plugin": "workspace:*"
14
14
  },
15
- "main": "dist/index.cjs.js",
16
- "module": "dist/index.esm.js",
17
- "typings": "dist/index.d.ts",
15
+ "module": "dist/index.legacy-esm.js",
16
+ "types": "types/index.d.ts",
17
+ "bundle": "dist/ComputedPropertiesPlugin.native.js",
18
18
  "sideEffects": false,
19
- "license": "MIT",
20
- "repository": {
21
- "type": "git",
22
- "url": "https://github.com/player-ui/player-ui"
23
- },
24
- "bugs": {
25
- "url": "https://github.com/player-ui/player-ui/issues"
26
- },
27
- "homepage": "https://player-ui.github.io",
28
- "contributors": [
29
- {
30
- "name": "Adam Dierkens",
31
- "url": "https://github.com/adierkens"
32
- },
33
- {
34
- "name": "Spencer Hamm",
35
- "url": "https://github.com/spentacular"
36
- },
37
- {
38
- "name": "Harris Borawski",
39
- "url": "https://github.com/hborawski"
40
- },
41
- {
42
- "name": "Jeremiah Zucker",
43
- "url": "https://github.com/sugarmanz"
44
- },
45
- {
46
- "name": "Ketan Reddy",
47
- "url": "https://github.com/KetanReddy"
48
- },
49
- {
50
- "name": "Brocollie08",
51
- "url": "https://github.com/brocollie08"
52
- },
53
- {
54
- "name": "Kelly Harrop",
55
- "url": "https://github.com/kharrop"
56
- },
57
- {
58
- "name": "Alejandro Fimbres",
59
- "url": "https://github.com/lexfm"
60
- },
61
- {
62
- "name": "Rafael Campos",
63
- "url": "https://github.com/rafbcampos"
19
+ "exports": {
20
+ "./package.json": "./package.json",
21
+ "./dist/index.css": "./dist/index.css",
22
+ ".": {
23
+ "types": "./types/index.d.ts",
24
+ "import": "./dist/index.mjs",
25
+ "default": "./dist/cjs/index.cjs"
64
26
  }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "src",
31
+ "types"
65
32
  ],
66
- "bundle": "./dist/computed-properties-plugin.prod.js"
33
+ "dependencies": {
34
+ "tapable-ts": "^0.2.3",
35
+ "tslib": "^2.6.2"
36
+ }
67
37
  }
@@ -0,0 +1,219 @@
1
+ import { test, expect, vitest } from "vitest";
2
+ import type { InProgressState, Flow } from "@player-ui/player";
3
+ import { Player } from "@player-ui/player";
4
+ import { makeFlow } from "@player-ui/make-flow";
5
+ import { ComputedPropertiesPlugin } from "..";
6
+
7
+ const flowWithComputedValues = makeFlow({
8
+ id: "view-1",
9
+ type: "view",
10
+ value: "{{foo.bar.computedValue}}",
11
+ otherValue: "{{foo.bar.otherValue}}",
12
+ });
13
+
14
+ flowWithComputedValues.schema = {
15
+ ROOT: {
16
+ foo: {
17
+ type: "FooType",
18
+ },
19
+ },
20
+ FooType: {
21
+ bar: {
22
+ type: "BarType",
23
+ },
24
+ },
25
+ BarType: {
26
+ computedValue: {
27
+ type: "Expression",
28
+ exp: "1 + 2 + 3",
29
+ },
30
+ },
31
+ } as any;
32
+
33
+ flowWithComputedValues.data = {
34
+ foo: {
35
+ bar: {
36
+ otherValue: "not 6",
37
+ },
38
+ },
39
+ };
40
+
41
+ test("computes property values for Expression schema types", () => {
42
+ const player = new Player({ plugins: [new ComputedPropertiesPlugin()] });
43
+ player.start(flowWithComputedValues);
44
+
45
+ const currentState = player.getState() as InProgressState;
46
+
47
+ expect(currentState.controllers.view.currentView?.lastUpdate).toStrictEqual({
48
+ id: "view-1",
49
+ type: "view",
50
+ value: 6,
51
+ otherValue: "not 6",
52
+ });
53
+ });
54
+
55
+ test("throws an error if writing to a computed value", () => {
56
+ const player = new Player({ plugins: [new ComputedPropertiesPlugin()] });
57
+ player.start(flowWithComputedValues);
58
+
59
+ const state = player.getState() as InProgressState;
60
+
61
+ expect(() =>
62
+ state.controllers.data.set([["foo.bar.computedValue", "val"]]),
63
+ ).toThrowError(
64
+ "Invalid 'set' operation on computed property: foo.bar.computedValue",
65
+ );
66
+ });
67
+
68
+ test("sets fall through", () => {
69
+ const player = new Player({ plugins: [new ComputedPropertiesPlugin()] });
70
+ player.start(flowWithComputedValues);
71
+
72
+ const state = player.getState() as InProgressState;
73
+
74
+ expect(state.controllers.data.get("foo.bar.otherValue")).toBe("not 6");
75
+ state.controllers.data.set([["foo.bar.otherValue", "updated"]]);
76
+ expect(state.controllers.data.get("foo.bar.otherValue")).toBe("updated");
77
+ });
78
+
79
+ const flowWithComputedApplicability = makeFlow({
80
+ id: "view-1",
81
+ type: "view",
82
+ label: {
83
+ asset: {
84
+ applicability: "{{foo.computedValue}}",
85
+ id: "label",
86
+ type: "text",
87
+ value: "view label",
88
+ },
89
+ },
90
+ });
91
+
92
+ flowWithComputedApplicability.schema = {
93
+ ROOT: {
94
+ foo: {
95
+ type: "FooType",
96
+ },
97
+ },
98
+ FooType: {
99
+ computedValue: {
100
+ type: "Expression",
101
+ exp: '{{foo.type}} === "valid"',
102
+ },
103
+ },
104
+ };
105
+
106
+ flowWithComputedApplicability.data = {
107
+ foo: { type: "not-valid" },
108
+ };
109
+
110
+ test("updates work across computations", async () => {
111
+ const player = new Player({ plugins: [new ComputedPropertiesPlugin()] });
112
+ player.start(flowWithComputedApplicability);
113
+
114
+ const getView = () => {
115
+ return (player.getState() as InProgressState).controllers.view.currentView
116
+ ?.lastUpdate as any;
117
+ };
118
+
119
+ // The label should start off as not there
120
+
121
+ expect(getView().label).toBe(undefined);
122
+
123
+ (player.getState() as InProgressState).controllers.data.set([
124
+ ["foo.type", "valid"],
125
+ ]);
126
+
127
+ await vitest.waitFor(() =>
128
+ expect(getView().label).toStrictEqual({
129
+ asset: {
130
+ id: "label",
131
+ type: "text",
132
+ value: "view label",
133
+ },
134
+ }),
135
+ );
136
+
137
+ (player.getState() as InProgressState).controllers.data.set([
138
+ ["foo", { type: "not-valid" }],
139
+ ]);
140
+
141
+ await vitest.waitFor(() => expect(getView().label).toBe(undefined));
142
+ });
143
+
144
+ test("expressions update dependent expressions", async () => {
145
+ const flowWithDependentComputedValues: Flow = makeFlow({
146
+ views: [
147
+ {
148
+ id: "view-1",
149
+ type: "view",
150
+ computed: {
151
+ asset: {
152
+ id: "computed",
153
+ type: "text",
154
+ applicability: "{{foo.bar.computedValue}}",
155
+ },
156
+ },
157
+ dependent: {
158
+ asset: {
159
+ id: "dependent",
160
+ type: "text",
161
+ applicability: "{{foo.bar.dependentValue}}",
162
+ },
163
+ },
164
+ },
165
+ ],
166
+ data: {
167
+ foo: {
168
+ bar: {
169
+ sourceValue: false,
170
+ },
171
+ },
172
+ },
173
+ schema: {
174
+ ROOT: {
175
+ foo: {
176
+ type: "FooType",
177
+ },
178
+ },
179
+ FooType: {
180
+ bar: {
181
+ type: "BarType",
182
+ },
183
+ },
184
+ BarType: {
185
+ sourceValue: {
186
+ type: "boolean",
187
+ },
188
+ computedValue: {
189
+ type: "Expression",
190
+ exp: "{{foo.bar.sourceValue}} == true",
191
+ },
192
+ dependentValue: {
193
+ type: "Expression",
194
+ exp: "{{foo.bar.computedValue}} == false",
195
+ },
196
+ },
197
+ },
198
+ });
199
+ const player = new Player({ plugins: [new ComputedPropertiesPlugin()] });
200
+ player.start(flowWithDependentComputedValues);
201
+
202
+ const getView = () => {
203
+ return (player.getState() as InProgressState).controllers.view.currentView
204
+ ?.lastUpdate as any;
205
+ };
206
+
207
+ // The label should start off as not there
208
+
209
+ expect(getView().computed).toBeUndefined();
210
+ expect(getView().dependent).toBeDefined();
211
+
212
+ (player.getState() as InProgressState).controllers.data.set([
213
+ ["foo.bar.sourceValue", true],
214
+ ]);
215
+ await vitest.waitFor(() => {
216
+ expect(getView().computed).toBeDefined();
217
+ expect(getView().dependent).toBeUndefined();
218
+ });
219
+ });
@@ -0,0 +1,217 @@
1
+ import { test, expect, describe } from "vitest";
2
+ import { CommonExpressionsPlugin } from "@player-ui/common-expressions-plugin";
3
+ import { CommonTypesPlugin } from "@player-ui/common-types-plugin";
4
+ import { Registry } from "@player-ui/partial-match-registry";
5
+ import { AssetTransformPlugin } from "@player-ui/asset-transform-plugin";
6
+ import { makeFlow } from "@player-ui/make-flow";
7
+ import { Player } from "@player-ui/player";
8
+ import type {
9
+ Asset,
10
+ BindingInstance,
11
+ TransformFunction,
12
+ ValidationResponse,
13
+ } from "@player-ui/player";
14
+ import { ComputedPropertiesPlugin } from "..";
15
+
16
+ // This is a flow that uses computed properties for evaluating cross field validation
17
+ const flowWithComputedValidation = makeFlow({
18
+ id: "view-1",
19
+ type: "view",
20
+ template: [
21
+ {
22
+ data: "items",
23
+ output: "bindings",
24
+ value: "items._index_.isRelevant",
25
+ },
26
+ ],
27
+ validation: [
28
+ {
29
+ type: "expression",
30
+ ref: "items.0.isRelevant",
31
+ message: "Please select at least one item.",
32
+ exp: "{{expressions.SelectionValidation}}",
33
+ },
34
+ ],
35
+ });
36
+
37
+ flowWithComputedValidation.schema = {
38
+ ROOT: {
39
+ items: {
40
+ type: "ItemType",
41
+ isArray: true,
42
+ },
43
+ expressions: {
44
+ type: "ExpressionsType",
45
+ },
46
+ },
47
+ itemType: {
48
+ name: {
49
+ type: "TextType",
50
+ },
51
+ isRelevant: {
52
+ type: "BooleanType",
53
+ },
54
+ },
55
+ ExpressionsType: {
56
+ SelectionValidation: {
57
+ type: "Expression",
58
+ exp: 'findProperty({{items}}, "isRelevant", true, "isRelevant", false)',
59
+ },
60
+ },
61
+ };
62
+
63
+ flowWithComputedValidation.data = {
64
+ items: [
65
+ {
66
+ name: "One",
67
+ isRelevant: false,
68
+ },
69
+ {
70
+ name: "Two",
71
+ isRelevant: false,
72
+ },
73
+ ],
74
+ };
75
+
76
+ interface ValidationView extends Asset<"view"> {
77
+ /**
78
+ *
79
+ */
80
+ bindings: string[];
81
+ }
82
+
83
+ /**
84
+ *
85
+ */
86
+ const validationTrackerTransform: TransformFunction<
87
+ ValidationView,
88
+ ValidationView & {
89
+ /**
90
+ *
91
+ */
92
+ validation?: ValidationResponse;
93
+ }
94
+ > = (asset, options) => {
95
+ const { bindings } = asset;
96
+ let validation: ValidationResponse | undefined;
97
+
98
+ // Setup tracking on each binding
99
+ bindings.forEach((binding) => {
100
+ validation =
101
+ options.validation?.get(binding, { track: true }) ?? validation;
102
+ });
103
+
104
+ return {
105
+ ...asset,
106
+ validation,
107
+ };
108
+ };
109
+
110
+ describe("cross field validation can use computed properties", () => {
111
+ /**
112
+ *
113
+ */
114
+ const baseValidationTest = (dataUpdate: Record<string, any>) => async () => {
115
+ const player = new Player({
116
+ plugins: [
117
+ // necessary for data middleware to reference {{expressions}}
118
+ new ComputedPropertiesPlugin(),
119
+
120
+ // necessary for expression type validation
121
+ new CommonTypesPlugin(),
122
+ // necessary for findProperty
123
+ new CommonExpressionsPlugin(),
124
+
125
+ // necessary to track validations
126
+ new AssetTransformPlugin(
127
+ new Registry([[{ type: "view" }, validationTrackerTransform]]),
128
+ ),
129
+ ],
130
+ });
131
+
132
+ const result = player.start(flowWithComputedValidation);
133
+
134
+ /**
135
+ *
136
+ */
137
+ const getControllers = () => {
138
+ const state = player.getState();
139
+ if (state.status === "in-progress") {
140
+ return state.controllers;
141
+ }
142
+ };
143
+
144
+ /**
145
+ *
146
+ */
147
+ const getCurrentView = () => {
148
+ const controllers = getControllers();
149
+ return controllers ? controllers.view.currentView : undefined;
150
+ };
151
+
152
+ /**
153
+ *
154
+ */
155
+ const withValidations = (
156
+ assertions: (validations: {
157
+ /**
158
+ *
159
+ */
160
+ canTransition: boolean;
161
+ /**
162
+ *
163
+ */
164
+ validations?: Map<BindingInstance, ValidationResponse>;
165
+ }) => void,
166
+ ) => assertions(getControllers()!.validation.validateView()!);
167
+
168
+ expect(getCurrentView()?.initialView.id).toBe("view-1");
169
+
170
+ withValidations(({ canTransition, validations }) => {
171
+ expect(canTransition).toBe(false);
172
+ expect(validations?.size).toBe(1);
173
+ });
174
+
175
+ getControllers()?.flow.transition("Next");
176
+
177
+ // Transition fails do to blocking validation
178
+ expect(getCurrentView()?.initialView.id).toBe("view-1");
179
+
180
+ getControllers()?.data.set(dataUpdate);
181
+
182
+ withValidations(({ canTransition, validations }) => {
183
+ expect(canTransition).toBe(true);
184
+ expect(validations).toBeUndefined();
185
+ });
186
+
187
+ getControllers()?.flow.transition("Next");
188
+
189
+ const { endState } = await result;
190
+ expect(endState).toStrictEqual({
191
+ outcome: "done",
192
+ state_type: "END",
193
+ });
194
+ };
195
+
196
+ test(
197
+ "updating ref data should remove validation",
198
+ baseValidationTest({
199
+ "items.0.isRelevant": true,
200
+ }),
201
+ );
202
+
203
+ test(
204
+ "updating non-ref data should remove validation",
205
+ baseValidationTest({
206
+ "items.1.isRelevant": true,
207
+ }),
208
+ );
209
+
210
+ test(
211
+ "updating both should remove validation",
212
+ baseValidationTest({
213
+ "items.0.isRelevant": true,
214
+ "items.1.isRelevant": true,
215
+ }),
216
+ );
217
+ });
package/src/index.ts CHANGED
@@ -8,9 +8,9 @@ import type {
8
8
  Updates,
9
9
  SchemaController,
10
10
  BindingInstance,
11
- } from '@player-ui/player';
11
+ } from "@player-ui/player";
12
12
 
13
- export interface ExpressionDataType extends Schema.DataType<'Expression'> {
13
+ export interface ExpressionDataType extends Schema.DataType<"Expression"> {
14
14
  /** The expression to evaluate to compute the value of this node */
15
15
  exp?: Expression;
16
16
  }
@@ -20,7 +20,7 @@ export interface ExpressionDataType extends Schema.DataType<'Expression'> {
20
20
  * It automatically keeps track of the current user's view, and adds additional metaData to each beacon event.
21
21
  */
22
22
  export class ComputedPropertiesPlugin implements PlayerPlugin {
23
- name = 'ComputedProperties';
23
+ name = "ComputedProperties";
24
24
 
25
25
  apply(player: Player) {
26
26
  // Inject a middleware into the data-model to intercept any calls to an expression type in the schema
@@ -31,12 +31,12 @@ export class ComputedPropertiesPlugin implements PlayerPlugin {
31
31
 
32
32
  /** Look up the data-type of the binding, and check for an Expression type */
33
33
  const getExpressionType = (
34
- binding: BindingInstance
34
+ binding: BindingInstance,
35
35
  ): ExpressionDataType | undefined => {
36
36
  // Check to see if the data-type of the binding is an `Expression`
37
37
  const dataType = schemaController?.getType(binding);
38
38
 
39
- if (dataType?.type === 'Expression') {
39
+ if (dataType?.type === "Expression") {
40
40
  return dataType as ExpressionDataType;
41
41
  }
42
42
  };
@@ -60,7 +60,7 @@ export class ComputedPropertiesPlugin implements PlayerPlugin {
60
60
  for (const setOperation of transaction) {
61
61
  if (getExpressionType(setOperation[0])) {
62
62
  throw new Error(
63
- `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`
63
+ `Invalid 'set' operation on computed property: ${setOperation[0].asString()}`,
64
64
  );
65
65
  }
66
66
  }
@@ -70,7 +70,7 @@ export class ComputedPropertiesPlugin implements PlayerPlugin {
70
70
  delete(binding, options, next) {
71
71
  if (getExpressionType(binding)) {
72
72
  throw new Error(
73
- `Invalid 'delete' operation on computed property: ${binding.asString()}`
73
+ `Invalid 'delete' operation on computed property: ${binding.asString()}`,
74
74
  );
75
75
  }
76
76
 
@@ -1,6 +1,5 @@
1
- import { Schema, Expression, PlayerPlugin, Player } from '@player-ui/player';
2
-
3
- interface ExpressionDataType extends Schema.DataType<'Expression'> {
1
+ import type { Player, PlayerPlugin, Schema, Expression } from "@player-ui/player";
2
+ export interface ExpressionDataType extends Schema.DataType<"Expression"> {
4
3
  /** The expression to evaluate to compute the value of this node */
5
4
  exp?: Expression;
6
5
  }
@@ -8,9 +7,8 @@ interface ExpressionDataType extends Schema.DataType<'Expression'> {
8
7
  * A player plugin to manage beacon events.
9
8
  * It automatically keeps track of the current user's view, and adds additional metaData to each beacon event.
10
9
  */
11
- declare class ComputedPropertiesPlugin implements PlayerPlugin {
10
+ export declare class ComputedPropertiesPlugin implements PlayerPlugin {
12
11
  name: string;
13
12
  apply(player: Player): void;
14
13
  }
15
-
16
- export { ComputedPropertiesPlugin, ExpressionDataType };
14
+ //# sourceMappingURL=index.d.ts.map
@@ -1,170 +0,0 @@
1
- (function webpackUniversalModuleDefinition(root, factory) {
2
- if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory();
4
- else if(typeof define === 'function' && define.amd)
5
- define([], factory);
6
- else if(typeof exports === 'object')
7
- exports["ComputedPropertiesPlugin"] = factory();
8
- else
9
- root["ComputedPropertiesPlugin"] = factory();
10
- })(this, function() {
11
- return /******/ (function(modules) { // webpackBootstrap
12
- /******/ // The module cache
13
- /******/ var installedModules = {};
14
- /******/
15
- /******/ // The require function
16
- /******/ function __webpack_require__(moduleId) {
17
- /******/
18
- /******/ // Check if module is in cache
19
- /******/ if(installedModules[moduleId]) {
20
- /******/ return installedModules[moduleId].exports;
21
- /******/ }
22
- /******/ // Create a new module (and put it into the cache)
23
- /******/ var module = installedModules[moduleId] = {
24
- /******/ i: moduleId,
25
- /******/ l: false,
26
- /******/ exports: {}
27
- /******/ };
28
- /******/
29
- /******/ // Execute the module function
30
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31
- /******/
32
- /******/ // Flag the module as loaded
33
- /******/ module.l = true;
34
- /******/
35
- /******/ // Return the exports of the module
36
- /******/ return module.exports;
37
- /******/ }
38
- /******/
39
- /******/
40
- /******/ // expose the modules object (__webpack_modules__)
41
- /******/ __webpack_require__.m = modules;
42
- /******/
43
- /******/ // expose the module cache
44
- /******/ __webpack_require__.c = installedModules;
45
- /******/
46
- /******/ // define getter function for harmony exports
47
- /******/ __webpack_require__.d = function(exports, name, getter) {
48
- /******/ if(!__webpack_require__.o(exports, name)) {
49
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
50
- /******/ }
51
- /******/ };
52
- /******/
53
- /******/ // define __esModule on exports
54
- /******/ __webpack_require__.r = function(exports) {
55
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
56
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
57
- /******/ }
58
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
59
- /******/ };
60
- /******/
61
- /******/ // create a fake namespace object
62
- /******/ // mode & 1: value is a module id, require it
63
- /******/ // mode & 2: merge all properties of value into the ns
64
- /******/ // mode & 4: return value when already ns object
65
- /******/ // mode & 8|1: behave like require
66
- /******/ __webpack_require__.t = function(value, mode) {
67
- /******/ if(mode & 1) value = __webpack_require__(value);
68
- /******/ if(mode & 8) return value;
69
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
70
- /******/ var ns = Object.create(null);
71
- /******/ __webpack_require__.r(ns);
72
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
73
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
74
- /******/ return ns;
75
- /******/ };
76
- /******/
77
- /******/ // getDefaultExport function for compatibility with non-harmony modules
78
- /******/ __webpack_require__.n = function(module) {
79
- /******/ var getter = module && module.__esModule ?
80
- /******/ function getDefault() { return module['default']; } :
81
- /******/ function getModuleExports() { return module; };
82
- /******/ __webpack_require__.d(getter, 'a', getter);
83
- /******/ return getter;
84
- /******/ };
85
- /******/
86
- /******/ // Object.prototype.hasOwnProperty.call
87
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
88
- /******/
89
- /******/ // __webpack_public_path__
90
- /******/ __webpack_require__.p = "";
91
- /******/
92
- /******/
93
- /******/ // Load entry module and return exports
94
- /******/ return __webpack_require__(__webpack_require__.s = "./bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/dist/index.esm.js");
95
- /******/ })
96
- /************************************************************************/
97
- /******/ ({
98
-
99
- /***/ "./bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/dist/index.esm.js":
100
- /*!***************************************************************************************!*\
101
- !*** ./bazel-out/k8-fastbuild/bin/plugins/computed-properties/core/dist/index.esm.js ***!
102
- \***************************************************************************************/
103
- /*! exports provided: ComputedPropertiesPlugin */
104
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
105
-
106
- "use strict";
107
- __webpack_require__.r(__webpack_exports__);
108
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ComputedPropertiesPlugin", function() { return ComputedPropertiesPlugin; });
109
- class ComputedPropertiesPlugin {
110
- constructor() {
111
- this.name = "ComputedProperties";
112
- }
113
- apply(player) {
114
- let schemaController;
115
- let expressionEvaluator;
116
- const getExpressionType = (binding) => {
117
- const dataType = schemaController == null ? void 0 : schemaController.getType(binding);
118
- if ((dataType == null ? void 0 : dataType.type) === "Expression") {
119
- return dataType;
120
- }
121
- };
122
- const computedPropertyMiddleware = {
123
- name: this.name,
124
- get(binding, options, next) {
125
- const expType = getExpressionType(binding);
126
- if (expType) {
127
- const { exp } = expType;
128
- const result = exp && (expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp, options == null ? void 0 : options.context));
129
- return result != null ? result : expType.default;
130
- }
131
- return next == null ? void 0 : next.get(binding, options);
132
- },
133
- set(transaction, options, next) {
134
- var _a;
135
- for (const setOperation of transaction) {
136
- if (getExpressionType(setOperation[0])) {
137
- throw new Error(`Invalid 'set' operation on computed property: ${setOperation[0].asString()}`);
138
- }
139
- }
140
- return (_a = next == null ? void 0 : next.set(transaction, options)) != null ? _a : [];
141
- },
142
- delete(binding, options, next) {
143
- if (getExpressionType(binding)) {
144
- throw new Error(`Invalid 'delete' operation on computed property: ${binding.asString()}`);
145
- }
146
- return next == null ? void 0 : next.delete(binding, options);
147
- }
148
- };
149
- player.hooks.dataController.tap(this.name, (dataController) => {
150
- dataController.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {
151
- return [...dataPipeline, computedPropertyMiddleware];
152
- });
153
- });
154
- player.hooks.schema.tap(this.name, (schema) => {
155
- schemaController = schema;
156
- });
157
- player.hooks.expressionEvaluator.tap(this.name, (evaluator) => {
158
- expressionEvaluator = evaluator;
159
- });
160
- }
161
- }
162
-
163
-
164
- //# sourceMappingURL=index.esm.js.map
165
-
166
-
167
- /***/ })
168
-
169
- /******/ });
170
- });
@@ -1 +0,0 @@
1
- !function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t():"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports.ComputedPropertiesPlugin=t():e.ComputedPropertiesPlugin=t()}(this,(function(){return function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)o.d(n,r,function(t){return e[t]}.bind(null,r));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t,o){"use strict";o.r(t),o.d(t,"ComputedPropertiesPlugin",(function(){return n}));class n{constructor(){this.name="ComputedProperties"}apply(e){let t,o;const n=e=>{const o=null==t?void 0:t.getType(e);if("Expression"===(null==o?void 0:o.type))return o},r={name:this.name,get(e,t,r){const u=n(e);if(u){const{exp:e}=u,n=e&&(null==o?void 0:o.evaluate(e,null==t?void 0:t.context));return null!=n?n:u.default}return null==r?void 0:r.get(e,t)},set(e,t,o){var r;for(const u of e)if(n(u[0]))throw new Error(`Invalid 'set' operation on computed property: ${u[0].asString()}`);return null!=(r=null==o?void 0:o.set(e,t))?r:[]},delete(e,t,o){if(n(e))throw new Error(`Invalid 'delete' operation on computed property: ${e.asString()}`);return null==o?void 0:o.delete(e,t)}};e.hooks.dataController.tap(this.name,(e=>{e.hooks.resolveDataStages.tap(this.name,(e=>[...e,r]))})),e.hooks.schema.tap(this.name,(e=>{t=e})),e.hooks.expressionEvaluator.tap(this.name,(e=>{o=e}))}}}])}));