@microsoft/fast-html 1.0.0-alpha.3 → 1.0.0-alpha.31

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 (56) hide show
  1. package/README.md +255 -18
  2. package/dist/dts/components/element.d.ts +10 -0
  3. package/dist/dts/components/index.d.ts +3 -1
  4. package/dist/dts/components/observer-map.d.ts +26 -0
  5. package/dist/dts/components/schema.d.ts +144 -0
  6. package/dist/dts/components/template.d.ts +83 -7
  7. package/dist/dts/components/utilities.d.ts +109 -18
  8. package/dist/dts/fixtures/lifecycle-callbacks/lifecycle-callbacks.spec.d.ts +1 -0
  9. package/dist/dts/fixtures/lifecycle-callbacks/main.d.ts +5 -0
  10. package/dist/dts/fixtures/observer-map/main.d.ts +1 -0
  11. package/dist/dts/fixtures/observer-map/observer-map.spec.d.ts +1 -0
  12. package/dist/dts/index.d.ts +1 -1
  13. package/dist/esm/components/element.js +28 -0
  14. package/dist/esm/components/index.js +3 -1
  15. package/dist/esm/components/observer-map.js +53 -0
  16. package/dist/esm/components/observer-map.spec.js +19 -0
  17. package/dist/esm/components/schema.js +250 -0
  18. package/dist/esm/components/schema.spec.js +485 -0
  19. package/dist/esm/components/template.js +199 -111
  20. package/dist/esm/components/utilities.js +741 -43
  21. package/dist/esm/components/utilities.spec.js +317 -44
  22. package/dist/esm/fixtures/attribute/main.js +3 -2
  23. package/dist/esm/fixtures/binding/binding.spec.js +6 -0
  24. package/dist/esm/fixtures/binding/main.js +13 -2
  25. package/dist/esm/fixtures/children/children.spec.js +4 -0
  26. package/dist/esm/fixtures/children/main.js +3 -2
  27. package/dist/esm/fixtures/dot-syntax/dot-syntax.spec.js +109 -2
  28. package/dist/esm/fixtures/dot-syntax/main.js +30 -4
  29. package/dist/esm/fixtures/event/event.spec.js +28 -5
  30. package/dist/esm/fixtures/event/main.js +21 -5
  31. package/dist/esm/fixtures/lifecycle-callbacks/lifecycle-callbacks.spec.js +166 -0
  32. package/dist/esm/fixtures/lifecycle-callbacks/main.js +126 -0
  33. package/dist/esm/fixtures/observer-map/main.js +375 -0
  34. package/dist/esm/fixtures/observer-map/observer-map.spec.js +251 -0
  35. package/dist/esm/fixtures/ref/main.js +3 -2
  36. package/dist/esm/fixtures/ref/ref.spec.js +2 -6
  37. package/dist/esm/fixtures/repeat/main.js +27 -2
  38. package/dist/esm/fixtures/repeat/repeat.spec.js +16 -6
  39. package/dist/esm/fixtures/slotted/main.js +15 -4
  40. package/dist/esm/fixtures/slotted/slotted.spec.js +18 -19
  41. package/dist/esm/fixtures/when/main.js +139 -2
  42. package/dist/esm/fixtures/when/when.spec.js +64 -1
  43. package/dist/esm/index.js +1 -1
  44. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  45. package/dist/fast-html.api.json +333 -0
  46. package/dist/fast-html.d.ts +282 -6
  47. package/dist/fast-html.untrimmed.d.ts +282 -6
  48. package/package.json +12 -7
  49. package/rules/attribute-directives.yml +38 -0
  50. package/rules/call-expression-with-event-argument.yml +41 -0
  51. package/rules/member-expression.yml +33 -0
  52. package/rules/tag-function-to-template-literal.yml +16 -0
  53. package/dist/esm/fixtures/partial/main.js +0 -31
  54. package/dist/esm/fixtures/partial/partial.spec.js +0 -14
  55. /package/dist/dts/{fixtures/partial/main.d.ts → components/observer-map.spec.d.ts} +0 -0
  56. /package/dist/dts/{fixtures/partial/partial.spec.d.ts → components/schema.spec.d.ts} +0 -0
