@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.
- package/README.md +217 -0
- package/esm2022/index.js +17 -0
- package/esm2022/index.js.map +1 -0
- package/esm2022/kaskad-schema.js +5 -0
- package/esm2022/kaskad-schema.js.map +1 -0
- package/esm2022/lib/load/load-schema.js +16 -0
- package/esm2022/lib/load/load-schema.js.map +1 -0
- package/esm2022/lib/load/load-templates.js +136 -0
- package/esm2022/lib/load/load-templates.js.map +1 -0
- package/esm2022/lib/load/register-declared-type.js +28 -0
- package/esm2022/lib/load/register-declared-type.js.map +1 -0
- package/esm2022/lib/load/schema-component-extractor.js +101 -0
- package/esm2022/lib/load/schema-component-extractor.js.map +1 -0
- package/esm2022/lib/load/template-registry.js +51 -0
- package/esm2022/lib/load/template-registry.js.map +1 -0
- package/esm2022/lib/types/component-definition.js +1 -0
- package/esm2022/lib/types/component-definition.js.map +1 -0
- package/esm2022/lib/types/component-schema.js +1 -0
- package/esm2022/lib/types/component-schema.js.map +1 -0
- package/esm2022/lib/types/raw-schemas.js +3 -0
- package/esm2022/lib/types/raw-schemas.js.map +1 -0
- package/esm2022/lib/types/template-raw-definition.js +1 -0
- package/esm2022/lib/types/template-raw-definition.js.map +1 -0
- package/esm2022/lib/unfolding/computation/unfold-computation-schema.js +70 -0
- package/esm2022/lib/unfolding/computation/unfold-computation-schema.js.map +1 -0
- package/esm2022/lib/unfolding/computation/unfold-for-new-syntax.js +147 -0
- package/esm2022/lib/unfolding/computation/unfold-for-new-syntax.js.map +1 -0
- package/esm2022/lib/unfolding/computation/unfold-for.js +45 -0
- package/esm2022/lib/unfolding/computation/unfold-for.js.map +1 -0
- package/esm2022/lib/unfolding/computation/unfold-if.js +18 -0
- package/esm2022/lib/unfolding/computation/unfold-if.js.map +1 -0
- package/esm2022/lib/unfolding/computation/unfold-import.js +26 -0
- package/esm2022/lib/unfolding/computation/unfold-import.js.map +1 -0
- package/esm2022/lib/unfolding/computation/unfold-interpolation.js +44 -0
- package/esm2022/lib/unfolding/computation/unfold-interpolation.js.map +1 -0
- package/esm2022/lib/unfolding/parse-binding-shorthand.js +40 -0
- package/esm2022/lib/unfolding/parse-binding-shorthand.js.map +1 -0
- package/esm2022/lib/unfolding/parse-property-key-shorthand.js +9 -0
- package/esm2022/lib/unfolding/parse-property-key-shorthand.js.map +1 -0
- package/esm2022/lib/unfolding/parse-value-type.js +115 -0
- package/esm2022/lib/unfolding/parse-value-type.js.map +1 -0
- package/esm2022/lib/unfolding/to-full-notation.js +124 -0
- package/esm2022/lib/unfolding/to-full-notation.js.map +1 -0
- package/esm2022/lib/unfolding/unfold-flat-wrapper-notation.js +72 -0
- package/esm2022/lib/unfolding/unfold-flat-wrapper-notation.js.map +1 -0
- package/esm2022/lib/unfolding/unfold-node-schema.js +35 -0
- package/esm2022/lib/unfolding/unfold-node-schema.js.map +1 -0
- package/esm2022/lib/unfolding/unfold-property.js +21 -0
- package/esm2022/lib/unfolding/unfold-property.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/index.js +11 -0
- package/esm2022/lib/unfolding/value/handlers/index.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-array.js +9 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-array.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-boolean.js +8 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-boolean.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-command.js +22 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-command.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-component-schema.js +14 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-component-schema.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-component.js +66 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-component.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-map.js +13 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-map.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-number.js +11 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-number.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-object.js +15 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-object.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-set.js +6 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-set.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-shape.js +13 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-shape.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-string.js +8 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-string.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-unknown.js +4 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-unknown.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-variant-shape.js +61 -0
- package/esm2022/lib/unfolding/value/handlers/unfold-variant-shape.js.map +1 -0
- package/esm2022/lib/unfolding/value/handlers/validate-props.js +20 -0
- package/esm2022/lib/unfolding/value/handlers/validate-props.js.map +1 -0
- package/esm2022/lib/unfolding/value/throw-unfold-value-error.js +11 -0
- package/esm2022/lib/unfolding/value/throw-unfold-value-error.js.map +1 -0
- package/esm2022/lib/unfolding/value/unfold-node-value.js +30 -0
- package/esm2022/lib/unfolding/value/unfold-node-value.js.map +1 -0
- package/esm2022/lib/util/is-object.js +4 -0
- package/esm2022/lib/util/is-object.js.map +1 -0
- package/esm2022/lib/util/stringify-object.js +4 -0
- package/esm2022/lib/util/stringify-object.js.map +1 -0
- package/esm2022/lib/util/unfold-component-definitions.js +21 -0
- package/esm2022/lib/util/unfold-component-definitions.js.map +1 -0
- package/index.d.ts +16 -0
- package/kaskad-schema.d.ts +5 -0
- package/lib/load/load-schema.d.ts +3 -0
- package/lib/load/load-templates.d.ts +2 -0
- package/lib/load/register-declared-type.d.ts +1 -0
- package/lib/load/schema-component-extractor.d.ts +2 -0
- package/lib/load/template-registry.d.ts +16 -0
- package/lib/types/component-definition.d.ts +5 -0
- package/lib/types/component-schema.d.ts +26 -0
- package/lib/types/raw-schemas.d.ts +25 -0
- package/lib/types/template-raw-definition.d.ts +7 -0
- package/lib/unfolding/computation/unfold-computation-schema.d.ts +2 -0
- package/lib/unfolding/computation/unfold-for-new-syntax.d.ts +6 -0
- package/lib/unfolding/computation/unfold-for.d.ts +2 -0
- package/lib/unfolding/computation/unfold-if.d.ts +3 -0
- package/lib/unfolding/computation/unfold-import.d.ts +2 -0
- package/lib/unfolding/computation/unfold-interpolation.d.ts +3 -0
- package/lib/unfolding/parse-binding-shorthand.d.ts +3 -0
- package/lib/unfolding/parse-property-key-shorthand.d.ts +2 -0
- package/lib/unfolding/parse-value-type.d.ts +2 -0
- package/lib/unfolding/to-full-notation.d.ts +8 -0
- package/lib/unfolding/unfold-flat-wrapper-notation.d.ts +13 -0
- package/lib/unfolding/unfold-node-schema.d.ts +3 -0
- package/lib/unfolding/unfold-property.d.ts +2 -0
- package/lib/unfolding/value/handlers/index.d.ts +10 -0
- package/lib/unfolding/value/handlers/unfold-array.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-boolean.d.ts +2 -0
- package/lib/unfolding/value/handlers/unfold-command.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-component-schema.d.ts +4 -0
- package/lib/unfolding/value/handlers/unfold-component.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-map.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-number.d.ts +2 -0
- package/lib/unfolding/value/handlers/unfold-object.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-set.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-shape.d.ts +3 -0
- package/lib/unfolding/value/handlers/unfold-string.d.ts +2 -0
- package/lib/unfolding/value/handlers/unfold-unknown.d.ts +2 -0
- package/lib/unfolding/value/handlers/unfold-variant-shape.d.ts +3 -0
- package/lib/unfolding/value/handlers/validate-props.d.ts +2 -0
- package/lib/unfolding/value/throw-unfold-value-error.d.ts +2 -0
- package/lib/unfolding/value/unfold-node-value.d.ts +8 -0
- package/lib/util/is-object.d.ts +1 -0
- package/lib/util/stringify-object.d.ts +1 -0
- package/lib/util/unfold-component-definitions.d.ts +4 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# @kaskad/schema
|
|
2
|
+
|
|
3
|
+
Schema transformation and normalization library for the Kaskad framework.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@kaskad/schema` library provides utilities for transforming and normalizing schema definitions in the Kaskad framework. It handles the conversion of shorthand notations and raw schemas into fully normalized `NodeSchema` structures that can be processed by the core engine.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Schema Unfolding**: Transform shorthand and compact schema notations into fully normalized structures
|
|
12
|
+
- **Type Parsing**: Parse complex type expressions including arrays, maps, objects, and commands
|
|
13
|
+
- **Wrapper Notation**: Support for component wrapper syntax with automatic slot detection
|
|
14
|
+
- **Property Shorthand**: Convert property key shorthands like `name@string` into full schema definitions
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @kaskad/schema
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Unfolding Properties
|
|
25
|
+
|
|
26
|
+
Transform property shorthands into full schema definitions:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { unfoldProperty } from '@kaskad/schema';
|
|
30
|
+
|
|
31
|
+
// Simple property with type annotation
|
|
32
|
+
const [key, schema] = unfoldProperty('name@string', 'John');
|
|
33
|
+
// Returns: ['name', { value: 'John', valueType: { type: 'string' }, ... }]
|
|
34
|
+
|
|
35
|
+
// Array property
|
|
36
|
+
const [key, schema] = unfoldProperty('items@string[]', null);
|
|
37
|
+
// Returns: ['items', { value: null, valueType: { type: 'array', item: { type: 'string' } }, ... }]
|
|
38
|
+
|
|
39
|
+
// Object property
|
|
40
|
+
const [key, schema] = unfoldProperty('user@{name:string,age:number}', null);
|
|
41
|
+
// Returns object type with field definitions
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Parsing Value Types
|
|
45
|
+
|
|
46
|
+
Parse type expressions into structured type definitions:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { parseValueType } from '@kaskad/schema';
|
|
50
|
+
|
|
51
|
+
// Simple types
|
|
52
|
+
parseValueType('string'); // { type: 'string' }
|
|
53
|
+
parseValueType('number'); // { type: 'number' }
|
|
54
|
+
|
|
55
|
+
// Array types
|
|
56
|
+
parseValueType('string[]'); // { type: 'array', item: { type: 'string' } }
|
|
57
|
+
|
|
58
|
+
// Map types
|
|
59
|
+
parseValueType('string{}'); // { type: 'map', item: { type: 'string' } }
|
|
60
|
+
|
|
61
|
+
// Object types
|
|
62
|
+
parseValueType('{name:string,age:number}');
|
|
63
|
+
// { type: 'object', fields: { name: { type: 'string' }, age: { type: 'number' } } }
|
|
64
|
+
|
|
65
|
+
// Command types
|
|
66
|
+
parseValueType('(string,number)');
|
|
67
|
+
// { type: 'command', args: [{ type: 'string' }, { type: 'number' }] }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Schema Normalization
|
|
71
|
+
|
|
72
|
+
Convert raw schemas to full notation:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { toFullNotation } from '@kaskad/schema';
|
|
76
|
+
|
|
77
|
+
// Simple value
|
|
78
|
+
const result = toFullNotation('hello', { type: 'string' });
|
|
79
|
+
// Returns: { _value: 'hello', _valueType: { type: 'string' }, ... }
|
|
80
|
+
|
|
81
|
+
// Formula computation
|
|
82
|
+
const result = toFullNotation('=getValue()', { type: 'string' });
|
|
83
|
+
// Returns: { _computation: '=getValue()', _valueType: { type: 'string' }, ... }
|
|
84
|
+
|
|
85
|
+
// Conditional schema
|
|
86
|
+
const result = toFullNotation(
|
|
87
|
+
{ if: 'isActive', then: 'active', else: 'inactive' },
|
|
88
|
+
{ type: 'string' }
|
|
89
|
+
);
|
|
90
|
+
// Returns conditional computation structure
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Wrapper Notation
|
|
94
|
+
|
|
95
|
+
Handle component wrapper syntax:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { extractWrappers, hasWrappers, unfoldFlatWrappers } from '@kaskad/schema';
|
|
99
|
+
|
|
100
|
+
const schema = {
|
|
101
|
+
'+card': { title: 'My Card' },
|
|
102
|
+
'+modal': { size: 'large' },
|
|
103
|
+
componentType: 'text',
|
|
104
|
+
value: 'Hello'
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Check for wrappers
|
|
108
|
+
hasWrappers(schema); // true
|
|
109
|
+
|
|
110
|
+
// Extract wrapper configuration
|
|
111
|
+
const [wrappers, cleanSchema] = extractWrappers(schema);
|
|
112
|
+
// wrappers: [['card', { title: 'My Card' }], ['modal', { size: 'large' }]]
|
|
113
|
+
// cleanSchema: { componentType: 'text', value: 'Hello' }
|
|
114
|
+
|
|
115
|
+
// Apply wrappers to create nested structure
|
|
116
|
+
const result = unfoldFlatWrappers(wrappers, cleanSchema, resultNode);
|
|
117
|
+
// Creates nested component structure with wrappers
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Type System
|
|
121
|
+
|
|
122
|
+
### Supported Value Types
|
|
123
|
+
|
|
124
|
+
- **Primitive Types**: `string`, `number`, `boolean`, `unknown`
|
|
125
|
+
- **Collection Types**:
|
|
126
|
+
- Arrays: `string[]`, `number[][]`
|
|
127
|
+
- Maps: `string{}`, `number[]{}`
|
|
128
|
+
- **Structured Types**:
|
|
129
|
+
- Objects: `{field1:type1,field2:type2}`
|
|
130
|
+
- Commands: `(arg1Type,arg2Type)`
|
|
131
|
+
- **Entity Types**: Custom entity and polymorphic entity types
|
|
132
|
+
- **Component Type**: For component schemas
|
|
133
|
+
|
|
134
|
+
### Schema Structure
|
|
135
|
+
|
|
136
|
+
A fully normalized `NodeSchema` contains:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
interface NodeSchema {
|
|
140
|
+
value: unknown; // The actual value
|
|
141
|
+
valueType: ValueType; // Type definition
|
|
142
|
+
computation: Computation; // Formula or computation definition
|
|
143
|
+
binding: BindingSchema; // Data binding configuration
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## API Reference
|
|
148
|
+
|
|
149
|
+
### Core Functions
|
|
150
|
+
|
|
151
|
+
#### `unfoldProperty(key: string, value: unknown): [string, NodeSchema]`
|
|
152
|
+
Transforms a property key with type annotation and value into a normalized schema.
|
|
153
|
+
|
|
154
|
+
#### `unfoldNodeSchema(value: unknown, valueType: ValueType): NodeSchema`
|
|
155
|
+
Unfolds a value into a complete NodeSchema based on the provided type.
|
|
156
|
+
|
|
157
|
+
#### `toFullNotation(nodeSchema: unknown, valueType: ValueType): RawNode`
|
|
158
|
+
Converts various schema notations into full notation format.
|
|
159
|
+
|
|
160
|
+
#### `parseValueType(type: string): ValueType`
|
|
161
|
+
Parses a type expression string into a structured ValueType.
|
|
162
|
+
|
|
163
|
+
#### `parsePropertyKeyShorthand(shorthand: string): [string, ValueType]`
|
|
164
|
+
Extracts property key and type from shorthand notation.
|
|
165
|
+
|
|
166
|
+
### Wrapper Functions
|
|
167
|
+
|
|
168
|
+
#### `hasWrappers(schema: ComponentRawSchema | TemplateRawSchema): boolean`
|
|
169
|
+
Checks if a schema contains wrapper notation (properties starting with '+').
|
|
170
|
+
|
|
171
|
+
#### `extractWrappers(schema: ComponentRawSchema | TemplateRawSchema): [WrapperEntity[], Schema]`
|
|
172
|
+
Separates wrapper configuration from the main schema.
|
|
173
|
+
|
|
174
|
+
#### `unfoldFlatWrappers(wrappers: WrapperEntity[], schema: Schema, resultNode: RawNode): RawNode`
|
|
175
|
+
Applies wrapper configuration to create nested component structure.
|
|
176
|
+
|
|
177
|
+
## Examples
|
|
178
|
+
|
|
179
|
+
### Complete Example: Component with Wrappers and Computed Properties
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { unfoldProperty, toFullNotation } from '@kaskad/schema';
|
|
183
|
+
|
|
184
|
+
// Define a form input component with validation
|
|
185
|
+
const rawSchema = {
|
|
186
|
+
'+card': { title: 'User Input' },
|
|
187
|
+
componentType: 'input',
|
|
188
|
+
properties: {
|
|
189
|
+
'value@string': null,
|
|
190
|
+
'validators@validator[]': [],
|
|
191
|
+
'validity@validity': '=validate(value, validators)',
|
|
192
|
+
'disabled@boolean': false
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Process each property
|
|
197
|
+
const properties = {};
|
|
198
|
+
for (const [key, value] of Object.entries(rawSchema.properties)) {
|
|
199
|
+
const [propKey, propSchema] = unfoldProperty(key, value);
|
|
200
|
+
properties[propKey] = propSchema;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Result: Fully normalized component schema with:
|
|
204
|
+
// - Typed properties
|
|
205
|
+
// - Computed validity based on validators
|
|
206
|
+
// - Wrapper configuration for card display
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Running Tests
|
|
210
|
+
|
|
211
|
+
This library was generated with [Nx](https://nx.dev).
|
|
212
|
+
|
|
213
|
+
Run `nx test schema` to execute the unit tests.
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
Part of the Kaskad framework.
|
package/esm2022/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './lib/types/component-schema';
|
|
2
|
+
export * from './lib/types/raw-schemas';
|
|
3
|
+
export * from './lib/types/component-definition';
|
|
4
|
+
export * from './lib/types/template-raw-definition';
|
|
5
|
+
export * from './lib/unfolding/unfold-node-schema';
|
|
6
|
+
export * from './lib/unfolding/unfold-property';
|
|
7
|
+
export * from './lib/unfolding/unfold-flat-wrapper-notation';
|
|
8
|
+
export * from './lib/unfolding/parse-value-type';
|
|
9
|
+
export * from './lib/unfolding/to-full-notation';
|
|
10
|
+
export * from './lib/load/schema-component-extractor';
|
|
11
|
+
export * from './lib/load/template-registry';
|
|
12
|
+
export * from './lib/load/load-templates';
|
|
13
|
+
export * from './lib/load/load-schema';
|
|
14
|
+
export * from './lib/load/register-declared-type';
|
|
15
|
+
export * from './lib/util/unfold-component-definitions';
|
|
16
|
+
export * from './lib/util/is-object';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/schema/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,sBAAsB,CAAC","sourcesContent":["export * from './lib/types/component-schema';\nexport * from './lib/types/raw-schemas';\nexport * from './lib/types/component-definition';\nexport * from './lib/types/template-raw-definition';\nexport * from './lib/unfolding/unfold-node-schema';\nexport * from './lib/unfolding/unfold-property';\nexport * from './lib/unfolding/unfold-flat-wrapper-notation';\nexport * from './lib/unfolding/parse-value-type';\nexport * from './lib/unfolding/to-full-notation';\nexport * from './lib/load/schema-component-extractor';\nexport * from './lib/load/template-registry';\nexport * from './lib/load/load-templates';\nexport * from './lib/load/load-schema';\nexport * from './lib/load/register-declared-type';\nexport * from './lib/util/unfold-component-definitions';\nexport * from './lib/util/is-object';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kaskad-schema.js","sourceRoot":"","sources":["../../../../libs/schema/src/kaskad-schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC","sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parse } from 'yaml';
|
|
2
|
+
export const withBaseTemplateUrl = (url) => `/recipes/${url}.yml`;
|
|
3
|
+
export async function loadRecipe(url) {
|
|
4
|
+
const response = await fetch(withBaseTemplateUrl(url));
|
|
5
|
+
if (response.status === 404) {
|
|
6
|
+
throw new Error(`Schema not found: ${url}`);
|
|
7
|
+
}
|
|
8
|
+
const text = await response.text();
|
|
9
|
+
try {
|
|
10
|
+
return parse(text);
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
throw new Error(`Failed to parse YAML: ${e}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=load-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-schema.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/load/load-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAI7B,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,YAAY,GAAG,MAAM,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;IAEvD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC","sourcesContent":["import { parse } from 'yaml';\n\nimport { TemplateRecipeDefinition } from '../types/template-raw-definition';\n\nexport const withBaseTemplateUrl = (url: string) => `/recipes/${url}.yml`;\n\nexport async function loadRecipe(url: string): Promise<TemplateRecipeDefinition> {\n const response = await fetch(withBaseTemplateUrl(url));\n\n if (response.status === 404) {\n throw new Error(`Schema not found: ${url}`);\n }\n\n const text = await response.text();\n try {\n return parse(text);\n } catch (e) {\n throw new Error(`Failed to parse YAML: ${e}`);\n }\n}\n"]}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { log } from '@kaskad/config';
|
|
2
|
+
import { PathSymbol, WrapperPrefix } from '../unfolding/unfold-flat-wrapper-notation';
|
|
3
|
+
import { unfoldNodeSchema } from '../unfolding/unfold-node-schema';
|
|
4
|
+
import { isObject } from '../util/is-object';
|
|
5
|
+
import { loadRecipe } from './load-schema';
|
|
6
|
+
import { registerDeclaredType } from './register-declared-type';
|
|
7
|
+
import { extractComponentTypes } from './schema-component-extractor';
|
|
8
|
+
import { templateRegistry } from './template-registry';
|
|
9
|
+
const reservedKeys = new Set(['importTypes', 'types', 'contract', 'defaultSlot']);
|
|
10
|
+
function isTypeOnlyTemplate(template) {
|
|
11
|
+
const contentKeys = Object.keys(template).filter((k) => !reservedKeys.has(k));
|
|
12
|
+
return contentKeys.length > 0 && contentKeys.every((k) => k.includes('.'));
|
|
13
|
+
}
|
|
14
|
+
export async function loadTemplates(recipe) {
|
|
15
|
+
// Pass 1: Recursively load all templates and register types immediately
|
|
16
|
+
const allTemplates = new Map();
|
|
17
|
+
await collectAllTemplates(recipe, allTemplates);
|
|
18
|
+
// Register types from the root recipe (after all dependencies are loaded)
|
|
19
|
+
const rootTypes = recipe.types;
|
|
20
|
+
if (rootTypes) {
|
|
21
|
+
for (const [key, value] of Object.entries(rootTypes)) {
|
|
22
|
+
if (typeof value === 'string' || isObject(value)) {
|
|
23
|
+
registerDeclaredType(key, value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Pass 2: Unfold and register all templates (types are already registered)
|
|
28
|
+
for (const [url, template] of allTemplates) {
|
|
29
|
+
try {
|
|
30
|
+
const { types: _types, importTypes: _importTypes, contract: _contract, defaultSlot: _defaultSlot, ...rootRawSchema } = template;
|
|
31
|
+
// Skip unfolding for type-only templates (all keys are namespaced)
|
|
32
|
+
if (isTypeOnlyTemplate(template)) {
|
|
33
|
+
templateRegistry.set(url, template, new Set(), extractUrls(template));
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const schema = unfoldNodeSchema(rootRawSchema, { type: 'component' });
|
|
37
|
+
const componentTypes = extractComponentTypes(schema);
|
|
38
|
+
const dependencies = extractUrls(template);
|
|
39
|
+
templateRegistry.set(url, template, componentTypes, dependencies);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
log.error(`Failed to resolve template: ${url}`, e);
|
|
43
|
+
throw new Error(`Failed to resolve template: ${url}`, { cause: e });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function collectAllTemplates(recipe, collected) {
|
|
48
|
+
const urls = extractUrls(recipe);
|
|
49
|
+
const newUrls = Array.from(urls).filter((url) => !templateRegistry.has(url) && !collected.has(url));
|
|
50
|
+
if (newUrls.length === 0)
|
|
51
|
+
return;
|
|
52
|
+
const templates = await Promise.all(newUrls.map((url) => loadRecipe(url)));
|
|
53
|
+
// Register types immediately after loading (before recursive collection)
|
|
54
|
+
const pending = new Map();
|
|
55
|
+
for (const template of templates) {
|
|
56
|
+
const isTypeOnlyFile = isTypeOnlyTemplate(template);
|
|
57
|
+
const typesToRegister = isTypeOnlyFile ? template : (template.types ?? {});
|
|
58
|
+
for (const [key, value] of Object.entries(typesToRegister)) {
|
|
59
|
+
if (key === 'importTypes')
|
|
60
|
+
continue;
|
|
61
|
+
if (isTypeOnlyFile && !key.includes('.')) {
|
|
62
|
+
throw new Error(`Invalid key "${key}" in type-only file. Type names must be namespaced (e.g., "app.MyType")`);
|
|
63
|
+
}
|
|
64
|
+
if (typeof value !== 'string' && !isObject(value)) {
|
|
65
|
+
throw new Error(`Invalid type definition for "${key}". Expected string or object, got ${typeof value}`);
|
|
66
|
+
}
|
|
67
|
+
pending.set(key, value);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Register with retries to handle forward references between types
|
|
71
|
+
let lastSize = -1;
|
|
72
|
+
while (pending.size > 0 && pending.size !== lastSize) {
|
|
73
|
+
lastSize = pending.size;
|
|
74
|
+
for (const [key, value] of pending) {
|
|
75
|
+
try {
|
|
76
|
+
registerDeclaredType(key, value);
|
|
77
|
+
pending.delete(key);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Will retry after other types are registered
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
for (const [key, value] of pending) {
|
|
85
|
+
try {
|
|
86
|
+
registerDeclaredType(key, value);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
throw new Error(`Failed to register type "${key}"`, { cause: e });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (let i = 0; i < newUrls.length; i++) {
|
|
93
|
+
collected.set(newUrls[i], templates[i]);
|
|
94
|
+
}
|
|
95
|
+
// Recursively collect from loaded templates
|
|
96
|
+
await Promise.all(templates.map((t) => collectAllTemplates(t, collected)));
|
|
97
|
+
}
|
|
98
|
+
function extractUrls(value, urls = new Set()) {
|
|
99
|
+
if (value == null)
|
|
100
|
+
return urls;
|
|
101
|
+
if (Array.isArray(value)) {
|
|
102
|
+
value.forEach((item) => extractUrls(item, urls));
|
|
103
|
+
return urls;
|
|
104
|
+
}
|
|
105
|
+
if (!isObject(value))
|
|
106
|
+
return urls;
|
|
107
|
+
if ('_defer' in value)
|
|
108
|
+
return urls;
|
|
109
|
+
for (const [key, val] of Object.entries(value)) {
|
|
110
|
+
if (key.startsWith(WrapperPrefix) && key.includes(PathSymbol)) {
|
|
111
|
+
urls.add(key.slice(1));
|
|
112
|
+
}
|
|
113
|
+
if (key === 'importTypes') {
|
|
114
|
+
if (!Array.isArray(val)) {
|
|
115
|
+
throw new Error(`"importTypes" must be an array, got ${typeof val}`);
|
|
116
|
+
}
|
|
117
|
+
for (const url of val) {
|
|
118
|
+
if (typeof url !== 'string') {
|
|
119
|
+
throw new Error(`"importTypes" entries must be strings, got ${typeof url}`);
|
|
120
|
+
}
|
|
121
|
+
urls.add(url);
|
|
122
|
+
}
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (typeof val !== 'string') {
|
|
126
|
+
extractUrls(val, urls);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (key === 'templateUrl') {
|
|
130
|
+
urls.add(val);
|
|
131
|
+
}
|
|
132
|
+
extractUrls(val, urls);
|
|
133
|
+
}
|
|
134
|
+
return urls;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=load-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-templates.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/load/load-templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAIrC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;AAElF,SAAS,kBAAkB,CAAC,QAAiC;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAwC;IAC1E,wEAAwE;IACxE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoC,CAAC;IACjE,MAAM,mBAAmB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAEhD,0EAA0E;IAC1E,MAAM,SAAS,GAAI,MAAmC,CAAC,KAAK,CAAC;IAC7D,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,oBAAoB,CAAC,GAAG,EAAE,KAAwC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,EACJ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,YAAY,EACzB,QAAQ,EAAE,SAAS,EACnB,WAAW,EAAE,YAAY,EACzB,GAAG,aAAa,EACjB,GAAG,QAAQ,CAAC;YAEb,mEAAmE;YACnE,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtE,SAAS;YACX,CAAC;YAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YACtE,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;YACrD,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3C,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,KAAK,CAAC,+BAA+B,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,MAAwC,EACxC,SAAgD;IAEhD,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAE3E,yEAAyE;IACzE,MAAM,OAAO,GAAG,IAAI,GAAG,EAA2C,CAAC;IAEnE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,cAAc,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAE3E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3D,IAAI,GAAG,KAAK,aAAa;gBAAE,SAAS;YAEpC,IAAI,cAAc,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,yEAAyE,CAAC,CAAC;YAChH,CAAC;YAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClD,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,qCAAqC,OAAO,KAAK,EAAE,CAAC,CAAC;YAC1G,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAwC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;IAClB,OAAO,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrD,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;QACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBACjC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,4CAA4C;IAC5C,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,WAAW,CAAC,KAAc,EAAE,OAAoB,IAAI,GAAG,EAAE;IAChE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAE/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAElC,IAAI,QAAQ,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IAEnC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,GAAG,EAAE,CAAC,CAAC;YACvE,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;gBACtB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,8CAA8C,OAAO,GAAG,EAAE,CAAC,CAAC;gBAC9E,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;QAED,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { log } from '@kaskad/config';\n\nimport { ComponentRecipe, TemplateRecipe } from '../types/component-schema';\nimport { TemplateRecipeDefinition } from '../types/template-raw-definition';\nimport { PathSymbol, WrapperPrefix } from '../unfolding/unfold-flat-wrapper-notation';\nimport { unfoldNodeSchema } from '../unfolding/unfold-node-schema';\nimport { isObject } from '../util/is-object';\nimport { loadRecipe } from './load-schema';\nimport { registerDeclaredType } from './register-declared-type';\nimport { extractComponentTypes } from './schema-component-extractor';\nimport { templateRegistry } from './template-registry';\n\nconst reservedKeys = new Set(['importTypes', 'types', 'contract', 'defaultSlot']);\n\nfunction isTypeOnlyTemplate(template: Record<string, unknown>): boolean {\n const contentKeys = Object.keys(template).filter((k) => !reservedKeys.has(k));\n return contentKeys.length > 0 && contentKeys.every((k) => k.includes('.'));\n}\n\nexport async function loadTemplates(recipe: TemplateRecipe | ComponentRecipe) {\n // Pass 1: Recursively load all templates and register types immediately\n const allTemplates = new Map<string, TemplateRecipeDefinition>();\n await collectAllTemplates(recipe, allTemplates);\n\n // Register types from the root recipe (after all dependencies are loaded)\n const rootTypes = (recipe as TemplateRecipeDefinition).types;\n if (rootTypes) {\n for (const [key, value] of Object.entries(rootTypes)) {\n if (typeof value === 'string' || isObject(value)) {\n registerDeclaredType(key, value as string | Record<string, string>);\n }\n }\n }\n\n // Pass 2: Unfold and register all templates (types are already registered)\n for (const [url, template] of allTemplates) {\n try {\n const {\n types: _types,\n importTypes: _importTypes,\n contract: _contract,\n defaultSlot: _defaultSlot,\n ...rootRawSchema\n } = template;\n\n // Skip unfolding for type-only templates (all keys are namespaced)\n if (isTypeOnlyTemplate(template)) {\n templateRegistry.set(url, template, new Set(), extractUrls(template));\n continue;\n }\n\n const schema = unfoldNodeSchema(rootRawSchema, { type: 'component' });\n const componentTypes = extractComponentTypes(schema);\n const dependencies = extractUrls(template);\n templateRegistry.set(url, template, componentTypes, dependencies);\n } catch (e) {\n log.error(`Failed to resolve template: ${url}`, e);\n throw new Error(`Failed to resolve template: ${url}`, { cause: e });\n }\n }\n}\n\nasync function collectAllTemplates(\n recipe: TemplateRecipe | ComponentRecipe,\n collected: Map<string, TemplateRecipeDefinition>,\n): Promise<void> {\n const urls = extractUrls(recipe);\n const newUrls = Array.from(urls).filter((url) => !templateRegistry.has(url) && !collected.has(url));\n\n if (newUrls.length === 0) return;\n\n const templates = await Promise.all(newUrls.map((url) => loadRecipe(url)));\n\n // Register types immediately after loading (before recursive collection)\n const pending = new Map<string, string | Record<string, string>>();\n\n for (const template of templates) {\n const isTypeOnlyFile = isTypeOnlyTemplate(template);\n const typesToRegister = isTypeOnlyFile ? template : (template.types ?? {});\n\n for (const [key, value] of Object.entries(typesToRegister)) {\n if (key === 'importTypes') continue;\n\n if (isTypeOnlyFile && !key.includes('.')) {\n throw new Error(`Invalid key \"${key}\" in type-only file. Type names must be namespaced (e.g., \"app.MyType\")`);\n }\n\n if (typeof value !== 'string' && !isObject(value)) {\n throw new Error(`Invalid type definition for \"${key}\". Expected string or object, got ${typeof value}`);\n }\n\n pending.set(key, value as string | Record<string, string>);\n }\n }\n\n // Register with retries to handle forward references between types\n let lastSize = -1;\n while (pending.size > 0 && pending.size !== lastSize) {\n lastSize = pending.size;\n for (const [key, value] of pending) {\n try {\n registerDeclaredType(key, value);\n pending.delete(key);\n } catch {\n // Will retry after other types are registered\n }\n }\n }\n\n for (const [key, value] of pending) {\n try {\n registerDeclaredType(key, value);\n } catch (e) {\n throw new Error(`Failed to register type \"${key}\"`, { cause: e });\n }\n }\n\n for (let i = 0; i < newUrls.length; i++) {\n collected.set(newUrls[i], templates[i]);\n }\n\n // Recursively collect from loaded templates\n await Promise.all(templates.map((t) => collectAllTemplates(t, collected)));\n}\n\nfunction extractUrls(value: unknown, urls: Set<string> = new Set()): Set<string> {\n if (value == null) return urls;\n\n if (Array.isArray(value)) {\n value.forEach((item) => extractUrls(item, urls));\n return urls;\n }\n\n if (!isObject(value)) return urls;\n\n if ('_defer' in value) return urls;\n\n for (const [key, val] of Object.entries(value)) {\n if (key.startsWith(WrapperPrefix) && key.includes(PathSymbol)) {\n urls.add(key.slice(1));\n }\n\n if (key === 'importTypes') {\n if (!Array.isArray(val)) {\n throw new Error(`\"importTypes\" must be an array, got ${typeof val}`);\n }\n for (const url of val) {\n if (typeof url !== 'string') {\n throw new Error(`\"importTypes\" entries must be strings, got ${typeof url}`);\n }\n urls.add(url);\n }\n continue;\n }\n\n if (typeof val !== 'string') {\n extractUrls(val, urls);\n continue;\n }\n\n if (key === 'templateUrl') {\n urls.add(val);\n }\n\n extractUrls(val, urls);\n }\n\n return urls;\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DefinitionStore } from '@kaskad/definition';
|
|
2
|
+
import { parseValueType } from '../unfolding/parse-value-type';
|
|
3
|
+
export function registerDeclaredType(name, definition) {
|
|
4
|
+
let properties;
|
|
5
|
+
if (typeof definition === 'string') {
|
|
6
|
+
const parsed = parseValueType(definition);
|
|
7
|
+
if (parsed.type !== 'object') {
|
|
8
|
+
throw new Error(`Type "${name}" must be an object type, got "${parsed.type}"`);
|
|
9
|
+
}
|
|
10
|
+
properties = parsed.fields;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
properties = {};
|
|
14
|
+
for (const [propName, propType] of Object.entries(definition)) {
|
|
15
|
+
properties[propName] = parseValueType(propType);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const store = DefinitionStore.getInstance();
|
|
19
|
+
const existing = store.shapes[name];
|
|
20
|
+
if (existing && !isEqualType(existing.properties, properties)) {
|
|
21
|
+
throw new Error(`Type "${name}" is already defined with a different shape`);
|
|
22
|
+
}
|
|
23
|
+
store.setShape(name, properties);
|
|
24
|
+
}
|
|
25
|
+
function isEqualType(a, b) {
|
|
26
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=register-declared-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-declared-type.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/load/register-declared-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,UAA2C;IAC5F,IAAI,UAAqC,CAAC;IAE1C,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,kCAAkC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QACjF,CAAC;QACD,UAAU,GAAI,MAA0B,CAAC,MAAM,CAAC;IAClD,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,UAAU,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEpC,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,6CAA6C,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,WAAW,CAAC,CAA4B,EAAE,CAA4B;IAC7E,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC","sourcesContent":["import { DefinitionStore } from '@kaskad/definition';\nimport { ObjectValueType, ValueType } from '@kaskad/types';\n\nimport { parseValueType } from '../unfolding/parse-value-type';\n\nexport function registerDeclaredType(name: string, definition: string | Record<string, string>): void {\n let properties: Record<string, ValueType>;\n\n if (typeof definition === 'string') {\n const parsed = parseValueType(definition);\n if (parsed.type !== 'object') {\n throw new Error(`Type \"${name}\" must be an object type, got \"${parsed.type}\"`);\n }\n properties = (parsed as ObjectValueType).fields;\n } else {\n properties = {};\n for (const [propName, propType] of Object.entries(definition)) {\n properties[propName] = parseValueType(propType);\n }\n }\n\n const store = DefinitionStore.getInstance();\n const existing = store.shapes[name];\n\n if (existing && !isEqualType(existing.properties, properties)) {\n throw new Error(`Type \"${name}\" is already defined with a different shape`);\n }\n\n store.setShape(name, properties);\n}\n\nfunction isEqualType(a: Record<string, ValueType>, b: Record<string, ValueType>): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n"]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { isForComputation, isIfComputation, isSwitchComputation, isTemplateComputation, } from '@kaskad/types';
|
|
2
|
+
import { isObject } from '../util/is-object';
|
|
3
|
+
export function extractComponentTypes(schema, types = new Set()) {
|
|
4
|
+
extractFromValue(schema, types);
|
|
5
|
+
extractFromComputations(schema, types);
|
|
6
|
+
return types;
|
|
7
|
+
}
|
|
8
|
+
function extractFromValue(schema, types) {
|
|
9
|
+
if (!schema.value) {
|
|
10
|
+
return types;
|
|
11
|
+
}
|
|
12
|
+
const type = schema.valueType.type;
|
|
13
|
+
if (type === 'component') {
|
|
14
|
+
const componentSchema = schema;
|
|
15
|
+
if (!isObject(componentSchema.value)) {
|
|
16
|
+
return types;
|
|
17
|
+
}
|
|
18
|
+
types.add(componentSchema.value.componentType);
|
|
19
|
+
for (const prop of componentSchema.value.props.values()) {
|
|
20
|
+
extractComponentTypes(prop, types);
|
|
21
|
+
}
|
|
22
|
+
for (const variable of componentSchema.value.variables.values()) {
|
|
23
|
+
extractComponentTypes(variable, types);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (type === 'componentSchema' || type === 'unknown') {
|
|
27
|
+
const componentSchema = schema;
|
|
28
|
+
if (isObject(componentSchema.value) && 'componentType' in componentSchema.value) {
|
|
29
|
+
extractFromRawComponentSchema(componentSchema.value, types);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (type === 'array') {
|
|
33
|
+
const arraySchema = schema;
|
|
34
|
+
for (const item of arraySchema.value || []) {
|
|
35
|
+
extractComponentTypes(item, types);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (type === 'object' || type === 'map') {
|
|
39
|
+
const objectSchema = schema;
|
|
40
|
+
for (const prop of Object.values(objectSchema.value || {})) {
|
|
41
|
+
extractComponentTypes(prop, types);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return types;
|
|
45
|
+
}
|
|
46
|
+
function extractFromComputations(schema, types) {
|
|
47
|
+
if (!schema.computation) {
|
|
48
|
+
return types;
|
|
49
|
+
}
|
|
50
|
+
if (isSwitchComputation(schema.computation)) {
|
|
51
|
+
for (const caseItem of schema.computation.cases) {
|
|
52
|
+
extractComponentTypes(caseItem.then, types);
|
|
53
|
+
}
|
|
54
|
+
extractComponentTypes(schema.computation.default, types);
|
|
55
|
+
}
|
|
56
|
+
if (isIfComputation(schema.computation)) {
|
|
57
|
+
extractComponentTypes(schema.computation.then, types);
|
|
58
|
+
extractComponentTypes(schema.computation.else, types);
|
|
59
|
+
}
|
|
60
|
+
if (isForComputation(schema.computation)) {
|
|
61
|
+
extractComponentTypes(schema.computation.yield, types);
|
|
62
|
+
}
|
|
63
|
+
if (isTemplateComputation(schema.computation)) {
|
|
64
|
+
if (schema.computation.defer) {
|
|
65
|
+
if (schema.computation.defer.placeholder) {
|
|
66
|
+
extractComponentTypes(schema.computation.defer.placeholder, types);
|
|
67
|
+
}
|
|
68
|
+
if (schema.computation.defer.error) {
|
|
69
|
+
extractComponentTypes(schema.computation.defer.error, types);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const variable of Object.values(schema.computation.contractVariables)) {
|
|
73
|
+
if (isObject(variable) || Array.isArray(variable)) {
|
|
74
|
+
extractFromRawComponentSchema(variable, types);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return types;
|
|
79
|
+
}
|
|
80
|
+
function extractFromRawComponentSchema(schema, types) {
|
|
81
|
+
if (Array.isArray(schema)) {
|
|
82
|
+
for (const item of schema) {
|
|
83
|
+
if (isObject(item) || Array.isArray(item)) {
|
|
84
|
+
extractFromRawComponentSchema(item, types);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return types;
|
|
88
|
+
}
|
|
89
|
+
if (isObject(schema)) {
|
|
90
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
91
|
+
if (key === 'componentType' && typeof value === 'string') {
|
|
92
|
+
types.add(value);
|
|
93
|
+
}
|
|
94
|
+
if (isObject(value) || Array.isArray(value)) {
|
|
95
|
+
extractFromRawComponentSchema(value, types);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return types;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=schema-component-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-component-extractor.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/load/schema-component-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ArrayNodeSchema,\n ComponentNodeSchema,\n ComponentSchemaNodeSchema,\n isForComputation,\n isIfComputation,\n isSwitchComputation,\n isTemplateComputation,\n NodeSchema,\n ObjectNodeSchema,\n} from '@kaskad/types';\n\nimport { isObject } from '../util/is-object';\n\nexport function extractComponentTypes(schema: NodeSchema, types: Set<string> = new Set()): Set<string> {\n extractFromValue(schema, types);\n extractFromComputations(schema, types);\n\n return types;\n}\n\nfunction extractFromValue(schema: NodeSchema, types: Set<string>) {\n if (!schema.value) {\n return types;\n }\n\n const type = schema.valueType.type;\n\n if (type === 'component') {\n const componentSchema = schema as ComponentNodeSchema;\n if (!isObject(componentSchema.value)) {\n return types;\n }\n\n types.add(componentSchema.value.componentType);\n\n for (const prop of componentSchema.value.props.values()) {\n extractComponentTypes(prop, types);\n }\n for (const variable of componentSchema.value.variables.values()) {\n extractComponentTypes(variable, types);\n }\n }\n\n if (type === 'componentSchema' || type === 'unknown') {\n const componentSchema = schema as ComponentSchemaNodeSchema;\n\n if (isObject(componentSchema.value) && 'componentType' in componentSchema.value) {\n extractFromRawComponentSchema(componentSchema.value, types);\n }\n }\n\n if (type === 'array') {\n const arraySchema = schema as ArrayNodeSchema;\n for (const item of arraySchema.value || []) {\n extractComponentTypes(item, types);\n }\n }\n\n if (type === 'object' || type === 'map') {\n const objectSchema = schema as ObjectNodeSchema;\n for (const prop of Object.values(objectSchema.value || {})) {\n extractComponentTypes(prop, types);\n }\n }\n\n return types;\n}\n\nfunction extractFromComputations(schema: NodeSchema, types: Set<string>) {\n if (!schema.computation) {\n return types;\n }\n\n if (isSwitchComputation(schema.computation)) {\n for (const caseItem of schema.computation.cases) {\n extractComponentTypes(caseItem.then, types);\n }\n extractComponentTypes(schema.computation.default, types);\n }\n\n if (isIfComputation(schema.computation)) {\n extractComponentTypes(schema.computation.then, types);\n extractComponentTypes(schema.computation.else, types);\n }\n\n if (isForComputation(schema.computation)) {\n extractComponentTypes(schema.computation.yield as NodeSchema, types);\n }\n\n if (isTemplateComputation(schema.computation)) {\n if (schema.computation.defer) {\n if (schema.computation.defer.placeholder) {\n extractComponentTypes(schema.computation.defer.placeholder, types);\n }\n if (schema.computation.defer.error) {\n extractComponentTypes(schema.computation.defer.error, types);\n }\n }\n\n for (const variable of Object.values(schema.computation.contractVariables)) {\n if (isObject(variable) || Array.isArray(variable)) {\n extractFromRawComponentSchema(variable, types);\n }\n }\n }\n\n return types;\n}\n\nfunction extractFromRawComponentSchema(schema: Record<string, unknown> | unknown[], types: Set<string>): Set<string> {\n if (Array.isArray(schema)) {\n for (const item of schema) {\n if (isObject(item) || Array.isArray(item)) {\n extractFromRawComponentSchema(item, types);\n }\n }\n return types;\n }\n\n if (isObject(schema)) {\n for (const [key, value] of Object.entries(schema)) {\n if (key === 'componentType' && typeof value === 'string') {\n types.add(value);\n }\n if (isObject(value) || Array.isArray(value)) {\n extractFromRawComponentSchema(value, types);\n }\n }\n }\n\n return types;\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const templateRegistry = {
|
|
2
|
+
entries: new Map(),
|
|
3
|
+
get(url) {
|
|
4
|
+
return this.entries.get(url);
|
|
5
|
+
},
|
|
6
|
+
getAggregatedComponentTypes(url) {
|
|
7
|
+
const aggregated = new Set();
|
|
8
|
+
const visited = new Set();
|
|
9
|
+
const collect = (currentUrl) => {
|
|
10
|
+
if (visited.has(currentUrl))
|
|
11
|
+
return;
|
|
12
|
+
visited.add(currentUrl);
|
|
13
|
+
const entry = this.entries.get(currentUrl);
|
|
14
|
+
if (!entry)
|
|
15
|
+
return;
|
|
16
|
+
// Add own component types
|
|
17
|
+
for (const type of entry.ownComponentTypes) {
|
|
18
|
+
aggregated.add(type);
|
|
19
|
+
}
|
|
20
|
+
// Recursively collect from dependencies
|
|
21
|
+
for (const depUrl of entry.dependencies) {
|
|
22
|
+
collect(depUrl);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
collect(url);
|
|
26
|
+
return aggregated;
|
|
27
|
+
},
|
|
28
|
+
getAllComponentTypes() {
|
|
29
|
+
const allTypes = new Set();
|
|
30
|
+
for (const entry of this.entries.values()) {
|
|
31
|
+
for (const type of entry.ownComponentTypes) {
|
|
32
|
+
allTypes.add(type);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return allTypes;
|
|
36
|
+
},
|
|
37
|
+
set(url, recipe, ownComponentTypes, dependencies) {
|
|
38
|
+
this.entries.set(url, {
|
|
39
|
+
recipe,
|
|
40
|
+
ownComponentTypes,
|
|
41
|
+
dependencies: dependencies || new Set(),
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
has(url) {
|
|
45
|
+
return this.entries.has(url);
|
|
46
|
+
},
|
|
47
|
+
reset() {
|
|
48
|
+
this.entries.clear();
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=template-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-registry.js","sourceRoot":"","sources":["../../../../../../libs/schema/src/lib/load/template-registry.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,OAAO,EAAE,IAAI,GAAG,EAAyB;IAEzC,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,2BAA2B,CAAC,GAAW;QACrC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAElC,MAAM,OAAO,GAAG,CAAC,UAAkB,EAAE,EAAE;YACrC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,OAAO;YACpC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAExB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK;gBAAE,OAAO;YAEnB,0BAA0B;YAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;YAED,wCAAwC;YACxC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;gBACxC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,oBAAoB;QAClB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QAEnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,MAAgC,EAAE,iBAA8B,EAAE,YAA0B;QAC3G,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;YACpB,MAAM;YACN,iBAAiB;YACjB,YAAY,EAAE,YAAY,IAAI,IAAI,GAAG,EAAE;SACxC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF,CAAC","sourcesContent":["import { TemplateRecipeDefinition } from '../types/template-raw-definition';\n\ninterface TemplateEntry {\n recipe: TemplateRecipeDefinition;\n ownComponentTypes: Set<string>;\n dependencies: Set<string>;\n}\n\nexport const templateRegistry = {\n entries: new Map<string, TemplateEntry>(),\n\n get(url: string): TemplateEntry | undefined {\n return this.entries.get(url);\n },\n\n getAggregatedComponentTypes(url: string): Set<string> {\n const aggregated = new Set<string>();\n const visited = new Set<string>();\n\n const collect = (currentUrl: string) => {\n if (visited.has(currentUrl)) return;\n visited.add(currentUrl);\n\n const entry = this.entries.get(currentUrl);\n if (!entry) return;\n\n // Add own component types\n for (const type of entry.ownComponentTypes) {\n aggregated.add(type);\n }\n\n // Recursively collect from dependencies\n for (const depUrl of entry.dependencies) {\n collect(depUrl);\n }\n };\n\n collect(url);\n return aggregated;\n },\n\n getAllComponentTypes(): Set<string> {\n const allTypes = new Set<string>();\n\n for (const entry of this.entries.values()) {\n for (const type of entry.ownComponentTypes) {\n allTypes.add(type);\n }\n }\n\n return allTypes;\n },\n\n set(url: string, recipe: TemplateRecipeDefinition, ownComponentTypes: Set<string>, dependencies?: Set<string>) {\n this.entries.set(url, {\n recipe,\n ownComponentTypes,\n dependencies: dependencies || new Set(),\n });\n },\n\n has(url: string): boolean {\n return this.entries.has(url);\n },\n\n reset() {\n this.entries.clear();\n },\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=component-definition.js.map
|