@speclynx/apidom-datamodel 4.0.1 → 4.0.3
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/CHANGELOG.md +10 -0
- package/package.json +4 -5
- package/src/KeyValuePair.cjs +31 -0
- package/src/KeyValuePair.mjs +27 -0
- package/src/KeyValuePair.ts +31 -0
- package/src/Metadata.cjs +91 -0
- package/src/Metadata.mjs +87 -0
- package/src/Metadata.ts +100 -0
- package/src/Namespace.cjs +212 -0
- package/src/Namespace.mjs +206 -0
- package/src/Namespace.ts +260 -0
- package/src/ObjectSlice.cjs +199 -0
- package/src/ObjectSlice.mjs +195 -0
- package/src/ObjectSlice.ts +228 -0
- package/src/clone/errors/CloneError.cjs +22 -0
- package/src/clone/errors/CloneError.mjs +19 -0
- package/src/clone/errors/CloneError.ts +26 -0
- package/src/clone/errors/DeepCloneError.cjs +11 -0
- package/src/clone/errors/DeepCloneError.mjs +6 -0
- package/src/clone/errors/DeepCloneError.ts +8 -0
- package/src/clone/errors/ShallowCloneError.cjs +11 -0
- package/src/clone/errors/ShallowCloneError.mjs +6 -0
- package/src/clone/errors/ShallowCloneError.ts +8 -0
- package/src/clone/index.cjs +188 -0
- package/src/clone/index.mjs +178 -0
- package/src/clone/index.ts +195 -0
- package/src/elements/Annotation.cjs +35 -0
- package/src/elements/Annotation.mjs +30 -0
- package/src/elements/Annotation.ts +35 -0
- package/src/elements/Comment.cjs +18 -0
- package/src/elements/Comment.mjs +13 -0
- package/src/elements/Comment.ts +16 -0
- package/src/elements/LinkElement.cjs +50 -0
- package/src/elements/LinkElement.mjs +45 -0
- package/src/elements/LinkElement.ts +49 -0
- package/src/elements/ParseResult.cjs +91 -0
- package/src/elements/ParseResult.mjs +86 -0
- package/src/elements/ParseResult.ts +94 -0
- package/src/elements/RefElement.cjs +34 -0
- package/src/elements/RefElement.mjs +29 -0
- package/src/elements/RefElement.ts +33 -0
- package/src/elements/SourceMap.cjs +140 -0
- package/src/elements/SourceMap.mjs +134 -0
- package/src/elements/SourceMap.ts +170 -0
- package/src/elements/Style.cjs +54 -0
- package/src/elements/Style.mjs +48 -0
- package/src/elements/Style.ts +56 -0
- package/src/index.cjs +58 -0
- package/src/index.mjs +11 -0
- package/src/index.ts +79 -0
- package/src/predicates/elements.cjs +46 -0
- package/src/predicates/elements.mjs +35 -0
- package/src/predicates/elements.ts +42 -0
- package/src/predicates/index.cjs +77 -0
- package/src/predicates/index.mjs +56 -0
- package/src/predicates/index.ts +89 -0
- package/src/predicates/primitives.cjs +69 -0
- package/src/predicates/primitives.mjs +56 -0
- package/src/predicates/primitives.ts +79 -0
- package/src/primitives/ArrayElement.cjs +155 -0
- package/src/primitives/ArrayElement.mjs +148 -0
- package/src/primitives/ArrayElement.ts +161 -0
- package/src/primitives/BooleanElement.cjs +20 -0
- package/src/primitives/BooleanElement.mjs +15 -0
- package/src/primitives/BooleanElement.ts +18 -0
- package/src/primitives/CollectionElement.cjs +180 -0
- package/src/primitives/CollectionElement.mjs +173 -0
- package/src/primitives/CollectionElement.ts +191 -0
- package/src/primitives/Element.cjs +510 -0
- package/src/primitives/Element.mjs +505 -0
- package/src/primitives/Element.ts +556 -0
- package/src/primitives/MemberElement.cjs +58 -0
- package/src/primitives/MemberElement.mjs +53 -0
- package/src/primitives/MemberElement.ts +61 -0
- package/src/primitives/NullElement.cjs +28 -0
- package/src/primitives/NullElement.mjs +23 -0
- package/src/primitives/NullElement.ts +26 -0
- package/src/primitives/NumberElement.cjs +20 -0
- package/src/primitives/NumberElement.mjs +15 -0
- package/src/primitives/NumberElement.ts +18 -0
- package/src/primitives/ObjectElement.cjs +220 -0
- package/src/primitives/ObjectElement.mjs +214 -0
- package/src/primitives/ObjectElement.ts +263 -0
- package/src/primitives/StringElement.cjs +27 -0
- package/src/primitives/StringElement.mjs +22 -0
- package/src/primitives/StringElement.ts +25 -0
- package/src/registration.cjs +101 -0
- package/src/registration.mjs +79 -0
- package/src/registration.ts +111 -0
- package/src/serialisers/JSONSerialiser.cjs +230 -0
- package/src/serialisers/JSONSerialiser.mjs +221 -0
- package/src/serialisers/JSONSerialiser.ts +295 -0
- package/src/types.cjs +3 -0
- package/src/types.mjs +1 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import JSONSerialiser from "./serialisers/JSONSerialiser.mjs";
|
|
2
|
+
import * as elements from "./registration.mjs";
|
|
3
|
+
const isNull = value => value === null;
|
|
4
|
+
const isString = value => typeof value === 'string';
|
|
5
|
+
const isNumber = value => typeof value === 'number';
|
|
6
|
+
const isBoolean = value => typeof value === 'boolean';
|
|
7
|
+
const isObject = value => value !== null && typeof value === 'object';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Constructor type for Element classes.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Function to test if a value should be converted to a specific element type.
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Tuple of detection test and element class.
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Options for Namespace constructor.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Plugin interface for extending Namespace.
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Map of registered element classes.
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A refract element implementation with an extensible namespace, able to
|
|
42
|
+
* load other namespaces into it.
|
|
43
|
+
*
|
|
44
|
+
* The namespace allows you to register your own classes to be instantiated
|
|
45
|
+
* when a particular refract element is encountered, and allows you to specify
|
|
46
|
+
* which elements get instantiated for existing JavaScript objects.
|
|
47
|
+
*
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
class Namespace {
|
|
51
|
+
elementMap = {};
|
|
52
|
+
elementDetection = [];
|
|
53
|
+
Element;
|
|
54
|
+
KeyValuePair;
|
|
55
|
+
_elements;
|
|
56
|
+
_attributeElementKeys = [];
|
|
57
|
+
_attributeElementArrayKeys = [];
|
|
58
|
+
constructor(options) {
|
|
59
|
+
this.Element = elements.Element;
|
|
60
|
+
this.KeyValuePair = elements.KeyValuePair;
|
|
61
|
+
if (!options || !options.noDefault) {
|
|
62
|
+
this.useDefault();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Use a namespace plugin or load a generic plugin.
|
|
68
|
+
*/
|
|
69
|
+
use(plugin) {
|
|
70
|
+
if (plugin.namespace) {
|
|
71
|
+
plugin.namespace({
|
|
72
|
+
base: this
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (plugin.load) {
|
|
76
|
+
plugin.load({
|
|
77
|
+
base: this
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Use the default namespace. This preloads all the default elements
|
|
85
|
+
* into this registry instance.
|
|
86
|
+
*/
|
|
87
|
+
useDefault() {
|
|
88
|
+
// Set up classes for default elements
|
|
89
|
+
this.register('null', elements.NullElement).register('string', elements.StringElement).register('number', elements.NumberElement).register('boolean', elements.BooleanElement).register('array', elements.ArrayElement).register('object', elements.ObjectElement).register('member', elements.MemberElement).register('ref', elements.RefElement).register('link', elements.LinkElement).register('sourceMap', elements.SourceMapElement);
|
|
90
|
+
|
|
91
|
+
// Add instance detection functions to convert existing objects into
|
|
92
|
+
// the corresponding refract elements.
|
|
93
|
+
this.detect(isNull, elements.NullElement, false).detect(isString, elements.StringElement, false).detect(isNumber, elements.NumberElement, false).detect(isBoolean, elements.BooleanElement, false).detect(Array.isArray, elements.ArrayElement, false).detect(isObject, elements.ObjectElement, false);
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Register a new element class for an element.
|
|
99
|
+
*/
|
|
100
|
+
register(name, ElementClass) {
|
|
101
|
+
this._elements = undefined;
|
|
102
|
+
this.elementMap[name] = ElementClass;
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Unregister a previously registered class for an element.
|
|
108
|
+
*/
|
|
109
|
+
unregister(name) {
|
|
110
|
+
this._elements = undefined;
|
|
111
|
+
delete this.elementMap[name];
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Add a new detection function to determine which element
|
|
117
|
+
* class to use when converting existing JS instances into
|
|
118
|
+
* refract elements.
|
|
119
|
+
*/
|
|
120
|
+
detect(test, ElementClass, givenPrepend) {
|
|
121
|
+
const prepend = givenPrepend === undefined ? true : givenPrepend;
|
|
122
|
+
if (prepend) {
|
|
123
|
+
this.elementDetection.unshift([test, ElementClass]);
|
|
124
|
+
} else {
|
|
125
|
+
this.elementDetection.push([test, ElementClass]);
|
|
126
|
+
}
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Convert an existing JavaScript object into refract element instances.
|
|
132
|
+
* If the item passed in is already refracted, then it is returned unmodified.
|
|
133
|
+
*/
|
|
134
|
+
toElement(value) {
|
|
135
|
+
if (value instanceof this.Element) {
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
let element;
|
|
139
|
+
for (const [test, ElementClass] of this.elementDetection) {
|
|
140
|
+
if (test(value)) {
|
|
141
|
+
element = new ElementClass(value);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return element;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get an element class given an element name.
|
|
150
|
+
*/
|
|
151
|
+
getElementClass(element) {
|
|
152
|
+
const ElementClass = this.elementMap[element];
|
|
153
|
+
if (ElementClass === undefined) {
|
|
154
|
+
// Fall back to the base element. We may not know what
|
|
155
|
+
// to do with the `content`, but downstream software
|
|
156
|
+
// may know.
|
|
157
|
+
return this.Element;
|
|
158
|
+
}
|
|
159
|
+
return ElementClass;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Convert a refract document into refract element instances.
|
|
164
|
+
*/
|
|
165
|
+
fromRefract(doc) {
|
|
166
|
+
return this.serialiser.deserialise(doc);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Convert an element to a Refracted JSON object.
|
|
171
|
+
*/
|
|
172
|
+
toRefract(element) {
|
|
173
|
+
return this.serialiser.serialise(element);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get an object that contains all registered element classes, where
|
|
178
|
+
* the key is the PascalCased element name and the value is the class.
|
|
179
|
+
*/
|
|
180
|
+
get elements() {
|
|
181
|
+
if (this._elements === undefined) {
|
|
182
|
+
this._elements = {
|
|
183
|
+
Element: this.Element
|
|
184
|
+
};
|
|
185
|
+
Object.keys(this.elementMap).forEach(name => {
|
|
186
|
+
// Currently, all registered element types use a camelCaseName.
|
|
187
|
+
// Converting to PascalCase is as simple as upper-casing the first letter.
|
|
188
|
+
const pascal = name[0].toUpperCase() + name.substring(1);
|
|
189
|
+
this._elements[pascal] = this.elementMap[name];
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return this._elements;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Convenience method for getting a JSON Serialiser configured with the
|
|
197
|
+
* current namespace.
|
|
198
|
+
*/
|
|
199
|
+
get serialiser() {
|
|
200
|
+
return new JSONSerialiser(this);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Set up the circular reference for JSONSerialiser
|
|
205
|
+
JSONSerialiser.prototype.Namespace = Namespace;
|
|
206
|
+
export default Namespace;
|
package/src/Namespace.ts
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import JSONSerialiser from './serialisers/JSONSerialiser.ts';
|
|
2
|
+
import * as elements from './registration.ts';
|
|
3
|
+
import type Element from './primitives/Element.ts';
|
|
4
|
+
import type ElementConstructor from './primitives/Element.ts';
|
|
5
|
+
import type KeyValuePairConstructor from './KeyValuePair.ts';
|
|
6
|
+
|
|
7
|
+
const isNull = (value: unknown): value is null => value === null;
|
|
8
|
+
const isString = (value: unknown): value is string => typeof value === 'string';
|
|
9
|
+
const isNumber = (value: unknown): value is number => typeof value === 'number';
|
|
10
|
+
const isBoolean = (value: unknown): value is boolean => typeof value === 'boolean';
|
|
11
|
+
const isObject = (value: unknown): value is Record<string, unknown> =>
|
|
12
|
+
value !== null && typeof value === 'object';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Constructor type for Element classes.
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
type ElementClass = new (...args: any[]) => Element;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Function to test if a value should be converted to a specific element type.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
type DetectionTest = (value: unknown) => boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Tuple of detection test and element class.
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
type DetectionEntry = [DetectionTest, ElementClass];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Options for Namespace constructor.
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
interface NamespaceOptions {
|
|
38
|
+
noDefault?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Plugin interface for extending Namespace.
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
interface NamespacePlugin {
|
|
46
|
+
namespace?: (options: { base: Namespace }) => void;
|
|
47
|
+
load?: (options: { base: Namespace }) => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Map of registered element classes.
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
interface ElementsMap {
|
|
55
|
+
Element: ElementClass;
|
|
56
|
+
[key: string]: ElementClass;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A refract element implementation with an extensible namespace, able to
|
|
61
|
+
* load other namespaces into it.
|
|
62
|
+
*
|
|
63
|
+
* The namespace allows you to register your own classes to be instantiated
|
|
64
|
+
* when a particular refract element is encountered, and allows you to specify
|
|
65
|
+
* which elements get instantiated for existing JavaScript objects.
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
class Namespace {
|
|
70
|
+
public elementMap: Record<string, ElementClass> = {};
|
|
71
|
+
public elementDetection: DetectionEntry[] = [];
|
|
72
|
+
public Element: typeof ElementConstructor;
|
|
73
|
+
public KeyValuePair: typeof KeyValuePairConstructor;
|
|
74
|
+
|
|
75
|
+
protected _elements?: ElementsMap;
|
|
76
|
+
protected _attributeElementKeys: string[] = [];
|
|
77
|
+
protected _attributeElementArrayKeys: string[] = [];
|
|
78
|
+
|
|
79
|
+
constructor(options?: NamespaceOptions) {
|
|
80
|
+
this.Element = elements.Element;
|
|
81
|
+
this.KeyValuePair = elements.KeyValuePair;
|
|
82
|
+
|
|
83
|
+
if (!options || !options.noDefault) {
|
|
84
|
+
this.useDefault();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Use a namespace plugin or load a generic plugin.
|
|
90
|
+
*/
|
|
91
|
+
use(plugin: NamespacePlugin): this {
|
|
92
|
+
if (plugin.namespace) {
|
|
93
|
+
plugin.namespace({ base: this });
|
|
94
|
+
}
|
|
95
|
+
if (plugin.load) {
|
|
96
|
+
plugin.load({ base: this });
|
|
97
|
+
}
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Use the default namespace. This preloads all the default elements
|
|
103
|
+
* into this registry instance.
|
|
104
|
+
*/
|
|
105
|
+
useDefault(): this {
|
|
106
|
+
// Set up classes for default elements
|
|
107
|
+
this.register('null', elements.NullElement)
|
|
108
|
+
.register('string', elements.StringElement)
|
|
109
|
+
.register('number', elements.NumberElement)
|
|
110
|
+
.register('boolean', elements.BooleanElement)
|
|
111
|
+
.register('array', elements.ArrayElement)
|
|
112
|
+
.register('object', elements.ObjectElement)
|
|
113
|
+
.register('member', elements.MemberElement)
|
|
114
|
+
.register('ref', elements.RefElement)
|
|
115
|
+
.register('link', elements.LinkElement)
|
|
116
|
+
.register('sourceMap', elements.SourceMapElement);
|
|
117
|
+
|
|
118
|
+
// Add instance detection functions to convert existing objects into
|
|
119
|
+
// the corresponding refract elements.
|
|
120
|
+
this.detect(isNull, elements.NullElement, false)
|
|
121
|
+
.detect(isString, elements.StringElement, false)
|
|
122
|
+
.detect(isNumber, elements.NumberElement, false)
|
|
123
|
+
.detect(isBoolean, elements.BooleanElement, false)
|
|
124
|
+
.detect(Array.isArray, elements.ArrayElement, false)
|
|
125
|
+
.detect(isObject, elements.ObjectElement, false);
|
|
126
|
+
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Register a new element class for an element.
|
|
132
|
+
*/
|
|
133
|
+
register(name: string, ElementClass: ElementClass): this {
|
|
134
|
+
this._elements = undefined;
|
|
135
|
+
this.elementMap[name] = ElementClass;
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Unregister a previously registered class for an element.
|
|
141
|
+
*/
|
|
142
|
+
unregister(name: string): this {
|
|
143
|
+
this._elements = undefined;
|
|
144
|
+
delete this.elementMap[name];
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Add a new detection function to determine which element
|
|
150
|
+
* class to use when converting existing JS instances into
|
|
151
|
+
* refract elements.
|
|
152
|
+
*/
|
|
153
|
+
detect(test: DetectionTest, ElementClass: ElementClass, givenPrepend?: boolean): this {
|
|
154
|
+
const prepend = givenPrepend === undefined ? true : givenPrepend;
|
|
155
|
+
|
|
156
|
+
if (prepend) {
|
|
157
|
+
this.elementDetection.unshift([test, ElementClass]);
|
|
158
|
+
} else {
|
|
159
|
+
this.elementDetection.push([test, ElementClass]);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Convert an existing JavaScript object into refract element instances.
|
|
167
|
+
* If the item passed in is already refracted, then it is returned unmodified.
|
|
168
|
+
*/
|
|
169
|
+
toElement(value: unknown): Element | undefined {
|
|
170
|
+
if (value instanceof this.Element) {
|
|
171
|
+
return value as Element;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let element: Element | undefined;
|
|
175
|
+
|
|
176
|
+
for (const [test, ElementClass] of this.elementDetection) {
|
|
177
|
+
if (test(value)) {
|
|
178
|
+
element = new ElementClass(value);
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return element;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get an element class given an element name.
|
|
188
|
+
*/
|
|
189
|
+
getElementClass(element: string): ElementClass {
|
|
190
|
+
const ElementClass = this.elementMap[element];
|
|
191
|
+
|
|
192
|
+
if (ElementClass === undefined) {
|
|
193
|
+
// Fall back to the base element. We may not know what
|
|
194
|
+
// to do with the `content`, but downstream software
|
|
195
|
+
// may know.
|
|
196
|
+
return this.Element as unknown as ElementClass;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return ElementClass;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Convert a refract document into refract element instances.
|
|
204
|
+
*/
|
|
205
|
+
fromRefract(doc: Record<string, unknown>): Element {
|
|
206
|
+
return this.serialiser.deserialise(
|
|
207
|
+
doc as unknown as Parameters<JSONSerialiser['deserialise']>[0],
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Convert an element to a Refracted JSON object.
|
|
213
|
+
*/
|
|
214
|
+
toRefract(element: Element): ReturnType<JSONSerialiser['serialise']> {
|
|
215
|
+
return this.serialiser.serialise(element);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get an object that contains all registered element classes, where
|
|
220
|
+
* the key is the PascalCased element name and the value is the class.
|
|
221
|
+
*/
|
|
222
|
+
get elements(): ElementsMap {
|
|
223
|
+
if (this._elements === undefined) {
|
|
224
|
+
this._elements = {
|
|
225
|
+
Element: this.Element,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
Object.keys(this.elementMap).forEach((name) => {
|
|
229
|
+
// Currently, all registered element types use a camelCaseName.
|
|
230
|
+
// Converting to PascalCase is as simple as upper-casing the first letter.
|
|
231
|
+
const pascal = name[0].toUpperCase() + name.substring(1);
|
|
232
|
+
this._elements![pascal] = this.elementMap[name];
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return this._elements;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Convenience method for getting a JSON Serialiser configured with the
|
|
241
|
+
* current namespace.
|
|
242
|
+
*/
|
|
243
|
+
get serialiser(): JSONSerialiser {
|
|
244
|
+
return new JSONSerialiser(this);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Set up the circular reference for JSONSerialiser
|
|
249
|
+
JSONSerialiser.prototype.Namespace = Namespace;
|
|
250
|
+
|
|
251
|
+
export default Namespace;
|
|
252
|
+
|
|
253
|
+
export type {
|
|
254
|
+
ElementClass,
|
|
255
|
+
DetectionTest,
|
|
256
|
+
DetectionEntry,
|
|
257
|
+
NamespaceOptions,
|
|
258
|
+
NamespacePlugin,
|
|
259
|
+
ElementsMap,
|
|
260
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Callback type for ObjectSlice iteration methods.
|
|
7
|
+
* Receives (value, key, member) - the standard pattern for object-like iteration.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Callback type for ObjectSlice forEach that also receives the index.
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* ObjectSlice is a collection wrapper for MemberElement arrays.
|
|
18
|
+
* It provides functional methods with (value, key, member) callback signatures,
|
|
19
|
+
* which is the standard pattern for iterating over object-like structures.
|
|
20
|
+
*
|
|
21
|
+
* Unlike ArraySlice, ObjectSlice uses composition rather than inheritance
|
|
22
|
+
* because its callback signatures are fundamentally different.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
class ObjectSlice {
|
|
27
|
+
elements;
|
|
28
|
+
constructor(elements) {
|
|
29
|
+
this.elements = elements ?? [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Converts all member elements to their JavaScript values.
|
|
34
|
+
* Returns an array of \{ key, value \} objects.
|
|
35
|
+
*/
|
|
36
|
+
toValue() {
|
|
37
|
+
return this.elements.map(member => ({
|
|
38
|
+
key: member.key?.toValue(),
|
|
39
|
+
value: member.value?.toValue()
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Maps over the member elements, calling callback with (value, key, member).
|
|
45
|
+
* @param callback - Function to execute for each member
|
|
46
|
+
* @param thisArg - Value to use as this when executing callback
|
|
47
|
+
*/
|
|
48
|
+
map(callback, thisArg) {
|
|
49
|
+
return this.elements.map(member => {
|
|
50
|
+
const value = member.value;
|
|
51
|
+
const key = member.key;
|
|
52
|
+
if (value === undefined || key === undefined) {
|
|
53
|
+
throw new Error('MemberElement must have both key and value');
|
|
54
|
+
}
|
|
55
|
+
return thisArg !== undefined ? callback.call(thisArg, value, key, member) : callback(value, key, member);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Filters member elements using the provided callback.
|
|
61
|
+
* @param callback - Function that receives (value, key, member) and returns boolean
|
|
62
|
+
* @param thisArg - Value to use as this when executing callback
|
|
63
|
+
*/
|
|
64
|
+
filter(callback, thisArg) {
|
|
65
|
+
const filtered = this.elements.filter(member => {
|
|
66
|
+
const value = member.value;
|
|
67
|
+
const key = member.key;
|
|
68
|
+
if (value === undefined || key === undefined) {
|
|
69
|
+
return false; // Skip malformed members
|
|
70
|
+
}
|
|
71
|
+
return thisArg !== undefined ? callback.call(thisArg, value, key, member) : callback(value, key, member);
|
|
72
|
+
});
|
|
73
|
+
return new ObjectSlice(filtered);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Rejects member elements that match the provided callback.
|
|
78
|
+
* @param callback - Function that receives (value, key, member) and returns boolean
|
|
79
|
+
* @param thisArg - Value to use as this when executing callback
|
|
80
|
+
*/
|
|
81
|
+
reject(callback, thisArg) {
|
|
82
|
+
const results = [];
|
|
83
|
+
for (const member of this.elements) {
|
|
84
|
+
const value = member.value;
|
|
85
|
+
const key = member.key;
|
|
86
|
+
if (value === undefined || key === undefined) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (!callback.call(thisArg, value, key, member)) {
|
|
90
|
+
results.push(member);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return new ObjectSlice(results);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Executes a provided function once for each member element.
|
|
98
|
+
* @param callback - Function that receives (value, key, member, index)
|
|
99
|
+
* @param thisArg - Value to use as this when executing callback
|
|
100
|
+
*/
|
|
101
|
+
forEach(callback, thisArg) {
|
|
102
|
+
this.elements.forEach((member, index) => {
|
|
103
|
+
const value = member.value;
|
|
104
|
+
const key = member.key;
|
|
105
|
+
if (value === undefined || key === undefined) {
|
|
106
|
+
return; // Skip malformed members
|
|
107
|
+
}
|
|
108
|
+
if (thisArg !== undefined) {
|
|
109
|
+
callback.call(thisArg, value, key, member, index);
|
|
110
|
+
} else {
|
|
111
|
+
callback(value, key, member, index);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Returns the first member element that satisfies the callback.
|
|
118
|
+
* @param callback - Function that receives (value, key, member) and returns boolean
|
|
119
|
+
* @param thisArg - Value to use as this when executing callback
|
|
120
|
+
*/
|
|
121
|
+
find(callback, thisArg) {
|
|
122
|
+
return this.elements.find(member => {
|
|
123
|
+
const value = member.value;
|
|
124
|
+
const key = member.key;
|
|
125
|
+
if (value === undefined || key === undefined) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
return thisArg !== undefined ? callback.call(thisArg, value, key, member) : callback(value, key, member);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Returns an array of all keys' values.
|
|
134
|
+
*/
|
|
135
|
+
keys() {
|
|
136
|
+
return this.elements.map(member => member.key?.toValue()).filter(key => key !== undefined);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns an array of all values' values.
|
|
141
|
+
*/
|
|
142
|
+
values() {
|
|
143
|
+
return this.elements.map(member => member.value?.toValue()).filter(value => value !== undefined);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Returns the number of elements in the slice.
|
|
148
|
+
*/
|
|
149
|
+
get length() {
|
|
150
|
+
return this.elements.length;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Returns whether the slice is empty.
|
|
155
|
+
*/
|
|
156
|
+
get isEmpty() {
|
|
157
|
+
return this.length === 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Returns the first element in the slice or undefined if empty.
|
|
162
|
+
*/
|
|
163
|
+
get first() {
|
|
164
|
+
return this.elements[0];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Gets the element at the specified index.
|
|
169
|
+
* @param index - The index of the element to get
|
|
170
|
+
*/
|
|
171
|
+
get(index) {
|
|
172
|
+
return this.elements[index];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Adds the given member element to the end of the slice.
|
|
177
|
+
* @param member - The member element to add
|
|
178
|
+
*/
|
|
179
|
+
push(member) {
|
|
180
|
+
this.elements.push(member);
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Determines whether the slice includes a member with the given key value.
|
|
186
|
+
* @param keyValue - The key value to search for
|
|
187
|
+
*/
|
|
188
|
+
includesKey(keyValue) {
|
|
189
|
+
return this.elements.some(member => member.key?.equals(keyValue));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Iterator support - allows for...of loops.
|
|
194
|
+
*/
|
|
195
|
+
[Symbol.iterator]() {
|
|
196
|
+
return this.elements[Symbol.iterator]();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
var _default = exports.default = ObjectSlice;
|