@kaskad/schema 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +217 -0
  2. package/esm2022/index.js +17 -0
  3. package/esm2022/index.js.map +1 -0
  4. package/esm2022/kaskad-schema.js +5 -0
  5. package/esm2022/kaskad-schema.js.map +1 -0
  6. package/esm2022/lib/load/load-schema.js +16 -0
  7. package/esm2022/lib/load/load-schema.js.map +1 -0
  8. package/esm2022/lib/load/load-templates.js +136 -0
  9. package/esm2022/lib/load/load-templates.js.map +1 -0
  10. package/esm2022/lib/load/register-declared-type.js +28 -0
  11. package/esm2022/lib/load/register-declared-type.js.map +1 -0
  12. package/esm2022/lib/load/schema-component-extractor.js +101 -0
  13. package/esm2022/lib/load/schema-component-extractor.js.map +1 -0
  14. package/esm2022/lib/load/template-registry.js +51 -0
  15. package/esm2022/lib/load/template-registry.js.map +1 -0
  16. package/esm2022/lib/types/component-definition.js +1 -0
  17. package/esm2022/lib/types/component-definition.js.map +1 -0
  18. package/esm2022/lib/types/component-schema.js +1 -0
  19. package/esm2022/lib/types/component-schema.js.map +1 -0
  20. package/esm2022/lib/types/raw-schemas.js +3 -0
  21. package/esm2022/lib/types/raw-schemas.js.map +1 -0
  22. package/esm2022/lib/types/template-raw-definition.js +1 -0
  23. package/esm2022/lib/types/template-raw-definition.js.map +1 -0
  24. package/esm2022/lib/unfolding/computation/unfold-computation-schema.js +70 -0
  25. package/esm2022/lib/unfolding/computation/unfold-computation-schema.js.map +1 -0
  26. package/esm2022/lib/unfolding/computation/unfold-for-new-syntax.js +147 -0
  27. package/esm2022/lib/unfolding/computation/unfold-for-new-syntax.js.map +1 -0
  28. package/esm2022/lib/unfolding/computation/unfold-for.js +45 -0
  29. package/esm2022/lib/unfolding/computation/unfold-for.js.map +1 -0
  30. package/esm2022/lib/unfolding/computation/unfold-if.js +18 -0
  31. package/esm2022/lib/unfolding/computation/unfold-if.js.map +1 -0
  32. package/esm2022/lib/unfolding/computation/unfold-import.js +26 -0
  33. package/esm2022/lib/unfolding/computation/unfold-import.js.map +1 -0
  34. package/esm2022/lib/unfolding/computation/unfold-interpolation.js +44 -0
  35. package/esm2022/lib/unfolding/computation/unfold-interpolation.js.map +1 -0
  36. package/esm2022/lib/unfolding/parse-binding-shorthand.js +40 -0
  37. package/esm2022/lib/unfolding/parse-binding-shorthand.js.map +1 -0
  38. package/esm2022/lib/unfolding/parse-property-key-shorthand.js +9 -0
  39. package/esm2022/lib/unfolding/parse-property-key-shorthand.js.map +1 -0
  40. package/esm2022/lib/unfolding/parse-value-type.js +115 -0
  41. package/esm2022/lib/unfolding/parse-value-type.js.map +1 -0
  42. package/esm2022/lib/unfolding/to-full-notation.js +124 -0
  43. package/esm2022/lib/unfolding/to-full-notation.js.map +1 -0
  44. package/esm2022/lib/unfolding/unfold-flat-wrapper-notation.js +72 -0
  45. package/esm2022/lib/unfolding/unfold-flat-wrapper-notation.js.map +1 -0
  46. package/esm2022/lib/unfolding/unfold-node-schema.js +35 -0
  47. package/esm2022/lib/unfolding/unfold-node-schema.js.map +1 -0
  48. package/esm2022/lib/unfolding/unfold-property.js +21 -0
  49. package/esm2022/lib/unfolding/unfold-property.js.map +1 -0
  50. package/esm2022/lib/unfolding/value/handlers/index.js +11 -0
  51. package/esm2022/lib/unfolding/value/handlers/index.js.map +1 -0
  52. package/esm2022/lib/unfolding/value/handlers/unfold-array.js +9 -0
  53. package/esm2022/lib/unfolding/value/handlers/unfold-array.js.map +1 -0
  54. package/esm2022/lib/unfolding/value/handlers/unfold-boolean.js +8 -0
  55. package/esm2022/lib/unfolding/value/handlers/unfold-boolean.js.map +1 -0
  56. package/esm2022/lib/unfolding/value/handlers/unfold-command.js +22 -0
  57. package/esm2022/lib/unfolding/value/handlers/unfold-command.js.map +1 -0
  58. package/esm2022/lib/unfolding/value/handlers/unfold-component-schema.js +14 -0
  59. package/esm2022/lib/unfolding/value/handlers/unfold-component-schema.js.map +1 -0
  60. package/esm2022/lib/unfolding/value/handlers/unfold-component.js +66 -0
  61. package/esm2022/lib/unfolding/value/handlers/unfold-component.js.map +1 -0
  62. package/esm2022/lib/unfolding/value/handlers/unfold-map.js +13 -0
  63. package/esm2022/lib/unfolding/value/handlers/unfold-map.js.map +1 -0
  64. package/esm2022/lib/unfolding/value/handlers/unfold-number.js +11 -0
  65. package/esm2022/lib/unfolding/value/handlers/unfold-number.js.map +1 -0
  66. package/esm2022/lib/unfolding/value/handlers/unfold-object.js +15 -0
  67. package/esm2022/lib/unfolding/value/handlers/unfold-object.js.map +1 -0
  68. package/esm2022/lib/unfolding/value/handlers/unfold-set.js +6 -0
  69. package/esm2022/lib/unfolding/value/handlers/unfold-set.js.map +1 -0
  70. package/esm2022/lib/unfolding/value/handlers/unfold-shape.js +13 -0
  71. package/esm2022/lib/unfolding/value/handlers/unfold-shape.js.map +1 -0
  72. package/esm2022/lib/unfolding/value/handlers/unfold-string.js +8 -0
  73. package/esm2022/lib/unfolding/value/handlers/unfold-string.js.map +1 -0
  74. package/esm2022/lib/unfolding/value/handlers/unfold-unknown.js +4 -0
  75. package/esm2022/lib/unfolding/value/handlers/unfold-unknown.js.map +1 -0
  76. package/esm2022/lib/unfolding/value/handlers/unfold-variant-shape.js +61 -0
  77. package/esm2022/lib/unfolding/value/handlers/unfold-variant-shape.js.map +1 -0
  78. package/esm2022/lib/unfolding/value/handlers/validate-props.js +20 -0
  79. package/esm2022/lib/unfolding/value/handlers/validate-props.js.map +1 -0
  80. package/esm2022/lib/unfolding/value/throw-unfold-value-error.js +11 -0
  81. package/esm2022/lib/unfolding/value/throw-unfold-value-error.js.map +1 -0
  82. package/esm2022/lib/unfolding/value/unfold-node-value.js +30 -0
  83. package/esm2022/lib/unfolding/value/unfold-node-value.js.map +1 -0
  84. package/esm2022/lib/util/is-object.js +4 -0
  85. package/esm2022/lib/util/is-object.js.map +1 -0
  86. package/esm2022/lib/util/stringify-object.js +4 -0
  87. package/esm2022/lib/util/stringify-object.js.map +1 -0
  88. package/esm2022/lib/util/unfold-component-definitions.js +21 -0
  89. package/esm2022/lib/util/unfold-component-definitions.js.map +1 -0
  90. package/index.d.ts +16 -0
  91. package/kaskad-schema.d.ts +5 -0
  92. package/lib/load/load-schema.d.ts +3 -0
  93. package/lib/load/load-templates.d.ts +2 -0
  94. package/lib/load/register-declared-type.d.ts +1 -0
  95. package/lib/load/schema-component-extractor.d.ts +2 -0
  96. package/lib/load/template-registry.d.ts +16 -0
  97. package/lib/types/component-definition.d.ts +5 -0
  98. package/lib/types/component-schema.d.ts +26 -0
  99. package/lib/types/raw-schemas.d.ts +25 -0
  100. package/lib/types/template-raw-definition.d.ts +7 -0
  101. package/lib/unfolding/computation/unfold-computation-schema.d.ts +2 -0
  102. package/lib/unfolding/computation/unfold-for-new-syntax.d.ts +6 -0
  103. package/lib/unfolding/computation/unfold-for.d.ts +2 -0
  104. package/lib/unfolding/computation/unfold-if.d.ts +3 -0
  105. package/lib/unfolding/computation/unfold-import.d.ts +2 -0
  106. package/lib/unfolding/computation/unfold-interpolation.d.ts +3 -0
  107. package/lib/unfolding/parse-binding-shorthand.d.ts +3 -0
  108. package/lib/unfolding/parse-property-key-shorthand.d.ts +2 -0
  109. package/lib/unfolding/parse-value-type.d.ts +2 -0
  110. package/lib/unfolding/to-full-notation.d.ts +8 -0
  111. package/lib/unfolding/unfold-flat-wrapper-notation.d.ts +13 -0
  112. package/lib/unfolding/unfold-node-schema.d.ts +3 -0
  113. package/lib/unfolding/unfold-property.d.ts +2 -0
  114. package/lib/unfolding/value/handlers/index.d.ts +10 -0
  115. package/lib/unfolding/value/handlers/unfold-array.d.ts +3 -0
  116. package/lib/unfolding/value/handlers/unfold-boolean.d.ts +2 -0
  117. package/lib/unfolding/value/handlers/unfold-command.d.ts +3 -0
  118. package/lib/unfolding/value/handlers/unfold-component-schema.d.ts +4 -0
  119. package/lib/unfolding/value/handlers/unfold-component.d.ts +3 -0
  120. package/lib/unfolding/value/handlers/unfold-map.d.ts +3 -0
  121. package/lib/unfolding/value/handlers/unfold-number.d.ts +2 -0
  122. package/lib/unfolding/value/handlers/unfold-object.d.ts +3 -0
  123. package/lib/unfolding/value/handlers/unfold-set.d.ts +3 -0
  124. package/lib/unfolding/value/handlers/unfold-shape.d.ts +3 -0
  125. package/lib/unfolding/value/handlers/unfold-string.d.ts +2 -0
  126. package/lib/unfolding/value/handlers/unfold-unknown.d.ts +2 -0
  127. package/lib/unfolding/value/handlers/unfold-variant-shape.d.ts +3 -0
  128. package/lib/unfolding/value/handlers/validate-props.d.ts +2 -0
  129. package/lib/unfolding/value/throw-unfold-value-error.d.ts +2 -0
  130. package/lib/unfolding/value/unfold-node-value.d.ts +8 -0
  131. package/lib/util/is-object.d.ts +1 -0
  132. package/lib/util/stringify-object.d.ts +1 -0
  133. package/lib/util/unfold-component-definitions.d.ts +4 -0
  134. package/package.json +28 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-definition.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/types/component-definition.ts"],"names":[],"mappings":"","sourcesContent":["export type ComponentRawDefinition = {\n readonly traits?: string[];\n readonly properties: Record<string, unknown>;\n readonly defaultSlot?: string;\n};\n"]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=component-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-schema.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/types/component-schema.ts"],"names":[],"mappings":"","sourcesContent":["import { ComponentRef } from '@kaskad/types';\n\nexport type Defer = {\n placeholder?: { componentType: string } & { [key: string]: unknown };\n error?: { componentType: string } & { [key: string]: unknown };\n};\n\nexport interface NodeChangeHandlerRecipe {\n selector: string;\n command: unknown;\n}\n\nexport interface ComponentRecipe {\n ref?: ComponentRef;\n componentType: string;\n onNodeChange?: NodeChangeHandlerRecipe[];\n [propOrVariable: string]: unknown;\n}\n\nexport type TemplateRecipe = Omit<ComponentRecipe, 'componentType'> & {\n templateUrl: string;\n};\n"]}
