velocious 1.0.465 → 1.0.466
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/build/environment-handlers/node/cli/commands/lint/relationships.js +95 -2
- package/build/src/environment-handlers/node/cli/commands/lint/relationships.d.ts +29 -0
- package/build/src/environment-handlers/node/cli/commands/lint/relationships.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/lint/relationships.js +83 -3
- package/package.json +1 -1
- package/src/environment-handlers/node/cli/commands/lint/relationships.js +95 -2
- package/src/types/external-modules.d.ts +13 -0
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
import BaseCommand from "../../../../../cli/base-command.js"
|
|
4
4
|
import fs from "node:fs/promises"
|
|
5
5
|
import path from "node:path"
|
|
6
|
+
import requireContext from "require-context"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {(id: string) => {default: typeof import("../../../../../database/record/index.js").default}} ModelFileRequireContextIdFunctionType
|
|
10
|
+
* @typedef {ModelFileRequireContextIdFunctionType & {keys: () => string[]}} ModelFileRequireContextType
|
|
11
|
+
*/
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* Lints model relationships: every non-polymorphic belongs-to relationship should have an inverse
|
|
@@ -27,7 +33,9 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
27
33
|
// current configuration, so make this command's configuration the current one.
|
|
28
34
|
this.getConfiguration().setCurrent()
|
|
29
35
|
|
|
30
|
-
await this.
|
|
36
|
+
if (!await this._registerStaticModelFiles()) {
|
|
37
|
+
await this.getConfiguration().initializeModels()
|
|
38
|
+
}
|
|
31
39
|
|
|
32
40
|
const ignoredRelationships = await this._loadIgnoredRelationships()
|
|
33
41
|
const offences = []
|
|
@@ -66,7 +74,11 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
66
74
|
if (candidate.through) return false
|
|
67
75
|
|
|
68
76
|
try {
|
|
69
|
-
|
|
77
|
+
const candidateTargetModelClass = candidate.getTargetModelClass()
|
|
78
|
+
|
|
79
|
+
if (!candidateTargetModelClass) return false
|
|
80
|
+
|
|
81
|
+
return this._modelClassesMatch(candidateTargetModelClass, modelClass)
|
|
70
82
|
} catch {
|
|
71
83
|
// A has-many/has-one with an unresolvable target can't be the inverse of this belongs-to.
|
|
72
84
|
// It is reported separately when its own model's belongs-to relationships are linted.
|
|
@@ -97,6 +109,87 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
97
109
|
return {offences}
|
|
98
110
|
}
|
|
99
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Registers model classes from the conventional src/models directory without
|
|
114
|
+
* running the application's full database/server initialization.
|
|
115
|
+
* @returns {Promise<boolean>} Whether static model files were registered.
|
|
116
|
+
*/
|
|
117
|
+
async _registerStaticModelFiles() {
|
|
118
|
+
if (this.args.testing) return false
|
|
119
|
+
|
|
120
|
+
const modelsDirectory = path.join(this.directory(), "src/models")
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const stats = await fs.stat(modelsDirectory)
|
|
124
|
+
|
|
125
|
+
if (!stats.isDirectory()) return false
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code == "ENOENT") return false
|
|
128
|
+
|
|
129
|
+
throw error
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if ((await this._javascriptFilesInDirectory(modelsDirectory)).length === 0) return false
|
|
133
|
+
|
|
134
|
+
/** @type {ModelFileRequireContextType} */
|
|
135
|
+
const requireContextModels = requireContext(modelsDirectory, true, /^(.+)\.js$/)
|
|
136
|
+
|
|
137
|
+
const modelFileNames = requireContextModels.keys()
|
|
138
|
+
for (const fileName of modelFileNames) {
|
|
139
|
+
const modelClassImport = requireContextModels(fileName)
|
|
140
|
+
const modelClass = modelClassImport.default
|
|
141
|
+
|
|
142
|
+
if (!modelClass) {
|
|
143
|
+
throw new Error(`Model wasn't exported from: ${fileName}`)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
modelClass.registerRecordClass({configuration: this.getConfiguration()})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Finds JavaScript files below a directory.
|
|
154
|
+
* @param {string} directory - Directory to scan.
|
|
155
|
+
* @returns {Promise<string[]>} JavaScript file paths.
|
|
156
|
+
*/
|
|
157
|
+
async _javascriptFilesInDirectory(directory) {
|
|
158
|
+
const filePaths = []
|
|
159
|
+
const entries = await fs.readdir(directory, {withFileTypes: true})
|
|
160
|
+
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
const entryPath = path.join(directory, entry.name)
|
|
163
|
+
|
|
164
|
+
if (entry.isDirectory()) {
|
|
165
|
+
filePaths.push(...await this._javascriptFilesInDirectory(entryPath))
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
170
|
+
filePaths.push(entryPath)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return filePaths
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Checks whether two model class objects describe the same registered model.
|
|
179
|
+
* @param {typeof import("../../../../../database/record/index.js").default} leftModelClass - Candidate target model class.
|
|
180
|
+
* @param {typeof import("../../../../../database/record/index.js").default} rightModelClass - Belongs-to source model class.
|
|
181
|
+
* @returns {boolean} Whether both model classes represent the same model identity.
|
|
182
|
+
*/
|
|
183
|
+
_modelClassesMatch(leftModelClass, rightModelClass) {
|
|
184
|
+
if (leftModelClass === rightModelClass) return true
|
|
185
|
+
// `translates()` creates an internal translation class; apps may also define
|
|
186
|
+
// a concrete class for the same model/table so generated code has a stable
|
|
187
|
+
// file and type name.
|
|
188
|
+
if (leftModelClass.getModelName() != rightModelClass.getModelName()) return false
|
|
189
|
+
|
|
190
|
+
return leftModelClass.tableName() == rightModelClass.tableName()
|
|
191
|
+
}
|
|
192
|
+
|
|
100
193
|
/**
|
|
101
194
|
* Loads the ignored relationship keys from the lint config file. The file is optional; when the
|
|
102
195
|
* default path doesn't exist, no relationships are ignored. An explicitly passed `--config` path
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {(id: string) => {default: typeof import("../../../../../database/record/index.js").default}} ModelFileRequireContextIdFunctionType
|
|
3
|
+
* @typedef {ModelFileRequireContextIdFunctionType & {keys: () => string[]}} ModelFileRequireContextType
|
|
4
|
+
*/
|
|
1
5
|
/**
|
|
2
6
|
* Lints model relationships: every non-polymorphic belongs-to relationship should have an inverse
|
|
3
7
|
* has-many or has-one relationship declared on its target model class. A missing inverse usually
|
|
@@ -22,6 +26,25 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
22
26
|
message: string;
|
|
23
27
|
}>;
|
|
24
28
|
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Registers model classes from the conventional src/models directory without
|
|
31
|
+
* running the application's full database/server initialization.
|
|
32
|
+
* @returns {Promise<boolean>} Whether static model files were registered.
|
|
33
|
+
*/
|
|
34
|
+
_registerStaticModelFiles(): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Finds JavaScript files below a directory.
|
|
37
|
+
* @param {string} directory - Directory to scan.
|
|
38
|
+
* @returns {Promise<string[]>} JavaScript file paths.
|
|
39
|
+
*/
|
|
40
|
+
_javascriptFilesInDirectory(directory: string): Promise<string[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Checks whether two model class objects describe the same registered model.
|
|
43
|
+
* @param {typeof import("../../../../../database/record/index.js").default} leftModelClass - Candidate target model class.
|
|
44
|
+
* @param {typeof import("../../../../../database/record/index.js").default} rightModelClass - Belongs-to source model class.
|
|
45
|
+
* @returns {boolean} Whether both model classes represent the same model identity.
|
|
46
|
+
*/
|
|
47
|
+
_modelClassesMatch(leftModelClass: typeof import("../../../../../database/record/index.js").default, rightModelClass: typeof import("../../../../../database/record/index.js").default): boolean;
|
|
25
48
|
/**
|
|
26
49
|
* Loads the ignored relationship keys from the lint config file. The file is optional; when the
|
|
27
50
|
* default path doesn't exist, no relationships are ignored. An explicitly passed `--config` path
|
|
@@ -30,5 +53,11 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
30
53
|
*/
|
|
31
54
|
_loadIgnoredRelationships(): Promise<Set<string>>;
|
|
32
55
|
}
|
|
56
|
+
export type ModelFileRequireContextIdFunctionType = (id: string) => {
|
|
57
|
+
default: typeof import("../../../../../database/record/index.js").default;
|
|
58
|
+
};
|
|
59
|
+
export type ModelFileRequireContextType = ModelFileRequireContextIdFunctionType & {
|
|
60
|
+
keys: () => string[];
|
|
61
|
+
};
|
|
33
62
|
import BaseCommand from "../../../../../cli/base-command.js";
|
|
34
63
|
//# sourceMappingURL=relationships.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../../../../../../src/environment-handlers/node/cli/commands/lint/relationships.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../../../../../../src/environment-handlers/node/cli/commands/lint/relationships.js"],"names":[],"mappings":"AAOA;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AACH;IACE;;;OAGG;IACH,WAFa,OAAO,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAC,CAAC,CAAA;KAAC,CAAC,CAiF5E;IAED;;;;OAIG;IACH,6BAFa,OAAO,CAAC,OAAO,CAAC,CAmC5B;IAED;;;;OAIG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB7B;IAED;;;;;OAKG;IACH,mCAJW,cAAc,yCAAyC,EAAE,OAAO,mBAChE,cAAc,yCAAyC,EAAE,OAAO,GAC9D,OAAO,CAUnB;IAED;;;;;OAKG;IACH,6BAFa,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAuChC;CACF;oDApOY,CAAC,EAAE,EAAE,MAAM,KAAK;IAAC,OAAO,EAAE,cAAc,yCAAyC,EAAE,OAAO,CAAA;CAAC;0CAC3F,qCAAqC,GAAG;IAAC,IAAI,EAAE,MAAM,MAAM,EAAE,CAAA;CAAC;wBAPnD,oCAAoC"}
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
import BaseCommand from "../../../../../cli/base-command.js";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import requireContext from "require-context";
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {(id: string) => {default: typeof import("../../../../../database/record/index.js").default}} ModelFileRequireContextIdFunctionType
|
|
8
|
+
* @typedef {ModelFileRequireContextIdFunctionType & {keys: () => string[]}} ModelFileRequireContextType
|
|
9
|
+
*/
|
|
5
10
|
/**
|
|
6
11
|
* Lints model relationships: every non-polymorphic belongs-to relationship should have an inverse
|
|
7
12
|
* has-many or has-one relationship declared on its target model class. A missing inverse usually
|
|
@@ -24,7 +29,9 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
24
29
|
// Relationship target resolution (getTargetModelClass) looks model classes up through the
|
|
25
30
|
// current configuration, so make this command's configuration the current one.
|
|
26
31
|
this.getConfiguration().setCurrent();
|
|
27
|
-
await this.
|
|
32
|
+
if (!await this._registerStaticModelFiles()) {
|
|
33
|
+
await this.getConfiguration().initializeModels();
|
|
34
|
+
}
|
|
28
35
|
const ignoredRelationships = await this._loadIgnoredRelationships();
|
|
29
36
|
const offences = [];
|
|
30
37
|
const modelClasses = Object.values(this.getConfiguration().getModelClasses());
|
|
@@ -58,7 +65,10 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
58
65
|
if (candidate.through)
|
|
59
66
|
return false;
|
|
60
67
|
try {
|
|
61
|
-
|
|
68
|
+
const candidateTargetModelClass = candidate.getTargetModelClass();
|
|
69
|
+
if (!candidateTargetModelClass)
|
|
70
|
+
return false;
|
|
71
|
+
return this._modelClassesMatch(candidateTargetModelClass, modelClass);
|
|
62
72
|
}
|
|
63
73
|
catch {
|
|
64
74
|
// A has-many/has-one with an unresolvable target can't be the inverse of this belongs-to.
|
|
@@ -84,6 +94,76 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
84
94
|
console.log(`Relationship lint passed for ${modelClasses.length} model(s).`);
|
|
85
95
|
return { offences };
|
|
86
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Registers model classes from the conventional src/models directory without
|
|
99
|
+
* running the application's full database/server initialization.
|
|
100
|
+
* @returns {Promise<boolean>} Whether static model files were registered.
|
|
101
|
+
*/
|
|
102
|
+
async _registerStaticModelFiles() {
|
|
103
|
+
if (this.args.testing)
|
|
104
|
+
return false;
|
|
105
|
+
const modelsDirectory = path.join(this.directory(), "src/models");
|
|
106
|
+
try {
|
|
107
|
+
const stats = await fs.stat(modelsDirectory);
|
|
108
|
+
if (!stats.isDirectory())
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if ( /** @type {NodeJS.ErrnoException} */(error).code == "ENOENT")
|
|
113
|
+
return false;
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
if ((await this._javascriptFilesInDirectory(modelsDirectory)).length === 0)
|
|
117
|
+
return false;
|
|
118
|
+
/** @type {ModelFileRequireContextType} */
|
|
119
|
+
const requireContextModels = requireContext(modelsDirectory, true, /^(.+)\.js$/);
|
|
120
|
+
const modelFileNames = requireContextModels.keys();
|
|
121
|
+
for (const fileName of modelFileNames) {
|
|
122
|
+
const modelClassImport = requireContextModels(fileName);
|
|
123
|
+
const modelClass = modelClassImport.default;
|
|
124
|
+
if (!modelClass) {
|
|
125
|
+
throw new Error(`Model wasn't exported from: ${fileName}`);
|
|
126
|
+
}
|
|
127
|
+
modelClass.registerRecordClass({ configuration: this.getConfiguration() });
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Finds JavaScript files below a directory.
|
|
133
|
+
* @param {string} directory - Directory to scan.
|
|
134
|
+
* @returns {Promise<string[]>} JavaScript file paths.
|
|
135
|
+
*/
|
|
136
|
+
async _javascriptFilesInDirectory(directory) {
|
|
137
|
+
const filePaths = [];
|
|
138
|
+
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
const entryPath = path.join(directory, entry.name);
|
|
141
|
+
if (entry.isDirectory()) {
|
|
142
|
+
filePaths.push(...await this._javascriptFilesInDirectory(entryPath));
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
146
|
+
filePaths.push(entryPath);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return filePaths;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Checks whether two model class objects describe the same registered model.
|
|
153
|
+
* @param {typeof import("../../../../../database/record/index.js").default} leftModelClass - Candidate target model class.
|
|
154
|
+
* @param {typeof import("../../../../../database/record/index.js").default} rightModelClass - Belongs-to source model class.
|
|
155
|
+
* @returns {boolean} Whether both model classes represent the same model identity.
|
|
156
|
+
*/
|
|
157
|
+
_modelClassesMatch(leftModelClass, rightModelClass) {
|
|
158
|
+
if (leftModelClass === rightModelClass)
|
|
159
|
+
return true;
|
|
160
|
+
// `translates()` creates an internal translation class; apps may also define
|
|
161
|
+
// a concrete class for the same model/table so generated code has a stable
|
|
162
|
+
// file and type name.
|
|
163
|
+
if (leftModelClass.getModelName() != rightModelClass.getModelName())
|
|
164
|
+
return false;
|
|
165
|
+
return leftModelClass.tableName() == rightModelClass.tableName();
|
|
166
|
+
}
|
|
87
167
|
/**
|
|
88
168
|
* Loads the ignored relationship keys from the lint config file. The file is optional; when the
|
|
89
169
|
* default path doesn't exist, no relationships are ignored. An explicitly passed `--config` path
|
|
@@ -120,4 +200,4 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
120
200
|
return new Set(ignore);
|
|
121
201
|
}
|
|
122
202
|
}
|
|
123
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpb25zaGlwcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9lbnZpcm9ubWVudC1oYW5kbGVycy9ub2RlL2NsaS9jb21tYW5kcy9saW50L3JlbGF0aW9uc2hpcHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sV0FBVyxNQUFNLG9DQUFvQyxDQUFBO0FBQzVELE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ2pDLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUU1Qjs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLHFDQUFzQyxTQUFRLFdBQVc7SUFDNUU7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLE9BQU87UUFDWCwwRkFBMEY7UUFDMUYsK0VBQStFO1FBQy9FLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFBO1FBRXBDLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtRQUVoRCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUE7UUFDbkUsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFBO1FBQ25CLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQTtRQUU3RSxLQUFLLE1BQU0sVUFBVSxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ3RDLEtBQUssTUFBTSxZQUFZLElBQUksVUFBVSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQztnQkFDekQsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLElBQUksV0FBVztvQkFBRSxTQUFRO2dCQUNuRCxJQUFJLFlBQVksQ0FBQyxjQUFjLEVBQUU7b0JBQUUsU0FBUTtnQkFFM0MsTUFBTSxTQUFTLEdBQUcsR0FBRyxVQUFVLENBQUMsSUFBSSxJQUFJLFlBQVksQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLENBQUE7Z0JBRTVFLElBQUksb0JBQW9CLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztvQkFBRSxTQUFRO2dCQUVqRCxJQUFJLGdCQUFnQixDQUFBO2dCQUVwQixJQUFJLENBQUM7b0JBQ0gsZ0JBQWdCLEdBQUcsWUFBWSxDQUFDLG1CQUFtQixFQUFFLENBQUE7Z0JBQ3ZELENBQUM7Z0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztvQkFDZixRQUFRLENBQUMsSUFBSSxDQUFDO3dCQUNaLFNBQVM7d0JBQ1QsT0FBTyxFQUFFLEdBQUcsU0FBUyw4Q0FBOEMsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFO3FCQUNwSCxDQUFDLENBQUE7b0JBRUYsU0FBUTtnQkFDVixDQUFDO2dCQUVELElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUN0QixRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxHQUFHLFNBQVMsMkNBQTJDLEVBQUMsQ0FBQyxDQUFBO29CQUU1RixTQUFRO2dCQUNWLENBQUM7Z0JBRUQsTUFBTSxtQkFBbUIsR0FBRyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO29CQUNqRixJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxJQUFJLFFBQVE7d0JBQUUsT0FBTyxLQUFLLENBQUE7b0JBQ3JGLElBQUksU0FBUyxDQUFDLE9BQU87d0JBQUUsT0FBTyxLQUFLLENBQUE7b0JBRW5DLElBQUksQ0FBQzt3QkFDSCxPQUFPLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLFVBQVUsQ0FBQTtvQkFDdkQsQ0FBQztvQkFBQyxNQUFNLENBQUM7d0JBQ1AsMEZBQTBGO3dCQUMxRixzRkFBc0Y7d0JBQ3RGLE9BQU8sS0FBSyxDQUFBO29CQUNkLENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUE7Z0JBRUYsSUFBSSxtQkFBbUI7b0JBQUUsU0FBUTtnQkFFakMsUUFBUSxDQUFDLElBQUksQ0FBQztvQkFDWixTQUFTO29CQUNULE9BQU8sRUFBRSxHQUFHLGdCQUFnQixDQUFDLElBQUksMERBQTBELFNBQVMsZ0JBQWdCO3dCQUNsSCwwQkFBMEIsZ0JBQWdCLENBQUMsSUFBSSxZQUFZLFNBQVMseUJBQXlCO2lCQUNoRyxDQUFDLENBQUE7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUVELEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7WUFDL0IsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDaEMsQ0FBQztRQUVELElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxRQUFRLENBQUMsTUFBTSxpQkFBaUIsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDM0ksQ0FBQztRQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLFlBQVksQ0FBQyxNQUFNLFlBQVksQ0FBQyxDQUFBO1FBRTVFLE9BQU8sRUFBQyxRQUFRLEVBQUMsQ0FBQTtJQUNuQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMseUJBQXlCO1FBQzdCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO1FBQ2xFLE1BQU0sa0JBQWtCLEdBQUcsY0FBYyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFBO1FBRW5HLElBQUksY0FBYyxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDL0MsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFBO1FBQy9ELENBQUM7UUFFRCxNQUFNLFVBQVUsR0FBRyxrQkFBa0I7WUFDbkMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLGtCQUFrQixDQUFDO1lBQ3BELENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSx3QkFBd0IsQ0FBQyxDQUFBO1FBRXpELElBQUksYUFBYSxDQUFBO1FBRWpCLElBQUksQ0FBQztZQUNILGFBQWEsR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZELENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLGtCQUFrQixJQUFJLG9DQUFvQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUN6RixPQUFPLElBQUksR0FBRyxFQUFFLENBQUE7WUFDbEIsQ0FBQztZQUVELE1BQU0sS0FBSyxDQUFBO1FBQ2IsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUE7UUFFeEMsSUFBSSxNQUFNLEtBQUssSUFBSSxJQUFJLE9BQU8sTUFBTSxJQUFJLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDMUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUNsRixDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUE7UUFFbEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsT0FBTyxLQUFLLElBQUksUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUMvRSxNQUFNLElBQUksS0FBSyxDQUFDLDJGQUEyRixVQUFVLEVBQUUsQ0FBQyxDQUFBO1FBQzFILENBQUM7UUFFRCxPQUFPLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3hCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQmFzZUNvbW1hbmQgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2NsaS9iYXNlLWNvbW1hbmQuanNcIlxuaW1wb3J0IGZzIGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCJcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuXG4vKipcbiAqIExpbnRzIG1vZGVsIHJlbGF0aW9uc2hpcHM6IGV2ZXJ5IG5vbi1wb2x5bW9ycGhpYyBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcCBzaG91bGQgaGF2ZSBhbiBpbnZlcnNlXG4gKiBoYXMtbWFueSBvciBoYXMtb25lIHJlbGF0aW9uc2hpcCBkZWNsYXJlZCBvbiBpdHMgdGFyZ2V0IG1vZGVsIGNsYXNzLiBBIG1pc3NpbmcgaW52ZXJzZSB1c3VhbGx5XG4gKiBtZWFucyB0aGUgdGFyZ2V0IG1vZGVsIHdhcyBuZXZlciB0b2xkIGFib3V0IHRoZSBhc3NvY2lhdGlvbiAoZS5nLiBhbiBFdmVudCBtb2RlbCBtaXNzaW5nXG4gKiBgaGFzTWFueShcInByaWNlQ2F0ZWdvcnlTZXR0aW5nc1wiKWAgd2hpbGUgUHJpY2VDYXRlZ29yeVNldHRpbmcgZGVjbGFyZXMgYGJlbG9uZ3NUbyhcImV2ZW50XCIpYCkuXG4gKlxuICogU3BlY2lmaWMgcmVsYXRpb25zaGlwcyBjYW4gYmUgaWdub3JlZCB0aHJvdWdoIGEgSlNPTiBjb25maWcgZmlsZSAoZGVmYXVsdDpcbiAqIGByZWxhdGlvbnNoaXAtbGludC5qc29uYCBpbiB0aGUgcHJvamVjdCBkaXJlY3RvcnksIG92ZXJyaWRhYmxlIHdpdGggYC0tY29uZmlnIDxwYXRoPmApOlxuICpcbiAqICAge1wiaWdub3JlXCI6IFtcIlByaWNlQ2F0ZWdvcnlTZXR0aW5nI2V2ZW50XCJdfVxuICpcbiAqIHdoZXJlIGVhY2ggZW50cnkgaXMgYDxtb2RlbCBjbGFzcyBuYW1lPiM8YmVsb25ncy10byByZWxhdGlvbnNoaXAgbmFtZT5gLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWZWxvY2lvdXNDbGlDb21tYW5kc0xpbnRSZWxhdGlvbnNoaXBzIGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICAvKipcbiAgICogUnVucyBleGVjdXRlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx7b2ZmZW5jZXM6IEFycmF5PHtpZ25vcmVLZXk6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nfT59Pn0gLSBSZXNvbHZlcyB3aXRoIHRoZSBmb3VuZCBvZmZlbmNlcyAoZW1wdHkgd2hlbiB0aGUgbGludCBwYXNzZXMpLlxuICAgKi9cbiAgYXN5bmMgZXhlY3V0ZSgpIHtcbiAgICAvLyBSZWxhdGlvbnNoaXAgdGFyZ2V0IHJlc29sdXRpb24gKGdldFRhcmdldE1vZGVsQ2xhc3MpIGxvb2tzIG1vZGVsIGNsYXNzZXMgdXAgdGhyb3VnaCB0aGVcbiAgICAvLyBjdXJyZW50IGNvbmZpZ3VyYXRpb24sIHNvIG1ha2UgdGhpcyBjb21tYW5kJ3MgY29uZmlndXJhdGlvbiB0aGUgY3VycmVudCBvbmUuXG4gICAgdGhpcy5nZXRDb25maWd1cmF0aW9uKCkuc2V0Q3VycmVudCgpXG5cbiAgICBhd2FpdCB0aGlzLmdldENvbmZpZ3VyYXRpb24oKS5pbml0aWFsaXplTW9kZWxzKClcblxuICAgIGNvbnN0IGlnbm9yZWRSZWxhdGlvbnNoaXBzID0gYXdhaXQgdGhpcy5fbG9hZElnbm9yZWRSZWxhdGlvbnNoaXBzKClcbiAgICBjb25zdCBvZmZlbmNlcyA9IFtdXG4gICAgY29uc3QgbW9kZWxDbGFzc2VzID0gT2JqZWN0LnZhbHVlcyh0aGlzLmdldENvbmZpZ3VyYXRpb24oKS5nZXRNb2RlbENsYXNzZXMoKSlcblxuICAgIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBtb2RlbENsYXNzZXMpIHtcbiAgICAgIGZvciAoY29uc3QgcmVsYXRpb25zaGlwIG9mIG1vZGVsQ2xhc3MuZ2V0UmVsYXRpb25zaGlwcygpKSB7XG4gICAgICAgIGlmIChyZWxhdGlvbnNoaXAuZ2V0VHlwZSgpICE9IFwiYmVsb25nc1RvXCIpIGNvbnRpbnVlXG4gICAgICAgIGlmIChyZWxhdGlvbnNoaXAuZ2V0UG9seW1vcnBoaWMoKSkgY29udGludWVcblxuICAgICAgICBjb25zdCBpZ25vcmVLZXkgPSBgJHttb2RlbENsYXNzLm5hbWV9IyR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX1gXG5cbiAgICAgICAgaWYgKGlnbm9yZWRSZWxhdGlvbnNoaXBzLmhhcyhpZ25vcmVLZXkpKSBjb250aW51ZVxuXG4gICAgICAgIGxldCB0YXJnZXRNb2RlbENsYXNzXG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0YXJnZXRNb2RlbENsYXNzID0gcmVsYXRpb25zaGlwLmdldFRhcmdldE1vZGVsQ2xhc3MoKVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIG9mZmVuY2VzLnB1c2goe1xuICAgICAgICAgICAgaWdub3JlS2V5LFxuICAgICAgICAgICAgbWVzc2FnZTogYCR7aWdub3JlS2V5fTogY291bGRuJ3QgcmVzb2x2ZSB0aGUgdGFyZ2V0IG1vZGVsIGNsYXNzOiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogZXJyb3J9YFxuICAgICAgICAgIH0pXG5cbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0YXJnZXRNb2RlbENsYXNzKSB7XG4gICAgICAgICAgb2ZmZW5jZXMucHVzaCh7aWdub3JlS2V5LCBtZXNzYWdlOiBgJHtpZ25vcmVLZXl9OiBjb3VsZG4ndCByZXNvbHZlIHRoZSB0YXJnZXQgbW9kZWwgY2xhc3NgfSlcblxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpbnZlcnNlUmVsYXRpb25zaGlwID0gdGFyZ2V0TW9kZWxDbGFzcy5nZXRSZWxhdGlvbnNoaXBzKCkuZmluZCgoY2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgaWYgKGNhbmRpZGF0ZS5nZXRUeXBlKCkgIT0gXCJoYXNNYW55XCIgJiYgY2FuZGlkYXRlLmdldFR5cGUoKSAhPSBcImhhc09uZVwiKSByZXR1cm4gZmFsc2VcbiAgICAgICAgICBpZiAoY2FuZGlkYXRlLnRocm91Z2gpIHJldHVybiBmYWxzZVxuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBjYW5kaWRhdGUuZ2V0VGFyZ2V0TW9kZWxDbGFzcygpID09PSBtb2RlbENsYXNzXG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBBIGhhcy1tYW55L2hhcy1vbmUgd2l0aCBhbiB1bnJlc29sdmFibGUgdGFyZ2V0IGNhbid0IGJlIHRoZSBpbnZlcnNlIG9mIHRoaXMgYmVsb25ncy10by5cbiAgICAgICAgICAgIC8vIEl0IGlzIHJlcG9ydGVkIHNlcGFyYXRlbHkgd2hlbiBpdHMgb3duIG1vZGVsJ3MgYmVsb25ncy10byByZWxhdGlvbnNoaXBzIGFyZSBsaW50ZWQuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG5cbiAgICAgICAgaWYgKGludmVyc2VSZWxhdGlvbnNoaXApIGNvbnRpbnVlXG5cbiAgICAgICAgb2ZmZW5jZXMucHVzaCh7XG4gICAgICAgICAgaWdub3JlS2V5LFxuICAgICAgICAgIG1lc3NhZ2U6IGAke3RhcmdldE1vZGVsQ2xhc3MubmFtZX0gaXMgbWlzc2luZyBhbiBpbnZlcnNlIGhhc01hbnkvaGFzT25lIHJlbGF0aW9uc2hpcCBmb3IgJHtpZ25vcmVLZXl9IChiZWxvbmdzVG8pLiBgICtcbiAgICAgICAgICAgIGBEZWNsYXJlIHRoZSBpbnZlcnNlIG9uICR7dGFyZ2V0TW9kZWxDbGFzcy5uYW1lfSBvciBhZGQgXCIke2lnbm9yZUtleX1cIiB0byB0aGUgaWdub3JlIGNvbmZpZy5gXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBvZmZlbmNlIG9mIG9mZmVuY2VzKSB7XG4gICAgICBjb25zb2xlLmVycm9yKG9mZmVuY2UubWVzc2FnZSlcbiAgICB9XG5cbiAgICBpZiAob2ZmZW5jZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWxhdGlvbnNoaXAgbGludCBmYWlsZWQgd2l0aCAke29mZmVuY2VzLmxlbmd0aH0gb2ZmZW5jZShzKTpcXG4ke29mZmVuY2VzLm1hcCgob2ZmZW5jZSkgPT4gb2ZmZW5jZS5tZXNzYWdlKS5qb2luKFwiXFxuXCIpfWApXG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coYFJlbGF0aW9uc2hpcCBsaW50IHBhc3NlZCBmb3IgJHttb2RlbENsYXNzZXMubGVuZ3RofSBtb2RlbChzKS5gKVxuXG4gICAgcmV0dXJuIHtvZmZlbmNlc31cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgaWdub3JlZCByZWxhdGlvbnNoaXAga2V5cyBmcm9tIHRoZSBsaW50IGNvbmZpZyBmaWxlLiBUaGUgZmlsZSBpcyBvcHRpb25hbDsgd2hlbiB0aGVcbiAgICogZGVmYXVsdCBwYXRoIGRvZXNuJ3QgZXhpc3QsIG5vIHJlbGF0aW9uc2hpcHMgYXJlIGlnbm9yZWQuIEFuIGV4cGxpY2l0bHkgcGFzc2VkIGAtLWNvbmZpZ2AgcGF0aFxuICAgKiBtdXN0IGV4aXN0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTZXQ8c3RyaW5nPj59IC0gSWdub3JlZCBgPG1vZGVsPiM8cmVsYXRpb25zaGlwPmAga2V5cy5cbiAgICovXG4gIGFzeW5jIF9sb2FkSWdub3JlZFJlbGF0aW9uc2hpcHMoKSB7XG4gICAgY29uc3QgY29uZmlnQXJnSW5kZXggPSB0aGlzLnByb2Nlc3NBcmdzPy5pbmRleE9mKFwiLS1jb25maWdcIikgPz8gLTFcbiAgICBjb25zdCBleHBsaWNpdENvbmZpZ1BhdGggPSBjb25maWdBcmdJbmRleCA+PSAwID8gdGhpcy5wcm9jZXNzQXJncz8uW2NvbmZpZ0FyZ0luZGV4ICsgMV0gOiB1bmRlZmluZWRcblxuICAgIGlmIChjb25maWdBcmdJbmRleCA+PSAwICYmICFleHBsaWNpdENvbmZpZ1BhdGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIi0tY29uZmlnIHdhcyBnaXZlbiB3aXRob3V0IGEgcGF0aCBhcmd1bWVudFwiKVxuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpZ1BhdGggPSBleHBsaWNpdENvbmZpZ1BhdGhcbiAgICAgID8gcGF0aC5yZXNvbHZlKHRoaXMuZGlyZWN0b3J5KCksIGV4cGxpY2l0Q29uZmlnUGF0aClcbiAgICAgIDogcGF0aC5qb2luKHRoaXMuZGlyZWN0b3J5KCksIFwicmVsYXRpb25zaGlwLWxpbnQuanNvblwiKVxuXG4gICAgbGV0IGNvbmZpZ0NvbnRlbnRcblxuICAgIHRyeSB7XG4gICAgICBjb25maWdDb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoY29uZmlnUGF0aCwgXCJ1dGY4XCIpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICghZXhwbGljaXRDb25maWdQYXRoICYmIC8qKiBAdHlwZSB7Tm9kZUpTLkVycm5vRXhjZXB0aW9ufSAqLyAoZXJyb3IpLmNvZGUgPT0gXCJFTk9FTlRcIikge1xuICAgICAgICByZXR1cm4gbmV3IFNldCgpXG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycm9yXG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlnID0gSlNPTi5wYXJzZShjb25maWdDb250ZW50KVxuXG4gICAgaWYgKGNvbmZpZyA9PT0gbnVsbCB8fCB0eXBlb2YgY29uZmlnICE9IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShjb25maWcpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlbGF0aW9uc2hpcCBsaW50IGNvbmZpZyBtdXN0IGJlIGEgSlNPTiBvYmplY3Q6ICR7Y29uZmlnUGF0aH1gKVxuICAgIH1cblxuICAgIGNvbnN0IGlnbm9yZSA9IGNvbmZpZy5pZ25vcmUgPz8gW11cblxuICAgIGlmICghQXJyYXkuaXNBcnJheShpZ25vcmUpIHx8IGlnbm9yZS5zb21lKChlbnRyeSkgPT4gdHlwZW9mIGVudHJ5ICE9IFwic3RyaW5nXCIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlbGF0aW9uc2hpcCBsaW50IGNvbmZpZyBcImlnbm9yZVwiIG11c3QgYmUgYW4gYXJyYXkgb2YgXCI8bW9kZWw+IzxyZWxhdGlvbnNoaXA+XCIgc3RyaW5nczogJHtjb25maWdQYXRofWApXG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBTZXQoaWdub3JlKVxuICB9XG59XG4iXX0=
|
|
203
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpb25zaGlwcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9lbnZpcm9ubWVudC1oYW5kbGVycy9ub2RlL2NsaS9jb21tYW5kcy9saW50L3JlbGF0aW9uc2hpcHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sV0FBVyxNQUFNLG9DQUFvQyxDQUFBO0FBQzVELE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ2pDLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUM1QixPQUFPLGNBQWMsTUFBTSxpQkFBaUIsQ0FBQTtBQUU1Qzs7O0dBR0c7QUFFSDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLHFDQUFzQyxTQUFRLFdBQVc7SUFDNUU7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLE9BQU87UUFDWCwwRkFBMEY7UUFDMUYsK0VBQStFO1FBQy9FLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFBO1FBRXBDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxFQUFFLENBQUM7WUFDNUMsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1FBQ2xELENBQUM7UUFFRCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUE7UUFDbkUsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFBO1FBQ25CLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQTtRQUU3RSxLQUFLLE1BQU0sVUFBVSxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ3RDLEtBQUssTUFBTSxZQUFZLElBQUksVUFBVSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQztnQkFDekQsSUFB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QUVELE1BQU0sS0FBSyxDQUFBO1FBQ2IsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUE7UUFFeEMsSUFBSSxNQUFNLEtBQUssSUFBSSxJQUFJLE9BQU8sTUFBTSxJQUFJLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDMUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUNsRixDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUE7UUFFbEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsT0FBTyxLQUFLLElBQUksUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUMvRSxNQUFNLElBQUksS0FBSyxDQUFDLDJGQUEyRixVQUFVLEVBQUUsQ0FBQyxDQUFBO1FBQzFILENBQUM7UUFFRCxPQUFPLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3hCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQmFzZUNvbW1hbmQgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2NsaS9iYXNlLWNvbW1hbmQuanNcIlxuaW1wb3J0IGZzIGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCJcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHJlcXVpcmVDb250ZXh0IGZyb20gXCJyZXF1aXJlLWNvbnRleHRcIlxuXG4vKipcbiAqIEB0eXBlZGVmIHsoaWQ6IHN0cmluZykgPT4ge2RlZmF1bHQ6IHR5cGVvZiBpbXBvcnQoXCIuLi8uLi8uLi8uLi8uLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH19IE1vZGVsRmlsZVJlcXVpcmVDb250ZXh0SWRGdW5jdGlvblR5cGVcbiAqIEB0eXBlZGVmIHtNb2RlbEZpbGVSZXF1aXJlQ29udGV4dElkRnVuY3Rpb25UeXBlICYge2tleXM6ICgpID0+IHN0cmluZ1tdfX0gTW9kZWxGaWxlUmVxdWlyZUNvbnRleHRUeXBlXG4gKi9cblxuLyoqXG4gKiBMaW50cyBtb2RlbCByZWxhdGlvbnNoaXBzOiBldmVyeSBub24tcG9seW1vcnBoaWMgYmVsb25ncy10byByZWxhdGlvbnNoaXAgc2hvdWxkIGhhdmUgYW4gaW52ZXJzZVxuICogaGFzLW1hbnkgb3IgaGFzLW9uZSByZWxhdGlvbnNoaXAgZGVjbGFyZWQgb24gaXRzIHRhcmdldCBtb2RlbCBjbGFzcy4gQSBtaXNzaW5nIGludmVyc2UgdXN1YWxseVxuICogbWVhbnMgdGhlIHRhcmdldCBtb2RlbCB3YXMgbmV2ZXIgdG9sZCBhYm91dCB0aGUgYXNzb2NpYXRpb24gKGUuZy4gYW4gRXZlbnQgbW9kZWwgbWlzc2luZ1xuICogYGhhc01hbnkoXCJwcmljZUNhdGVnb3J5U2V0dGluZ3NcIilgIHdoaWxlIFByaWNlQ2F0ZWdvcnlTZXR0aW5nIGRlY2xhcmVzIGBiZWxvbmdzVG8oXCJldmVudFwiKWApLlxuICpcbiAqIFNwZWNpZmljIHJlbGF0aW9uc2hpcHMgY2FuIGJlIGlnbm9yZWQgdGhyb3VnaCBhIEpTT04gY29uZmlnIGZpbGUgKGRlZmF1bHQ6XG4gKiBgcmVsYXRpb25zaGlwLWxpbnQuanNvbmAgaW4gdGhlIHByb2plY3QgZGlyZWN0b3J5LCBvdmVycmlkYWJsZSB3aXRoIGAtLWNvbmZpZyA8cGF0aD5gKTpcbiAqXG4gKiAgIHtcImlnbm9yZVwiOiBbXCJQcmljZUNhdGVnb3J5U2V0dGluZyNldmVudFwiXX1cbiAqXG4gKiB3aGVyZSBlYWNoIGVudHJ5IGlzIGA8bW9kZWwgY2xhc3MgbmFtZT4jPGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwIG5hbWU+YC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmVsb2Npb3VzQ2xpQ29tbWFuZHNMaW50UmVsYXRpb25zaGlwcyBleHRlbmRzIEJhc2VDb21tYW5kIHtcbiAgLyoqXG4gICAqIFJ1bnMgZXhlY3V0ZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8e29mZmVuY2VzOiBBcnJheTx7aWdub3JlS2V5OiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZ30+fT59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgZm91bmQgb2ZmZW5jZXMgKGVtcHR5IHdoZW4gdGhlIGxpbnQgcGFzc2VzKS5cbiAgICovXG4gIGFzeW5jIGV4ZWN1dGUoKSB7XG4gICAgLy8gUmVsYXRpb25zaGlwIHRhcmdldCByZXNvbHV0aW9uIChnZXRUYXJnZXRNb2RlbENsYXNzKSBsb29rcyBtb2RlbCBjbGFzc2VzIHVwIHRocm91Z2ggdGhlXG4gICAgLy8gY3VycmVudCBjb25maWd1cmF0aW9uLCBzbyBtYWtlIHRoaXMgY29tbWFuZCdzIGNvbmZpZ3VyYXRpb24gdGhlIGN1cnJlbnQgb25lLlxuICAgIHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLnNldEN1cnJlbnQoKVxuXG4gICAgaWYgKCFhd2FpdCB0aGlzLl9yZWdpc3RlclN0YXRpY01vZGVsRmlsZXMoKSkge1xuICAgICAgYXdhaXQgdGhpcy5nZXRDb25maWd1cmF0aW9uKCkuaW5pdGlhbGl6ZU1vZGVscygpXG4gICAgfVxuXG4gICAgY29uc3QgaWdub3JlZFJlbGF0aW9uc2hpcHMgPSBhd2FpdCB0aGlzLl9sb2FkSWdub3JlZFJlbGF0aW9uc2hpcHMoKVxuICAgIGNvbnN0IG9mZmVuY2VzID0gW11cbiAgICBjb25zdCBtb2RlbENsYXNzZXMgPSBPYmplY3QudmFsdWVzKHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmdldE1vZGVsQ2xhc3NlcygpKVxuXG4gICAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIG1vZGVsQ2xhc3Nlcykge1xuICAgICAgZm9yIChjb25zdCByZWxhdGlvbnNoaXAgb2YgbW9kZWxDbGFzcy5nZXRSZWxhdGlvbnNoaXBzKCkpIHtcbiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5nZXRUeXBlKCkgIT0gXCJiZWxvbmdzVG9cIikgY29udGludWVcbiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5nZXRQb2x5bW9ycGhpYygpKSBjb250aW51ZVxuXG4gICAgICAgIGNvbnN0IGlnbm9yZUtleSA9IGAke21vZGVsQ2xhc3MubmFtZX0jJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfWBcblxuICAgICAgICBpZiAoaWdub3JlZFJlbGF0aW9uc2hpcHMuaGFzKGlnbm9yZUtleSkpIGNvbnRpbnVlXG5cbiAgICAgICAgbGV0IHRhcmdldE1vZGVsQ2xhc3NcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIHRhcmdldE1vZGVsQ2xhc3MgPSByZWxhdGlvbnNoaXAuZ2V0VGFyZ2V0TW9kZWxDbGFzcygpXG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgb2ZmZW5jZXMucHVzaCh7XG4gICAgICAgICAgICBpZ25vcmVLZXksXG4gICAgICAgICAgICBtZXNzYWdlOiBgJHtpZ25vcmVLZXl9OiBjb3VsZG4ndCByZXNvbHZlIHRoZSB0YXJnZXQgbW9kZWwgY2xhc3M6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBlcnJvcn1gXG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRhcmdldE1vZGVsQ2xhc3MpIHtcbiAgICAgICAgICBvZmZlbmNlcy5wdXNoKHtpZ25vcmVLZXksIG1lc3NhZ2U6IGAke2lnbm9yZUtleX06IGNvdWxkbid0IHJlc29sdmUgdGhlIHRhcmdldCBtb2RlbCBjbGFzc2B9KVxuXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGludmVyc2VSZWxhdGlvbnNoaXAgPSB0YXJnZXRNb2RlbENsYXNzLmdldFJlbGF0aW9uc2hpcHMoKS5maW5kKChjYW5kaWRhdGUpID0+IHtcbiAgICAgICAgICBpZiAoY2FuZGlkYXRlLmdldFR5cGUoKSAhPSBcImhhc01hbnlcIiAmJiBjYW5kaWRhdGUuZ2V0VHlwZSgpICE9IFwiaGFzT25lXCIpIHJldHVybiBmYWxzZVxuICAgICAgICAgIGlmIChjYW5kaWRhdGUudGhyb3VnaCkgcmV0dXJuIGZhbHNlXG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlVGFyZ2V0TW9kZWxDbGFzcyA9IGNhbmRpZGF0ZS5nZXRUYXJnZXRNb2RlbENsYXNzKClcblxuICAgICAgICAgICAgaWYgKCFjYW5kaWRhdGVUYXJnZXRNb2RlbENsYXNzKSByZXR1cm4gZmFsc2VcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vZGVsQ2xhc3Nlc01hdGNoKGNhbmRpZGF0ZVRhcmdldE1vZGVsQ2xhc3MsIG1vZGVsQ2xhc3MpXG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBBIGhhcy1tYW55L2hhcy1vbmUgd2l0aCBhbiB1bnJlc29sdmFibGUgdGFyZ2V0IGNhbid0IGJlIHRoZSBpbnZlcnNlIG9mIHRoaXMgYmVsb25ncy10by5cbiAgICAgICAgICAgIC8vIEl0IGlzIHJlcG9ydGVkIHNlcGFyYXRlbHkgd2hlbiBpdHMgb3duIG1vZGVsJ3MgYmVsb25ncy10byByZWxhdGlvbnNoaXBzIGFyZSBsaW50ZWQuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG5cbiAgICAgICAgaWYgKGludmVyc2VSZWxhdGlvbnNoaXApIGNvbnRpbnVlXG5cbiAgICAgICAgb2ZmZW5jZXMucHVzaCh7XG4gICAgICAgICAgaWdub3JlS2V5LFxuICAgICAgICAgIG1lc3NhZ2U6IGAke3RhcmdldE1vZGVsQ2xhc3MubmFtZX0gaXMgbWlzc2luZyBhbiBpbnZlcnNlIGhhc01hbnkvaGFzT25lIHJlbGF0aW9uc2hpcCBmb3IgJHtpZ25vcmVLZXl9IChiZWxvbmdzVG8pLiBgICtcbiAgICAgICAgICAgIGBEZWNsYXJlIHRoZSBpbnZlcnNlIG9uICR7dGFyZ2V0TW9kZWxDbGFzcy5uYW1lfSBvciBhZGQgXCIke2lnbm9yZUtleX1cIiB0byB0aGUgaWdub3JlIGNvbmZpZy5gXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBvZmZlbmNlIG9mIG9mZmVuY2VzKSB7XG4gICAgICBjb25zb2xlLmVycm9yKG9mZmVuY2UubWVzc2FnZSlcbiAgICB9XG5cbiAgICBpZiAob2ZmZW5jZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWxhdGlvbnNoaXAgbGludCBmYWlsZWQgd2l0aCAke29mZmVuY2VzLmxlbmd0aH0gb2ZmZW5jZShzKTpcXG4ke29mZmVuY2VzLm1hcCgob2ZmZW5jZSkgPT4gb2ZmZW5jZS5tZXNzYWdlKS5qb2luKFwiXFxuXCIpfWApXG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coYFJlbGF0aW9uc2hpcCBsaW50IHBhc3NlZCBmb3IgJHttb2RlbENsYXNzZXMubGVuZ3RofSBtb2RlbChzKS5gKVxuXG4gICAgcmV0dXJuIHtvZmZlbmNlc31cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgbW9kZWwgY2xhc3NlcyBmcm9tIHRoZSBjb252ZW50aW9uYWwgc3JjL21vZGVscyBkaXJlY3Rvcnkgd2l0aG91dFxuICAgKiBydW5uaW5nIHRoZSBhcHBsaWNhdGlvbidzIGZ1bGwgZGF0YWJhc2Uvc2VydmVyIGluaXRpYWxpemF0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gV2hldGhlciBzdGF0aWMgbW9kZWwgZmlsZXMgd2VyZSByZWdpc3RlcmVkLlxuICAgKi9cbiAgYXN5bmMgX3JlZ2lzdGVyU3RhdGljTW9kZWxGaWxlcygpIHtcbiAgICBpZiAodGhpcy5hcmdzLnRlc3RpbmcpIHJldHVybiBmYWxzZVxuXG4gICAgY29uc3QgbW9kZWxzRGlyZWN0b3J5ID0gcGF0aC5qb2luKHRoaXMuZGlyZWN0b3J5KCksIFwic3JjL21vZGVsc1wiKVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgZnMuc3RhdChtb2RlbHNEaXJlY3RvcnkpXG5cbiAgICAgIGlmICghc3RhdHMuaXNEaXJlY3RvcnkoKSkgcmV0dXJuIGZhbHNlXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICgvKiogQHR5cGUge05vZGVKUy5FcnJub0V4Y2VwdGlvbn0gKi8gKGVycm9yKS5jb2RlID09IFwiRU5PRU5UXCIpIHJldHVybiBmYWxzZVxuXG4gICAgICB0aHJvdyBlcnJvclxuICAgIH1cblxuICAgIGlmICgoYXdhaXQgdGhpcy5famF2YXNjcmlwdEZpbGVzSW5EaXJlY3RvcnkobW9kZWxzRGlyZWN0b3J5KSkubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2VcblxuICAgIC8qKiBAdHlwZSB7TW9kZWxGaWxlUmVxdWlyZUNvbnRleHRUeXBlfSAqL1xuICAgIGNvbnN0IHJlcXVpcmVDb250ZXh0TW9kZWxzID0gcmVxdWlyZUNvbnRleHQobW9kZWxzRGlyZWN0b3J5LCB0cnVlLCAvXiguKylcXC5qcyQvKVxuXG4gICAgY29uc3QgbW9kZWxGaWxlTmFtZXMgPSByZXF1aXJlQ29udGV4dE1vZGVscy5rZXlzKClcbiAgICBmb3IgKGNvbnN0IGZpbGVOYW1lIG9mIG1vZGVsRmlsZU5hbWVzKSB7XG4gICAgICBjb25zdCBtb2RlbENsYXNzSW1wb3J0ID0gcmVxdWlyZUNvbnRleHRNb2RlbHMoZmlsZU5hbWUpXG4gICAgICBjb25zdCBtb2RlbENsYXNzID0gbW9kZWxDbGFzc0ltcG9ydC5kZWZhdWx0XG5cbiAgICAgIGlmICghbW9kZWxDbGFzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1vZGVsIHdhc24ndCBleHBvcnRlZCBmcm9tOiAke2ZpbGVOYW1lfWApXG4gICAgICB9XG5cbiAgICAgIG1vZGVsQ2xhc3MucmVnaXN0ZXJSZWNvcmRDbGFzcyh7Y29uZmlndXJhdGlvbjogdGhpcy5nZXRDb25maWd1cmF0aW9uKCl9KVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICAvKipcbiAgICogRmluZHMgSmF2YVNjcmlwdCBmaWxlcyBiZWxvdyBhIGRpcmVjdG9yeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGRpcmVjdG9yeSAtIERpcmVjdG9yeSB0byBzY2FuLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXT59IEphdmFTY3JpcHQgZmlsZSBwYXRocy5cbiAgICovXG4gIGFzeW5jIF9qYXZhc2NyaXB0RmlsZXNJbkRpcmVjdG9yeShkaXJlY3RvcnkpIHtcbiAgICBjb25zdCBmaWxlUGF0aHMgPSBbXVxuICAgIGNvbnN0IGVudHJpZXMgPSBhd2FpdCBmcy5yZWFkZGlyKGRpcmVjdG9yeSwge3dpdGhGaWxlVHlwZXM6IHRydWV9KVxuXG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICBjb25zdCBlbnRyeVBhdGggPSBwYXRoLmpvaW4oZGlyZWN0b3J5LCBlbnRyeS5uYW1lKVxuXG4gICAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBmaWxlUGF0aHMucHVzaCguLi5hd2FpdCB0aGlzLl9qYXZhc2NyaXB0RmlsZXNJbkRpcmVjdG9yeShlbnRyeVBhdGgpKVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBpZiAoZW50cnkuaXNGaWxlKCkgJiYgZW50cnkubmFtZS5lbmRzV2l0aChcIi5qc1wiKSkge1xuICAgICAgICBmaWxlUGF0aHMucHVzaChlbnRyeVBhdGgpXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbGVQYXRoc1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB3aGV0aGVyIHR3byBtb2RlbCBjbGFzcyBvYmplY3RzIGRlc2NyaWJlIHRoZSBzYW1lIHJlZ2lzdGVyZWQgbW9kZWwuXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBsZWZ0TW9kZWxDbGFzcyAtIENhbmRpZGF0ZSB0YXJnZXQgbW9kZWwgY2xhc3MuXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSByaWdodE1vZGVsQ2xhc3MgLSBCZWxvbmdzLXRvIHNvdXJjZSBtb2RlbCBjbGFzcy5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgYm90aCBtb2RlbCBjbGFzc2VzIHJlcHJlc2VudCB0aGUgc2FtZSBtb2RlbCBpZGVudGl0eS5cbiAgICovXG4gIF9tb2RlbENsYXNzZXNNYXRjaChsZWZ0TW9kZWxDbGFzcywgcmlnaHRNb2RlbENsYXNzKSB7XG4gICAgaWYgKGxlZnRNb2RlbENsYXNzID09PSByaWdodE1vZGVsQ2xhc3MpIHJldHVybiB0cnVlXG4gICAgLy8gYHRyYW5zbGF0ZXMoKWAgY3JlYXRlcyBhbiBpbnRlcm5hbCB0cmFuc2xhdGlvbiBjbGFzczsgYXBwcyBtYXkgYWxzbyBkZWZpbmVcbiAgICAvLyBhIGNvbmNyZXRlIGNsYXNzIGZvciB0aGUgc2FtZSBtb2RlbC90YWJsZSBzbyBnZW5lcmF0ZWQgY29kZSBoYXMgYSBzdGFibGVcbiAgICAvLyBmaWxlIGFuZCB0eXBlIG5hbWUuXG4gICAgaWYgKGxlZnRNb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpICE9IHJpZ2h0TW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKSkgcmV0dXJuIGZhbHNlXG5cbiAgICByZXR1cm4gbGVmdE1vZGVsQ2xhc3MudGFibGVOYW1lKCkgPT0gcmlnaHRNb2RlbENsYXNzLnRhYmxlTmFtZSgpXG4gIH1cblxuICAvKipcbiAgICogTG9hZHMgdGhlIGlnbm9yZWQgcmVsYXRpb25zaGlwIGtleXMgZnJvbSB0aGUgbGludCBjb25maWcgZmlsZS4gVGhlIGZpbGUgaXMgb3B0aW9uYWw7IHdoZW4gdGhlXG4gICAqIGRlZmF1bHQgcGF0aCBkb2Vzbid0IGV4aXN0LCBubyByZWxhdGlvbnNoaXBzIGFyZSBpZ25vcmVkLiBBbiBleHBsaWNpdGx5IHBhc3NlZCBgLS1jb25maWdgIHBhdGhcbiAgICogbXVzdCBleGlzdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U2V0PHN0cmluZz4+fSAtIElnbm9yZWQgYDxtb2RlbD4jPHJlbGF0aW9uc2hpcD5gIGtleXMuXG4gICAqL1xuICBhc3luYyBfbG9hZElnbm9yZWRSZWxhdGlvbnNoaXBzKCkge1xuICAgIGNvbnN0IGNvbmZpZ0FyZ0luZGV4ID0gdGhpcy5wcm9jZXNzQXJncz8uaW5kZXhPZihcIi0tY29uZmlnXCIpID8/IC0xXG4gICAgY29uc3QgZXhwbGljaXRDb25maWdQYXRoID0gY29uZmlnQXJnSW5kZXggPj0gMCA/IHRoaXMucHJvY2Vzc0FyZ3M/Lltjb25maWdBcmdJbmRleCArIDFdIDogdW5kZWZpbmVkXG5cbiAgICBpZiAoY29uZmlnQXJnSW5kZXggPj0gMCAmJiAhZXhwbGljaXRDb25maWdQYXRoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCItLWNvbmZpZyB3YXMgZ2l2ZW4gd2l0aG91dCBhIHBhdGggYXJndW1lbnRcIilcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWdQYXRoID0gZXhwbGljaXRDb25maWdQYXRoXG4gICAgICA/IHBhdGgucmVzb2x2ZSh0aGlzLmRpcmVjdG9yeSgpLCBleHBsaWNpdENvbmZpZ1BhdGgpXG4gICAgICA6IHBhdGguam9pbih0aGlzLmRpcmVjdG9yeSgpLCBcInJlbGF0aW9uc2hpcC1saW50Lmpzb25cIilcblxuICAgIGxldCBjb25maWdDb250ZW50XG5cbiAgICB0cnkge1xuICAgICAgY29uZmlnQ29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGNvbmZpZ1BhdGgsIFwidXRmOFwiKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoIWV4cGxpY2l0Q29uZmlnUGF0aCAmJiAvKiogQHR5cGUge05vZGVKUy5FcnJub0V4Y2VwdGlvbn0gKi8gKGVycm9yKS5jb2RlID09IFwiRU5PRU5UXCIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTZXQoKVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnJvclxuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpZyA9IEpTT04ucGFyc2UoY29uZmlnQ29udGVudClcblxuICAgIGlmIChjb25maWcgPT09IG51bGwgfHwgdHlwZW9mIGNvbmZpZyAhPSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoY29uZmlnKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWxhdGlvbnNoaXAgbGludCBjb25maWcgbXVzdCBiZSBhIEpTT04gb2JqZWN0OiAke2NvbmZpZ1BhdGh9YClcbiAgICB9XG5cbiAgICBjb25zdCBpZ25vcmUgPSBjb25maWcuaWdub3JlID8/IFtdXG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoaWdub3JlKSB8fCBpZ25vcmUuc29tZSgoZW50cnkpID0+IHR5cGVvZiBlbnRyeSAhPSBcInN0cmluZ1wiKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWxhdGlvbnNoaXAgbGludCBjb25maWcgXCJpZ25vcmVcIiBtdXN0IGJlIGFuIGFycmF5IG9mIFwiPG1vZGVsPiM8cmVsYXRpb25zaGlwPlwiIHN0cmluZ3M6ICR7Y29uZmlnUGF0aH1gKVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgU2V0KGlnbm9yZSlcbiAgfVxufVxuIl19
|
package/package.json
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
import BaseCommand from "../../../../../cli/base-command.js"
|
|
4
4
|
import fs from "node:fs/promises"
|
|
5
5
|
import path from "node:path"
|
|
6
|
+
import requireContext from "require-context"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {(id: string) => {default: typeof import("../../../../../database/record/index.js").default}} ModelFileRequireContextIdFunctionType
|
|
10
|
+
* @typedef {ModelFileRequireContextIdFunctionType & {keys: () => string[]}} ModelFileRequireContextType
|
|
11
|
+
*/
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* Lints model relationships: every non-polymorphic belongs-to relationship should have an inverse
|
|
@@ -27,7 +33,9 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
27
33
|
// current configuration, so make this command's configuration the current one.
|
|
28
34
|
this.getConfiguration().setCurrent()
|
|
29
35
|
|
|
30
|
-
await this.
|
|
36
|
+
if (!await this._registerStaticModelFiles()) {
|
|
37
|
+
await this.getConfiguration().initializeModels()
|
|
38
|
+
}
|
|
31
39
|
|
|
32
40
|
const ignoredRelationships = await this._loadIgnoredRelationships()
|
|
33
41
|
const offences = []
|
|
@@ -66,7 +74,11 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
66
74
|
if (candidate.through) return false
|
|
67
75
|
|
|
68
76
|
try {
|
|
69
|
-
|
|
77
|
+
const candidateTargetModelClass = candidate.getTargetModelClass()
|
|
78
|
+
|
|
79
|
+
if (!candidateTargetModelClass) return false
|
|
80
|
+
|
|
81
|
+
return this._modelClassesMatch(candidateTargetModelClass, modelClass)
|
|
70
82
|
} catch {
|
|
71
83
|
// A has-many/has-one with an unresolvable target can't be the inverse of this belongs-to.
|
|
72
84
|
// It is reported separately when its own model's belongs-to relationships are linted.
|
|
@@ -97,6 +109,87 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
|
|
|
97
109
|
return {offences}
|
|
98
110
|
}
|
|
99
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Registers model classes from the conventional src/models directory without
|
|
114
|
+
* running the application's full database/server initialization.
|
|
115
|
+
* @returns {Promise<boolean>} Whether static model files were registered.
|
|
116
|
+
*/
|
|
117
|
+
async _registerStaticModelFiles() {
|
|
118
|
+
if (this.args.testing) return false
|
|
119
|
+
|
|
120
|
+
const modelsDirectory = path.join(this.directory(), "src/models")
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const stats = await fs.stat(modelsDirectory)
|
|
124
|
+
|
|
125
|
+
if (!stats.isDirectory()) return false
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code == "ENOENT") return false
|
|
128
|
+
|
|
129
|
+
throw error
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if ((await this._javascriptFilesInDirectory(modelsDirectory)).length === 0) return false
|
|
133
|
+
|
|
134
|
+
/** @type {ModelFileRequireContextType} */
|
|
135
|
+
const requireContextModels = requireContext(modelsDirectory, true, /^(.+)\.js$/)
|
|
136
|
+
|
|
137
|
+
const modelFileNames = requireContextModels.keys()
|
|
138
|
+
for (const fileName of modelFileNames) {
|
|
139
|
+
const modelClassImport = requireContextModels(fileName)
|
|
140
|
+
const modelClass = modelClassImport.default
|
|
141
|
+
|
|
142
|
+
if (!modelClass) {
|
|
143
|
+
throw new Error(`Model wasn't exported from: ${fileName}`)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
modelClass.registerRecordClass({configuration: this.getConfiguration()})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Finds JavaScript files below a directory.
|
|
154
|
+
* @param {string} directory - Directory to scan.
|
|
155
|
+
* @returns {Promise<string[]>} JavaScript file paths.
|
|
156
|
+
*/
|
|
157
|
+
async _javascriptFilesInDirectory(directory) {
|
|
158
|
+
const filePaths = []
|
|
159
|
+
const entries = await fs.readdir(directory, {withFileTypes: true})
|
|
160
|
+
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
const entryPath = path.join(directory, entry.name)
|
|
163
|
+
|
|
164
|
+
if (entry.isDirectory()) {
|
|
165
|
+
filePaths.push(...await this._javascriptFilesInDirectory(entryPath))
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
170
|
+
filePaths.push(entryPath)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return filePaths
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Checks whether two model class objects describe the same registered model.
|
|
179
|
+
* @param {typeof import("../../../../../database/record/index.js").default} leftModelClass - Candidate target model class.
|
|
180
|
+
* @param {typeof import("../../../../../database/record/index.js").default} rightModelClass - Belongs-to source model class.
|
|
181
|
+
* @returns {boolean} Whether both model classes represent the same model identity.
|
|
182
|
+
*/
|
|
183
|
+
_modelClassesMatch(leftModelClass, rightModelClass) {
|
|
184
|
+
if (leftModelClass === rightModelClass) return true
|
|
185
|
+
// `translates()` creates an internal translation class; apps may also define
|
|
186
|
+
// a concrete class for the same model/table so generated code has a stable
|
|
187
|
+
// file and type name.
|
|
188
|
+
if (leftModelClass.getModelName() != rightModelClass.getModelName()) return false
|
|
189
|
+
|
|
190
|
+
return leftModelClass.tableName() == rightModelClass.tableName()
|
|
191
|
+
}
|
|
192
|
+
|
|
100
193
|
/**
|
|
101
194
|
* Loads the ignored relationship keys from the lint config file. The file is optional; when the
|
|
102
195
|
* default path doesn't exist, no relationships are ignored. An explicitly passed `--config` path
|
|
@@ -55,3 +55,16 @@ declare module "is-plain-object" {
|
|
|
55
55
|
declare module "escape-string-regexp" {
|
|
56
56
|
export default function escapeStringRegexp(value: string): string
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
declare module "require-context" {
|
|
60
|
+
export interface RequireContext<TModule = {default?: unknown}> {
|
|
61
|
+
(id: string): TModule
|
|
62
|
+
keys(): string[]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default function requireContext<TModule = {default?: unknown}>(
|
|
66
|
+
directory: string,
|
|
67
|
+
useSubdirectories?: boolean,
|
|
68
|
+
regExp?: RegExp
|
|
69
|
+
): RequireContext<TModule>
|
|
70
|
+
}
|