@@ -1,9 +1,12 @@
1
+ import { JSONSchema, JSONSchemaDefinition, Schema } from "./schema.js";
1
2
  type BehaviorType = "dataBinding" | "templateDirective";
2
- type TemplateDirective = "when" | "repeat" | "apply";
3
+ type TemplateDirective = "when" | "repeat";
3
4
  export type AttributeDirective = "children" | "slotted" | "ref";
5
+ type DataBindingBindingType = "client" | "default" | "unescaped";
4
6
  interface BehaviorConfig {
5
7
  type: BehaviorType;
6
8
  }
9
+ export type PathType = "access" | "default" | "event" | "repeat";
7
10
  export interface ContentDataBindingBehaviorConfig extends BaseDataBindingBehaviorConfig {
8
11
  subtype: "content";
9
12
  }
@@ -18,6 +21,7 @@ export interface AttributeDirectiveBindingBehaviorConfig extends BaseDataBinding
18
21
  export type DataBindingBehaviorConfig = ContentDataBindingBehaviorConfig | AttributeDataBindingBehaviorConfig | AttributeDirectiveBindingBehaviorConfig;
19
22
  export interface BaseDataBindingBehaviorConfig extends BehaviorConfig {
20
23
  type: "dataBinding";
24
+ bindingType: DataBindingBindingType;
21
25
  openingStartIndex: number;
22
26
  openingEndIndex: number;
23
27
  closingStartIndex: number;
@@ -32,10 +36,9 @@ export interface TemplateDirectiveBehaviorConfig extends BehaviorConfig {
32
36
  closingTagStartIndex: number;
33
37
  closingTagEndIndex: number;
34
38
  }
35
- interface PartialTemplateConfig {
36
- innerHTML: string;
37
- startIndex: number;
38
- endIndex: number;
39
+ export interface ChildrenMap {
40
+ customElementName: string;
41
+ attributeName: string;
39
42
  }
40
43
  /**
41
44
  * Get the index of the next matching tag
@@ -52,18 +55,6 @@ export declare function getIndexOfNextMatchingTag(openingTagStartSlice: string,
52
55
  * @returns DataBindingBehaviorConfig | DirectiveBehaviorConfig | null - A configuration object or null
53
56
  */
54
57
  export declare function getNextBehavior(innerHTML: string): DataBindingBehaviorConfig | TemplateDirectiveBehaviorConfig | null;
55
- /**
56
- * Gets all the partials with their IDs
57
- * @param innerHTML - The innerHTML string to evaluate
58
- * @param offset - The index offset from the innerHTML
59
- * @param partials - The partials found
60
- * @returns {[key: string]: PartialTemplateConfig}
61
- */
62
- export declare function getAllPartials(innerHTML: string, offset?: number, partials?: {
63
- [key: string]: PartialTemplateConfig;
64
- }): {
65
- [key: string]: PartialTemplateConfig;
66
- };
67
58
  /**
68
59
  * Create a function to resolve a value from an object using a path with dot syntax.
69
60
  * e.g. "foo.bar"
@@ -71,5 +62,105 @@ export declare function getAllPartials(innerHTML: string, offset?: number, parti
71
62
  * @param self - Where the first item in the path path refers to the item itself (used by repeat).
72
63
  * @returns A function to access the value from a given path.
73
64
  */
74
- export declare function pathResolver(path: string, self?: boolean): (accessibleObject: any) => any;
65
+ export declare function pathResolver(path: string, contextPath: string | null, level: number, rootSchema: JSONSchema): (accessibleObject: any, context: any) => any;
66
+ export declare function bindingResolver(previousString: string | null, rootPropertyName: string | null, path: string, parentContext: string | null, type: PathType, schema: Schema, currentContext: string | null, level: number): (accessibleObject: any, context: any) => any;
67
+ export declare function expressionResolver(rootPropertyName: string | null, expression: ChainedExpression, parentContext: string | null, level: number, schema: Schema): (accessibleObject: any, context: any) => any;
68
+ /**
69
+ * Extracts all paths from a ChainedExpression, including nested expressions
70
+ * @param chainedExpression - The chained expression to extract paths from
71
+ * @returns A Set containing all unique paths found in the expression chain
72
+ */
73
+ export declare function extractPathsFromChainedExpression(chainedExpression: ChainedExpression): Set<string>;
74
+ /**
75
+ * Available operators include:
76
+ *
77
+ * - access (no operator)
78
+ * - not (!)
79
+ * - equals (==)
80
+ * - not equal (!=)
81
+ * - greater than or equal (>=)
82
+ * - greater than (>)
83
+ * - less than or equal (<=)
84
+ * - less than (<)
85
+ * - or (||)
86
+ * - and (&&) and the HTML character entity (&amp;&amp;)
87
+ */
88
+ type Operator = "access" | "!" | "==" | "!=" | ">=" | ">" | "<=" | "<";
89
+ type ChainingOperator = "||" | "&&" | "&amp;&amp;";
90
+ interface Expression {
91
+ operator: Operator;
92
+ left: string;
93
+ leftIsValue: boolean | null;
94
+ right: string | boolean | number | null;
95
+ rightIsValue: boolean | null;
96
+ }
97
+ export interface ChainedExpression {
98
+ operator?: ChainingOperator;
99
+ expression: Expression;
100
+ next?: ChainedExpression;
101
+ }
102
+ /**
103
+ * Gets the expression chain as a configuration object
104
+ * @param value - The binding string value
105
+ * @returns - A configuration object containing information about the expression
106
+ */
107
+ export declare function getExpressionChain(value: string): ChainedExpression | void;
108
+ /**
109
+ * This is the transform utility for rationalizing declarative HTML syntax
110
+ * with bindings in the ViewTemplate
111
+ * @param innerHTML The innerHTML to transform
112
+ * @param index The index to start the current slice of HTML to evaluate
113
+ */
114
+ export declare function transformInnerHTML(innerHTML: string, index?: number): string;
115
+ /**
116
+ * Resolves f-when
117
+ * @param self - Where the first item in the path path refers to the item itself (used by repeat).
118
+ * @param chainedExpression - The chained expression which includes the expression and the next expression
119
+ * if there is another in the chain
120
+ * @returns - A binding that resolves the chained expression logic
121
+ */
122
+ export declare function resolveWhen(rootPropertyName: string | null, expression: ChainedExpression, parentContext: string | null, level: number, schema: Schema): (x: boolean, c: any) => any;
123
+ /**
124
+ * Find a definition
125
+ * This may exist as a $ref at the root or as a $ref in any anyOf or not at all
126
+ * if the Observer Map has not been enabled on a child component
127
+ * @param schema - The JSON schema to find the ref in
128
+ * @returns The definition or null
129
+ */
130
+ export declare function findDef(schema: JSONSchema | JSONSchemaDefinition): string | null;
131
+ /**
132
+ * Assign observables to data
133
+ * @param schema - The schema
134
+ * @param rootSchema - The root schema mapping to the root property
135
+ * @param data - The data
136
+ * @param target - The target custom element
137
+ * @param rootProperty - The root property
138
+ * @returns
139
+ */
140
+ export declare function assignObservables(schema: JSONSchema | JSONSchemaDefinition, rootSchema: JSONSchema, data: any, target: any, rootProperty: string): typeof Proxy;
141
+ /**
142
+ * Assign a proxy to an object
143
+ * @param schema - The current schema
144
+ * @param rootSchema - The root schema for the root property
145
+ * @param target - The target custom element
146
+ * @param rootProperty - The root property
147
+ * @param object - The object to assign the proxy to
148
+ * @returns Proxy object
149
+ */
150
+ export declare function assignProxy(schema: JSONSchema | JSONSchemaDefinition, rootSchema: JSONSchema, target: any, rootProperty: string, object: any): typeof Proxy;
151
+ /**
152
+ * Get the root property name
153
+ * @param rootPropertyName - The root property
154
+ * @param path - The dot syntax path
155
+ * @param context - The context created by a repeat
156
+ * @param type - The type of path binding
157
+ * @returns
158
+ */
159
+ export declare function getRootPropertyName(rootPropertyName: string | null, path: string, context: null | string, type: PathType): string | null;
160
+ /**
161
+ * Get details of bindings to the attributes of child custom elements
162
+ * @param previousString - The previous string before the binding
163
+ * @returns null, or a custom element name and attribute name
164
+ */
165
+ export declare function getChildrenMap(previousString: string | null): ChildrenMap | null;
75
166
  export {};
@@ -0,0 +1,5 @@
1
+ export declare const lifecycleEvents: Array<{
2
+ callback: string;
3
+ name?: string;
4
+ }>;
5
+ export declare let hydrationCompleteEmitted: boolean;
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1 @@
1
- export { TemplateElement } from "./components/index.js";
1
+ export { RenderableFASTElement, TemplateElement, ObserverMap, } from "./components/index.js";
@@ -0,0 +1,28 @@
1
+ import { attr } from "@microsoft/fast-element";
2
+ /**
3
+ * A mixin function that extends a base class with additional functionality for
4
+ * rendering and hydration.
5
+ *
6
+ * @param BaseCtor - The base class to extend.
7
+ * @returns A new class that extends the provided base class with additional functionality for rendering and hydration.
8
+ * @public
9
+ */
10
+ export function RenderableFASTElement(BaseCtor) {
11
+ const C = class extends BaseCtor {
12
+ constructor(...args) {
13
+ var _a, _b;
14
+ super(...args);
15
+ this.deferHydration = true;
16
+ this.needsHydration = true;
17
+ if (this.$fastController.hasExistingShadowRoot) {
18
+ this.toggleAttribute("defer-hydration", true);
19
+ }
20
+ ((_b = (_a = this.prepare) === null || _a === void 0 ? void 0 : _a.call(this)) !== null && _b !== void 0 ? _b : Promise.resolve()).then(() => {
21
+ this.deferHydration = false;
22
+ });
23
+ }
24
+ };
25
+ attr({ mode: "boolean", attribute: "defer-hydration" })(C.prototype, "deferHydration");
26
+ attr({ mode: "boolean", attribute: "defer-hydration" })(C.prototype, "needsHydration");
27
+ return C;
28
+ }
@@ -1 +1,3 @@
1
- export { TemplateElement } from "./template.js";
1
+ export { RenderableFASTElement } from "./element.js";
2
+ export { ObserverMap } from "./observer-map.js";
3
+ export { ObserverMapOption, TemplateElement, } from "./template.js";
@@ -0,0 +1,53 @@
1
+ import { Observable } from "@microsoft/fast-element/observable.js";
2
+ import { assignObservables } from "./utilities.js";
3
+ /**
4
+ * ObserverMap provides functionality for caching binding paths, extracting root properties,
5
+ * and defining observable properties on class prototypes
6
+ */
7
+ export class ObserverMap {
8
+ constructor(classPrototype, schema) {
9
+ /**
10
+ * Creates a property change handler function for observable properties
11
+ * This handler is called when an observable property transitions from undefined to a defined value
12
+ * @param propertyName - The name of the property for which to create the change handler
13
+ * @returns A function that handles property changes and sets up proxies for object values
14
+ */
15
+ this.defineChanged = (propertyName) => {
16
+ const getAndAssignObservablesAlias = this.getAndAssignObservables;
17
+ const schema = this.schema;
18
+ function instanceResolverChanged(prev, next) {
19
+ if (prev === undefined ||
20
+ ((prev === null || prev === void 0 ? void 0 : prev.$isProxy) && !(next === null || next === void 0 ? void 0 : next.$isProxy)) ||
21
+ (Array.isArray(prev) &&
22
+ Array.isArray(next) &&
23
+ !(next === null || next === void 0 ? void 0 : next.$fastController))) {
24
+ const proxy = getAndAssignObservablesAlias(this, propertyName, next, schema);
25
+ this[propertyName] = proxy;
26
+ }
27
+ }
28
+ return instanceResolverChanged;
29
+ };
30
+ this.classPrototype = classPrototype;
31
+ this.schema = schema;
32
+ }
33
+ defineProperties() {
34
+ const propertyNames = this.schema.getRootProperties();
35
+ for (const propertyName of propertyNames) {
36
+ Observable.defineProperty(this.classPrototype, propertyName);
37
+ this.classPrototype[`${propertyName}Changed`] =
38
+ this.defineChanged(propertyName);
39
+ }
40
+ }
41
+ /**
42
+ * Creates a proxy for an object that intercepts property mutations and triggers Observable notifications
43
+ * @param target - The target instance that owns the root property
44
+ * @param rootProperty - The name of the root property for notification purposes
45
+ * @param object - The object to wrap with a proxy
46
+ * @returns A proxy that triggers notifications on property mutations
47
+ */
48
+ getAndAssignObservables(target, rootProperty, object, schema) {
49
+ let proxiedObject = object;
50
+ proxiedObject = assignObservables(schema.getSchema(rootProperty), schema.getSchema(rootProperty), proxiedObject, target, rootProperty);
51
+ return proxiedObject;
52
+ }
53
+ }
@@ -0,0 +1,19 @@
1
+ import { __awaiter } from "tslib";
2
+ import { expect, test } from "@playwright/test";
3
+ import { ObserverMap } from "./observer-map.js";
4
+ import { Schema } from "./schema.js";
5
+ test.describe("ObserverMap", () => __awaiter(void 0, void 0, void 0, function* () {
6
+ let observerMap;
7
+ let schema = new Schema("test-class");
8
+ class TestClass {
9
+ }
10
+ test.beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
11
+ // Use TestClass.prototype so instances will have the observable properties
12
+ observerMap = new ObserverMap(TestClass.prototype, schema);
13
+ }));
14
+ test("should create new instances", () => __awaiter(void 0, void 0, void 0, function* () {
15
+ const instance1 = new ObserverMap(TestClass.prototype, schema);
16
+ const instance2 = new ObserverMap(TestClass.prototype, schema);
17
+ expect(instance1).not.toBe(instance2);
18
+ }));
19
+ }));
@@ -0,0 +1,250 @@
1
+ // The context, in most cases the array property e.g. users
2
+ export const fastContextMetaData = "$fast_context";
3
+ // The list of contexts preceeding this context, the first of which should be the root property
4
+ export const fastContextsMetaData = "$fast_parent_contexts";
5
+ export const defsPropertyName = "$defs";
6
+ export const refPropertyName = "$ref";
7
+ /**
8
+ * A constructed JSON schema from a template
9
+ */
10
+ export class Schema {
11
+ constructor(name) {
12
+ this.customElementName = name;
13
+ Schema.jsonSchemaMap.set(this.customElementName, new Map());
14
+ }
15
+ /**
16
+ * Add a path to a schema
17
+ * @param config RegisterPathConfig
18
+ */
19
+ addPath(config) {
20
+ var _a, _b, _c;
21
+ const splitPath = this.getSplitPath(config.pathConfig.path);
22
+ let schema = Schema.jsonSchemaMap.get(this.customElementName).get(config.rootPropertyName);
23
+ let childRef = null;
24
+ // Create a root level property JSON
25
+ if (!schema) {
26
+ this.addNewSchema(config.rootPropertyName);
27
+ schema = Schema.jsonSchemaMap.get(this.customElementName).get(config.rootPropertyName);
28
+ }
29
+ if (config.childrenMap) {
30
+ childRef = this.getSchemaId(config.childrenMap.customElementName, config.childrenMap.attributeName);
31
+ if (splitPath.length === 1) {
32
+ schema.anyOf
33
+ ? schema.anyOf.push({ [refPropertyName]: childRef })
34
+ : (schema.anyOf = [{ [refPropertyName]: childRef }]);
35
+ }
36
+ }
37
+ switch (config.pathConfig.type) {
38
+ case "default":
39
+ case "access": {
40
+ if (splitPath.length > 1) {
41
+ if (config.pathConfig.currentContext === null) {
42
+ this.addPropertiesToAnObject(schema, splitPath.slice(1), config.pathConfig.currentContext, childRef);
43
+ }
44
+ else {
45
+ if (!((_a = schema[defsPropertyName]) === null || _a === void 0 ? void 0 : _a[splitPath[0]])) {
46
+ schema[defsPropertyName] = {
47
+ [splitPath[0]]: {},
48
+ };
49
+ }
50
+ this.addPropertiesToAContext(schema[defsPropertyName][splitPath[0]], splitPath.slice(1), config.pathConfig.currentContext, childRef);
51
+ }
52
+ }
53
+ break;
54
+ }
55
+ case "repeat": {
56
+ this.addContext(schema, splitPath.at(-1), // example items
57
+ config.pathConfig.currentContext, // example item
58
+ config.pathConfig.parentContext);
59
+ if (splitPath.length > 2) {
60
+ let updatedSchema = schema;
61
+ const hasParentContext = !!config.pathConfig.parentContext;
62
+ if (hasParentContext) {
63
+ updatedSchema = this.addPropertiesToAnObject((_b = schema[defsPropertyName]) === null || _b === void 0 ? void 0 : _b[config.pathConfig.parentContext], splitPath.slice(1, -1), config.pathConfig.parentContext, childRef);
64
+ }
65
+ this.addPropertiesToAnObject(updatedSchema, hasParentContext ? splitPath.slice(2) : splitPath.slice(1), config.pathConfig.currentContext, childRef, "array");
66
+ }
67
+ else if (splitPath.length > 1) {
68
+ let schemaDefinition;
69
+ if (config.pathConfig.parentContext) {
70
+ schemaDefinition = (_c = schema === null || schema === void 0 ? void 0 : schema[defsPropertyName]) === null || _c === void 0 ? void 0 : _c[config.pathConfig.parentContext];
71
+ }
72
+ this.addPropertiesToAnObject(schemaDefinition !== null && schemaDefinition !== void 0 ? schemaDefinition : schema, splitPath.slice(1), config.pathConfig.currentContext, childRef, "array");
73
+ }
74
+ else {
75
+ schema.type = "array";
76
+ schema[refPropertyName] = this.getDefsPath(config.pathConfig.currentContext);
77
+ }
78
+ break;
79
+ }
80
+ }
81
+ }
82
+ /**
83
+ * Gets the JSON schema for a property name
84
+ * @param rootPropertyName - the root property the JSON schema is mapped to
85
+ * @returns The JSON schema for the root property
86
+ */
87
+ getSchema(rootPropertyName) {
88
+ var _a;
89
+ return ((_a = Schema.jsonSchemaMap.get(this.customElementName).get(rootPropertyName)) !== null && _a !== void 0 ? _a : null);
90
+ }
91
+ /**
92
+ * Gets root properties
93
+ * @returns IterableIterator<string>
94
+ */
95
+ getRootProperties() {
96
+ return Schema.jsonSchemaMap.get(this.customElementName).keys();
97
+ }
98
+ /**
99
+ * Get a path split into property names
100
+ * @param path The dot syntax path e.g. a.b.c
101
+ * @returns An array of items in the path
102
+ */
103
+ getSplitPath(path) {
104
+ return path.split(".");
105
+ }
106
+ /**
107
+ * Gets the path to the $def
108
+ * @param context The context name e.g. {{item in items}} in a repeat creates the "item" context
109
+ * @returns A string to use as a $ref
110
+ */
111
+ getDefsPath(context) {
112
+ return `#/${defsPropertyName}/${context}`;
113
+ }
114
+ /**
115
+ * Get the schema $id
116
+ * @param customElementName - The custom element name
117
+ * @param propertyName - The property name
118
+ * @returns The ID that can be used in the JSON schema as $id
119
+ */
120
+ getSchemaId(customElementName, propertyName) {
121
+ return `https://fast.design/schemas/${customElementName}/${propertyName}.json`;
122
+ }
123
+ /**
124
+ * Add a new JSON schema to the JSON schema map
125
+ * @param propertyName The name of the property to assign this JSON schema to
126
+ */
127
+ addNewSchema(propertyName) {
128
+ Schema.jsonSchemaMap.get(this.customElementName).set(propertyName, {
129
+ $schema: "https://json-schema.org/draft/2019-09/schema",
130
+ $id: this.getSchemaId(this.customElementName, propertyName),
131
+ [defsPropertyName]: {},
132
+ });
133
+ }
134
+ /**
135
+ * Add properties to a context
136
+ * @param schema The schema to add the properties to
137
+ * @param splitPath The path split into property/context names
138
+ * @param context The paths context
139
+ */
140
+ addPropertiesToAContext(schema, splitPath, context, childRef) {
141
+ schema.type = "object";
142
+ if (schema.properties && !schema.properties[splitPath[0]]) {
143
+ schema.properties[splitPath[0]] = {};
144
+ }
145
+ else if (!schema.properties) {
146
+ schema.properties = {
147
+ [splitPath[0]]: {},
148
+ };
149
+ }
150
+ if (splitPath.length > 1) {
151
+ this.addPropertiesToAnObject(schema.properties[splitPath[0]], splitPath.slice(1), context, childRef);
152
+ }
153
+ else if (childRef) {
154
+ if (schema.properties[splitPath[0]].anyOf) {
155
+ schema.properties[splitPath[0]].anyOf.push({
156
+ [refPropertyName]: childRef,
157
+ });
158
+ }
159
+ else {
160
+ schema.properties[splitPath[0]].anyOf = [{ [refPropertyName]: childRef }];
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * Add properties to an object
166
+ * @param schema The schema to add the properties to
167
+ * @param splitPath The path split into property/context names
168
+ * @param context The paths context
169
+ * @param type The data type (see JSON schema for details)
170
+ */
171
+ addPropertiesToAnObject(schema, splitPath, context, childRef, type = "object") {
172
+ schema.type = "object";
173
+ if (schema.properties && !schema.properties[splitPath[0]]) {
174
+ schema.properties[splitPath[0]] = {};
175
+ }
176
+ else if (!schema.properties) {
177
+ schema.properties = {
178
+ [splitPath[0]]: {},
179
+ };
180
+ }
181
+ if (type === "object" && splitPath.length > 1) {
182
+ return this.addPropertiesToAnObject(schema.properties[splitPath[0]], splitPath.slice(1), context, childRef, type);
183
+ }
184
+ else if (type === "array") {
185
+ if (splitPath.length > 1) {
186
+ return this.addPropertiesToAnObject(schema.properties[splitPath[0]], splitPath.slice(1), context, childRef, type);
187
+ }
188
+ else {
189
+ return this.addArrayToAnObject(schema.properties[splitPath[0]], context);
190
+ }
191
+ }
192
+ if (schema.properties[splitPath[0]].anyOf && childRef) {
193
+ schema.properties[splitPath[0]].anyOf.push({ [refPropertyName]: childRef });
194
+ }
195
+ else if (childRef) {
196
+ schema.properties[splitPath[0]].anyOf = [{ [refPropertyName]: childRef }];
197
+ }
198
+ return schema.properties[splitPath[0]];
199
+ }
200
+ /**
201
+ * Add an array to an object property
202
+ * @param schema The schema to add the properties to
203
+ * @param context The name of the context
204
+ */
205
+ addArrayToAnObject(schema, context) {
206
+ schema.type = "array";
207
+ schema.items = {
208
+ [refPropertyName]: this.getDefsPath(context),
209
+ };
210
+ return schema.items;
211
+ }
212
+ /**
213
+ * Add a context to the $defs property
214
+ * @param schema The schema to use
215
+ * @param propertyName The name of the property the context belongs to
216
+ * @param currentContext The current context
217
+ * @param parentContext The parent context
218
+ * @returns
219
+ */
220
+ addContext(schema, propertyName, // e.g items
221
+ currentContext, // e.g. item
222
+ parentContext) {
223
+ if (schema[defsPropertyName][currentContext]) {
224
+ return;
225
+ }
226
+ schema[defsPropertyName][currentContext] = {
227
+ [fastContextMetaData]: propertyName,
228
+ [fastContextsMetaData]: this.getParentContexts(schema, parentContext),
229
+ };
230
+ }
231
+ /**
232
+ * Get parent contexts
233
+ * @param schema The schema to use
234
+ * @param parentContext The parent context
235
+ * @param contexts A list of parent contexts
236
+ * @returns
237
+ */
238
+ getParentContexts(schema, parentContext, contexts = []) {
239
+ var _a;
240
+ if (parentContext === null) {
241
+ return [null, ...contexts];
242
+ }
243
+ const parentParentContext = (_a = schema === null || schema === void 0 ? void 0 : schema[defsPropertyName]) === null || _a === void 0 ? void 0 : _a[parentContext][fastContextsMetaData];
244
+ return this.getParentContexts(schema, parentParentContext.at(-1), [parentContext, ...contexts]);
245
+ }
246
+ }
247
+ /**
248
+ * A JSON schema describing each root schema
249
+ */
250
+ Schema.jsonSchemaMap = new Map();