@@ -0,0 +1,3 @@
1
+ // Recipe types used for unfolding
2
+ // These types represent the raw input format before normalization
3
+ //# sourceMappingURL=raw-schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-schemas.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/types/raw-schemas.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,kEAAkE","sourcesContent":["// Recipe types used for unfolding\n// These types represent the raw input format before normalization\n\nexport type FormulaComputationRecipe = {\n formula: string;\n};\n\nexport type ForComputationRecipe = {\n items: unknown[];\n as?: {\n item: unknown;\n index: unknown;\n first?: unknown;\n last?: unknown;\n };\n yield: unknown;\n};\n\nexport type IfComputationRecipe = Record<'if' | 'then' | 'else', unknown> | ({ if: unknown } & Record<string, unknown>);\n\nexport type SwitchComputationRecipe = {\n computationType: 'switch';\n source: unknown;\n cases: { equals: unknown; then: unknown }[];\n default: unknown;\n};\n"]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=template-raw-definition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-raw-definition.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/types/template-raw-definition.ts"],"names":[],"mappings":"","sourcesContent":["import { ComponentRecipe } from './component-schema';\n\nexport interface TemplateRecipeDefinition extends ComponentRecipe {\n types?: Record<string, string | Record<string, string>>;\n importTypes?: string[];\n contract?: Record<string, string>;\n defaultSlot?: string;\n}\n"]}
@@ -0,0 +1,70 @@
1
+ import { isObject } from '../../util/is-object';
2
+ import { stringifyObject } from '../../util/stringify-object';
3
+ import { unfoldNodeSchema } from '../unfold-node-schema';
4
+ import { unfoldForComputationSchema as unfoldFor } from './unfold-for';
5
+ import { unfoldForWithNewSyntax } from './unfold-for-new-syntax';
6
+ import { unfoldIfComputationSchema as unfoldIf } from './unfold-if';
7
+ import { unfoldImportComputationSchema as unfoldTemplate } from './unfold-import';
8
+ import { replaceInterpolationsInFormula, unfoldInterpolationComputationSchema } from './unfold-interpolation';
9
+ const unfoldFormula = (schema) => {
10
+ const result = {
11
+ computationType: 'formula',
12
+ formula: schema.formula,
13
+ [Symbol.for('type')]: 'ComputationSchema',
14
+ };
15
+ return result;
16
+ };
17
+ const unfoldSwitch = (schema) => {
18
+ return {
19
+ computationType: 'switch',
20
+ source: unfoldNodeSchema(schema.source, { type: 'unknown' }, []),
21
+ cases: schema.cases.map((c) => {
22
+ return {
23
+ equals: c.equals,
24
+ then: unfoldNodeSchema(c.then, { type: 'componentSchema' }),
25
+ };
26
+ }),
27
+ default: unfoldNodeSchema(schema.default, { type: 'componentSchema' }),
28
+ [Symbol.for('type')]: 'ComputationSchema',
29
+ };
30
+ };
31
+ export function unfoldComputationSchema(schema) {
32
+ if (typeof schema === 'string') {
33
+ if (schema.startsWith('=> ')) {
34
+ let formula = schema.slice(3);
35
+ if (formula.includes('{{')) {
36
+ formula = replaceInterpolationsInFormula(formula);
37
+ }
38
+ return { computationType: 'formula', formula };
39
+ }
40
+ if (schema.includes('{{') && schema.includes('}}')) {
41
+ return unfoldInterpolationComputationSchema(schema);
42
+ }
43
+ }
44
+ // Check for new for-loop syntax (before computationType check)
45
+ if (isObject(schema) && 'for' in schema && !('computationType' in schema)) {
46
+ return unfoldForWithNewSyntax(schema);
47
+ }
48
+ if (!isObject(schema) || !('computationType' in schema)) {
49
+ return null;
50
+ }
51
+ if (isUnfoldedComputationSchema(schema)) {
52
+ return schema;
53
+ }
54
+ const computationUnfolders = {
55
+ formula: (schema) => unfoldFormula(schema),
56
+ for: (schema) => unfoldFor(schema),
57
+ template: (schema) => unfoldTemplate(schema),
58
+ if: (schema) => unfoldIf(schema),
59
+ switch: (schema) => unfoldSwitch(schema),
60
+ };
61
+ const unfolder = computationUnfolders[schema['computationType']];
62
+ if (unfolder) {
63
+ return unfolder(schema);
64
+ }
65
+ throw new Error(`Unable to unfold computation schema.\n${stringifyObject('Schema', schema)}`);
66
+ }
67
+ function isUnfoldedComputationSchema(schema) {
68
+ return isObject(schema) && Symbol.for('type') in schema;
69
+ }
70
+ //# sourceMappingURL=unfold-computation-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unfold-computation-schema.js","sourceRoot":"","sources":["../../../../../../../libs/schema/src/lib/unfolding/computation/unfold-computation-schema.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ComponentSchemaNodeSchema,\n ComputationSchema,\n FormulaComputationSchema,\n SwitchComputationSchema,\n} from '@kaskad/types';\n\nimport { FormulaComputationRecipe, IfComputationRecipe, SwitchComputationRecipe } from '../../types/raw-schemas';\nimport { isObject } from '../../util/is-object';\nimport { stringifyObject } from '../../util/stringify-object';\nimport { unfoldNodeSchema } from '../unfold-node-schema';\nimport { unfoldForComputationSchema as unfoldFor } from './unfold-for';\nimport { unfoldForWithNewSyntax } from './unfold-for-new-syntax';\nimport { unfoldIfComputationSchema as unfoldIf } from './unfold-if';\nimport { unfoldImportComputationSchema as unfoldTemplate } from './unfold-import';\nimport { replaceInterpolationsInFormula, unfoldInterpolationComputationSchema } from './unfold-interpolation';\n\nconst unfoldFormula = (schema: FormulaComputationRecipe): ComputationSchema => {\n const result: FormulaComputationSchema = {\n computationType: 'formula',\n formula: schema.formula,\n [Symbol.for('type')]: 'ComputationSchema',\n };\n return result;\n};\n\nconst unfoldSwitch = (schema: SwitchComputationRecipe): SwitchComputationSchema => {\n return {\n computationType: 'switch',\n source: unfoldNodeSchema(schema.source, { type: 'unknown' }, []),\n cases: schema.cases.map((c) => {\n return {\n equals: c.equals,\n then: unfoldNodeSchema(c.then, { type: 'componentSchema' }) as ComponentSchemaNodeSchema,\n };\n }),\n default: unfoldNodeSchema(schema.default, { type: 'componentSchema' }) as ComponentSchemaNodeSchema,\n [Symbol.for('type')]: 'ComputationSchema',\n };\n};\n\nexport function unfoldComputationSchema(schema: unknown): ComputationSchema | null {\n if (typeof schema === 'string') {\n if (schema.startsWith('=> ')) {\n let formula = schema.slice(3);\n if (formula.includes('{{')) {\n formula = replaceInterpolationsInFormula(formula);\n }\n return { computationType: 'formula', formula } as FormulaComputationSchema;\n }\n\n if (schema.includes('{{') && schema.includes('}}')) {\n return unfoldInterpolationComputationSchema(schema);\n }\n }\n\n // Check for new for-loop syntax (before computationType check)\n if (isObject(schema) && 'for' in schema && !('computationType' in schema)) {\n return unfoldForWithNewSyntax(schema);\n }\n\n if (!isObject(schema) || !('computationType' in schema)) {\n return null;\n }\n\n if (isUnfoldedComputationSchema(schema)) {\n return schema;\n }\n\n const computationUnfolders: Record<string, (schema: unknown) => ComputationSchema | null> = {\n formula: (schema) => unfoldFormula(schema as FormulaComputationRecipe),\n for: (schema) => unfoldFor(schema),\n template: (schema) => unfoldTemplate(schema),\n if: (schema) => unfoldIf(schema as IfComputationRecipe),\n switch: (schema) => unfoldSwitch(schema as SwitchComputationRecipe),\n };\n\n const unfolder = computationUnfolders[schema['computationType'] as string];\n if (unfolder) {\n return unfolder(schema);\n }\n\n throw new Error(`Unable to unfold computation schema.\\n${stringifyObject('Schema', schema)}`);\n}\n\nfunction isUnfoldedComputationSchema(schema: unknown): schema is ComputationSchema {\n return isObject(schema) && Symbol.for('type') in schema;\n}\n"]}
@@ -0,0 +1,147 @@
1
+ import { isObject } from '../../util/is-object';
2
+ import { parseValueType } from '../parse-value-type';
3
+ import { unfoldNodeSchema } from '../unfold-node-schema';
4
+ /**
5
+ * Parses metadata object from the `with` clause
6
+ * Example: "index: $i, first: $isFirst, last: $isLast"
7
+ */
8
+ function parseMetadata(str) {
9
+ const result = {};
10
+ const trimmed = str.trim();
11
+ if (!trimmed) {
12
+ throw new Error('Empty metadata block. Omit "with" clause if no metadata is needed.');
13
+ }
14
+ const pairs = trimmed.split(',').map((s) => s.trim());
15
+ for (const pair of pairs) {
16
+ const colonIndex = pair.indexOf(':');
17
+ if (colonIndex === -1) {
18
+ throw new Error(`Invalid metadata pair: "${pair}". Expected format: "key: $value"`);
19
+ }
20
+ const key = pair.slice(0, colonIndex).trim();
21
+ const value = pair.slice(colonIndex + 1).trim();
22
+ if (!['index', 'first', 'last'].includes(key)) {
23
+ throw new Error(`Invalid metadata key: "${key}". Only "index", "first", and "last" are allowed.`);
24
+ }
25
+ if (!value || !value.startsWith('$')) {
26
+ throw new Error(`Invalid metadata value: "${value}". Must be a variable starting with $.`);
27
+ }
28
+ result[key] = value.slice(1); // Remove $
29
+ }
30
+ return result;
31
+ }
32
+ /**
33
+ * Parses a single for-loop specification
34
+ * Example: "$row@Row of $rows with { index: $i, first: $isFirst } trackBy $row.id"
35
+ */
36
+ function parseForSpec(spec) {
37
+ const trimmed = spec.trim();
38
+ // First, extract trackBy if present at the end
39
+ // trackBy uses $variable or $variable.property syntax (e.g., "$item" or "$item.id")
40
+ let trackBy = null;
41
+ let specWithoutTrackBy = trimmed;
42
+ const trackByMatch = trimmed.match(/\s+trackBy\s+(\$\w+(?:\.\w+)*)$/);
43
+ if (trackByMatch) {
44
+ const trackByValue = trackByMatch[1].trim();
45
+ specWithoutTrackBy = trimmed.slice(0, trackByMatch.index).trim();
46
+ // Parse the $variable.property syntax
47
+ const pathMatch = trackByValue.match(/^\$(\w+)((?:\.\w+)*)$/);
48
+ if (!pathMatch) {
49
+ throw new Error(`Invalid trackBy syntax: ${trackByValue}. Expected format: $variable or $variable.property`);
50
+ }
51
+ const variableName = pathMatch[1]; // e.g., "item"
52
+ const propertyPath = pathMatch[2]; // e.g., ".id" or ""
53
+ // We'll validate against itemName after parsing the main pattern
54
+ // Store both parts temporarily - validation happens after we know itemName
55
+ trackBy = `${variableName}${propertyPath}`;
56
+ }
57
+ // Pattern: $item@Type of $items with { metadata }
58
+ // ^^^^^ ^^^^ ^^^^^^ ^^^^^^^^^^^^^^^
59
+ // name type expr metadata (optional)
60
+ // Note: Type can include dots for namespaced types like "app.table.Row"
61
+ const pattern = /^\$(\w+)@([\w.[\]{}:,\s]+)\s+of\s+(.+?)(?:\s+with\s*\{([^}]+)})?$/;
62
+ const match = specWithoutTrackBy.match(pattern);
63
+ if (!match) {
64
+ throw new Error(`Invalid for-loop syntax: "${spec}". Expected format: "$item@Type of $items" or "$item@Type of $items with { index: $i }"`);
65
+ }
66
+ const [, itemName, typeStr, itemsExpr, metadataStr] = match;
67
+ // Validate and process trackBy
68
+ // null = no trackBy specified (use index)
69
+ // "" = trackBy $var (use item value directly for primitives)
70
+ // "id" or "user.id" = trackBy $var.property (use property path)
71
+ let processedTrackBy = null;
72
+ if (trackBy !== null) {
73
+ // trackBy is in format "variableName" or "variableName.property.path"
74
+ const parts = trackBy.split('.');
75
+ const variableName = parts[0];
76
+ // Validate that trackBy references the loop variable
77
+ if (variableName !== itemName) {
78
+ throw new Error(`trackBy must reference loop variable $${itemName}, got $${variableName}`);
79
+ }
80
+ // Extract the property path (everything after the variable name)
81
+ // If parts.length === 1, it's just the variable (primitive array) -> "" (use item value)
82
+ // If parts.length > 1, it's a property path -> "id" or "user.id"
83
+ processedTrackBy = parts.length > 1 ? parts.slice(1).join('.') : '';
84
+ }
85
+ return {
86
+ itemName,
87
+ itemType: typeStr.trim(),
88
+ itemsExpr,
89
+ metadata: metadataStr ? parseMetadata(metadataStr) : {},
90
+ trackBy: processedTrackBy,
91
+ };
92
+ }
93
+ /**
94
+ * Unfolds the new for-loop syntax into a ForComputationSchema
95
+ * Supports: for: "$item@Type of $items" or for: ["$item1@Type1 of $items1", "$item2@Type2 of $items2"]
96
+ */
97
+ export function unfoldForWithNewSyntax(schema) {
98
+ if (!isObject(schema) || !('for' in schema)) {
99
+ return null;
100
+ }
101
+ const forSpec = schema['for'];
102
+ const specs = Array.isArray(forSpec) ? forSpec : [forSpec];
103
+ if (specs.length === 0) {
104
+ throw new Error('For-loop requires at least one dimension');
105
+ }
106
+ const dimensions = specs.map((spec) => {
107
+ if (typeof spec !== 'string') {
108
+ throw new Error(`Invalid for-loop spec: ${JSON.stringify(spec)}. Must be a string.`);
109
+ }
110
+ const parsed = parseForSpec(spec);
111
+ // Parse the type annotation
112
+ // The type can be either:
113
+ // 1. An item type (e.g., "string") - we need to wrap in array
114
+ // 2. Already an array type (e.g., "string[]") - use as-is
115
+ const parsedType = parseValueType(parsed.itemType);
116
+ const itemsType = parsedType.type === 'array' ? parsedType : { type: 'array', item: parsedType };
117
+ return {
118
+ items: unfoldNodeSchema(parsed.itemsExpr, itemsType, []),
119
+ itemsType,
120
+ item: unfoldNodeSchema(parsed.itemName, { type: 'string' }, []),
121
+ index: unfoldNodeSchema(parsed.metadata.index || 'index', { type: 'string' }, []),
122
+ first: unfoldNodeSchema(parsed.metadata.first || null, { type: 'string' }, []),
123
+ last: unfoldNodeSchema(parsed.metadata.last || null, { type: 'string' }, []),
124
+ // trackBy: null = use index, property path (e.g., "id") = extract from item
125
+ trackBy: unfoldNodeSchema(parsed.trackBy, { type: 'string' }, []),
126
+ };
127
+ });
128
+ // Extract yield: either explicit 'yield' property or all other properties (inline yield)
129
+ let yieldSchema;
130
+ if ('yield' in schema) {
131
+ yieldSchema = schema['yield'];
132
+ }
133
+ else {
134
+ // Inline yield: all properties except 'for'
135
+ const { for: _, ...rest } = schema;
136
+ yieldSchema = rest;
137
+ }
138
+ const normalizedYield = unfoldNodeSchema(yieldSchema, { type: 'componentSchema' }, []);
139
+ const result = {
140
+ computationType: 'for',
141
+ dimensions,
142
+ yield: normalizedYield,
143
+ [Symbol.for('type')]: 'ComputationSchema',
144
+ };
145
+ return result;
146
+ }
147
+ //# sourceMappingURL=unfold-for-new-syntax.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unfold-for-new-syntax.js","sourceRoot":"","sources":["../../../../../../../libs/schema/src/lib/unfolding/computation/unfold-for-new-syntax.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComputationSchema, ForComputationSchema } from '@kaskad/types';\n\nimport { isObject } from '../../util/is-object';\nimport { parseValueType } from '../parse-value-type';\nimport { unfoldNodeSchema } from '../unfold-node-schema';\n\ninterface ParsedForSpec {\n itemName: string;\n itemType: string;\n itemsExpr: unknown;\n metadata: {\n index?: string;\n first?: string;\n last?: string;\n };\n trackBy: string | null;\n}\n\n/**\n * Parses metadata object from the `with` clause\n * Example: \"index: $i, first: $isFirst, last: $isLast\"\n */\nfunction parseMetadata(str: string): { index?: string; first?: string; last?: string } {\n const result: { index?: string; first?: string; last?: string } = {};\n const trimmed = str.trim();\n\n if (!trimmed) {\n throw new Error('Empty metadata block. Omit \"with\" clause if no metadata is needed.');\n }\n\n const pairs = trimmed.split(',').map((s) => s.trim());\n\n for (const pair of pairs) {\n const colonIndex = pair.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid metadata pair: \"${pair}\". Expected format: \"key: $value\"`);\n }\n\n const key = pair.slice(0, colonIndex).trim();\n const value = pair.slice(colonIndex + 1).trim();\n\n if (!['index', 'first', 'last'].includes(key)) {\n throw new Error(`Invalid metadata key: \"${key}\". Only \"index\", \"first\", and \"last\" are allowed.`);\n }\n\n if (!value || !value.startsWith('$')) {\n throw new Error(`Invalid metadata value: \"${value}\". Must be a variable starting with $.`);\n }\n\n result[key as 'index' | 'first' | 'last'] = value.slice(1); // Remove $\n }\n\n return result;\n}\n\n/**\n * Parses a single for-loop specification\n * Example: \"$row@Row of $rows with { index: $i, first: $isFirst } trackBy $row.id\"\n */\nfunction parseForSpec(spec: string): ParsedForSpec {\n const trimmed = spec.trim();\n\n // First, extract trackBy if present at the end\n // trackBy uses $variable or $variable.property syntax (e.g., \"$item\" or \"$item.id\")\n let trackBy: string | null = null;\n let specWithoutTrackBy = trimmed;\n\n const trackByMatch = trimmed.match(/\\s+trackBy\\s+(\\$\\w+(?:\\.\\w+)*)$/);\n if (trackByMatch) {\n const trackByValue = trackByMatch[1].trim();\n specWithoutTrackBy = trimmed.slice(0, trackByMatch.index).trim();\n\n // Parse the $variable.property syntax\n const pathMatch = trackByValue.match(/^\\$(\\w+)((?:\\.\\w+)*)$/);\n if (!pathMatch) {\n throw new Error(`Invalid trackBy syntax: ${trackByValue}. Expected format: $variable or $variable.property`);\n }\n\n const variableName = pathMatch[1]; // e.g., \"item\"\n const propertyPath = pathMatch[2]; // e.g., \".id\" or \"\"\n\n // We'll validate against itemName after parsing the main pattern\n // Store both parts temporarily - validation happens after we know itemName\n trackBy = `${variableName}${propertyPath}`;\n }\n\n // Pattern: $item@Type of $items with { metadata }\n // ^^^^^ ^^^^ ^^^^^^ ^^^^^^^^^^^^^^^\n // name type expr metadata (optional)\n // Note: Type can include dots for namespaced types like \"app.table.Row\"\n const pattern = /^\\$(\\w+)@([\\w.[\\]{}:,\\s]+)\\s+of\\s+(.+?)(?:\\s+with\\s*\\{([^}]+)})?$/;\n const match = specWithoutTrackBy.match(pattern);\n\n if (!match) {\n throw new Error(\n `Invalid for-loop syntax: \"${spec}\". Expected format: \"$item@Type of $items\" or \"$item@Type of $items with { index: $i }\"`,\n );\n }\n\n const [, itemName, typeStr, itemsExpr, metadataStr] = match;\n\n // Validate and process trackBy\n // null = no trackBy specified (use index)\n // \"\" = trackBy $var (use item value directly for primitives)\n // \"id\" or \"user.id\" = trackBy $var.property (use property path)\n let processedTrackBy: string | null = null;\n if (trackBy !== null) {\n // trackBy is in format \"variableName\" or \"variableName.property.path\"\n const parts = trackBy.split('.');\n const variableName = parts[0];\n\n // Validate that trackBy references the loop variable\n if (variableName !== itemName) {\n throw new Error(`trackBy must reference loop variable $${itemName}, got $${variableName}`);\n }\n\n // Extract the property path (everything after the variable name)\n // If parts.length === 1, it's just the variable (primitive array) -> \"\" (use item value)\n // If parts.length > 1, it's a property path -> \"id\" or \"user.id\"\n processedTrackBy = parts.length > 1 ? parts.slice(1).join('.') : '';\n }\n\n return {\n itemName,\n itemType: typeStr.trim(),\n itemsExpr,\n metadata: metadataStr ? parseMetadata(metadataStr) : {},\n trackBy: processedTrackBy,\n };\n}\n\n/**\n * Unfolds the new for-loop syntax into a ForComputationSchema\n * Supports: for: \"$item@Type of $items\" or for: [\"$item1@Type1 of $items1\", \"$item2@Type2 of $items2\"]\n */\nexport function unfoldForWithNewSyntax(schema: unknown): ComputationSchema | null {\n if (!isObject(schema) || !('for' in schema)) {\n return null;\n }\n\n const forSpec = schema['for'];\n const specs = Array.isArray(forSpec) ? forSpec : [forSpec];\n\n if (specs.length === 0) {\n throw new Error('For-loop requires at least one dimension');\n }\n\n const dimensions = specs.map((spec) => {\n if (typeof spec !== 'string') {\n throw new Error(`Invalid for-loop spec: ${JSON.stringify(spec)}. Must be a string.`);\n }\n\n const parsed = parseForSpec(spec);\n\n // Parse the type annotation\n // The type can be either:\n // 1. An item type (e.g., \"string\") - we need to wrap in array\n // 2. Already an array type (e.g., \"string[]\") - use as-is\n const parsedType = parseValueType(parsed.itemType);\n const itemsType = parsedType.type === 'array' ? parsedType : { type: 'array' as const, item: parsedType };\n\n return {\n items: unfoldNodeSchema(parsed.itemsExpr, itemsType, []),\n itemsType,\n item: unfoldNodeSchema(parsed.itemName, { type: 'string' }, []),\n index: unfoldNodeSchema(parsed.metadata.index || 'index', { type: 'string' }, []),\n first: unfoldNodeSchema(parsed.metadata.first || null, { type: 'string' }, []),\n last: unfoldNodeSchema(parsed.metadata.last || null, { type: 'string' }, []),\n // trackBy: null = use index, property path (e.g., \"id\") = extract from item\n trackBy: unfoldNodeSchema(parsed.trackBy, { type: 'string' }, []),\n };\n });\n\n // Extract yield: either explicit 'yield' property or all other properties (inline yield)\n let yieldSchema: unknown;\n if ('yield' in schema) {\n yieldSchema = schema['yield'];\n } else {\n // Inline yield: all properties except 'for'\n const { for: _, ...rest } = schema as Record<string, unknown>;\n yieldSchema = rest;\n }\n\n const normalizedYield = unfoldNodeSchema(yieldSchema, { type: 'componentSchema' }, []);\n\n const result: ForComputationSchema = {\n computationType: 'for',\n dimensions,\n yield: normalizedYield,\n [Symbol.for('type')]: 'ComputationSchema',\n };\n\n return result;\n}\n"]}
@@ -0,0 +1,45 @@
1
+ import { isObject } from '../../util/is-object';
2
+ import { parsePropertyKeyShorthand } from '../parse-property-key-shorthand';
3
+ import { unfoldNodeSchema } from '../unfold-node-schema';
4
+ export function unfoldForComputationSchema(schema) {
5
+ if (!isObject(schema) || !('computationType' in schema)) {
6
+ return null;
7
+ }
8
+ let rawDimensions = schema['dimensions'];
9
+ if (rawDimensions) {
10
+ if (!Array.isArray(rawDimensions)) {
11
+ throw new Error(`Invalid dimensions schema "${JSON.stringify(rawDimensions)}". It must be an array.`);
12
+ }
13
+ }
14
+ else {
15
+ // schema can be a flat object if only one dimension is defined
16
+ rawDimensions = [schema];
17
+ }
18
+ const dimensions = rawDimensions.map((dimension) => {
19
+ const { item = 'item', index = 'index', first = null, last = null } = dimension.as || {};
20
+ const itemsKey = Object.keys(dimension).find((key) => key.startsWith('items'));
21
+ const [items, itemsType] = parsePropertyKeyShorthand(itemsKey ?? '');
22
+ if (items !== 'items') {
23
+ throw new Error(`Computation "for" requires "items" field: ${JSON.stringify(schema)}`);
24
+ }
25
+ const itemsArr = dimension[itemsKey];
26
+ return {
27
+ items: unfoldNodeSchema(itemsArr, itemsType, []),
28
+ itemsType,
29
+ item: unfoldNodeSchema(item, { type: 'string' }, []),
30
+ index: unfoldNodeSchema(index, { type: 'string' }, []),
31
+ first: unfoldNodeSchema(first, { type: 'string' }, []),
32
+ last: unfoldNodeSchema(last, { type: 'string' }, []),
33
+ trackBy: unfoldNodeSchema(null, { type: 'unknown' }, []),
34
+ };
35
+ });
36
+ const normalizedYield = unfoldNodeSchema(schema['yield'], { type: 'unknown' }, []);
37
+ const result = {
38
+ computationType: 'for',
39
+ dimensions,
40
+ yield: normalizedYield,
41
+ [Symbol.for('type')]: 'ComputationSchema',
42
+ };
43
+ return result;
44
+ }
45
+ //# sourceMappingURL=unfold-for.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unfold-for.js","sourceRoot":"","sources":["../../../../../../../libs/schema/src/lib/unfolding/computation/unfold-for.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACxD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,MAAM,CAAC,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,aAAa,GAAG,MAAM,CAAC,YAAY,CAA2B,CAAC;IACnE,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;QACxG,CAAC;IACH,CAAC;SAAM,CAAC;QACN,+DAA+D;QAC/D,aAAa,GAAG,CAAC,MAA8B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;QACjD,MAAM,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;QAEzF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAA2B,CAAC;QAEzG,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,yBAAyB,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QACrE,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,6CAA6C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAErC,OAAO;YACL,KAAK,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC;YAChD,SAAS;YACT,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACpD,KAAK,EAAE,gBAAgB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACtD,KAAK,EAAE,gBAAgB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACtD,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACpD,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;SACzD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAEnF,MAAM,MAAM,GAAyB;QACnC,eAAe,EAAE,KAAK;QACtB,UAAU;QACV,KAAK,EAAE,eAAe;QACtB,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,mBAAmB;KAC1C,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { ComputationSchema, ForComputationSchema } from '@kaskad/types';\n\nimport { ForComputationRecipe } from '../../types/raw-schemas';\nimport { isObject } from '../../util/is-object';\nimport { parsePropertyKeyShorthand } from '../parse-property-key-shorthand';\nimport { unfoldNodeSchema } from '../unfold-node-schema';\n\nexport function unfoldForComputationSchema(schema: unknown): ComputationSchema | null {\n if (!isObject(schema) || !('computationType' in schema)) {\n return null;\n }\n let rawDimensions = schema['dimensions'] as ForComputationRecipe[];\n if (rawDimensions) {\n if (!Array.isArray(rawDimensions)) {\n throw new Error(`Invalid dimensions schema \"${JSON.stringify(rawDimensions)}\". It must be an array.`);\n }\n } else {\n // schema can be a flat object if only one dimension is defined\n rawDimensions = [schema as ForComputationRecipe];\n }\n\n const dimensions = rawDimensions.map((dimension) => {\n const { item = 'item', index = 'index', first = null, last = null } = dimension.as || {};\n\n const itemsKey = Object.keys(dimension).find((key) => key.startsWith('items')) as keyof typeof dimension;\n\n const [items, itemsType] = parsePropertyKeyShorthand(itemsKey ?? '');\n if (items !== 'items') {\n throw new Error(`Computation \"for\" requires \"items\" field: ${JSON.stringify(schema)}`);\n }\n\n const itemsArr = dimension[itemsKey];\n\n return {\n items: unfoldNodeSchema(itemsArr, itemsType, []),\n itemsType,\n item: unfoldNodeSchema(item, { type: 'string' }, []),\n index: unfoldNodeSchema(index, { type: 'string' }, []),\n first: unfoldNodeSchema(first, { type: 'string' }, []),\n last: unfoldNodeSchema(last, { type: 'string' }, []),\n trackBy: unfoldNodeSchema(null, { type: 'unknown' }, []),\n };\n });\n\n const normalizedYield = unfoldNodeSchema(schema['yield'], { type: 'unknown' }, []);\n\n const result: ForComputationSchema = {\n computationType: 'for',\n dimensions,\n yield: normalizedYield,\n [Symbol.for('type')]: 'ComputationSchema',\n };\n return result;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { unfoldNodeSchema } from '../unfold-node-schema';
2
+ export function unfoldIfComputationSchema(schema) {
3
+ if (schema.if === undefined) {
4
+ throw new Error('If computation requires the "if" field.');
5
+ }
6
+ const result = {
7
+ computationType: 'if',
8
+ if: unfoldNodeSchema(schema.if, { type: 'boolean' }, []),
9
+ then: createBranch(schema.then),
10
+ else: createBranch(schema.else),
11
+ [Symbol.for('type')]: 'ComputationSchema',
12
+ };
13
+ return result;
14
+ }
15
+ function createBranch(schema = null) {
16
+ return unfoldNodeSchema(schema, { type: 'componentSchema' }, []);
17
+ }
18
+ //# sourceMappingURL=unfold-if.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unfold-if.js","sourceRoot":"","sources":["../../../../../../../libs/schema/src/lib/unfolding/computation/unfold-if.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,UAAU,yBAAyB,CAAC,MAA2B;IACnE,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,MAAM,GAAwB;QAClC,eAAe,EAAE,IAAI;QACrB,EAAE,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QACxD,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;QAC/B,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;QAC/B,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,mBAAmB;KAC1C,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,SAAkB,IAAI;IAC1C,OAAO,gBAAgB,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { ComputationSchema, IfComputationSchema } from '@kaskad/types';\n\nimport { IfComputationRecipe } from '../../types/raw-schemas';\nimport { unfoldNodeSchema } from '../unfold-node-schema';\n\nexport function unfoldIfComputationSchema(schema: IfComputationRecipe): ComputationSchema {\n if (schema.if === undefined) {\n throw new Error('If computation requires the \"if\" field.');\n }\n\n const result: IfComputationSchema = {\n computationType: 'if',\n if: unfoldNodeSchema(schema.if, { type: 'boolean' }, []),\n then: createBranch(schema.then),\n else: createBranch(schema.else),\n [Symbol.for('type')]: 'ComputationSchema',\n };\n return result;\n}\n\nfunction createBranch(schema: unknown = null) {\n return unfoldNodeSchema(schema, { type: 'componentSchema' }, []);\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { isObject } from '../../util/is-object';
2
+ import { unfoldNodeSchema } from '../unfold-node-schema';
3
+ export function unfoldImportComputationSchema(schema) {
4
+ if (!isObject(schema) || !('computationType' in schema)) {
5
+ return null;
6
+ }
7
+ const { path, ref, computationType, _defer, ...contractVariables } = schema;
8
+ if (!path) {
9
+ throw new Error(`Import resolver requires a path field.`);
10
+ }
11
+ const defer = _defer
12
+ ? {
13
+ placeholder: unfoldNodeSchema(_defer.placeholder || null, { type: 'component' }, []),
14
+ error: unfoldNodeSchema(_defer.error || null, { type: 'component' }, []),
15
+ }
16
+ : null;
17
+ return {
18
+ computationType,
19
+ path,
20
+ defer,
21
+ ref,
22
+ contractVariables,
23
+ [Symbol.for('type')]: 'ComputationSchema',
24
+ };
25
+ }
26
+ //# sourceMappingURL=unfold-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unfold-import.js","sourceRoot":"","sources":["../../../../../../../libs/schema/src/lib/unfolding/computation/unfold-import.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AASzD,MAAM,UAAU,6BAA6B,CAAC,MAAe;IAC3D,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,MAAM,CAAC,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAA+B,CAAC;IACrG,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM;QAClB,CAAC,CAAC;YACE,WAAW,EAAE,gBAAgB,CAAC,MAAM,CAAC,WAAW,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;YACpF,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;SACzE;QACH,CAAC,CAAC,IAAI,CAAC;IAET,OAAO;QACL,eAAe;QACf,IAAI;QACJ,KAAK;QACL,GAAG;QACH,iBAAiB;QACjB,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,mBAAmB;KAC1C,CAAC;AACJ,CAAC","sourcesContent":["import { ComponentRef, TemplateComputationSchema } from '@kaskad/types';\n\nimport { Defer } from '../../types/component-schema';\nimport { isObject } from '../../util/is-object';\nimport { unfoldNodeSchema } from '../unfold-node-schema';\n\ntype TemplateFullRawSchema = {\n readonly computationType: 'template';\n readonly path: string;\n readonly ref?: ComponentRef;\n readonly _defer?: Defer;\n} & Record<string, unknown>;\n\nexport function unfoldImportComputationSchema(schema: unknown): TemplateComputationSchema | null {\n if (!isObject(schema) || !('computationType' in schema)) {\n return null;\n }\n\n const { path, ref, computationType, _defer, ...contractVariables } = schema as TemplateFullRawSchema;\n if (!path) {\n throw new Error(`Import resolver requires a path field.`);\n }\n\n const defer = _defer\n ? {\n placeholder: unfoldNodeSchema(_defer.placeholder || null, { type: 'component' }, []),\n error: unfoldNodeSchema(_defer.error || null, { type: 'component' }, []),\n }\n : null;\n\n return {\n computationType,\n path,\n defer,\n ref,\n contractVariables,\n [Symbol.for('type')]: 'ComputationSchema',\n };\n}\n"]}
@@ -0,0 +1,44 @@
1
+ export function unfoldInterpolationComputationSchema(schema) {
2
+ const args = stringToFuncArgs(schema);
3
+ return { computationType: 'formula', formula: `concat(${args})` };
4
+ }
5
+ export function replaceInterpolationsInFormula(formula) {
6
+ // Replace {{}} inside single-quoted string literals
7
+ let result = formula.replace(/'([^']*\{\{.*?\}\}[^']*)'/g, (_, content) => {
8
+ return `concat(${stringToFuncArgs(content)})`;
9
+ });
10
+ // Replace {{}} inside double-quoted string literals
11
+ result = result.replace(/"([^"]*\{\{.*?\}\}[^"]*)"/g, (_, content) => {
12
+ return `concat(${stringToFuncArgs(content)})`;
13
+ });
14
+ // Strip bare {{}} delimiters (expression is already valid formula syntax)
15
+ result = result.replace(/\{\{(.*?)\}\}/g, (_, expr) => expr.trim());
16
+ return result;
17
+ }
18
+ function stringToFuncArgs(str) {
19
+ const result = [];
20
+ let currentIndex = 0;
21
+ while (currentIndex < str.length) {
22
+ const startBrace = str.indexOf('{{', currentIndex);
23
+ if (startBrace === -1) {
24
+ const remaining = str.slice(currentIndex);
25
+ if (remaining)
26
+ result.push(`'${remaining}'`);
27
+ break;
28
+ }
29
+ const before = str.slice(currentIndex, startBrace);
30
+ if (before)
31
+ result.push(`'${before}'`);
32
+ const endBrace = str.indexOf('}}', startBrace);
33
+ if (!endBrace) {
34
+ result.push(str);
35
+ break;
36
+ }
37
+ const template = str.slice(startBrace + 2, endBrace).trim();
38
+ if (template)
39
+ result.push(template);
40
+ currentIndex = endBrace + 2;
41
+ }
42
+ return '[' + result.join(', ') + ']';
43
+ }
44
+ //# sourceMappingURL=unfold-interpolation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unfold-interpolation.js","sourceRoot":"","sources":["../../../../../../../libs/schema/src/lib/unfolding/computation/unfold-interpolation.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oCAAoC,CAAC,MAAc;IACjE,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,IAAI,GAAG,EAA8B,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,OAAe;IAC5D,oDAAoD;IACpD,IAAI,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE;QACxE,OAAO,UAAU,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,oDAAoD;IACpD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE;QACnE,OAAO,UAAU,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,0EAA0E;IAC1E,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,OAAO,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAEnD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC1C,IAAI,SAAS;gBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC;YAC7C,MAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACnD,IAAI,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;QAEvC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACjB,MAAM;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,IAAI,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEpC,YAAY,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;AACvC,CAAC","sourcesContent":["import { ComputationSchema, FormulaComputationSchema } from '@kaskad/types';\n\nexport function unfoldInterpolationComputationSchema(schema: string): ComputationSchema | null {\n const args = stringToFuncArgs(schema);\n return { computationType: 'formula', formula: `concat(${args})` } as FormulaComputationSchema;\n}\n\nexport function replaceInterpolationsInFormula(formula: string): string {\n // Replace {{}} inside single-quoted string literals\n let result = formula.replace(/'([^']*\\{\\{.*?\\}\\}[^']*)'/g, (_, content) => {\n return `concat(${stringToFuncArgs(content)})`;\n });\n // Replace {{}} inside double-quoted string literals\n result = result.replace(/\"([^\"]*\\{\\{.*?\\}\\}[^\"]*)\"/g, (_, content) => {\n return `concat(${stringToFuncArgs(content)})`;\n });\n // Strip bare {{}} delimiters (expression is already valid formula syntax)\n result = result.replace(/\\{\\{(.*?)\\}\\}/g, (_, expr) => expr.trim());\n return result;\n}\n\nfunction stringToFuncArgs(str: string): string {\n const result: string[] = [];\n let currentIndex = 0;\n\n while (currentIndex < str.length) {\n const startBrace = str.indexOf('{{', currentIndex);\n\n if (startBrace === -1) {\n const remaining = str.slice(currentIndex);\n if (remaining) result.push(`'${remaining}'`);\n break;\n }\n\n const before = str.slice(currentIndex, startBrace);\n if (before) result.push(`'${before}'`);\n\n const endBrace = str.indexOf('}}', startBrace);\n if (!endBrace) {\n result.push(str);\n break;\n }\n\n const template = str.slice(startBrace + 2, endBrace).trim();\n if (template) result.push(template);\n\n currentIndex = endBrace + 2;\n }\n return '[' + result.join(', ') + ']';\n}\n"]}
@@ -0,0 +1,40 @@
1
+ const MIRROR_PATTERN = /^<=>\s*(\S+)$/;
2
+ const SELECTION_PATTERN = /^<#>\s*(\S+)->\((\$\w+),\s*(\$\w+)\)$/;
3
+ const OBJECT_PATTERN = /^<\{\}>\s*(\S+)->\((\$\w+),\s*(\$\w+)\)$/;
4
+ const ARRAY_PATTERN = /^<\[\]>\s*(\S+)->\((\$\w+)\)$/;
5
+ export function parseBindingShorthand(value) {
6
+ let match;
7
+ match = value.match(MIRROR_PATTERN);
8
+ if (match) {
9
+ return { bindingType: 'mirror', selector: match[1] };
10
+ }
11
+ match = value.match(SELECTION_PATTERN);
12
+ if (match) {
13
+ return {
14
+ bindingType: 'selection',
15
+ componentSelector: match[1],
16
+ mapping: { key: match[2], selected: match[3] },
17
+ };
18
+ }
19
+ match = value.match(OBJECT_PATTERN);
20
+ if (match) {
21
+ return {
22
+ bindingType: 'object',
23
+ componentSelector: match[1],
24
+ mapping: { key: match[2], value: match[3] },
25
+ };
26
+ }
27
+ match = value.match(ARRAY_PATTERN);
28
+ if (match) {
29
+ return {
30
+ bindingType: 'array',
31
+ componentSelector: match[1],
32
+ mapping: { value: match[2] },
33
+ };
34
+ }
35
+ return null;
36
+ }
37
+ export function isBindingShorthand(value) {
38
+ return value.startsWith('<=>') || value.startsWith('<#>') || value.startsWith('<{}>') || value.startsWith('<[]>');
39
+ }
40
+ //# sourceMappingURL=parse-binding-shorthand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-binding-shorthand.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/unfolding/parse-binding-shorthand.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,eAAe,CAAC;AACvC,MAAM,iBAAiB,GAAG,uCAAuC,CAAC;AAClE,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAClE,MAAM,aAAa,GAAG,+BAA+B,CAAC;AAEtD,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,IAAI,KAA8B,CAAC;IAEnC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACpC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,CAAC;IAED,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACvC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO;YACL,WAAW,EAAE,WAAW;YACxB,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;YAC3B,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE;SAC/C,CAAC;IACJ,CAAC;IAED,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACpC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO;YACL,WAAW,EAAE,QAAQ;YACrB,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;YAC3B,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE;SAC5C,CAAC;IACJ,CAAC;IAED,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACnC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO;YACL,WAAW,EAAE,OAAO;YACpB,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;YAC3B,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE;SAC7B,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACpH,CAAC","sourcesContent":["import { BindingSchema } from '@kaskad/types';\n\nconst MIRROR_PATTERN = /^<=>\\s*(\\S+)$/;\nconst SELECTION_PATTERN = /^<#>\\s*(\\S+)->\\((\\$\\w+),\\s*(\\$\\w+)\\)$/;\nconst OBJECT_PATTERN = /^<\\{\\}>\\s*(\\S+)->\\((\\$\\w+),\\s*(\\$\\w+)\\)$/;\nconst ARRAY_PATTERN = /^<\\[\\]>\\s*(\\S+)->\\((\\$\\w+)\\)$/;\n\nexport function parseBindingShorthand(value: string): BindingSchema | null {\n let match: RegExpMatchArray | null;\n\n match = value.match(MIRROR_PATTERN);\n if (match) {\n return { bindingType: 'mirror', selector: match[1] };\n }\n\n match = value.match(SELECTION_PATTERN);\n if (match) {\n return {\n bindingType: 'selection',\n componentSelector: match[1],\n mapping: { key: match[2], selected: match[3] },\n };\n }\n\n match = value.match(OBJECT_PATTERN);\n if (match) {\n return {\n bindingType: 'object',\n componentSelector: match[1],\n mapping: { key: match[2], value: match[3] },\n };\n }\n\n match = value.match(ARRAY_PATTERN);\n if (match) {\n return {\n bindingType: 'array',\n componentSelector: match[1],\n mapping: { value: match[2] },\n };\n }\n\n return null;\n}\n\nexport function isBindingShorthand(value: string): boolean {\n return value.startsWith('<=>') || value.startsWith('<#>') || value.startsWith('<{}>') || value.startsWith('<[]>');\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { parseValueType } from './parse-value-type';
2
+ export function parsePropertyKeyShorthand(shorthand) {
3
+ const [key, type] = shorthand.split('@');
4
+ if (!type) {
5
+ throw new Error(`Invalid node key expression "${key}". Expected type for key "${key}"`);
6
+ }
7
+ return [key, parseValueType(type)];
8
+ }
9
+ //# sourceMappingURL=parse-property-key-shorthand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-property-key-shorthand.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/unfolding/parse-property-key-shorthand.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,yBAAyB,CAAC,SAAiB;IACzD,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;IAC/D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,6BAA6B,GAAG,GAAG,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { NodeType, ValueType } from '@kaskad/types';\n\nimport { parseValueType } from './parse-value-type';\n\nexport function parsePropertyKeyShorthand(shorthand: string): [string, ValueType] {\n const [key, type] = shorthand.split('@') as [string, NodeType];\n if (!type) {\n throw new Error(`Invalid node key expression \"${key}\". Expected type for key \"${key}\"`);\n }\n return [key, parseValueType(type)];\n}\n"]}