@milaboratories/pl-model-common 1.25.2 → 1.26.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.
- package/dist/drivers/pframe/query/query_spec.d.ts +2 -2
- package/dist/drivers/pframe/spec/anchored.cjs +58 -0
- package/dist/drivers/pframe/spec/anchored.cjs.map +1 -1
- package/dist/drivers/pframe/spec/anchored.d.ts +3 -0
- package/dist/drivers/pframe/spec/anchored.js +58 -0
- package/dist/drivers/pframe/spec/anchored.js.map +1 -1
- package/dist/drivers/pframe/spec/native_id.cjs +1 -0
- package/dist/drivers/pframe/spec/native_id.cjs.map +1 -1
- package/dist/drivers/pframe/spec/native_id.js +1 -0
- package/dist/drivers/pframe/spec/native_id.js.map +1 -1
- package/dist/drivers/pframe/spec/selectors.cjs +8 -0
- package/dist/drivers/pframe/spec/selectors.cjs.map +1 -1
- package/dist/drivers/pframe/spec/selectors.d.ts +13 -0
- package/dist/drivers/pframe/spec/selectors.js +8 -0
- package/dist/drivers/pframe/spec/selectors.js.map +1 -1
- package/dist/drivers/pframe/spec/spec.cjs +7 -2
- package/dist/drivers/pframe/spec/spec.cjs.map +1 -1
- package/dist/drivers/pframe/spec/spec.d.ts +13 -1
- package/dist/drivers/pframe/spec/spec.js +7 -2
- package/dist/drivers/pframe/spec/spec.js.map +1 -1
- package/dist/flags/block_flags.cjs +1 -1
- package/dist/flags/block_flags.cjs.map +1 -1
- package/dist/flags/block_flags.d.ts +2 -1
- package/dist/flags/block_flags.js +1 -1
- package/dist/flags/block_flags.js.map +1 -1
- package/dist/pool/query.cjs +1 -1
- package/dist/pool/query.cjs.map +1 -1
- package/dist/pool/query.js +1 -1
- package/dist/pool/query.js.map +1 -1
- package/dist/pool/spec.cjs.map +1 -1
- package/dist/pool/spec.d.ts +4 -1
- package/dist/pool/spec.js.map +1 -1
- package/package.json +4 -4
- package/src/drivers/pframe/query/query_spec.ts +2 -2
- package/src/drivers/pframe/query/utils.test.ts +2 -2
- package/src/drivers/pframe/spec/anchored.ts +73 -0
- package/src/drivers/pframe/spec/native_id.ts +1 -0
- package/src/drivers/pframe/spec/selectors.ts +28 -0
- package/src/drivers/pframe/spec/spec.ts +33 -3
- package/src/flags/block_flags.ts +2 -1
- package/src/pool/query.ts +6 -0
- package/src/pool/spec.ts +4 -0
package/dist/pool/query.cjs
CHANGED
|
@@ -17,7 +17,7 @@ function executePSpecPredicate(predicate, spec) {
|
|
|
17
17
|
case "name_pattern": return require_spec.isPColumnSpec(spec) && Boolean(spec.name.match(predicate.pattern));
|
|
18
18
|
case "annotation": return require_spec.isPColumnSpec(spec) && spec.annotations !== void 0 && spec.annotations[predicate.annotation] === predicate.value;
|
|
19
19
|
case "annotation_pattern": return require_spec.isPColumnSpec(spec) && spec.annotations !== void 0 && spec.annotations[predicate.annotation] !== void 0 && Boolean(spec.annotations[predicate.annotation].match(predicate.pattern));
|
|
20
|
-
case "has_axes": return require_spec.isPColumnSpec(spec) && predicate.axes.every((matcher) => spec.axesSpec.some((axisSpec) => (matcher.type === void 0 || matcher.type === axisSpec.type) && (matcher.name === void 0 || matcher.name === axisSpec.name) && (matcher.domain === void 0 || Object.keys(matcher.domain).length === 0 || axisSpec.domain !== void 0 && Object.entries(matcher.domain).every(([domain, domainValue]) => axisSpec.domain[domain] === domainValue))));
|
|
20
|
+
case "has_axes": return require_spec.isPColumnSpec(spec) && predicate.axes.every((matcher) => spec.axesSpec.some((axisSpec) => (matcher.type === void 0 || matcher.type === axisSpec.type) && (matcher.name === void 0 || matcher.name === axisSpec.name) && (matcher.domain === void 0 || Object.keys(matcher.domain).length === 0 || axisSpec.domain !== void 0 && Object.entries(matcher.domain).every(([domain, domainValue]) => axisSpec.domain[domain] === domainValue)) && (matcher.contextDomain === void 0 || Object.keys(matcher.contextDomain).length === 0 || axisSpec.contextDomain !== void 0 && Object.entries(matcher.contextDomain).every(([key, value]) => axisSpec.contextDomain[key] === value))));
|
|
21
21
|
default: assertNever(predicate);
|
|
22
22
|
}
|
|
23
23
|
}
|
package/dist/pool/query.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.cjs","names":["isPColumnSpec"],"sources":["../../src/pool/query.ts"],"sourcesContent":["import type { AxisId } from \"../drivers\";\nimport type { PObjectSpec } from \"./spec\";\nimport { isPColumnSpec } from \"./spec\";\n\nexport type PSpecPredicate =\n | {\n type: \"and\" | \"or\";\n operands: PSpecPredicate[];\n }\n | {\n type: \"not\";\n operand: PSpecPredicate;\n }\n | {\n type: \"name\";\n name: string;\n }\n | {\n type: \"name_pattern\";\n pattern: string;\n }\n | {\n type: \"annotation\";\n annotation: string;\n value: string;\n }\n | {\n type: \"annotation_pattern\";\n annotation: string;\n pattern: string;\n }\n | {\n type: \"has_axes\";\n axes: Partial<AxisId>[];\n };\n\nfunction assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x); // This is ok, because this is a possible runtime error\n}\n\nexport function executePSpecPredicate(predicate: PSpecPredicate, spec: PObjectSpec): boolean {\n switch (predicate.type) {\n case \"and\":\n for (const operator of predicate.operands)\n if (!executePSpecPredicate(operator, spec)) return false;\n return true;\n case \"or\":\n for (const operator of predicate.operands)\n if (executePSpecPredicate(operator, spec)) return true;\n return false;\n case \"not\":\n return !executePSpecPredicate(predicate.operand, spec);\n case \"name\":\n return isPColumnSpec(spec) && spec.name === predicate.name;\n case \"name_pattern\":\n return isPColumnSpec(spec) && Boolean(spec.name.match(predicate.pattern));\n case \"annotation\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] === predicate.value\n );\n case \"annotation_pattern\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] !== undefined &&\n Boolean(spec.annotations[predicate.annotation].match(predicate.pattern))\n );\n case \"has_axes\":\n return (\n isPColumnSpec(spec) &&\n predicate.axes.every((matcher) =>\n spec.axesSpec.some(\n (axisSpec) =>\n (matcher.type === undefined || matcher.type === axisSpec.type) &&\n (matcher.name === undefined || matcher.name === axisSpec.name) &&\n (matcher.domain === undefined ||\n Object.keys(matcher.domain).length === 0 ||\n (axisSpec.domain !== undefined &&\n Object.entries(matcher.domain).every(\n ([domain, domainValue]) => axisSpec.domain![domain] === domainValue,\n ))),\n ),\n )\n );\n default:\n assertNever(predicate);\n }\n}\n"],"mappings":";;;AAoCA,SAAS,YAAY,GAAiB;AACpC,OAAM,IAAI,MAAM,wBAAwB,EAAE;;AAG5C,SAAgB,sBAAsB,WAA2B,MAA4B;AAC3F,SAAQ,UAAU,MAAlB;EACE,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,CAAC,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACrD,UAAO;EACT,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACpD,UAAO;EACT,KAAK,MACH,QAAO,CAAC,sBAAsB,UAAU,SAAS,KAAK;EACxD,KAAK,OACH,QAAOA,2BAAc,KAAK,IAAI,KAAK,SAAS,UAAU;EACxD,KAAK,eACH,QAAOA,2BAAc,KAAK,IAAI,QAAQ,KAAK,KAAK,MAAM,UAAU,QAAQ,CAAC;EAC3E,KAAK,aACH,QACEA,2BAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAAU;EAEzD,KAAK,qBACH,QACEA,2BAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAC3C,QAAQ,KAAK,YAAY,UAAU,YAAY,MAAM,UAAU,QAAQ,CAAC;EAE5E,KAAK,WACH,QACEA,2BAAc,KAAK,IACnB,UAAU,KAAK,OAAO,YACpB,KAAK,SAAS,MACX,cACE,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,WAAW,UAClB,OAAO,KAAK,QAAQ,OAAO,CAAC,WAAW,KACtC,SAAS,WAAW,UACnB,OAAO,QAAQ,QAAQ,OAAO,CAAC,OAC5B,CAAC,QAAQ,iBAAiB,SAAS,OAAQ,YAAY,YACzD,EACR,CACF;EAEL,QACE,aAAY,UAAU"}
|
|
1
|
+
{"version":3,"file":"query.cjs","names":["isPColumnSpec"],"sources":["../../src/pool/query.ts"],"sourcesContent":["import type { AxisId } from \"../drivers\";\nimport type { PObjectSpec } from \"./spec\";\nimport { isPColumnSpec } from \"./spec\";\n\nexport type PSpecPredicate =\n | {\n type: \"and\" | \"or\";\n operands: PSpecPredicate[];\n }\n | {\n type: \"not\";\n operand: PSpecPredicate;\n }\n | {\n type: \"name\";\n name: string;\n }\n | {\n type: \"name_pattern\";\n pattern: string;\n }\n | {\n type: \"annotation\";\n annotation: string;\n value: string;\n }\n | {\n type: \"annotation_pattern\";\n annotation: string;\n pattern: string;\n }\n | {\n type: \"has_axes\";\n axes: Partial<AxisId>[];\n };\n\nfunction assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x); // This is ok, because this is a possible runtime error\n}\n\nexport function executePSpecPredicate(predicate: PSpecPredicate, spec: PObjectSpec): boolean {\n switch (predicate.type) {\n case \"and\":\n for (const operator of predicate.operands)\n if (!executePSpecPredicate(operator, spec)) return false;\n return true;\n case \"or\":\n for (const operator of predicate.operands)\n if (executePSpecPredicate(operator, spec)) return true;\n return false;\n case \"not\":\n return !executePSpecPredicate(predicate.operand, spec);\n case \"name\":\n return isPColumnSpec(spec) && spec.name === predicate.name;\n case \"name_pattern\":\n return isPColumnSpec(spec) && Boolean(spec.name.match(predicate.pattern));\n case \"annotation\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] === predicate.value\n );\n case \"annotation_pattern\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] !== undefined &&\n Boolean(spec.annotations[predicate.annotation].match(predicate.pattern))\n );\n case \"has_axes\":\n return (\n isPColumnSpec(spec) &&\n predicate.axes.every((matcher) =>\n spec.axesSpec.some(\n (axisSpec) =>\n (matcher.type === undefined || matcher.type === axisSpec.type) &&\n (matcher.name === undefined || matcher.name === axisSpec.name) &&\n (matcher.domain === undefined ||\n Object.keys(matcher.domain).length === 0 ||\n (axisSpec.domain !== undefined &&\n Object.entries(matcher.domain).every(\n ([domain, domainValue]) => axisSpec.domain![domain] === domainValue,\n ))) &&\n (matcher.contextDomain === undefined ||\n Object.keys(matcher.contextDomain).length === 0 ||\n (axisSpec.contextDomain !== undefined &&\n Object.entries(matcher.contextDomain).every(\n ([key, value]) => axisSpec.contextDomain![key] === value,\n ))),\n ),\n )\n );\n default:\n assertNever(predicate);\n }\n}\n"],"mappings":";;;AAoCA,SAAS,YAAY,GAAiB;AACpC,OAAM,IAAI,MAAM,wBAAwB,EAAE;;AAG5C,SAAgB,sBAAsB,WAA2B,MAA4B;AAC3F,SAAQ,UAAU,MAAlB;EACE,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,CAAC,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACrD,UAAO;EACT,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACpD,UAAO;EACT,KAAK,MACH,QAAO,CAAC,sBAAsB,UAAU,SAAS,KAAK;EACxD,KAAK,OACH,QAAOA,2BAAc,KAAK,IAAI,KAAK,SAAS,UAAU;EACxD,KAAK,eACH,QAAOA,2BAAc,KAAK,IAAI,QAAQ,KAAK,KAAK,MAAM,UAAU,QAAQ,CAAC;EAC3E,KAAK,aACH,QACEA,2BAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAAU;EAEzD,KAAK,qBACH,QACEA,2BAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAC3C,QAAQ,KAAK,YAAY,UAAU,YAAY,MAAM,UAAU,QAAQ,CAAC;EAE5E,KAAK,WACH,QACEA,2BAAc,KAAK,IACnB,UAAU,KAAK,OAAO,YACpB,KAAK,SAAS,MACX,cACE,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,WAAW,UAClB,OAAO,KAAK,QAAQ,OAAO,CAAC,WAAW,KACtC,SAAS,WAAW,UACnB,OAAO,QAAQ,QAAQ,OAAO,CAAC,OAC5B,CAAC,QAAQ,iBAAiB,SAAS,OAAQ,YAAY,YACzD,MACJ,QAAQ,kBAAkB,UACzB,OAAO,KAAK,QAAQ,cAAc,CAAC,WAAW,KAC7C,SAAS,kBAAkB,UAC1B,OAAO,QAAQ,QAAQ,cAAc,CAAC,OACnC,CAAC,KAAK,WAAW,SAAS,cAAe,SAAS,MACpD,EACR,CACF;EAEL,QACE,aAAY,UAAU"}
|
package/dist/pool/query.js
CHANGED
|
@@ -17,7 +17,7 @@ function executePSpecPredicate(predicate, spec) {
|
|
|
17
17
|
case "name_pattern": return isPColumnSpec(spec) && Boolean(spec.name.match(predicate.pattern));
|
|
18
18
|
case "annotation": return isPColumnSpec(spec) && spec.annotations !== void 0 && spec.annotations[predicate.annotation] === predicate.value;
|
|
19
19
|
case "annotation_pattern": return isPColumnSpec(spec) && spec.annotations !== void 0 && spec.annotations[predicate.annotation] !== void 0 && Boolean(spec.annotations[predicate.annotation].match(predicate.pattern));
|
|
20
|
-
case "has_axes": return isPColumnSpec(spec) && predicate.axes.every((matcher) => spec.axesSpec.some((axisSpec) => (matcher.type === void 0 || matcher.type === axisSpec.type) && (matcher.name === void 0 || matcher.name === axisSpec.name) && (matcher.domain === void 0 || Object.keys(matcher.domain).length === 0 || axisSpec.domain !== void 0 && Object.entries(matcher.domain).every(([domain, domainValue]) => axisSpec.domain[domain] === domainValue))));
|
|
20
|
+
case "has_axes": return isPColumnSpec(spec) && predicate.axes.every((matcher) => spec.axesSpec.some((axisSpec) => (matcher.type === void 0 || matcher.type === axisSpec.type) && (matcher.name === void 0 || matcher.name === axisSpec.name) && (matcher.domain === void 0 || Object.keys(matcher.domain).length === 0 || axisSpec.domain !== void 0 && Object.entries(matcher.domain).every(([domain, domainValue]) => axisSpec.domain[domain] === domainValue)) && (matcher.contextDomain === void 0 || Object.keys(matcher.contextDomain).length === 0 || axisSpec.contextDomain !== void 0 && Object.entries(matcher.contextDomain).every(([key, value]) => axisSpec.contextDomain[key] === value))));
|
|
21
21
|
default: assertNever(predicate);
|
|
22
22
|
}
|
|
23
23
|
}
|
package/dist/pool/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","names":[],"sources":["../../src/pool/query.ts"],"sourcesContent":["import type { AxisId } from \"../drivers\";\nimport type { PObjectSpec } from \"./spec\";\nimport { isPColumnSpec } from \"./spec\";\n\nexport type PSpecPredicate =\n | {\n type: \"and\" | \"or\";\n operands: PSpecPredicate[];\n }\n | {\n type: \"not\";\n operand: PSpecPredicate;\n }\n | {\n type: \"name\";\n name: string;\n }\n | {\n type: \"name_pattern\";\n pattern: string;\n }\n | {\n type: \"annotation\";\n annotation: string;\n value: string;\n }\n | {\n type: \"annotation_pattern\";\n annotation: string;\n pattern: string;\n }\n | {\n type: \"has_axes\";\n axes: Partial<AxisId>[];\n };\n\nfunction assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x); // This is ok, because this is a possible runtime error\n}\n\nexport function executePSpecPredicate(predicate: PSpecPredicate, spec: PObjectSpec): boolean {\n switch (predicate.type) {\n case \"and\":\n for (const operator of predicate.operands)\n if (!executePSpecPredicate(operator, spec)) return false;\n return true;\n case \"or\":\n for (const operator of predicate.operands)\n if (executePSpecPredicate(operator, spec)) return true;\n return false;\n case \"not\":\n return !executePSpecPredicate(predicate.operand, spec);\n case \"name\":\n return isPColumnSpec(spec) && spec.name === predicate.name;\n case \"name_pattern\":\n return isPColumnSpec(spec) && Boolean(spec.name.match(predicate.pattern));\n case \"annotation\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] === predicate.value\n );\n case \"annotation_pattern\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] !== undefined &&\n Boolean(spec.annotations[predicate.annotation].match(predicate.pattern))\n );\n case \"has_axes\":\n return (\n isPColumnSpec(spec) &&\n predicate.axes.every((matcher) =>\n spec.axesSpec.some(\n (axisSpec) =>\n (matcher.type === undefined || matcher.type === axisSpec.type) &&\n (matcher.name === undefined || matcher.name === axisSpec.name) &&\n (matcher.domain === undefined ||\n Object.keys(matcher.domain).length === 0 ||\n (axisSpec.domain !== undefined &&\n Object.entries(matcher.domain).every(\n ([domain, domainValue]) => axisSpec.domain![domain] === domainValue,\n ))),\n ),\n )\n );\n default:\n assertNever(predicate);\n }\n}\n"],"mappings":";;;AAoCA,SAAS,YAAY,GAAiB;AACpC,OAAM,IAAI,MAAM,wBAAwB,EAAE;;AAG5C,SAAgB,sBAAsB,WAA2B,MAA4B;AAC3F,SAAQ,UAAU,MAAlB;EACE,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,CAAC,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACrD,UAAO;EACT,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACpD,UAAO;EACT,KAAK,MACH,QAAO,CAAC,sBAAsB,UAAU,SAAS,KAAK;EACxD,KAAK,OACH,QAAO,cAAc,KAAK,IAAI,KAAK,SAAS,UAAU;EACxD,KAAK,eACH,QAAO,cAAc,KAAK,IAAI,QAAQ,KAAK,KAAK,MAAM,UAAU,QAAQ,CAAC;EAC3E,KAAK,aACH,QACE,cAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAAU;EAEzD,KAAK,qBACH,QACE,cAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAC3C,QAAQ,KAAK,YAAY,UAAU,YAAY,MAAM,UAAU,QAAQ,CAAC;EAE5E,KAAK,WACH,QACE,cAAc,KAAK,IACnB,UAAU,KAAK,OAAO,YACpB,KAAK,SAAS,MACX,cACE,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,WAAW,UAClB,OAAO,KAAK,QAAQ,OAAO,CAAC,WAAW,KACtC,SAAS,WAAW,UACnB,OAAO,QAAQ,QAAQ,OAAO,CAAC,OAC5B,CAAC,QAAQ,iBAAiB,SAAS,OAAQ,YAAY,YACzD,EACR,CACF;EAEL,QACE,aAAY,UAAU"}
|
|
1
|
+
{"version":3,"file":"query.js","names":[],"sources":["../../src/pool/query.ts"],"sourcesContent":["import type { AxisId } from \"../drivers\";\nimport type { PObjectSpec } from \"./spec\";\nimport { isPColumnSpec } from \"./spec\";\n\nexport type PSpecPredicate =\n | {\n type: \"and\" | \"or\";\n operands: PSpecPredicate[];\n }\n | {\n type: \"not\";\n operand: PSpecPredicate;\n }\n | {\n type: \"name\";\n name: string;\n }\n | {\n type: \"name_pattern\";\n pattern: string;\n }\n | {\n type: \"annotation\";\n annotation: string;\n value: string;\n }\n | {\n type: \"annotation_pattern\";\n annotation: string;\n pattern: string;\n }\n | {\n type: \"has_axes\";\n axes: Partial<AxisId>[];\n };\n\nfunction assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x); // This is ok, because this is a possible runtime error\n}\n\nexport function executePSpecPredicate(predicate: PSpecPredicate, spec: PObjectSpec): boolean {\n switch (predicate.type) {\n case \"and\":\n for (const operator of predicate.operands)\n if (!executePSpecPredicate(operator, spec)) return false;\n return true;\n case \"or\":\n for (const operator of predicate.operands)\n if (executePSpecPredicate(operator, spec)) return true;\n return false;\n case \"not\":\n return !executePSpecPredicate(predicate.operand, spec);\n case \"name\":\n return isPColumnSpec(spec) && spec.name === predicate.name;\n case \"name_pattern\":\n return isPColumnSpec(spec) && Boolean(spec.name.match(predicate.pattern));\n case \"annotation\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] === predicate.value\n );\n case \"annotation_pattern\":\n return (\n isPColumnSpec(spec) &&\n spec.annotations !== undefined &&\n spec.annotations[predicate.annotation] !== undefined &&\n Boolean(spec.annotations[predicate.annotation].match(predicate.pattern))\n );\n case \"has_axes\":\n return (\n isPColumnSpec(spec) &&\n predicate.axes.every((matcher) =>\n spec.axesSpec.some(\n (axisSpec) =>\n (matcher.type === undefined || matcher.type === axisSpec.type) &&\n (matcher.name === undefined || matcher.name === axisSpec.name) &&\n (matcher.domain === undefined ||\n Object.keys(matcher.domain).length === 0 ||\n (axisSpec.domain !== undefined &&\n Object.entries(matcher.domain).every(\n ([domain, domainValue]) => axisSpec.domain![domain] === domainValue,\n ))) &&\n (matcher.contextDomain === undefined ||\n Object.keys(matcher.contextDomain).length === 0 ||\n (axisSpec.contextDomain !== undefined &&\n Object.entries(matcher.contextDomain).every(\n ([key, value]) => axisSpec.contextDomain![key] === value,\n ))),\n ),\n )\n );\n default:\n assertNever(predicate);\n }\n}\n"],"mappings":";;;AAoCA,SAAS,YAAY,GAAiB;AACpC,OAAM,IAAI,MAAM,wBAAwB,EAAE;;AAG5C,SAAgB,sBAAsB,WAA2B,MAA4B;AAC3F,SAAQ,UAAU,MAAlB;EACE,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,CAAC,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACrD,UAAO;EACT,KAAK;AACH,QAAK,MAAM,YAAY,UAAU,SAC/B,KAAI,sBAAsB,UAAU,KAAK,CAAE,QAAO;AACpD,UAAO;EACT,KAAK,MACH,QAAO,CAAC,sBAAsB,UAAU,SAAS,KAAK;EACxD,KAAK,OACH,QAAO,cAAc,KAAK,IAAI,KAAK,SAAS,UAAU;EACxD,KAAK,eACH,QAAO,cAAc,KAAK,IAAI,QAAQ,KAAK,KAAK,MAAM,UAAU,QAAQ,CAAC;EAC3E,KAAK,aACH,QACE,cAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAAU;EAEzD,KAAK,qBACH,QACE,cAAc,KAAK,IACnB,KAAK,gBAAgB,UACrB,KAAK,YAAY,UAAU,gBAAgB,UAC3C,QAAQ,KAAK,YAAY,UAAU,YAAY,MAAM,UAAU,QAAQ,CAAC;EAE5E,KAAK,WACH,QACE,cAAc,KAAK,IACnB,UAAU,KAAK,OAAO,YACpB,KAAK,SAAS,MACX,cACE,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,SAAS,UAAa,QAAQ,SAAS,SAAS,UACxD,QAAQ,WAAW,UAClB,OAAO,KAAK,QAAQ,OAAO,CAAC,WAAW,KACtC,SAAS,WAAW,UACnB,OAAO,QAAQ,QAAQ,OAAO,CAAC,OAC5B,CAAC,QAAQ,iBAAiB,SAAS,OAAQ,YAAY,YACzD,MACJ,QAAQ,kBAAkB,UACzB,OAAO,KAAK,QAAQ,cAAc,CAAC,WAAW,KAC7C,SAAS,kBAAkB,UAC1B,OAAO,QAAQ,QAAQ,cAAc,CAAC,OACnC,CAAC,KAAK,WAAW,SAAS,cAAe,SAAS,MACpD,EACR,CACF;EAEL,QACE,aAAY,UAAU"}
|
package/dist/pool/spec.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.cjs","names":[],"sources":["../../src/pool/spec.ts"],"sourcesContent":["import type { Branded } from \"../branding\";\nimport type { JoinEntry, PColumn, PColumnLazy, PColumnSpec } from \"../drivers\";\nimport { assertNever } from \"../util\";\nimport type { ResultPoolEntry } from \"./entry\";\n\n/** Any object exported into the result pool by the block always have spec attached to it */\nexport type PObjectSpec = {\n /** PObject kind discriminator */\n readonly kind: string;\n\n /** Name is common part of PObject identity */\n readonly name: string;\n\n /** Domain is a set of key-value pairs that can be used to identify the object */\n readonly domain?: Record<string, string>;\n\n /** Additional information attached to the object */\n readonly annotations?: Record<string, string>;\n};\n\n/** Stable PObject id */\nexport type PObjectId = Branded<string, \"PColumnId\">;\n\n/**\n * Full PObject representation.\n *\n * @template Data type of the object referencing or describing the \"data\" part of the PObject\n * */\nexport interface PObject<Data> {\n /** Fully rendered PObjects are assigned a stable identifier. */\n readonly id: PObjectId;\n\n /** PObject spec, allowing it to be found among other PObjects */\n readonly spec: PObjectSpec;\n\n /** A handle to data object */\n readonly data: Data;\n}\n\nexport function isPColumnSpec(spec: PObjectSpec): spec is PColumnSpec {\n return spec.kind === \"PColumn\";\n}\n\nexport function isPColumn<T>(obj: PObject<T>): obj is PColumn<T> {\n return isPColumnSpec(obj.spec);\n}\n\nexport function isPColumnSpecResult(\n r: ResultPoolEntry<PObjectSpec>,\n): r is ResultPoolEntry<PColumnSpec> {\n return isPColumnSpec(r.obj);\n}\n\nexport function isPColumnResult<T>(\n r: ResultPoolEntry<PObject<T>>,\n): r is ResultPoolEntry<PColumn<T>> {\n return isPColumnSpec(r.obj.spec);\n}\n\nexport function ensurePColumn<T>(obj: PObject<T>): PColumn<T> {\n if (!isPColumn(obj)) throw new Error(`not a PColumn (kind = ${obj.spec.kind})`);\n return obj;\n}\n\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | PColumnLazy<D1>,\n cb: (d: D1) => D2,\n): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(pObj: PColumn<D1>, cb: (d: D1) => D2): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | undefined,\n cb: (d: D1) => D2,\n): PColumn<D2> | undefined;\nexport function mapPObjectData<D1, D2>(pObj: PObject<D1>, cb: (d: D1) => D2): PObject<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined {\n return pObj === undefined\n ? undefined\n : {\n ...pObj,\n data: cb(typeof pObj.data === \"function\" ? pObj.data() : pObj.data),\n };\n}\n\nexport function extractAllColumns<D>(entry: JoinEntry<PColumn<D>>): PColumn<D>[] {\n const columns = new Map<PObjectId, PColumn<D>>();\n const addAllColumns = (entry: JoinEntry<PColumn<D>>) => {\n switch (entry.type) {\n case \"column\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"slicedColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"artificialColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"inlineColumn\":\n return;\n case \"full\":\n case \"inner\":\n for (const e of entry.entries) addAllColumns(e);\n return;\n case \"outer\":\n addAllColumns(entry.primary);\n for (const e of entry.secondary) addAllColumns(e);\n return;\n default:\n assertNever(entry);\n }\n };\n addAllColumns(entry);\n return [...columns.values()];\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"spec.cjs","names":[],"sources":["../../src/pool/spec.ts"],"sourcesContent":["import type { Branded } from \"../branding\";\nimport type { JoinEntry, PColumn, PColumnLazy, PColumnSpec } from \"../drivers\";\nimport { assertNever } from \"../util\";\nimport type { ResultPoolEntry } from \"./entry\";\n\n/** Any object exported into the result pool by the block always have spec attached to it */\nexport type PObjectSpec = {\n /** PObject kind discriminator */\n readonly kind: string;\n\n /** Name is common part of PObject identity */\n readonly name: string;\n\n /** Domain is a set of key-value pairs that can be used to identify the object */\n readonly domain?: Record<string, string>;\n\n /** Context domain provides additional axis/column identity that is matched\n * by kinship rules (subset/superset/overlap) rather than exact equality */\n readonly contextDomain?: Record<string, string>;\n\n /** Additional information attached to the object */\n readonly annotations?: Record<string, string>;\n};\n\n/** Stable PObject id */\nexport type PObjectId = Branded<string, \"PColumnId\">;\n\n/**\n * Full PObject representation.\n *\n * @template Data type of the object referencing or describing the \"data\" part of the PObject\n * */\nexport interface PObject<Data> {\n /** Fully rendered PObjects are assigned a stable identifier. */\n readonly id: PObjectId;\n\n /** PObject spec, allowing it to be found among other PObjects */\n readonly spec: PObjectSpec;\n\n /** A handle to data object */\n readonly data: Data;\n}\n\nexport function isPColumnSpec(spec: PObjectSpec): spec is PColumnSpec {\n return spec.kind === \"PColumn\";\n}\n\nexport function isPColumn<T>(obj: PObject<T>): obj is PColumn<T> {\n return isPColumnSpec(obj.spec);\n}\n\nexport function isPColumnSpecResult(\n r: ResultPoolEntry<PObjectSpec>,\n): r is ResultPoolEntry<PColumnSpec> {\n return isPColumnSpec(r.obj);\n}\n\nexport function isPColumnResult<T>(\n r: ResultPoolEntry<PObject<T>>,\n): r is ResultPoolEntry<PColumn<T>> {\n return isPColumnSpec(r.obj.spec);\n}\n\nexport function ensurePColumn<T>(obj: PObject<T>): PColumn<T> {\n if (!isPColumn(obj)) throw new Error(`not a PColumn (kind = ${obj.spec.kind})`);\n return obj;\n}\n\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | PColumnLazy<D1>,\n cb: (d: D1) => D2,\n): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(pObj: PColumn<D1>, cb: (d: D1) => D2): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | undefined,\n cb: (d: D1) => D2,\n): PColumn<D2> | undefined;\nexport function mapPObjectData<D1, D2>(pObj: PObject<D1>, cb: (d: D1) => D2): PObject<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined {\n return pObj === undefined\n ? undefined\n : {\n ...pObj,\n data: cb(typeof pObj.data === \"function\" ? pObj.data() : pObj.data),\n };\n}\n\nexport function extractAllColumns<D>(entry: JoinEntry<PColumn<D>>): PColumn<D>[] {\n const columns = new Map<PObjectId, PColumn<D>>();\n const addAllColumns = (entry: JoinEntry<PColumn<D>>) => {\n switch (entry.type) {\n case \"column\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"slicedColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"artificialColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"inlineColumn\":\n return;\n case \"full\":\n case \"inner\":\n for (const e of entry.entries) addAllColumns(e);\n return;\n case \"outer\":\n addAllColumns(entry.primary);\n for (const e of entry.secondary) addAllColumns(e);\n return;\n default:\n assertNever(entry);\n }\n };\n addAllColumns(entry);\n return [...columns.values()];\n}\n"],"mappings":";;;AA2CA,SAAgB,cAAc,MAAwC;AACpE,QAAO,KAAK,SAAS;;AAGvB,SAAgB,UAAa,KAAoC;AAC/D,QAAO,cAAc,IAAI,KAAK;;AAGhC,SAAgB,oBACd,GACmC;AACnC,QAAO,cAAc,EAAE,IAAI;;AAG7B,SAAgB,gBACd,GACkC;AAClC,QAAO,cAAc,EAAE,IAAI,KAAK;;AAGlC,SAAgB,cAAiB,KAA6B;AAC5D,KAAI,CAAC,UAAU,IAAI,CAAE,OAAM,IAAI,MAAM,yBAAyB,IAAI,KAAK,KAAK,GAAG;AAC/E,QAAO;;AAiBT,SAAgB,eACd,MACA,IACyB;AACzB,QAAO,SAAS,SACZ,SACA;EACE,GAAG;EACH,MAAM,GAAG,OAAO,KAAK,SAAS,aAAa,KAAK,MAAM,GAAG,KAAK,KAAK;EACpE;;AAGP,SAAgB,kBAAqB,OAA4C;CAC/E,MAAM,0BAAU,IAAI,KAA4B;CAChD,MAAM,iBAAiB,UAAiC;AACtD,UAAQ,MAAM,MAAd;GACE,KAAK;AACH,YAAQ,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AAC1C;GACF,KAAK;AACH,YAAQ,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AAC1C;GACF,KAAK;AACH,YAAQ,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AAC1C;GACF,KAAK,eACH;GACF,KAAK;GACL,KAAK;AACH,SAAK,MAAM,KAAK,MAAM,QAAS,eAAc,EAAE;AAC/C;GACF,KAAK;AACH,kBAAc,MAAM,QAAQ;AAC5B,SAAK,MAAM,KAAK,MAAM,UAAW,eAAc,EAAE;AACjD;GACF,QACE,0BAAY,MAAM;;;AAGxB,eAAc,MAAM;AACpB,QAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC"}
|
package/dist/pool/spec.d.ts
CHANGED
|
@@ -9,7 +9,10 @@ import "../drivers/index.js";
|
|
|
9
9
|
type PObjectSpec = {
|
|
10
10
|
/** PObject kind discriminator */readonly kind: string; /** Name is common part of PObject identity */
|
|
11
11
|
readonly name: string; /** Domain is a set of key-value pairs that can be used to identify the object */
|
|
12
|
-
readonly domain?: Record<string, string>;
|
|
12
|
+
readonly domain?: Record<string, string>;
|
|
13
|
+
/** Context domain provides additional axis/column identity that is matched
|
|
14
|
+
* by kinship rules (subset/superset/overlap) rather than exact equality */
|
|
15
|
+
readonly contextDomain?: Record<string, string>; /** Additional information attached to the object */
|
|
13
16
|
readonly annotations?: Record<string, string>;
|
|
14
17
|
};
|
|
15
18
|
/** Stable PObject id */
|
package/dist/pool/spec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.js","names":[],"sources":["../../src/pool/spec.ts"],"sourcesContent":["import type { Branded } from \"../branding\";\nimport type { JoinEntry, PColumn, PColumnLazy, PColumnSpec } from \"../drivers\";\nimport { assertNever } from \"../util\";\nimport type { ResultPoolEntry } from \"./entry\";\n\n/** Any object exported into the result pool by the block always have spec attached to it */\nexport type PObjectSpec = {\n /** PObject kind discriminator */\n readonly kind: string;\n\n /** Name is common part of PObject identity */\n readonly name: string;\n\n /** Domain is a set of key-value pairs that can be used to identify the object */\n readonly domain?: Record<string, string>;\n\n /** Additional information attached to the object */\n readonly annotations?: Record<string, string>;\n};\n\n/** Stable PObject id */\nexport type PObjectId = Branded<string, \"PColumnId\">;\n\n/**\n * Full PObject representation.\n *\n * @template Data type of the object referencing or describing the \"data\" part of the PObject\n * */\nexport interface PObject<Data> {\n /** Fully rendered PObjects are assigned a stable identifier. */\n readonly id: PObjectId;\n\n /** PObject spec, allowing it to be found among other PObjects */\n readonly spec: PObjectSpec;\n\n /** A handle to data object */\n readonly data: Data;\n}\n\nexport function isPColumnSpec(spec: PObjectSpec): spec is PColumnSpec {\n return spec.kind === \"PColumn\";\n}\n\nexport function isPColumn<T>(obj: PObject<T>): obj is PColumn<T> {\n return isPColumnSpec(obj.spec);\n}\n\nexport function isPColumnSpecResult(\n r: ResultPoolEntry<PObjectSpec>,\n): r is ResultPoolEntry<PColumnSpec> {\n return isPColumnSpec(r.obj);\n}\n\nexport function isPColumnResult<T>(\n r: ResultPoolEntry<PObject<T>>,\n): r is ResultPoolEntry<PColumn<T>> {\n return isPColumnSpec(r.obj.spec);\n}\n\nexport function ensurePColumn<T>(obj: PObject<T>): PColumn<T> {\n if (!isPColumn(obj)) throw new Error(`not a PColumn (kind = ${obj.spec.kind})`);\n return obj;\n}\n\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | PColumnLazy<D1>,\n cb: (d: D1) => D2,\n): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(pObj: PColumn<D1>, cb: (d: D1) => D2): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | undefined,\n cb: (d: D1) => D2,\n): PColumn<D2> | undefined;\nexport function mapPObjectData<D1, D2>(pObj: PObject<D1>, cb: (d: D1) => D2): PObject<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined {\n return pObj === undefined\n ? undefined\n : {\n ...pObj,\n data: cb(typeof pObj.data === \"function\" ? pObj.data() : pObj.data),\n };\n}\n\nexport function extractAllColumns<D>(entry: JoinEntry<PColumn<D>>): PColumn<D>[] {\n const columns = new Map<PObjectId, PColumn<D>>();\n const addAllColumns = (entry: JoinEntry<PColumn<D>>) => {\n switch (entry.type) {\n case \"column\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"slicedColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"artificialColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"inlineColumn\":\n return;\n case \"full\":\n case \"inner\":\n for (const e of entry.entries) addAllColumns(e);\n return;\n case \"outer\":\n addAllColumns(entry.primary);\n for (const e of entry.secondary) addAllColumns(e);\n return;\n default:\n assertNever(entry);\n }\n };\n addAllColumns(entry);\n return [...columns.values()];\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"spec.js","names":[],"sources":["../../src/pool/spec.ts"],"sourcesContent":["import type { Branded } from \"../branding\";\nimport type { JoinEntry, PColumn, PColumnLazy, PColumnSpec } from \"../drivers\";\nimport { assertNever } from \"../util\";\nimport type { ResultPoolEntry } from \"./entry\";\n\n/** Any object exported into the result pool by the block always have spec attached to it */\nexport type PObjectSpec = {\n /** PObject kind discriminator */\n readonly kind: string;\n\n /** Name is common part of PObject identity */\n readonly name: string;\n\n /** Domain is a set of key-value pairs that can be used to identify the object */\n readonly domain?: Record<string, string>;\n\n /** Context domain provides additional axis/column identity that is matched\n * by kinship rules (subset/superset/overlap) rather than exact equality */\n readonly contextDomain?: Record<string, string>;\n\n /** Additional information attached to the object */\n readonly annotations?: Record<string, string>;\n};\n\n/** Stable PObject id */\nexport type PObjectId = Branded<string, \"PColumnId\">;\n\n/**\n * Full PObject representation.\n *\n * @template Data type of the object referencing or describing the \"data\" part of the PObject\n * */\nexport interface PObject<Data> {\n /** Fully rendered PObjects are assigned a stable identifier. */\n readonly id: PObjectId;\n\n /** PObject spec, allowing it to be found among other PObjects */\n readonly spec: PObjectSpec;\n\n /** A handle to data object */\n readonly data: Data;\n}\n\nexport function isPColumnSpec(spec: PObjectSpec): spec is PColumnSpec {\n return spec.kind === \"PColumn\";\n}\n\nexport function isPColumn<T>(obj: PObject<T>): obj is PColumn<T> {\n return isPColumnSpec(obj.spec);\n}\n\nexport function isPColumnSpecResult(\n r: ResultPoolEntry<PObjectSpec>,\n): r is ResultPoolEntry<PColumnSpec> {\n return isPColumnSpec(r.obj);\n}\n\nexport function isPColumnResult<T>(\n r: ResultPoolEntry<PObject<T>>,\n): r is ResultPoolEntry<PColumn<T>> {\n return isPColumnSpec(r.obj.spec);\n}\n\nexport function ensurePColumn<T>(obj: PObject<T>): PColumn<T> {\n if (!isPColumn(obj)) throw new Error(`not a PColumn (kind = ${obj.spec.kind})`);\n return obj;\n}\n\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | PColumnLazy<D1>,\n cb: (d: D1) => D2,\n): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(pObj: PColumn<D1>, cb: (d: D1) => D2): PColumn<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PColumn<D1> | undefined,\n cb: (d: D1) => D2,\n): PColumn<D2> | undefined;\nexport function mapPObjectData<D1, D2>(pObj: PObject<D1>, cb: (d: D1) => D2): PObject<D2>;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined;\nexport function mapPObjectData<D1, D2>(\n pObj: PObject<D1> | undefined,\n cb: (d: D1) => D2,\n): PObject<D2> | undefined {\n return pObj === undefined\n ? undefined\n : {\n ...pObj,\n data: cb(typeof pObj.data === \"function\" ? pObj.data() : pObj.data),\n };\n}\n\nexport function extractAllColumns<D>(entry: JoinEntry<PColumn<D>>): PColumn<D>[] {\n const columns = new Map<PObjectId, PColumn<D>>();\n const addAllColumns = (entry: JoinEntry<PColumn<D>>) => {\n switch (entry.type) {\n case \"column\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"slicedColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"artificialColumn\":\n columns.set(entry.column.id, entry.column);\n return;\n case \"inlineColumn\":\n return;\n case \"full\":\n case \"inner\":\n for (const e of entry.entries) addAllColumns(e);\n return;\n case \"outer\":\n addAllColumns(entry.primary);\n for (const e of entry.secondary) addAllColumns(e);\n return;\n default:\n assertNever(entry);\n }\n };\n addAllColumns(entry);\n return [...columns.values()];\n}\n"],"mappings":";;;AA2CA,SAAgB,cAAc,MAAwC;AACpE,QAAO,KAAK,SAAS;;AAGvB,SAAgB,UAAa,KAAoC;AAC/D,QAAO,cAAc,IAAI,KAAK;;AAGhC,SAAgB,oBACd,GACmC;AACnC,QAAO,cAAc,EAAE,IAAI;;AAG7B,SAAgB,gBACd,GACkC;AAClC,QAAO,cAAc,EAAE,IAAI,KAAK;;AAGlC,SAAgB,cAAiB,KAA6B;AAC5D,KAAI,CAAC,UAAU,IAAI,CAAE,OAAM,IAAI,MAAM,yBAAyB,IAAI,KAAK,KAAK,GAAG;AAC/E,QAAO;;AAiBT,SAAgB,eACd,MACA,IACyB;AACzB,QAAO,SAAS,SACZ,SACA;EACE,GAAG;EACH,MAAM,GAAG,OAAO,KAAK,SAAS,aAAa,KAAK,MAAM,GAAG,KAAK,KAAK;EACpE;;AAGP,SAAgB,kBAAqB,OAA4C;CAC/E,MAAM,0BAAU,IAAI,KAA4B;CAChD,MAAM,iBAAiB,UAAiC;AACtD,UAAQ,MAAM,MAAd;GACE,KAAK;AACH,YAAQ,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AAC1C;GACF,KAAK;AACH,YAAQ,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AAC1C;GACF,KAAK;AACH,YAAQ,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AAC1C;GACF,KAAK,eACH;GACF,KAAK;GACL,KAAK;AACH,SAAK,MAAM,KAAK,MAAM,QAAS,eAAc,EAAE;AAC/C;GACF,KAAK;AACH,kBAAc,MAAM,QAAQ;AAC5B,SAAK,MAAM,KAAK,MAAM,UAAW,eAAc,EAAE;AACjD;GACF,QACE,aAAY,MAAM;;;AAGxB,eAAc,MAAM;AACpB,QAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-model-common",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"description": "Platforma SDK Model",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/**/*",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"@vitest/coverage-istanbul": "^4.0.18",
|
|
26
26
|
"typescript": "~5.9.3",
|
|
27
27
|
"vitest": "^4.0.18",
|
|
28
|
-
"@milaboratories/
|
|
29
|
-
"@milaboratories/
|
|
30
|
-
"@milaboratories/ts-
|
|
28
|
+
"@milaboratories/ts-configs": "1.2.2",
|
|
29
|
+
"@milaboratories/build-configs": "1.5.2",
|
|
30
|
+
"@milaboratories/ts-builder": "1.3.0"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "ts-builder build --target node",
|
|
@@ -54,7 +54,7 @@ type ColumnIdAndSpec = {
|
|
|
54
54
|
* {
|
|
55
55
|
* entry: querySpec,
|
|
56
56
|
* qualifications: [
|
|
57
|
-
* { axis: { name: 'sample' },
|
|
57
|
+
* { axis: { name: 'sample' }, contextDomain: { ... } }
|
|
58
58
|
* ]
|
|
59
59
|
* }
|
|
60
60
|
*/
|
|
@@ -64,7 +64,7 @@ export type SpecQueryJoinEntry<C = PObjectId> = QueryJoinEntry<SpecQuery<C>> & {
|
|
|
64
64
|
/** Axis selector identifying which axis to qualify */
|
|
65
65
|
axis: SingleAxisSelector;
|
|
66
66
|
/** Additional domain constraints for this axis */
|
|
67
|
-
|
|
67
|
+
contextDomain: Domain;
|
|
68
68
|
}[];
|
|
69
69
|
};
|
|
70
70
|
|
|
@@ -242,8 +242,8 @@ describe("sortSpecQuery", () => {
|
|
|
242
242
|
{
|
|
243
243
|
entry: pcol("a"),
|
|
244
244
|
qualifications: [
|
|
245
|
-
{ axis: { name: "z" },
|
|
246
|
-
{ axis: { name: "a" },
|
|
245
|
+
{ axis: { name: "z" }, contextDomain: {} },
|
|
246
|
+
{ axis: { name: "a" }, contextDomain: {} },
|
|
247
247
|
],
|
|
248
248
|
},
|
|
249
249
|
],
|
|
@@ -32,16 +32,19 @@ function domainKey(key: string, value: string): string {
|
|
|
32
32
|
*/
|
|
33
33
|
export class AnchoredIdDeriver {
|
|
34
34
|
private readonly domains = new Map<string, string>();
|
|
35
|
+
private readonly contextDomains = new Map<string, string>();
|
|
35
36
|
private readonly axes = new Map<string, AnchorAxisRefByIdx>();
|
|
36
37
|
/**
|
|
37
38
|
* Domain packs are used to group domain keys that can be anchored to the same anchor
|
|
38
39
|
* This is used to optimize the lookup of domain anchors
|
|
39
40
|
*/
|
|
40
41
|
private readonly domainPacks: string[][] = [];
|
|
42
|
+
private readonly contextDomainPacks: string[][] = [];
|
|
41
43
|
/**
|
|
42
44
|
* Maps domain packs to anchors
|
|
43
45
|
*/
|
|
44
46
|
private readonly domainPackToAnchor = new Map<string, string>();
|
|
47
|
+
private readonly contextDomainPackToAnchor = new Map<string, string>();
|
|
45
48
|
|
|
46
49
|
/**
|
|
47
50
|
* Creates a new anchor context from a set of anchor column specifications
|
|
@@ -68,6 +71,18 @@ export class AnchoredIdDeriver {
|
|
|
68
71
|
this.domains.set(key, anchorId);
|
|
69
72
|
}
|
|
70
73
|
}
|
|
74
|
+
if (spec.contextDomain !== undefined) {
|
|
75
|
+
const contextDomainEntries = Object.entries(spec.contextDomain);
|
|
76
|
+
contextDomainEntries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
77
|
+
|
|
78
|
+
this.contextDomainPackToAnchor.set(JSON.stringify(contextDomainEntries), anchorId);
|
|
79
|
+
this.contextDomainPacks.push(contextDomainEntries.map(([dKey]) => dKey));
|
|
80
|
+
|
|
81
|
+
for (const [dKey, dValue] of contextDomainEntries) {
|
|
82
|
+
const key = domainKey(dKey, dValue);
|
|
83
|
+
this.contextDomains.set(key, anchorId);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
88
|
|
|
@@ -121,6 +136,32 @@ export class AnchoredIdDeriver {
|
|
|
121
136
|
result.domain[dKey] = anchorId ? { anchor: anchorId } : dValue;
|
|
122
137
|
}
|
|
123
138
|
|
|
139
|
+
let skipContextDomains: Set<string> | undefined = undefined;
|
|
140
|
+
if (spec.contextDomain !== undefined) {
|
|
141
|
+
outer: for (const contextDomainPack of this.contextDomainPacks) {
|
|
142
|
+
const dAnchor: string[][] = [];
|
|
143
|
+
for (const domainKey of contextDomainPack) {
|
|
144
|
+
const dValue = spec.contextDomain[domainKey];
|
|
145
|
+
if (dValue !== undefined) dAnchor.push([domainKey, dValue]);
|
|
146
|
+
else break outer;
|
|
147
|
+
}
|
|
148
|
+
const contextDomainAnchor = this.contextDomainPackToAnchor.get(JSON.stringify(dAnchor));
|
|
149
|
+
if (contextDomainAnchor !== undefined) {
|
|
150
|
+
result.contextDomainAnchor = contextDomainAnchor;
|
|
151
|
+
skipContextDomains = new Set(contextDomainPack);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
for (const [dKey, dValue] of Object.entries(spec.contextDomain ?? {})) {
|
|
158
|
+
if (skipContextDomains !== undefined && skipContextDomains.has(dKey)) continue;
|
|
159
|
+
const key = domainKey(dKey, dValue);
|
|
160
|
+
const anchorId = this.contextDomains.get(key);
|
|
161
|
+
result.contextDomain ??= {};
|
|
162
|
+
result.contextDomain[dKey] = anchorId ? { anchor: anchorId } : dValue;
|
|
163
|
+
}
|
|
164
|
+
|
|
124
165
|
result.axes = spec.axesSpec.map((axis) => {
|
|
125
166
|
const key = axisKey(axis);
|
|
126
167
|
const anchorAxisRef = this.axes.get(key);
|
|
@@ -239,6 +280,38 @@ export function resolveAnchors(
|
|
|
239
280
|
result.domain = resolvedDomain;
|
|
240
281
|
}
|
|
241
282
|
|
|
283
|
+
if (result.contextDomainAnchor !== undefined) {
|
|
284
|
+
const anchorSpec = anchors[result.contextDomainAnchor];
|
|
285
|
+
if (!anchorSpec) throw new Error(`Anchor "${result.contextDomainAnchor}" not found`);
|
|
286
|
+
|
|
287
|
+
const anchorContextDomains = anchorSpec.contextDomain || {};
|
|
288
|
+
result.contextDomain = { ...anchorContextDomains, ...result.contextDomain };
|
|
289
|
+
delete result.contextDomainAnchor;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (result.contextDomain) {
|
|
293
|
+
const resolvedContextDomain: Record<string, string> = {};
|
|
294
|
+
for (const [key, value] of Object.entries(result.contextDomain)) {
|
|
295
|
+
if (typeof value === "string") {
|
|
296
|
+
resolvedContextDomain[key] = value;
|
|
297
|
+
} else {
|
|
298
|
+
// It's an AnchorDomainRef
|
|
299
|
+
const anchorSpec = anchors[value.anchor];
|
|
300
|
+
if (!anchorSpec)
|
|
301
|
+
throw new Error(`Anchor "${value.anchor}" not found for contextDomain key "${key}"`);
|
|
302
|
+
|
|
303
|
+
if (!anchorSpec.contextDomain || anchorSpec.contextDomain[key] === undefined) {
|
|
304
|
+
if (!ignoreMissingDomains)
|
|
305
|
+
throw new Error(`Context domain key "${key}" not found in anchor "${value.anchor}"`);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
resolvedContextDomain[key] = anchorSpec.contextDomain[key];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
result.contextDomain = resolvedContextDomain;
|
|
313
|
+
}
|
|
314
|
+
|
|
242
315
|
if (result.axes) result.axes = result.axes.map((axis) => resolveAxisReference(anchors, axis));
|
|
243
316
|
|
|
244
317
|
return result as PColumnSelector;
|
|
@@ -10,6 +10,7 @@ export function deriveNativeId(spec: PObjectSpec): NativePObjectId {
|
|
|
10
10
|
name: spec.name,
|
|
11
11
|
};
|
|
12
12
|
if (spec.domain !== undefined) result.domain = spec.domain;
|
|
13
|
+
if (spec.contextDomain !== undefined) result.contextDomain = spec.contextDomain;
|
|
13
14
|
if (isPColumnSpec(spec)) result.axesSpec = getAxesId(spec.axesSpec);
|
|
14
15
|
return canonicalize(result) as NativePObjectId;
|
|
15
16
|
}
|
|
@@ -35,6 +35,13 @@ export interface AxisSelector {
|
|
|
35
35
|
* An axis with additional domain entries not present in this selector will still match.
|
|
36
36
|
*/
|
|
37
37
|
domain?: Record<string, string>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Optional context domain key-value pairs to match against.
|
|
41
|
+
* Context domains are matched by kinship rules (subset/superset/overlap) rather than exact equality.
|
|
42
|
+
* When specified, an axis will match only if it contains all the key-value pairs defined here.
|
|
43
|
+
*/
|
|
44
|
+
contextDomain?: Record<string, string>;
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
/** Single axis selector */
|
|
@@ -112,6 +119,11 @@ export interface AnchoredPColumnSelector {
|
|
|
112
119
|
/** Optional domain values to match, can include anchored references, if domainAnchor is specified,
|
|
113
120
|
* interpreted as additional domains to domain from the anchor */
|
|
114
121
|
domain?: Record<string, ADomain>;
|
|
122
|
+
/** If specified, the context domain values must be anchored to this anchor */
|
|
123
|
+
contextDomainAnchor?: string;
|
|
124
|
+
/** Optional context domain values to match, can include anchored references, if contextDomainAnchor is specified,
|
|
125
|
+
* interpreted as additional context domains to context domain from the anchor */
|
|
126
|
+
contextDomain?: Record<string, ADomain>;
|
|
115
127
|
/** Optional axes to match, can include anchored references */
|
|
116
128
|
axes?: AAxisSelector[];
|
|
117
129
|
/** When true, allows matching if only a subset of axes match */
|
|
@@ -130,6 +142,8 @@ export interface AnchoredPColumnSelector {
|
|
|
130
142
|
export interface PColumnSelector extends AnchoredPColumnSelector {
|
|
131
143
|
domainAnchor?: never;
|
|
132
144
|
domain?: Record<string, string>;
|
|
145
|
+
contextDomainAnchor?: never;
|
|
146
|
+
contextDomain?: Record<string, string>;
|
|
133
147
|
axes?: AxisSelector[];
|
|
134
148
|
}
|
|
135
149
|
|
|
@@ -193,6 +207,13 @@ export function matchAxis(selector: AxisSelector, axis: AxisId): boolean {
|
|
|
193
207
|
if (axisDomain[key] !== value) return false;
|
|
194
208
|
}
|
|
195
209
|
|
|
210
|
+
// Match contextDomain if specified
|
|
211
|
+
if (selector.contextDomain !== undefined) {
|
|
212
|
+
const axisContextDomain = axis.contextDomain || {};
|
|
213
|
+
for (const [key, value] of Object.entries(selector.contextDomain))
|
|
214
|
+
if (axisContextDomain[key] !== value) return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
196
217
|
return true;
|
|
197
218
|
}
|
|
198
219
|
|
|
@@ -227,6 +248,13 @@ export function matchPColumn(pcolumn: PColumnSpec, selector: PColumnSelector): b
|
|
|
227
248
|
if (columnDomain[key] !== value) return false;
|
|
228
249
|
}
|
|
229
250
|
|
|
251
|
+
// Match contextDomain if specified
|
|
252
|
+
if (selector.contextDomain !== undefined) {
|
|
253
|
+
const columnContextDomain = pcolumn.contextDomain || {};
|
|
254
|
+
for (const [key, value] of Object.entries(selector.contextDomain))
|
|
255
|
+
if (columnContextDomain[key] !== value) return false;
|
|
256
|
+
}
|
|
257
|
+
|
|
230
258
|
// Match axes if specified
|
|
231
259
|
if (selector.axes !== undefined) {
|
|
232
260
|
const pcolumnAxes = pcolumn.axesSpec.map(getAxisId);
|
|
@@ -312,6 +312,10 @@ export type AxisSpec = {
|
|
|
312
312
|
* unique identifier */
|
|
313
313
|
readonly domain?: Record<string, string>;
|
|
314
314
|
|
|
315
|
+
/** Context domain provides additional axis identity that is matched
|
|
316
|
+
* by kinship rules (subset/superset/overlap) rather than exact equality */
|
|
317
|
+
readonly contextDomain?: Record<string, string>;
|
|
318
|
+
|
|
315
319
|
/** Any additional information attached to the axis that does not affect its
|
|
316
320
|
* identifier */
|
|
317
321
|
readonly annotations?: Record<string, string>;
|
|
@@ -421,6 +425,12 @@ function normalizingAxesComparator(
|
|
|
421
425
|
return domain1 < domain2 ? 1 : -1;
|
|
422
426
|
}
|
|
423
427
|
|
|
428
|
+
const contextDomain1 = canonicalizeJson(axis1.contextDomain ?? {});
|
|
429
|
+
const contextDomain2 = canonicalizeJson(axis2.contextDomain ?? {});
|
|
430
|
+
if (contextDomain1 !== contextDomain2) {
|
|
431
|
+
return contextDomain1 < contextDomain2 ? 1 : -1;
|
|
432
|
+
}
|
|
433
|
+
|
|
424
434
|
const parents1 = canonicalizeAxisWithParents(axis1);
|
|
425
435
|
const parents2 = canonicalizeAxisWithParents(axis2);
|
|
426
436
|
|
|
@@ -592,6 +602,10 @@ export type PUniversalColumnSpec = PObjectSpec & {
|
|
|
592
602
|
* unique identifier */
|
|
593
603
|
readonly domain?: Record<string, string>;
|
|
594
604
|
|
|
605
|
+
/** Context domain provides additional column identity that is matched
|
|
606
|
+
* by kinship rules (subset/superset/overlap) rather than exact equality */
|
|
607
|
+
readonly contextDomain?: Record<string, string>;
|
|
608
|
+
|
|
595
609
|
/** Any additional information attached to the column that does not affect its
|
|
596
610
|
* identifier */
|
|
597
611
|
readonly annotations?: Record<string, string>;
|
|
@@ -635,6 +649,10 @@ export type PColumnSpecId = {
|
|
|
635
649
|
* unique identifier */
|
|
636
650
|
readonly domain?: Record<string, string>;
|
|
637
651
|
|
|
652
|
+
/** Context domain provides additional column identity that is matched
|
|
653
|
+
* by kinship rules (subset/superset/overlap) rather than exact equality */
|
|
654
|
+
readonly contextDomain?: Record<string, string>;
|
|
655
|
+
|
|
638
656
|
/** A list of zero-based indices of parent axes from the {@link axesSpec} array. */
|
|
639
657
|
readonly parentAxes?: number[];
|
|
640
658
|
|
|
@@ -648,6 +666,7 @@ export function getPColumnSpecId(spec: PColumnSpec): PColumnSpecId {
|
|
|
648
666
|
valueType: spec.valueType,
|
|
649
667
|
name: spec.name,
|
|
650
668
|
domain: spec.domain,
|
|
669
|
+
contextDomain: spec.contextDomain,
|
|
651
670
|
parentAxes: spec.parentAxes,
|
|
652
671
|
axesId: getAxesId(spec.axesSpec),
|
|
653
672
|
};
|
|
@@ -695,6 +714,10 @@ export interface AxisId {
|
|
|
695
714
|
/** Adds auxiliary information to the axis or column name and type to form a
|
|
696
715
|
* unique identifier */
|
|
697
716
|
readonly domain?: Record<string, string>;
|
|
717
|
+
|
|
718
|
+
/** Context domain provides additional axis identity that is matched
|
|
719
|
+
* by kinship rules (subset/superset/overlap) rather than exact equality */
|
|
720
|
+
readonly contextDomain?: Record<string, string>;
|
|
698
721
|
}
|
|
699
722
|
|
|
700
723
|
/** Array of axis ids */
|
|
@@ -702,11 +725,14 @@ export type AxesId = AxisId[];
|
|
|
702
725
|
|
|
703
726
|
/** Extracts axis ids from axis spec */
|
|
704
727
|
export function getAxisId(spec: AxisSpec): AxisId {
|
|
705
|
-
const { type, name, domain } = spec;
|
|
706
|
-
const result = { type, name };
|
|
728
|
+
const { type, name, domain, contextDomain } = spec;
|
|
729
|
+
const result: AxisId = { type, name };
|
|
707
730
|
if (domain && Object.entries(domain).length > 0) {
|
|
708
731
|
Object.assign(result, { domain });
|
|
709
732
|
}
|
|
733
|
+
if (contextDomain && Object.entries(contextDomain).length > 0) {
|
|
734
|
+
Object.assign(result, { contextDomain });
|
|
735
|
+
}
|
|
710
736
|
return result;
|
|
711
737
|
}
|
|
712
738
|
|
|
@@ -732,7 +758,11 @@ function matchDomain(query?: Record<string, string>, target?: Record<string, str
|
|
|
732
758
|
|
|
733
759
|
/** Returns whether "match" axis id is compatible with the "query" */
|
|
734
760
|
export function matchAxisId(query: AxisId, target: AxisId): boolean {
|
|
735
|
-
return
|
|
761
|
+
return (
|
|
762
|
+
query.name === target.name &&
|
|
763
|
+
matchDomain(query.domain, target.domain) &&
|
|
764
|
+
matchDomain(query.contextDomain, target.contextDomain)
|
|
765
|
+
);
|
|
736
766
|
}
|
|
737
767
|
|
|
738
768
|
export function getTypeFromPColumnOrAxisSpec(spec: PColumnSpec | AxisSpec): ValueType {
|
package/src/flags/block_flags.ts
CHANGED
|
@@ -16,12 +16,13 @@ export type BlockCodeFeatureFlags = Record<`supports${string}`, boolean | number
|
|
|
16
16
|
*/
|
|
17
17
|
export type BlockCodeKnownFeatureFlags = {
|
|
18
18
|
readonly supportsLazyState?: boolean;
|
|
19
|
+
readonly supportsPframeQueryRanking?: boolean;
|
|
19
20
|
readonly requiresModelAPIVersion?: number;
|
|
20
21
|
readonly requiresUIAPIVersion?: number;
|
|
21
22
|
readonly requiresCreatePTable?: number;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
export const AllSupportsFeatureFlags = ["supportsLazyState"] as const;
|
|
25
|
+
export const AllSupportsFeatureFlags = ["supportsLazyState", "supportsPframeQueryRanking"] as const;
|
|
25
26
|
|
|
26
27
|
export const AllRequiresFeatureFlags = [
|
|
27
28
|
"requiresUIAPIVersion",
|
package/src/pool/query.ts
CHANGED
|
@@ -80,6 +80,12 @@ export function executePSpecPredicate(predicate: PSpecPredicate, spec: PObjectSp
|
|
|
80
80
|
(axisSpec.domain !== undefined &&
|
|
81
81
|
Object.entries(matcher.domain).every(
|
|
82
82
|
([domain, domainValue]) => axisSpec.domain![domain] === domainValue,
|
|
83
|
+
))) &&
|
|
84
|
+
(matcher.contextDomain === undefined ||
|
|
85
|
+
Object.keys(matcher.contextDomain).length === 0 ||
|
|
86
|
+
(axisSpec.contextDomain !== undefined &&
|
|
87
|
+
Object.entries(matcher.contextDomain).every(
|
|
88
|
+
([key, value]) => axisSpec.contextDomain![key] === value,
|
|
83
89
|
))),
|
|
84
90
|
),
|
|
85
91
|
)
|
package/src/pool/spec.ts
CHANGED
|
@@ -14,6 +14,10 @@ export type PObjectSpec = {
|
|
|
14
14
|
/** Domain is a set of key-value pairs that can be used to identify the object */
|
|
15
15
|
readonly domain?: Record<string, string>;
|
|
16
16
|
|
|
17
|
+
/** Context domain provides additional axis/column identity that is matched
|
|
18
|
+
* by kinship rules (subset/superset/overlap) rather than exact equality */
|
|
19
|
+
readonly contextDomain?: Record<string, string>;
|
|
20
|
+
|
|
17
21
|
/** Additional information attached to the object */
|
|
18
22
|
readonly annotations?: Record<string, string>;
|
|
19
23
|
};
|