@decaf-ts/decoration 0.0.2
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/LICENSE.md +21 -0
- package/README.md +385 -0
- package/dist/decoration.cjs +649 -0
- package/dist/decoration.esm.cjs +633 -0
- package/lib/constants.cjs +64 -0
- package/lib/constants.d.ts +58 -0
- package/lib/decoration/Decoration.cjs +270 -0
- package/lib/decoration/Decoration.d.ts +196 -0
- package/lib/decoration/index.cjs +19 -0
- package/lib/decoration/index.d.ts +2 -0
- package/lib/decoration/types.cjs +3 -0
- package/lib/decoration/types.d.ts +95 -0
- package/lib/decorators.cjs +97 -0
- package/lib/decorators.d.ts +57 -0
- package/lib/esm/constants.d.ts +58 -0
- package/lib/esm/constants.js +61 -0
- package/lib/esm/decoration/Decoration.d.ts +196 -0
- package/lib/esm/decoration/Decoration.js +266 -0
- package/lib/esm/decoration/index.d.ts +2 -0
- package/lib/esm/decoration/index.js +3 -0
- package/lib/esm/decoration/types.d.ts +95 -0
- package/lib/esm/decoration/types.js +2 -0
- package/lib/esm/decorators.d.ts +57 -0
- package/lib/esm/decorators.js +90 -0
- package/lib/esm/index.d.ts +21 -0
- package/lib/esm/index.js +22 -0
- package/lib/esm/metadata/Metadata.d.ts +99 -0
- package/lib/esm/metadata/Metadata.js +199 -0
- package/lib/esm/metadata/index.d.ts +2 -0
- package/lib/esm/metadata/index.js +3 -0
- package/lib/esm/metadata/types.d.ts +16 -0
- package/lib/esm/metadata/types.js +2 -0
- package/lib/index.cjs +39 -0
- package/lib/index.d.ts +21 -0
- package/lib/metadata/Metadata.cjs +203 -0
- package/lib/metadata/Metadata.d.ts +99 -0
- package/lib/metadata/index.cjs +19 -0
- package/lib/metadata/index.d.ts +2 -0
- package/lib/metadata/types.cjs +4 -0
- package/lib/metadata/types.d.ts +16 -0
- package/package.json +114 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Metadata = void 0;
|
|
4
|
+
const constants_1 = require("./../constants.cjs");
|
|
5
|
+
require("reflect-metadata");
|
|
6
|
+
/**
|
|
7
|
+
* @description Retrieves a nested value from an object given a path
|
|
8
|
+
* @summary Walks an object structure using a splitter-delimited path and returns the value at that location or undefined if any key is missing.
|
|
9
|
+
* @param {Record<string, any>} obj The object to traverse
|
|
10
|
+
* @param {string} path The path to the desired value (e.g., "a.b.c")
|
|
11
|
+
* @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
|
|
12
|
+
* @return {*} The resolved value at the given path or undefined if not found
|
|
13
|
+
* @function getValueBySplitter
|
|
14
|
+
* @mermaid
|
|
15
|
+
* sequenceDiagram
|
|
16
|
+
* participant C as Caller
|
|
17
|
+
* participant F as getValueBySplitter
|
|
18
|
+
* participant O as Object
|
|
19
|
+
* C->>F: (obj, path, splitter)
|
|
20
|
+
* F->>F: split path into keys
|
|
21
|
+
* loop for each key
|
|
22
|
+
* F->>O: access current[key]
|
|
23
|
+
* alt missing or nullish
|
|
24
|
+
* F-->>C: return undefined
|
|
25
|
+
* end
|
|
26
|
+
* end
|
|
27
|
+
* F-->>C: return final value
|
|
28
|
+
* @memberOf module:decoration
|
|
29
|
+
*/
|
|
30
|
+
function getValueBySplitter(obj, path, splitter = constants_1.ObjectKeySplitter) {
|
|
31
|
+
const keys = path.split(splitter);
|
|
32
|
+
let current = obj;
|
|
33
|
+
for (const key of keys) {
|
|
34
|
+
if (current === null ||
|
|
35
|
+
current === undefined ||
|
|
36
|
+
!Object.prototype.hasOwnProperty.call(current, key))
|
|
37
|
+
return undefined;
|
|
38
|
+
current = current[key];
|
|
39
|
+
}
|
|
40
|
+
return current;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @description Sets a nested value on an object given a path
|
|
44
|
+
* @summary Traverses or creates intermediate objects following a splitter-delimited path and assigns the provided value at the destination key.
|
|
45
|
+
* @param {Record<string, any>} obj The object to mutate
|
|
46
|
+
* @param {string} path The destination path (e.g., "a.b.c")
|
|
47
|
+
* @param {*} value The value to set at the destination
|
|
48
|
+
* @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
|
|
49
|
+
* @return {void}
|
|
50
|
+
* @function setValueBySplitter
|
|
51
|
+
* @mermaid
|
|
52
|
+
* sequenceDiagram
|
|
53
|
+
* participant C as Caller
|
|
54
|
+
* participant F as setValueBySplitter
|
|
55
|
+
* participant O as Object
|
|
56
|
+
* C->>F: (obj, path, value, splitter)
|
|
57
|
+
* F->>F: split path into keys
|
|
58
|
+
* loop for each key
|
|
59
|
+
* alt key missing
|
|
60
|
+
* F->>O: create intermediate object
|
|
61
|
+
* else key exists
|
|
62
|
+
* F->>O: descend into existing object
|
|
63
|
+
* end
|
|
64
|
+
* end
|
|
65
|
+
* F-->>C: void
|
|
66
|
+
* @memberOf module:decoration
|
|
67
|
+
*/
|
|
68
|
+
function setValueBySplitter(obj, path, value, splitter = constants_1.ObjectKeySplitter) {
|
|
69
|
+
const keys = path.split(splitter).filter((k) => k.length > 0);
|
|
70
|
+
if (keys.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
let current = obj;
|
|
73
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
74
|
+
const key = keys[i];
|
|
75
|
+
if (current[key] === undefined ||
|
|
76
|
+
current[key] === null ||
|
|
77
|
+
typeof current[key] !== "object") {
|
|
78
|
+
current[key] = {};
|
|
79
|
+
}
|
|
80
|
+
current = current[key];
|
|
81
|
+
}
|
|
82
|
+
const lastKey = keys[keys.length - 1];
|
|
83
|
+
current[lastKey] = value;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @description Centralized runtime metadata store bound to constructors
|
|
87
|
+
* @summary Provides utilities to read and write structured metadata for classes and their members, with optional mirroring onto the constructor via a well-known symbol key. Supports nested key paths using a configurable splitter and offers both instance and static APIs.
|
|
88
|
+
* @template M The model type the metadata belongs to
|
|
89
|
+
* @template META Extends BasicMetadata<M> representing the metadata structure
|
|
90
|
+
* @class
|
|
91
|
+
* @example
|
|
92
|
+
* // Define and read metadata for a class
|
|
93
|
+
* class User { name!: string }
|
|
94
|
+
* Metadata.set(User, "description.class", "A user model");
|
|
95
|
+
* Metadata.set(User, "properties.name", String);
|
|
96
|
+
* const desc = Metadata.get(User, "description.class"); // "A user model"
|
|
97
|
+
* const type = Metadata.type(User, "name"); // String
|
|
98
|
+
* @mermaid
|
|
99
|
+
* sequenceDiagram
|
|
100
|
+
* participant C as Constructor
|
|
101
|
+
* participant S as Metadata (static)
|
|
102
|
+
* C->>S: set(User, "properties.name", String)
|
|
103
|
+
* C->>S: get(User, "properties.name")
|
|
104
|
+
* S-->>C: String
|
|
105
|
+
*/
|
|
106
|
+
class Metadata {
|
|
107
|
+
/**
|
|
108
|
+
* @description In-memory storage of metadata by constructor symbol
|
|
109
|
+
* @summary Maps a Symbol derived from the constructor to its metadata object, enabling efficient lookup.
|
|
110
|
+
*/
|
|
111
|
+
static { this._metadata = {}; }
|
|
112
|
+
/**
|
|
113
|
+
* @description Path delimiter for nested metadata keys
|
|
114
|
+
* @summary Used by get/set operations to navigate nested structures, defaults to ObjectKeySplitter.
|
|
115
|
+
*/
|
|
116
|
+
static { this.splitter = constants_1.ObjectKeySplitter; }
|
|
117
|
+
/**
|
|
118
|
+
* @description Symbol key used to mirror metadata on the constructor
|
|
119
|
+
* @summary When mirroring is enabled, the metadata object is defined on the constructor under this non-enumerable key.
|
|
120
|
+
*/
|
|
121
|
+
static { this.baseKey = constants_1.DecorationKeys.REFLECT; }
|
|
122
|
+
/**
|
|
123
|
+
* @description Controls whether metadata is mirrored onto the constructor
|
|
124
|
+
* @summary When true, the metadata object is defined on the constructor under the non-enumerable baseKey.
|
|
125
|
+
*/
|
|
126
|
+
static { this.mirror = true; }
|
|
127
|
+
constructor() { }
|
|
128
|
+
/**
|
|
129
|
+
* @description Lists known property keys for a model
|
|
130
|
+
* @summary Reads the metadata entry and returns the names of properties that have recorded type information.
|
|
131
|
+
* @param {Constructor} model The target constructor
|
|
132
|
+
* @return {string[]|undefined} Array of property names or undefined if no metadata exists
|
|
133
|
+
*/
|
|
134
|
+
static properties(model) {
|
|
135
|
+
const meta = this.get(model);
|
|
136
|
+
if (!meta)
|
|
137
|
+
return undefined;
|
|
138
|
+
return Object.keys(meta.properties);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* @description Retrieves a human-readable description for a class or a property
|
|
142
|
+
* @summary Looks up the description stored under the metadata "description" map. If a property key is provided, returns the property's description; otherwise returns the class description.
|
|
143
|
+
* @template M
|
|
144
|
+
* @param {Constructor<M>} model The target constructor whose description is being retrieved
|
|
145
|
+
* @param {string} [prop] Optional property key for which to fetch the description
|
|
146
|
+
* @return {string|undefined} The description text if present, otherwise undefined
|
|
147
|
+
*/
|
|
148
|
+
static description(model, prop) {
|
|
149
|
+
return this.get(model, [constants_1.DecorationKeys.DESCRIPTION, prop ? prop : constants_1.DecorationKeys.CLASS].join(constants_1.ObjectKeySplitter));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* @description Retrieves the recorded design type for a property
|
|
153
|
+
* @summary Reads the metadata entry under "properties.<prop>" to return the constructor recorded for the given property name.
|
|
154
|
+
* @param {Constructor} model The target constructor
|
|
155
|
+
* @param {string} prop The property name whose type should be returned
|
|
156
|
+
* @return {Constructor|undefined} The constructor reference of the property type or undefined if not available
|
|
157
|
+
*/
|
|
158
|
+
static type(model, prop) {
|
|
159
|
+
return this.get(model, `${constants_1.DecorationKeys.PROPERTIES}.${prop}`);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* @description Retrieves metadata for a model or a specific key within it
|
|
163
|
+
* @summary When called with a constructor only, returns the entire metadata object associated with the model. When a key path is provided, returns the value stored at that nested key.
|
|
164
|
+
* @template M
|
|
165
|
+
* @template META
|
|
166
|
+
* @param {Constructor<M>} model The target constructor used to locate the metadata record
|
|
167
|
+
* @param {string} [key] Optional nested key path to fetch a specific value
|
|
168
|
+
* @return {META|*|undefined} The metadata object, the value at the key path, or undefined if nothing exists
|
|
169
|
+
*/
|
|
170
|
+
static get(model, key) {
|
|
171
|
+
const symbol = Symbol.for(model.toString());
|
|
172
|
+
if (!this._metadata[symbol])
|
|
173
|
+
return undefined;
|
|
174
|
+
if (!key)
|
|
175
|
+
return this._metadata[symbol];
|
|
176
|
+
return getValueBySplitter(this._metadata[symbol], key, this.splitter);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* @description Writes a metadata value at a given nested key path
|
|
180
|
+
* @summary Ensures the metadata record exists for the constructor, mirrors it on the constructor when enabled, and sets the provided value on the nested key path using the configured splitter.
|
|
181
|
+
* @param {Constructor} model The target constructor to which the metadata belongs
|
|
182
|
+
* @param {string} key The nested key path at which to store the value
|
|
183
|
+
* @param {*} value The value to store in the metadata
|
|
184
|
+
* @return {void}
|
|
185
|
+
*/
|
|
186
|
+
static set(model, key, value) {
|
|
187
|
+
const symbol = Symbol.for(model.toString());
|
|
188
|
+
if (!this._metadata[symbol])
|
|
189
|
+
this._metadata[symbol] = {};
|
|
190
|
+
if (Metadata.mirror &&
|
|
191
|
+
!Object.prototype.hasOwnProperty.call(model, this.baseKey)) {
|
|
192
|
+
Object.defineProperty(model, this.baseKey, {
|
|
193
|
+
enumerable: false,
|
|
194
|
+
configurable: false,
|
|
195
|
+
writable: false,
|
|
196
|
+
value: this._metadata[symbol],
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
setValueBySplitter(this._metadata[symbol], key, value, this.splitter);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.Metadata = Metadata;
|
|
203
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWV0YWRhdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWV0YWRhdGEvTWV0YWRhdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0Esa0RBQWlFO0FBQ2pFLDRCQUEwQjtBQUUxQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxTQUFTLGtCQUFrQixDQUN6QixHQUF3QixFQUN4QixJQUFZLEVBQ1osV0FBbUIsNkJBQWlCO0lBRXBDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEMsSUFBSSxPQUFPLEdBQUcsR0FBRyxDQUFDO0lBRWxCLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdkIsSUFDRSxPQUFPLEtBQUssSUFBSTtZQUNoQixPQUFPLEtBQUssU0FBUztZQUNyQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDO1lBRW5ELE9BQU8sU0FBUyxDQUFDO1FBQ25CLE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCRztBQUNILFNBQVMsa0JBQWtCLENBQ3pCLEdBQXdCLEVBQ3hCLElBQVksRUFDWixLQUFVLEVBQ1YsUUFBUSxHQUFHLDZCQUFpQjtJQUU1QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM5RCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU87SUFFOUIsSUFBSSxPQUFPLEdBQXFCLEdBQUcsQ0FBQztJ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UUFBUSxFQUFFLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQVMsQ0FBQztRQUNoRSxJQUNFLFFBQVEsQ0FBQyxNQUFNO1lBQ2YsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsRUFDMUQsQ0FBQztZQUNELE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ3pDLFVBQVUsRUFBRSxLQUFLO2dCQUNqQixZQUFZLEVBQUUsS0FBSztnQkFDbkIsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO2FBQzlCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7O0FBN0hILDRCQThIQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJhc2ljTWV0YWRhdGEsIENvbnN0cnVjdG9yIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlY29yYXRpb25LZXlzLCBPYmplY3RLZXlTcGxpdHRlciB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgbmVzdGVkIHZhbHVlIGZyb20gYW4gb2JqZWN0IGdpdmVuIGEgcGF0aFxuICogQHN1bW1hcnkgV2Fsa3MgYW4gb2JqZWN0IHN0cnVjdHVyZSB1c2luZyBhIHNwbGl0dGVyLWRlbGltaXRlZCBwYXRoIGFuZCByZXR1cm5zIHRoZSB2YWx1ZSBhdCB0aGF0IGxvY2F0aW9uIG9yIHVuZGVmaW5lZCBpZiBhbnkga2V5IGlzIG1pc3NpbmcuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9iaiBUaGUgb2JqZWN0IHRvIHRyYXZlcnNlXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgcGF0aCB0byB0aGUgZGVzaXJlZCB2YWx1ZSAoZS5nLiwgXCJhLmIuY1wiKVxuICogQHBhcmFtIHtzdHJpbmd9IFtzcGxpdHRlcj1PYmplY3RLZXlTcGxpdHRlcl0gVGhlIGRlbGltaXRlciB1c2VkIHRvIHNwbGl0IHRoZSBwYXRoXG4gKiBAcmV0dXJuIHsqfSBUaGUgcmVzb2x2ZWQgdmFsdWUgYXQgdGhlIGdpdmVuIHBhdGggb3IgdW5kZWZpbmVkIGlmIG5vdCBmb3VuZFxuICogQGZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIGdldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgc3BsaXR0ZXIpXG4gKiAgIEYtPj5GOiBzcGxpdCBwYXRoIGludG8ga2V5c1xuICogICBsb29wIGZvciBlYWNoIGtleVxuICogICAgIEYtPj5POiBhY2Nlc3MgY3VycmVudFtrZXldXG4gKiAgICAgYWx0IG1pc3Npbmcgb3IgbnVsbGlzaFxuICogICAgICAgRi0tPj5DOiByZXR1cm4gdW5kZWZpbmVkXG4gKiAgICAgZW5kXG4gKiAgIGVuZFxuICogICBGLS0+PkM6IHJldHVybiBmaW5hbCB2YWx1ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHNwbGl0dGVyOiBzdHJpbmcgPSBPYmplY3RLZXlTcGxpdHRlclxuKTogYW55IHtcbiAgY29uc3Qga2V5cyA9IHBhdGguc3BsaXQoc3BsaXR0ZXIpO1xuICBsZXQgY3VycmVudCA9IG9iajtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgaWYgKFxuICAgICAgY3VycmVudCA9PT0gbnVsbCB8fFxuICAgICAgY3VycmVudCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIGtleSlcbiAgICApXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGN1cnJlbnQgPSBjdXJyZW50W2tleV07XG4gIH1cblxuICByZXR1cm4gY3VycmVudDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyBhIG5lc3RlZCB2YWx1ZSBvbiBhbiBvYmplY3QgZ2l2ZW4gYSBwYXRoXG4gKiBAc3VtbWFyeSBUcmF2ZXJzZXMgb3IgY3JlYXRlcyBpbnRlcm1lZGlhdGUgb2JqZWN0cyBmb2xsb3dpbmcgYSBzcGxpdHRlci1kZWxpbWl0ZWQgcGF0aCBhbmQgYXNzaWducyB0aGUgcHJvdmlkZWQgdmFsdWUgYXQgdGhlIGRlc3RpbmF0aW9uIGtleS5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gb2JqIFRoZSBvYmplY3QgdG8gbXV0YXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgZGVzdGluYXRpb24gcGF0aCAoZS5nLiwgXCJhLmIuY1wiKVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0IGF0IHRoZSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IFtzcGxpdHRlcj1PYmplY3RLZXlTcGxpdHRlcl0gVGhlIGRlbGltaXRlciB1c2VkIHRvIHNwbGl0IHRoZSBwYXRoXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIHNldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgdmFsdWUsIHNwbGl0dGVyKVxuICogICBGLT4+Rjogc3BsaXQgcGF0aCBpbnRvIGtleXNcbiAqICAgbG9vcCBmb3IgZWFjaCBrZXlcbiAqICAgICBhbHQga2V5IG1pc3NpbmdcbiAqICAgICAgIEYtPj5POiBjcmVhdGUgaW50ZXJtZWRpYXRlIG9iamVjdFxuICogICAgIGVsc2Uga2V5IGV4aXN0c1xuICogICAgICAgRi0+Pk86IGRlc2NlbmQgaW50byBleGlzdGluZyBvYmplY3RcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEYtLT4+Qzogdm9pZFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHZhbHVlOiBhbnksXG4gIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXJcbik6IHZvaWQge1xuICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdChzcGxpdHRlcikuZmlsdGVyKChrKSA9PiBrLmxlbmd0aCA+IDApO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICBsZXQgY3VycmVudDogUmVjb3JkPGFueSwgYW55PiA9IG9iajtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgY29uc3Qga2V5ID0ga2V5c1tpXTtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50W2tleV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgY3VycmVudFtrZXldID09PSBudWxsIHx8XG4gICAgICB0eXBlb2YgY3VycmVudFtrZXldICE9PSBcIm9iamVjdFwiXG4gICAgKSB7XG4gICAgICBjdXJyZW50W2tleV0gPSB7fTtcbiAgICB9XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuXG4gIGNvbnN0IGxhc3RLZXkgPSBrZXlzW2tleXMubGVuZ3RoIC0gMV07XG4gIGN1cnJlbnRbbGFzdEtleV0gPSB2YWx1ZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2VudHJhbGl6ZWQgcnVudGltZSBtZXRhZGF0YSBzdG9yZSBib3VuZCB0byBjb25zdHJ1Y3RvcnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHV0aWxpdGllcyB0byByZWFkIGFuZCB3cml0ZSBzdHJ1Y3R1cmVkIG1ldGFkYXRhIGZvciBjbGFzc2VzIGFuZCB0aGVpciBtZW1iZXJzLCB3aXRoIG9wdGlvbmFsIG1pcnJvcmluZyBvbnRvIHRoZSBjb25zdHJ1Y3RvciB2aWEgYSB3ZWxsLWtub3duIHN5bWJvbCBrZXkuIFN1cHBvcnRzIG5lc3RlZCBrZXkgcGF0aHMgdXNpbmcgYSBjb25maWd1cmFibGUgc3BsaXR0ZXIgYW5kIG9mZmVycyBib3RoIGluc3RhbmNlIGFuZCBzdGF0aWMgQVBJcy5cbiAqIEB0ZW1wbGF0ZSBNIFRoZSBtb2RlbCB0eXBlIHRoZSBtZXRhZGF0YSBiZWxvbmdzIHRvXG4gKiBAdGVtcGxhdGUgTUVUQSBFeHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gcmVwcmVzZW50aW5nIHRoZSBtZXRhZGF0YSBzdHJ1Y3R1cmVcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIC8vIERlZmluZSBhbmQgcmVhZCBtZXRhZGF0YSBmb3IgYSBjbGFzc1xuICogY2xhc3MgVXNlciB7IG5hbWUhOiBzdHJpbmcgfVxuICogTWV0YWRhdGEuc2V0KFVzZXIsIFwiZGVzY3JpcHRpb24uY2xhc3NcIiwgXCJBIHVzZXIgbW9kZWxcIik7XG4gKiBNZXRhZGF0YS5zZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKTtcbiAqIGNvbnN0IGRlc2MgPSBNZXRhZGF0YS5nZXQoVXNlciwgXCJkZXNjcmlwdGlvbi5jbGFzc1wiKTsgLy8gXCJBIHVzZXIgbW9kZWxcIlxuICogY29uc3QgdHlwZSA9IE1ldGFkYXRhLnR5cGUoVXNlciwgXCJuYW1lXCIpOyAvLyBTdHJpbmdcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb25zdHJ1Y3RvclxuICogICBwYXJ0aWNpcGFudCBTIGFzIE1ldGFkYXRhIChzdGF0aWMpXG4gKiAgIEMtPj5TOiBzZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKVxuICogICBDLT4+UzogZ2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIpXG4gKiAgIFMtLT4+QzogU3RyaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW4tbWVtb3J5IHN0b3JhZ2Ugb2YgbWV0YWRhdGEgYnkgY29uc3RydWN0b3Igc3ltYm9sXG4gICAqIEBzdW1tYXJ5IE1hcHMgYSBTeW1ib2wgZGVyaXZlZCBmcm9tIHRoZSBjb25zdHJ1Y3RvciB0byBpdHMgbWV0YWRhdGEgb2JqZWN0LCBlbmFibGluZyBlZmZpY2llbnQgbG9va3VwLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX21ldGFkYXRhOiBSZWNvcmQ8c3ltYm9sLCBhbnk+ID0ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXRoIGRlbGltaXRlciBmb3IgbmVzdGVkIG1ldGFkYXRhIGtleXNcbiAgICogQHN1bW1hcnkgVXNlZCBieSBnZXQvc2V0IG9wZXJhdGlvbnMgdG8gbmF2aWdhdGUgbmVzdGVkIHN0cnVjdHVyZXMsIGRlZmF1bHRzIHRvIE9iamVjdEtleVNwbGl0dGVyLlxuICAgKi9cbiAgc3RhdGljIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXI7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3ltYm9sIGtleSB1c2VkIHRvIG1pcnJvciBtZXRhZGF0YSBvbiB0aGUgY29uc3RydWN0b3JcbiAgICogQHN1bW1hcnkgV2hlbiBtaXJyb3JpbmcgaXMgZW5hYmxlZCwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGlzIG5vbi1lbnVtZXJhYmxlIGtleS5cbiAgICovXG4gIHN0YXRpYyBiYXNlS2V5ID0gRGVjb3JhdGlvbktleXMuUkVGTEVDVDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250cm9scyB3aGV0aGVyIG1ldGFkYXRhIGlzIG1pcnJvcmVkIG9udG8gdGhlIGNvbnN0cnVjdG9yXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGUgbm9uLWVudW1lcmFibGUgYmFzZUtleS5cbiAgICovXG4gIHN0YXRpYyBtaXJyb3I6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGlzdHMga25vd24gcHJvcGVydHkga2V5cyBmb3IgYSBtb2RlbFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgYW5kIHJldHVybnMgdGhlIG5hbWVzIG9mIHByb3BlcnRpZXMgdGhhdCBoYXZlIHJlY29yZGVkIHR5cGUgaW5mb3JtYXRpb24uXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3JcbiAgICogQHJldHVybiB7c3RyaW5nW118dW5kZWZpbmVkfSBBcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBvciB1bmRlZmluZWQgaWYgbm8gbWV0YWRhdGEgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgcHJvcGVydGllcyhtb2RlbDogQ29uc3RydWN0b3IpOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0KG1vZGVsKTtcbiAgICBpZiAoIW1ldGEpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG1ldGEucHJvcGVydGllcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIGh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIGZvciBhIGNsYXNzIG9yIGEgcHJvcGVydHlcbiAgICogQHN1bW1hcnkgTG9va3MgdXAgdGhlIGRlc2NyaXB0aW9uIHN0b3JlZCB1bmRlciB0aGUgbWV0YWRhdGEgXCJkZXNjcmlwdGlvblwiIG1hcC4gSWYgYSBwcm9wZXJ0eSBrZXkgaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHByb3BlcnR5J3MgZGVzY3JpcHRpb247IG90aGVyd2lzZSByZXR1cm5zIHRoZSBjbGFzcyBkZXNjcmlwdGlvbi5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB3aG9zZSBkZXNjcmlwdGlvbiBpcyBiZWluZyByZXRyaWV2ZWRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwcm9wXSBPcHRpb25hbCBwcm9wZXJ0eSBrZXkgZm9yIHdoaWNoIHRvIGZldGNoIHRoZSBkZXNjcmlwdGlvblxuICAgKiBAcmV0dXJuIHtzdHJpbmd8dW5kZWZpbmVkfSBUaGUgZGVzY3JpcHRpb24gdGV4dCBpZiBwcmVzZW50LCBvdGhlcndpc2UgdW5kZWZpbmVkXG4gICAqL1xuICBzdGF0aWMgZGVzY3JpcHRpb248TT4obW9kZWw6IENvbnN0cnVjdG9yPE0+LCBwcm9wPzoga2V5b2YgTSkge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLkRFU0NSSVBUSU9OLCBwcm9wID8gcHJvcCA6IERlY29yYXRpb25LZXlzLkNMQVNTXS5qb2luKFxuICAgICAgICBPYmplY3RLZXlTcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgZGVzaWduIHR5cGUgZm9yIGEgcHJvcGVydHlcbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IHVuZGVyIFwicHJvcGVydGllcy48cHJvcD5cIiB0byByZXR1cm4gdGhlIGNvbnN0cnVjdG9yIHJlY29yZGVkIGZvciB0aGUgZ2l2ZW4gcHJvcGVydHkgbmFtZS5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBUaGUgcHJvcGVydHkgbmFtZSB3aG9zZSB0eXBlIHNob3VsZCBiZSByZXR1cm5lZFxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3Rvcnx1bmRlZmluZWR9IFRoZSBjb25zdHJ1Y3RvciByZWZlcmVuY2Ugb2YgdGhlIHByb3BlcnR5IHR5cGUgb3IgdW5kZWZpbmVkIGlmIG5vdCBhdmFpbGFibGVcbiAgICovXG4gIHN0YXRpYyB0eXBlKG1vZGVsOiBDb25zdHJ1Y3RvciwgcHJvcDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KG1vZGVsLCBgJHtEZWNvcmF0aW9uS2V5cy5QUk9QRVJUSUVTfS4ke3Byb3B9YCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBtZXRhZGF0YSBmb3IgYSBtb2RlbCBvciBhIHNwZWNpZmljIGtleSB3aXRoaW4gaXRcbiAgICogQHN1bW1hcnkgV2hlbiBjYWxsZWQgd2l0aCBhIGNvbnN0cnVjdG9yIG9ubHksIHJldHVybnMgdGhlIGVudGlyZSBtZXRhZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbC4gV2hlbiBhIGtleSBwYXRoIGlzIHByb3ZpZGVkLCByZXR1cm5zIHRoZSB2YWx1ZSBzdG9yZWQgYXQgdGhhdCBuZXN0ZWQga2V5LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAdGVtcGxhdGUgTUVUQVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHVzZWQgdG8gbG9jYXRlIHRoZSBtZXRhZGF0YSByZWNvcmRcbiAgICogQHJldHVybiB7TUVUQXx1bmRlZmluZWR9IFRoZSBtZXRhZGF0YSBvYmplY3QsIHRoZSB2YWx1ZSBhdCB0aGUga2V5IHBhdGgsIG9yIHVuZGVmaW5lZCBpZiBub3RoaW5nIGV4aXN0c1xuICAgKi9cbiAgc3RhdGljIGdldDxNLCBNRVRBIGV4dGVuZHMgQmFzaWNNZXRhZGF0YTxNPiA9IEJhc2ljTWV0YWRhdGE8TT4+KFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPlxuICApOiBNRVRBIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBtZXRhZGF0YSBmb3IgYSBtb2RlbCBvciBhIHNwZWNpZmljIGtleSB3aXRoaW4gaXRcbiAgICogQHN1bW1hcnkgV2hlbiBjYWxsZWQgd2l0aCBhIGNvbnN0cnVjdG9yIG9ubHksIHJldHVybnMgdGhlIGVudGlyZSBtZXRhZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbC4gV2hlbiBhIGtleSBwYXRoIGlzIHByb3ZpZGVkLCByZXR1cm5zIHRoZSB2YWx1ZSBzdG9yZWQgYXQgdGhhdCBuZXN0ZWQga2V5LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAdGVtcGxhdGUgTUVUQVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHVzZWQgdG8gbG9jYXRlIHRoZSBtZXRhZGF0YSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBuZXN0ZWQga2V5IHBhdGggdG8gZmV0Y2ggYSBzcGVjaWZpYyB2YWx1ZVxuICAgKiBAcmV0dXJuIHtNRVRBfCp8dW5kZWZpbmVkfSBUaGUgbWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciB1bmRlZmluZWQgaWYgbm90aGluZyBleGlzdHNcbiAgICovXG4gIHN0YXRpYyBnZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk6IHN0cmluZyk6IGFueTtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0XG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBba2V5XSBPcHRpb25hbCBuZXN0ZWQga2V5IHBhdGggdG8gZmV0Y2ggYSBzcGVjaWZpYyB2YWx1ZVxuICAgKiBAcmV0dXJuIHtNRVRBfCp8dW5kZWZpbmVkfSBUaGUgbWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciB1bmRlZmluZWQgaWYgbm90aGluZyBleGlzdHNcbiAgICovXG4gIHN0YXRpYyBnZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBzeW1ib2wgPSBTeW1ib2wuZm9yKG1vZGVsLnRvU3RyaW5nKCkpO1xuICAgIGlmICghdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoIWtleSkgcmV0dXJuIHRoaXMuX21ldGFkYXRhW3N5bWJvbF07XG4gICAgcmV0dXJuIGdldFZhbHVlQnlTcGxpdHRlcih0aGlzLl9tZXRhZGF0YVtzeW1ib2xdLCBrZXksIHRoaXMuc3BsaXR0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgYSBtZXRhZGF0YSB2YWx1ZSBhdCBhIGdpdmVuIG5lc3RlZCBrZXkgcGF0aFxuICAgKiBAc3VtbWFyeSBFbnN1cmVzIHRoZSBtZXRhZGF0YSByZWNvcmQgZXhpc3RzIGZvciB0aGUgY29uc3RydWN0b3IsIG1pcnJvcnMgaXQgb24gdGhlIGNvbnN0cnVjdG9yIHdoZW4gZW5hYmxlZCwgYW5kIHNldHMgdGhlIHByb3ZpZGVkIHZhbHVlIG9uIHRoZSBuZXN0ZWQga2V5IHBhdGggdXNpbmcgdGhlIGNvbmZpZ3VyZWQgc3BsaXR0ZXIuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3IgdG8gd2hpY2ggdGhlIG1ldGFkYXRhIGJlbG9uZ3NcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgbmVzdGVkIGtleSBwYXRoIGF0IHdoaWNoIHRvIHN0b3JlIHRoZSB2YWx1ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzdG9yZSBpbiB0aGUgbWV0YWRhdGFcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyBzZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGNvbnN0IHN5bWJvbCA9IFN5bWJvbC5mb3IobW9kZWwudG9TdHJpbmcoKSk7XG4gICAgaWYgKCF0aGlzLl9tZXRhZGF0YVtzeW1ib2xdKSB0aGlzLl9tZXRhZGF0YVtzeW1ib2xdID0ge30gYXMgYW55O1xuICAgIGlmIChcbiAgICAgIE1ldGFkYXRhLm1pcnJvciAmJlxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgdGhpcy5iYXNlS2V5KVxuICAgICkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZGVsLCB0aGlzLmJhc2VLZXksIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sXG4gICAgICB9KTtcbiAgICB9XG4gICAgc2V0VmFsdWVCeVNwbGl0dGVyKHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sIGtleSwgdmFsdWUsIHRoaXMuc3BsaXR0ZXIpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { BasicMetadata, Constructor } from "./types";
|
|
2
|
+
import { DecorationKeys } from "../constants";
|
|
3
|
+
import "reflect-metadata";
|
|
4
|
+
/**
|
|
5
|
+
* @description Centralized runtime metadata store bound to constructors
|
|
6
|
+
* @summary Provides utilities to read and write structured metadata for classes and their members, with optional mirroring onto the constructor via a well-known symbol key. Supports nested key paths using a configurable splitter and offers both instance and static APIs.
|
|
7
|
+
* @template M The model type the metadata belongs to
|
|
8
|
+
* @template META Extends BasicMetadata<M> representing the metadata structure
|
|
9
|
+
* @class
|
|
10
|
+
* @example
|
|
11
|
+
* // Define and read metadata for a class
|
|
12
|
+
* class User { name!: string }
|
|
13
|
+
* Metadata.set(User, "description.class", "A user model");
|
|
14
|
+
* Metadata.set(User, "properties.name", String);
|
|
15
|
+
* const desc = Metadata.get(User, "description.class"); // "A user model"
|
|
16
|
+
* const type = Metadata.type(User, "name"); // String
|
|
17
|
+
* @mermaid
|
|
18
|
+
* sequenceDiagram
|
|
19
|
+
* participant C as Constructor
|
|
20
|
+
* participant S as Metadata (static)
|
|
21
|
+
* C->>S: set(User, "properties.name", String)
|
|
22
|
+
* C->>S: get(User, "properties.name")
|
|
23
|
+
* S-->>C: String
|
|
24
|
+
*/
|
|
25
|
+
export declare class Metadata {
|
|
26
|
+
/**
|
|
27
|
+
* @description In-memory storage of metadata by constructor symbol
|
|
28
|
+
* @summary Maps a Symbol derived from the constructor to its metadata object, enabling efficient lookup.
|
|
29
|
+
*/
|
|
30
|
+
private static _metadata;
|
|
31
|
+
/**
|
|
32
|
+
* @description Path delimiter for nested metadata keys
|
|
33
|
+
* @summary Used by get/set operations to navigate nested structures, defaults to ObjectKeySplitter.
|
|
34
|
+
*/
|
|
35
|
+
static splitter: string;
|
|
36
|
+
/**
|
|
37
|
+
* @description Symbol key used to mirror metadata on the constructor
|
|
38
|
+
* @summary When mirroring is enabled, the metadata object is defined on the constructor under this non-enumerable key.
|
|
39
|
+
*/
|
|
40
|
+
static baseKey: DecorationKeys;
|
|
41
|
+
/**
|
|
42
|
+
* @description Controls whether metadata is mirrored onto the constructor
|
|
43
|
+
* @summary When true, the metadata object is defined on the constructor under the non-enumerable baseKey.
|
|
44
|
+
*/
|
|
45
|
+
static mirror: boolean;
|
|
46
|
+
private constructor();
|
|
47
|
+
/**
|
|
48
|
+
* @description Lists known property keys for a model
|
|
49
|
+
* @summary Reads the metadata entry and returns the names of properties that have recorded type information.
|
|
50
|
+
* @param {Constructor} model The target constructor
|
|
51
|
+
* @return {string[]|undefined} Array of property names or undefined if no metadata exists
|
|
52
|
+
*/
|
|
53
|
+
static properties(model: Constructor): string[] | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* @description Retrieves a human-readable description for a class or a property
|
|
56
|
+
* @summary Looks up the description stored under the metadata "description" map. If a property key is provided, returns the property's description; otherwise returns the class description.
|
|
57
|
+
* @template M
|
|
58
|
+
* @param {Constructor<M>} model The target constructor whose description is being retrieved
|
|
59
|
+
* @param {string} [prop] Optional property key for which to fetch the description
|
|
60
|
+
* @return {string|undefined} The description text if present, otherwise undefined
|
|
61
|
+
*/
|
|
62
|
+
static description<M>(model: Constructor<M>, prop?: keyof M): any;
|
|
63
|
+
/**
|
|
64
|
+
* @description Retrieves the recorded design type for a property
|
|
65
|
+
* @summary Reads the metadata entry under "properties.<prop>" to return the constructor recorded for the given property name.
|
|
66
|
+
* @param {Constructor} model The target constructor
|
|
67
|
+
* @param {string} prop The property name whose type should be returned
|
|
68
|
+
* @return {Constructor|undefined} The constructor reference of the property type or undefined if not available
|
|
69
|
+
*/
|
|
70
|
+
static type(model: Constructor, prop: string): any;
|
|
71
|
+
/**
|
|
72
|
+
* @description Retrieves metadata for a model or a specific key within it
|
|
73
|
+
* @summary When called with a constructor only, returns the entire metadata object associated with the model. When a key path is provided, returns the value stored at that nested key.
|
|
74
|
+
* @template M
|
|
75
|
+
* @template META
|
|
76
|
+
* @param {Constructor<M>} model The target constructor used to locate the metadata record
|
|
77
|
+
* @return {META|undefined} The metadata object, the value at the key path, or undefined if nothing exists
|
|
78
|
+
*/
|
|
79
|
+
static get<M, META extends BasicMetadata<M> = BasicMetadata<M>>(model: Constructor<M>): META | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* @description Retrieves metadata for a model or a specific key within it
|
|
82
|
+
* @summary When called with a constructor only, returns the entire metadata object associated with the model. When a key path is provided, returns the value stored at that nested key.
|
|
83
|
+
* @template M
|
|
84
|
+
* @template META
|
|
85
|
+
* @param {Constructor<M>} model The target constructor used to locate the metadata record
|
|
86
|
+
* @param {string} key nested key path to fetch a specific value
|
|
87
|
+
* @return {META|*|undefined} The metadata object, the value at the key path, or undefined if nothing exists
|
|
88
|
+
*/
|
|
89
|
+
static get(model: Constructor, key: string): any;
|
|
90
|
+
/**
|
|
91
|
+
* @description Writes a metadata value at a given nested key path
|
|
92
|
+
* @summary Ensures the metadata record exists for the constructor, mirrors it on the constructor when enabled, and sets the provided value on the nested key path using the configured splitter.
|
|
93
|
+
* @param {Constructor} model The target constructor to which the metadata belongs
|
|
94
|
+
* @param {string} key The nested key path at which to store the value
|
|
95
|
+
* @param {*} value The value to store in the metadata
|
|
96
|
+
* @return {void}
|
|
97
|
+
*/
|
|
98
|
+
static set(model: Constructor, key: string, value: any): void;
|
|
99
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Metadata.cjs"), exports);
|
|
18
|
+
__exportStar(require("./types.cjs"), exports);
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWV0YWRhdGEvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQUEyQjtBQUMzQiw4Q0FBd0IiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9NZXRhZGF0YVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdHlwZXNcIjtcbiJdfQ==
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const constants_1 = require("./../constants.cjs");
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWV0YWRhdGEvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrREFBOEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEZWNvcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IHR5cGUgQmFzaWNNZXRhZGF0YTxNPiA9IHtcbiAgW0RlY29yYXRpb25LZXlzLkNMQVNTXTogQ29uc3RydWN0b3I8TT47XG4gIFtEZWNvcmF0aW9uS2V5cy5ERVNDUklQVElPTl0/OiBSZWNvcmQ8XG4gICAga2V5b2YgTSB8IGAke0RlY29yYXRpb25LZXlzLkNMQVNTfWAsXG4gICAgc3RyaW5nXG4gID47XG4gIFtEZWNvcmF0aW9uS2V5cy5QUk9QRVJUSUVTXTogUmVjb3JkPGtleW9mIE0sIENvbnN0cnVjdG9yPE0+IHwgdW5kZWZpbmVkPjtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnN0cnVjdG9yIHR5cGUgZm9yIGNyZWF0aW5nIGluc3RhbmNlcyBvZiBhIGdpdmVuIG9iamVjdCB0eXBlXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgZ2VuZXJpYyBjb25zdHJ1Y3RvciBzaWduYXR1cmUgdGhhdCBjYW4gaW5zdGFudGlhdGUgb2JqZWN0cyBvZiB0eXBlIE9CSiB3aXRoIGFueSBhcmd1bWVudHMuXG4gKiBAdGVtcGxhdGUgT0JKXG4gKiBAdHlwZWRlZiB7Q29uc3RydWN0b3I8T0JKPn0gQ29uc3RydWN0b3JcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgdHlwZSBDb25zdHJ1Y3RvcjxPQkogPSBhbnk+ID0geyBuZXcgKC4uLmFyZ3M6IGFueVtdKTogT0JKIH07XG4iXX0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DecorationKeys } from "../constants";
|
|
2
|
+
export type BasicMetadata<M> = {
|
|
3
|
+
[DecorationKeys.CLASS]: Constructor<M>;
|
|
4
|
+
[DecorationKeys.DESCRIPTION]?: Record<keyof M | `${DecorationKeys.CLASS}`, string>;
|
|
5
|
+
[DecorationKeys.PROPERTIES]: Record<keyof M, Constructor<M> | undefined>;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @description Constructor type for creating instances of a given object type
|
|
9
|
+
* @summary Defines a generic constructor signature that can instantiate objects of type OBJ with any arguments.
|
|
10
|
+
* @template OBJ
|
|
11
|
+
* @typedef {Constructor<OBJ>} Constructor
|
|
12
|
+
* @memberOf module:decoration
|
|
13
|
+
*/
|
|
14
|
+
export type Constructor<OBJ = any> = {
|
|
15
|
+
new (...args: any[]): OBJ;
|
|
16
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@decaf-ts/decoration",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Decoration and metadata mechanisms for decaf-ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"require": "./lib/index.cjs",
|
|
8
|
+
"import": "./lib/esm/index.js"
|
|
9
|
+
},
|
|
10
|
+
"types": "lib/index.d.ts",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"do-install": "TOKEN=$(cat .token) npm install",
|
|
13
|
+
"update-dependencies": "PREFIX=\"decaf-ts\"; npm ls | grep \"$PREFIX\" | awk -F/ '{print $NF}' | sed 's/@.*//' | xargs -I package npm update @\"$PREFIX\"/package",
|
|
14
|
+
"update-scripts": "npx update-scripts",
|
|
15
|
+
"on-first-run": "npx update-scripts --boot",
|
|
16
|
+
"set-git-auth": "git config url.\"https://api:$(cat .token)@github.com/\".insteadOf \"https://github.com/\" && git config url.\"https://ssh:$(cat .token)@github.com/\".insteadOf \"ssh://git@github.com/\" && git config url.\"https://git:$(cat .token)@github.com/\".insteadOf \"git@github.com:\"",
|
|
17
|
+
"flash-forward": "npx npm-check-updates -u && npm run do-install",
|
|
18
|
+
"reset": "rm -rf * && git checkout . && git pull && npm run do-install",
|
|
19
|
+
"build": "npx build-scripts --dev",
|
|
20
|
+
"build:prod": "npx build-scripts --prod",
|
|
21
|
+
"test": "jest --runInBand --coverage --detectOpenHandles",
|
|
22
|
+
"test:unit": "jest --testPathPattern=\"/tests/unit\" --passWithNoTests --detectOpenHandles",
|
|
23
|
+
"test:integration": "jest --testPathPattern=\"/tests/(integration)\" --passWithNoTests --detectOpenHandles",
|
|
24
|
+
"test:all": "jest --testPathPattern=\"/tests\" --passWithNoTests --detectOpenHandles",
|
|
25
|
+
"test:circular": "dpdm -T --no-warning --no-tree ./src/index.ts",
|
|
26
|
+
"coverage": "rimraf ./workdocs/reports/data/*.json && npm run test:all -- --coverage --config=./workdocs/reports/jest.coverage.config.ts",
|
|
27
|
+
"lint": "eslint .",
|
|
28
|
+
"lint-fix": "eslint --fix .",
|
|
29
|
+
"prepare-pr": "npm run lint-fix && npm run build:prod && npm run coverage && npm run docs",
|
|
30
|
+
"prepare-release": "npm run lint-fix && npm run build:prod && npm run coverage && npm run docs",
|
|
31
|
+
"release": "./bin/tag-release.sh",
|
|
32
|
+
"clean-publish": "npx clean-publish",
|
|
33
|
+
"drawings": "for FILE in workdocs/drawings/*.drawio; do echo \"converting $FILE to image...\" && docker run --rm -v $(pwd):/data rlespinasse/drawio-export --format png $FILE; done && cp -rf workdocs/drawings/export/* workdocs/resources/",
|
|
34
|
+
"uml": "cd workdocs/uml && for FILE in ./*.puml; do docker run --rm -v $(pwd):/work -w /work miy4/plantuml -DPLANTUML_LIMIT_SIZE=8192 -tpng $FILE; done && cd ../.. && cp -fr workdocs/uml/*.png workdocs/resources/",
|
|
35
|
+
"docs": "npx rimraf ./docs && mkdir docs && npx build-scripts --docs",
|
|
36
|
+
"publish-docs": "docker run -it --rm --user $(id -u):$(id -g) -v \"$(pwd)/workdocs/confluence:/content\" -e ATLASSIAN_API_TOKEN=$(cat .confluence-token) ghcr.io/markdown-confluence/publish:latest"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/decaf-ts/decoration.git"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20.0.0",
|
|
44
|
+
"npm": ">=10.0.0"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"lib",
|
|
48
|
+
"dist"
|
|
49
|
+
],
|
|
50
|
+
"keywords": [
|
|
51
|
+
"plantuml",
|
|
52
|
+
"mermaid",
|
|
53
|
+
"uml",
|
|
54
|
+
"drawio",
|
|
55
|
+
"mddocs",
|
|
56
|
+
"md",
|
|
57
|
+
"jsdoc",
|
|
58
|
+
"doc",
|
|
59
|
+
"docs",
|
|
60
|
+
"documentation",
|
|
61
|
+
"test",
|
|
62
|
+
"reports",
|
|
63
|
+
"confluence",
|
|
64
|
+
"ci/cd",
|
|
65
|
+
"ci",
|
|
66
|
+
"cd",
|
|
67
|
+
"template",
|
|
68
|
+
"typescript",
|
|
69
|
+
"ts"
|
|
70
|
+
],
|
|
71
|
+
"author": "Tiago Venceslau",
|
|
72
|
+
"bugs": {
|
|
73
|
+
"url": "https://github.com/decaf-ts/decoration/issues"
|
|
74
|
+
},
|
|
75
|
+
"homepage": "https://github.com/decaf-ts/decoration#readme",
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@decaf-ts/logging": "latest",
|
|
78
|
+
"@decaf-ts/utils": "latest",
|
|
79
|
+
"@eslint/js": "^9.25.1",
|
|
80
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
81
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
82
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
83
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
84
|
+
"@stylistic/eslint-plugin": "^4.2.0",
|
|
85
|
+
"@types/jest": "^29.5.14",
|
|
86
|
+
"clean-publish": "^5.1.0",
|
|
87
|
+
"dpdm": "^3.14.0",
|
|
88
|
+
"eslint": "^9.25.1",
|
|
89
|
+
"eslint-config-prettier": "^10.1.2",
|
|
90
|
+
"eslint-plugin-prettier": "^5.2.6",
|
|
91
|
+
"globals": "^16.0.0",
|
|
92
|
+
"jest": "^29.7.0",
|
|
93
|
+
"jest-html-reporters": "^3.1.7",
|
|
94
|
+
"jest-junit": "^16.0.0",
|
|
95
|
+
"jsdoc": "^4.0.4",
|
|
96
|
+
"jsdoc-mermaid": "^1.0.0",
|
|
97
|
+
"markdown-include": "^0.4.3",
|
|
98
|
+
"minimist": "^1.2.8",
|
|
99
|
+
"nodemon": "^3.1.9",
|
|
100
|
+
"npm-check-updates": "^18.0.0",
|
|
101
|
+
"prettier": "3.5.3",
|
|
102
|
+
"rimraf": "^6.0.1",
|
|
103
|
+
"rollup": "^4.40.0",
|
|
104
|
+
"ts-jest": "^29.3.2",
|
|
105
|
+
"ts-loader": "^9.5.2",
|
|
106
|
+
"ts-node": "^10.9.2",
|
|
107
|
+
"typescript": "^5.8.3",
|
|
108
|
+
"typescript-eslint": "^8.31.0"
|
|
109
|
+
},
|
|
110
|
+
"peerDependencies": {
|
|
111
|
+
"reflect-metadata": "^0.2.2",
|
|
112
|
+
"typed-object-accumulator": "^0.1.5"
|
|
113
|
+
}
|
|
114
|
+
}
|