@ditojs/server 0.273.0 → 1.0.0-rc.0
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/package.json +26 -44
- package/src/app/Application.js +121 -117
- package/src/app/Validator.js +6 -3
- package/src/app/index.js +2 -2
- package/src/cli/console.js +3 -3
- package/src/cli/db/createMigration.js +4 -4
- package/src/cli/db/index.js +7 -7
- package/src/cli/db/listAssetConfig.js +1 -1
- package/src/cli/db/migrate.js +4 -4
- package/src/cli/db/reset.js +5 -5
- package/src/cli/db/rollback.js +4 -4
- package/src/cli/db/seed.js +6 -6
- package/src/cli/db/unlock.js +2 -2
- package/src/cli/index.js +17 -8
- package/src/controllers/AdminController.js +164 -158
- package/src/controllers/CollectionController.js +8 -29
- package/src/controllers/Controller.js +78 -83
- package/src/controllers/ControllerAction.js +37 -18
- package/src/controllers/MemberAction.js +2 -2
- package/src/controllers/ModelController.js +4 -4
- package/src/controllers/RelationController.js +5 -5
- package/src/controllers/{UserController.js → UsersController.js} +8 -13
- package/src/controllers/index.js +5 -5
- package/src/decorators/action.js +3 -3
- package/src/decorators/authorize.js +1 -1
- package/src/decorators/index.js +6 -6
- package/src/decorators/parameters.js +1 -1
- package/src/decorators/returns.js +1 -1
- package/src/decorators/scope.js +1 -1
- package/src/decorators/transacted.js +1 -1
- package/src/errors/AssetError.js +1 -1
- package/src/errors/AuthenticationError.js +1 -1
- package/src/errors/AuthorizationError.js +1 -1
- package/src/errors/ControllerError.js +1 -1
- package/src/errors/DatabaseError.js +12 -3
- package/src/errors/GraphError.js +1 -1
- package/src/errors/ModelError.js +1 -1
- package/src/errors/NotFoundError.js +1 -1
- package/src/errors/NotImplementedError.js +1 -1
- package/src/errors/QueryBuilderError.js +1 -1
- package/src/errors/RelationError.js +1 -1
- package/src/errors/ValidationError.js +1 -1
- package/src/errors/WrappedError.js +1 -1
- package/src/errors/index.js +14 -14
- package/src/graph/DitoGraphProcessor.js +2 -1
- package/src/graph/graph.js +1 -1
- package/src/graph/index.js +3 -3
- package/src/index.js +11 -9
- package/src/lib/index.js +2 -2
- package/src/middleware/createTransaction.js +1 -1
- package/src/middleware/findRoute.js +3 -2
- package/src/middleware/handleConnectMiddleware.js +88 -0
- package/src/middleware/handleError.js +1 -1
- package/src/middleware/handleRoute.js +3 -3
- package/src/middleware/index.js +8 -7
- package/src/middleware/logRequests.js +9 -9
- package/src/mixins/AssetMixin.js +1 -1
- package/src/mixins/UserMixin.js +1 -1
- package/src/mixins/index.js +4 -4
- package/src/models/AssetModel.js +2 -2
- package/src/models/Model.js +16 -12
- package/src/models/RelationAccessor.js +1 -1
- package/src/models/SessionModel.js +2 -2
- package/src/models/TimeStampedModel.js +2 -2
- package/src/models/UserModel.js +2 -2
- package/src/models/definitions/assets.js +1 -1
- package/src/models/definitions/filters.js +57 -44
- package/src/models/definitions/hooks.js +1 -1
- package/src/models/definitions/index.js +9 -9
- package/src/models/definitions/modifiers.js +1 -1
- package/src/models/definitions/options.js +1 -1
- package/src/models/definitions/properties.js +2 -2
- package/src/models/definitions/relations.js +1 -1
- package/src/models/definitions/schema.js +1 -1
- package/src/models/definitions/scopes.js +2 -2
- package/src/models/index.js +5 -5
- package/src/query/QueryBuilder.js +5 -5
- package/src/query/QueryFilters.js +50 -50
- package/src/query/QueryParameters.js +2 -2
- package/src/query/index.js +3 -3
- package/src/schema/formats/index.js +2 -2
- package/src/schema/index.js +4 -4
- package/src/schema/keywords/_relate.js +1 -1
- package/src/schema/keywords/index.js +12 -12
- package/src/schema/properties.test.js +1 -1
- package/src/schema/relations.js +1 -1
- package/src/schema/relations.test.js +2 -2
- package/src/services/index.js +1 -1
- package/src/storage/DiskStorage.js +1 -1
- package/src/storage/S3Storage.js +4 -4
- package/src/storage/Storage.js +1 -1
- package/src/storage/index.js +4 -4
- package/src/utils/function.test.js +1 -1
- package/src/utils/handler.js +17 -0
- package/src/utils/index.js +8 -7
- package/src/utils/object.test.js +1 -1
- package/lib/app/Application.js +0 -955
- package/lib/app/SessionStore.js +0 -40
- package/lib/app/Validator.js +0 -355
- package/lib/app/index.js +0 -26
- package/lib/cli/console.js +0 -175
- package/lib/cli/db/createMigration.js +0 -237
- package/lib/cli/db/index.js +0 -66
- package/lib/cli/db/listAssetConfig.js +0 -16
- package/lib/cli/db/migrate.js +0 -15
- package/lib/cli/db/reset.js +0 -27
- package/lib/cli/db/rollback.js +0 -15
- package/lib/cli/db/seed.js +0 -104
- package/lib/cli/db/unlock.js +0 -15
- package/lib/cli/index.js +0 -90
- package/lib/controllers/AdminController.js +0 -258
- package/lib/controllers/CollectionController.js +0 -263
- package/lib/controllers/Controller.js +0 -462
- package/lib/controllers/ControllerAction.js +0 -276
- package/lib/controllers/MemberAction.js +0 -22
- package/lib/controllers/ModelController.js +0 -64
- package/lib/controllers/RelationController.js +0 -82
- package/lib/controllers/UserController.js +0 -98
- package/lib/controllers/index.js +0 -50
- package/lib/decorators/action.js +0 -14
- package/lib/decorators/authorize.js +0 -13
- package/lib/decorators/index.js +0 -58
- package/lib/decorators/parameters.js +0 -35
- package/lib/decorators/returns.js +0 -26
- package/lib/decorators/scope.js +0 -14
- package/lib/decorators/transacted.js +0 -12
- package/lib/errors/AssetError.js +0 -19
- package/lib/errors/AuthenticationError.js +0 -19
- package/lib/errors/AuthorizationError.js +0 -19
- package/lib/errors/ControllerError.js +0 -24
- package/lib/errors/DatabaseError.js +0 -27
- package/lib/errors/GraphError.js +0 -19
- package/lib/errors/ModelError.js +0 -24
- package/lib/errors/NotFoundError.js +0 -19
- package/lib/errors/NotImplementedError.js +0 -19
- package/lib/errors/QueryBuilderError.js +0 -19
- package/lib/errors/RelationError.js +0 -36
- package/lib/errors/ResponseError.js +0 -46
- package/lib/errors/ValidationError.js +0 -19
- package/lib/errors/WrappedError.js +0 -24
- package/lib/errors/index.js +0 -122
- package/lib/graph/DitoGraphProcessor.js +0 -185
- package/lib/graph/expression.js +0 -76
- package/lib/graph/graph.js +0 -300
- package/lib/graph/index.js +0 -34
- package/lib/index.js +0 -82
- package/lib/lib/EventEmitter.js +0 -76
- package/lib/lib/KnexHelper.js +0 -40
- package/lib/lib/index.js +0 -26
- package/lib/middleware/attachLogger.js +0 -16
- package/lib/middleware/createTransaction.js +0 -36
- package/lib/middleware/findRoute.js +0 -35
- package/lib/middleware/handleError.js +0 -26
- package/lib/middleware/handleRoute.js +0 -29
- package/lib/middleware/handleUser.js +0 -36
- package/lib/middleware/index.js +0 -66
- package/lib/middleware/logRequests.js +0 -122
- package/lib/mixins/AssetMixin.js +0 -81
- package/lib/mixins/SessionMixin.js +0 -22
- package/lib/mixins/TimeStampedMixin.js +0 -47
- package/lib/mixins/UserMixin.js +0 -151
- package/lib/mixins/index.js +0 -42
- package/lib/models/AssetModel.js +0 -12
- package/lib/models/Model.js +0 -953
- package/lib/models/RelationAccessor.js +0 -41
- package/lib/models/SessionModel.js +0 -12
- package/lib/models/TimeStampedModel.js +0 -12
- package/lib/models/UserModel.js +0 -12
- package/lib/models/definitions/assets.js +0 -11
- package/lib/models/definitions/filters.js +0 -101
- package/lib/models/definitions/hooks.js +0 -11
- package/lib/models/definitions/index.js +0 -38
- package/lib/models/definitions/modifiers.js +0 -11
- package/lib/models/definitions/options.js +0 -11
- package/lib/models/definitions/properties.js +0 -87
- package/lib/models/definitions/relations.js +0 -11
- package/lib/models/definitions/schema.js +0 -11
- package/lib/models/definitions/scopes.js +0 -51
- package/lib/models/index.js +0 -50
- package/lib/query/QueryBuilder.js +0 -745
- package/lib/query/QueryFilters.js +0 -82
- package/lib/query/QueryParameters.js +0 -77
- package/lib/query/Registry.js +0 -40
- package/lib/query/index.js +0 -34
- package/lib/schema/formats/_empty.js +0 -10
- package/lib/schema/formats/_required.js +0 -10
- package/lib/schema/formats/index.js +0 -26
- package/lib/schema/index.js +0 -49
- package/lib/schema/keywords/_computed.js +0 -11
- package/lib/schema/keywords/_foreign.js +0 -11
- package/lib/schema/keywords/_hidden.js +0 -11
- package/lib/schema/keywords/_index.js +0 -11
- package/lib/schema/keywords/_instanceof.js +0 -49
- package/lib/schema/keywords/_primary.js +0 -11
- package/lib/schema/keywords/_range.js +0 -26
- package/lib/schema/keywords/_relate.js +0 -19
- package/lib/schema/keywords/_specificType.js +0 -11
- package/lib/schema/keywords/_unique.js +0 -11
- package/lib/schema/keywords/_unsigned.js +0 -11
- package/lib/schema/keywords/_validate.js +0 -80
- package/lib/schema/keywords/index.js +0 -106
- package/lib/schema/properties.js +0 -227
- package/lib/schema/properties.test.js +0 -573
- package/lib/schema/relations.js +0 -274
- package/lib/schema/relations.test.js +0 -155
- package/lib/services/Service.js +0 -34
- package/lib/services/index.js +0 -18
- package/lib/storage/AssetFile.js +0 -97
- package/lib/storage/DiskStorage.js +0 -125
- package/lib/storage/S3Storage.js +0 -171
- package/lib/storage/Storage.js +0 -209
- package/lib/storage/index.js +0 -34
- package/lib/utils/decorator.js +0 -16
- package/lib/utils/deprecate.js +0 -46
- package/lib/utils/emitter.js +0 -13
- package/lib/utils/function.js +0 -14
- package/lib/utils/function.test.js +0 -49
- package/lib/utils/index.js +0 -66
- package/lib/utils/json.js +0 -9
- package/lib/utils/object.js +0 -92
- package/lib/utils/object.test.js +0 -65
- package/lib/utils/scope.js +0 -14
package/lib/app/Application.js
DELETED
|
@@ -1,955 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true;
|
|
4
|
-
exports.Application = void 0;
|
|
5
|
-
|
|
6
|
-
require("core-js/modules/esnext.async-iterator.filter.js");
|
|
7
|
-
|
|
8
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
9
|
-
|
|
10
|
-
require("core-js/modules/esnext.iterator.filter.js");
|
|
11
|
-
|
|
12
|
-
require("core-js/modules/es.error.cause.js");
|
|
13
|
-
|
|
14
|
-
require("core-js/modules/esnext.async-iterator.reduce.js");
|
|
15
|
-
|
|
16
|
-
require("core-js/modules/esnext.iterator.reduce.js");
|
|
17
|
-
|
|
18
|
-
require("core-js/modules/esnext.async-iterator.find.js");
|
|
19
|
-
|
|
20
|
-
require("core-js/modules/esnext.iterator.find.js");
|
|
21
|
-
|
|
22
|
-
require("core-js/modules/esnext.async-iterator.map.js");
|
|
23
|
-
|
|
24
|
-
require("core-js/modules/esnext.iterator.map.js");
|
|
25
|
-
|
|
26
|
-
var _koa = _interopRequireDefault(require("koa"));
|
|
27
|
-
|
|
28
|
-
var _knex2 = _interopRequireDefault(require("knex"));
|
|
29
|
-
|
|
30
|
-
var _util = _interopRequireDefault(require("util"));
|
|
31
|
-
|
|
32
|
-
var _axios = _interopRequireDefault(require("axios"));
|
|
33
|
-
|
|
34
|
-
var _chalk = _interopRequireDefault(require("chalk"));
|
|
35
|
-
|
|
36
|
-
var _zlib = _interopRequireDefault(require("zlib"));
|
|
37
|
-
|
|
38
|
-
var _pino = _interopRequireDefault(require("pino"));
|
|
39
|
-
|
|
40
|
-
var _os = _interopRequireDefault(require("os"));
|
|
41
|
-
|
|
42
|
-
var _parseDuration = _interopRequireDefault(require("parse-duration"));
|
|
43
|
-
|
|
44
|
-
var _koaBodyparser = _interopRequireDefault(require("koa-bodyparser"));
|
|
45
|
-
|
|
46
|
-
var _cors = _interopRequireDefault(require("@koa/cors"));
|
|
47
|
-
|
|
48
|
-
var _koaCompose = _interopRequireDefault(require("koa-compose"));
|
|
49
|
-
|
|
50
|
-
var _koaCompress = _interopRequireDefault(require("koa-compress"));
|
|
51
|
-
|
|
52
|
-
var _koaConditionalGet = _interopRequireDefault(require("koa-conditional-get"));
|
|
53
|
-
|
|
54
|
-
var _koaPassport = _interopRequireDefault(require("koa-passport"));
|
|
55
|
-
|
|
56
|
-
var _koaSession = _interopRequireDefault(require("koa-session"));
|
|
57
|
-
|
|
58
|
-
var _koaEtag = _interopRequireDefault(require("koa-etag"));
|
|
59
|
-
|
|
60
|
-
var _koaHelmet = _interopRequireDefault(require("koa-helmet"));
|
|
61
|
-
|
|
62
|
-
var _koaResponseTime = _interopRequireDefault(require("koa-response-time"));
|
|
63
|
-
|
|
64
|
-
var _router = _interopRequireDefault(require("@ditojs/router"));
|
|
65
|
-
|
|
66
|
-
var _lib = require("../lib");
|
|
67
|
-
|
|
68
|
-
var _controllers = require("../controllers");
|
|
69
|
-
|
|
70
|
-
var _services = require("../services");
|
|
71
|
-
|
|
72
|
-
var _storage = require("../storage");
|
|
73
|
-
|
|
74
|
-
var _schema = require("../schema");
|
|
75
|
-
|
|
76
|
-
var _utils = require("../utils");
|
|
77
|
-
|
|
78
|
-
var _errors = require("../errors");
|
|
79
|
-
|
|
80
|
-
var _SessionStore = _interopRequireDefault(require("./SessionStore"));
|
|
81
|
-
|
|
82
|
-
var _Validator = require("./Validator");
|
|
83
|
-
|
|
84
|
-
var _middleware = require("../middleware");
|
|
85
|
-
|
|
86
|
-
var _utils2 = require("@ditojs/utils");
|
|
87
|
-
|
|
88
|
-
var _objection = require("objection");
|
|
89
|
-
|
|
90
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
91
|
-
|
|
92
|
-
class Application extends _koa.default {
|
|
93
|
-
constructor({
|
|
94
|
-
config = {},
|
|
95
|
-
validator,
|
|
96
|
-
router,
|
|
97
|
-
events,
|
|
98
|
-
middleware,
|
|
99
|
-
models,
|
|
100
|
-
services,
|
|
101
|
-
controllers
|
|
102
|
-
} = {}) {
|
|
103
|
-
super();
|
|
104
|
-
|
|
105
|
-
this._setupEmitter(events);
|
|
106
|
-
|
|
107
|
-
const {
|
|
108
|
-
app: {
|
|
109
|
-
keys,
|
|
110
|
-
...app
|
|
111
|
-
} = {},
|
|
112
|
-
log = {},
|
|
113
|
-
...rest
|
|
114
|
-
} = config;
|
|
115
|
-
this.config = {
|
|
116
|
-
app,
|
|
117
|
-
log: log.silent || process.env.DITO_SILENT ? {} : log,
|
|
118
|
-
...rest
|
|
119
|
-
};
|
|
120
|
-
this.keys = keys;
|
|
121
|
-
this.proxy = !!app.proxy;
|
|
122
|
-
this.validator = validator || new _Validator.Validator();
|
|
123
|
-
this.router = router || new _router.default();
|
|
124
|
-
this.validator.app = this;
|
|
125
|
-
this.storages = Object.create(null);
|
|
126
|
-
this.models = Object.create(null);
|
|
127
|
-
this.services = Object.create(null);
|
|
128
|
-
this.controllers = Object.create(null);
|
|
129
|
-
this.hasControllerMiddleware = false;
|
|
130
|
-
this.setupLogger();
|
|
131
|
-
this.setupKnex();
|
|
132
|
-
this.setupGlobalMiddleware();
|
|
133
|
-
|
|
134
|
-
if (middleware) {
|
|
135
|
-
this.use(middleware);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (config.storages) {
|
|
139
|
-
this.addStorages(config.storages);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (models) {
|
|
143
|
-
this.addModels(models);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (services) {
|
|
147
|
-
this.addServices(services);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (controllers) {
|
|
151
|
-
this.addControllers(controllers);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
addRoute(verb, path, transacted, handlers, controller = null, action = null) {
|
|
156
|
-
handlers = (0, _utils2.asArray)(handlers);
|
|
157
|
-
const handler = handlers.length > 1 ? (0, _koaCompose.default)(handlers) : handlers[0];
|
|
158
|
-
const route = {
|
|
159
|
-
verb,
|
|
160
|
-
path,
|
|
161
|
-
transacted,
|
|
162
|
-
handler,
|
|
163
|
-
controller,
|
|
164
|
-
action
|
|
165
|
-
};
|
|
166
|
-
this.router[verb](path, route);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
addModels(models) {
|
|
170
|
-
for (const modelClass of Object.values(models)) {
|
|
171
|
-
this.addModel(modelClass);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
this.models = this.sortModels(this.models);
|
|
175
|
-
const sortedModels = Object.values(this.models).filter(modelClass => models[modelClass.name] === modelClass);
|
|
176
|
-
|
|
177
|
-
for (const modelClass of sortedModels) {
|
|
178
|
-
if (models[modelClass.name] === modelClass) {
|
|
179
|
-
modelClass.setup(this.knex);
|
|
180
|
-
modelClass.initialize();
|
|
181
|
-
this.validator.addSchema(modelClass.getJsonSchema());
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const {
|
|
186
|
-
log
|
|
187
|
-
} = this.config;
|
|
188
|
-
|
|
189
|
-
if (log.schema || log.relations) {
|
|
190
|
-
for (const modelClass of sortedModels) {
|
|
191
|
-
const shouldLog = option => option === true || (0, _utils2.asArray)(option).includes(modelClass.name);
|
|
192
|
-
|
|
193
|
-
const data = {};
|
|
194
|
-
|
|
195
|
-
if (shouldLog(log.schema)) {
|
|
196
|
-
data.schema = modelClass.getJsonSchema();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (shouldLog(log.relations)) {
|
|
200
|
-
data.relations = (0, _utils2.clone)(modelClass.relationMappings, value => _objection.Model.isPrototypeOf(value) ? `[Model: ${value.name}]` : value);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (Object.keys(data).length > 0) {
|
|
204
|
-
console.info(_chalk.default.yellow.bold(`\n${modelClass.name}:\n`), _util.default.inspect(data, {
|
|
205
|
-
colors: true,
|
|
206
|
-
depth: null,
|
|
207
|
-
maxArrayLength: null
|
|
208
|
-
}));
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
addModel(modelClass) {
|
|
215
|
-
if (_objection.Model.isPrototypeOf(modelClass)) {
|
|
216
|
-
modelClass.app = this;
|
|
217
|
-
this.models[modelClass.name] = modelClass;
|
|
218
|
-
} else {
|
|
219
|
-
throw new Error(`Invalid model class: ${modelClass}`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
sortModels(models) {
|
|
224
|
-
const sortByRelations = (list, collected = {}, excluded = {}) => {
|
|
225
|
-
for (const modelClass of list) {
|
|
226
|
-
const {
|
|
227
|
-
name
|
|
228
|
-
} = modelClass;
|
|
229
|
-
|
|
230
|
-
if (!collected[name] && !excluded[name]) {
|
|
231
|
-
for (const relation of Object.values(modelClass.getRelations())) {
|
|
232
|
-
if (!(relation instanceof _objection.BelongsToOneRelation)) {
|
|
233
|
-
const {
|
|
234
|
-
relatedModelClass,
|
|
235
|
-
joinTableModelClass
|
|
236
|
-
} = relation;
|
|
237
|
-
|
|
238
|
-
for (const related of [joinTableModelClass, relatedModelClass]) {
|
|
239
|
-
if (related && related !== modelClass && models[related.name]) {
|
|
240
|
-
sortByRelations([related], collected, {
|
|
241
|
-
[name]: modelClass,
|
|
242
|
-
...excluded
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
collected[name] = modelClass;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return Object.values(collected);
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
return sortByRelations(Object.values(models).reverse()).reverse().reduce((models, modelClass) => {
|
|
257
|
-
models[modelClass.name] = modelClass;
|
|
258
|
-
return models;
|
|
259
|
-
}, Object.create(null));
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
getModel(name) {
|
|
263
|
-
return this.models[name] || !name.endsWith('Model') && this.models[`${name}Model`] || null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
findModel(callback) {
|
|
267
|
-
return Object.values(this.models).find(callback);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
addServices(services) {
|
|
271
|
-
for (const [name, service] of Object.entries(services)) {
|
|
272
|
-
if (name === 'default' && (0, _utils2.isPlainObject)(service)) {
|
|
273
|
-
this.addServices(service);
|
|
274
|
-
} else {
|
|
275
|
-
this.addService(service, name);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
addService(service, name) {
|
|
281
|
-
if (_services.Service.isPrototypeOf(service)) {
|
|
282
|
-
service = new service(this, name);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (!(service instanceof _services.Service)) {
|
|
286
|
-
throw new Error(`Invalid service: ${service}`);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
({
|
|
290
|
-
name
|
|
291
|
-
} = service);
|
|
292
|
-
const config = this.config.services[name];
|
|
293
|
-
|
|
294
|
-
if (config === undefined) {
|
|
295
|
-
throw new Error(`Configuration missing for service '${name}'`);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (config !== false) {
|
|
299
|
-
service.setup(config);
|
|
300
|
-
this.services[name] = service;
|
|
301
|
-
service.initialize();
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
getService(name) {
|
|
306
|
-
return this.services[name] || null;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
findService(callback) {
|
|
310
|
-
return Object.values(this.services).find(callback);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
forEachService(callback) {
|
|
314
|
-
return Promise.all(Object.values(this.services).map(callback));
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
addControllers(controllers, namespace) {
|
|
318
|
-
for (const [key, value] of Object.entries(controllers)) {
|
|
319
|
-
if ((0, _utils2.isPlainObject)(value)) {
|
|
320
|
-
this.addControllers(value, namespace ? `${namespace}/${key}` : key);
|
|
321
|
-
} else {
|
|
322
|
-
this.addController(value, namespace);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
addController(controller, namespace) {
|
|
328
|
-
this.setupControllerMiddleware();
|
|
329
|
-
|
|
330
|
-
if (_controllers.Controller.isPrototypeOf(controller)) {
|
|
331
|
-
controller = new controller(this, namespace);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (!(controller instanceof _controllers.Controller)) {
|
|
335
|
-
throw new Error(`Invalid controller: ${controller}`);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
controller.setup();
|
|
339
|
-
this.controllers[controller.url] = controller;
|
|
340
|
-
controller.initialize();
|
|
341
|
-
const middleware = controller.compose();
|
|
342
|
-
|
|
343
|
-
if (middleware) {
|
|
344
|
-
this.use(middleware);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
getController(url) {
|
|
349
|
-
return this.controllers[url] || null;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
findController(callback) {
|
|
353
|
-
return Object.values(this.controllers).find(callback);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
getAdminController() {
|
|
357
|
-
return this.findController(controller => controller instanceof _controllers.AdminController);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
getAdminVueConfig() {
|
|
361
|
-
var _this$getAdminControl;
|
|
362
|
-
|
|
363
|
-
return ((_this$getAdminControl = this.getAdminController()) == null ? void 0 : _this$getAdminControl.getVueConfig()) || null;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
getAssetConfig({
|
|
367
|
-
models = Object.keys(this.models),
|
|
368
|
-
normalizeDbNames = this.config.knex.normalizeDbNames
|
|
369
|
-
} = {}) {
|
|
370
|
-
const assetConfig = {};
|
|
371
|
-
|
|
372
|
-
for (const modelName of models) {
|
|
373
|
-
const modelClass = this.models[modelName];
|
|
374
|
-
const {
|
|
375
|
-
assets
|
|
376
|
-
} = modelClass.definition;
|
|
377
|
-
|
|
378
|
-
if (assets) {
|
|
379
|
-
const normalizedModelName = normalizeDbNames ? this.normalizeIdentifier(modelName) : modelName;
|
|
380
|
-
const convertedAssets = {};
|
|
381
|
-
|
|
382
|
-
for (const [assetDataPath, config] of Object.entries(assets)) {
|
|
383
|
-
const {
|
|
384
|
-
property,
|
|
385
|
-
nestedDataPath,
|
|
386
|
-
name,
|
|
387
|
-
index
|
|
388
|
-
} = modelClass.getPropertyOrRelationAtDataPath(assetDataPath);
|
|
389
|
-
|
|
390
|
-
if (property && index === 0) {
|
|
391
|
-
const normalizedName = normalizeDbNames ? this.normalizeIdentifier(name) : name;
|
|
392
|
-
const dataPath = (0, _utils2.normalizeDataPath)([normalizedName, ...(0, _utils2.parseDataPath)(nestedDataPath)]);
|
|
393
|
-
const assetConfigs = convertedAssets[normalizedName] || (convertedAssets[normalizedName] = {});
|
|
394
|
-
assetConfigs[dataPath] = config;
|
|
395
|
-
} else {
|
|
396
|
-
throw new Error('Nested graph properties are not supported yet');
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
assetConfig[normalizedModelName] = convertedAssets;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return assetConfig;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
addStorages(storages) {
|
|
408
|
-
for (const [name, config] of Object.entries(storages)) {
|
|
409
|
-
this.addStorage(config, name);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
addStorage(config, name) {
|
|
414
|
-
let storage = null;
|
|
415
|
-
|
|
416
|
-
if ((0, _utils2.isPlainObject)(config)) {
|
|
417
|
-
const storageClass = _storage.Storage.get(config.type);
|
|
418
|
-
|
|
419
|
-
if (!storageClass) {
|
|
420
|
-
throw new Error(`Unsupported storage: ${config}`);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
storage = new storageClass(this, config);
|
|
424
|
-
} else if (config instanceof _storage.Storage) {
|
|
425
|
-
storage = config;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (storage) {
|
|
429
|
-
if (name) {
|
|
430
|
-
storage.name = name;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
this.storages[storage.name] = storage;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
return storage;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
getStorage(name) {
|
|
440
|
-
return this.storages[name] || null;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
compileValidator(jsonSchema, options) {
|
|
444
|
-
return jsonSchema ? this.validator.compile(jsonSchema, options) : null;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
compileParametersValidator(parameters, options = {}) {
|
|
448
|
-
const list = [];
|
|
449
|
-
const {
|
|
450
|
-
dataName = 'data'
|
|
451
|
-
} = options;
|
|
452
|
-
let properties = null;
|
|
453
|
-
|
|
454
|
-
const addParameter = (name, schema) => {
|
|
455
|
-
list.push({
|
|
456
|
-
name: name != null ? name : null,
|
|
457
|
-
...schema
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
if (!schema.member) {
|
|
461
|
-
properties || (properties = {});
|
|
462
|
-
properties[name || dataName] = schema;
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
let asObject = false;
|
|
467
|
-
|
|
468
|
-
if ((0, _utils2.isArray)(parameters)) {
|
|
469
|
-
for (const {
|
|
470
|
-
name,
|
|
471
|
-
...schema
|
|
472
|
-
} of parameters) {
|
|
473
|
-
addParameter(name, schema);
|
|
474
|
-
}
|
|
475
|
-
} else if ((0, _utils2.isObject)(parameters)) {
|
|
476
|
-
asObject = true;
|
|
477
|
-
|
|
478
|
-
for (const [name, schema] of Object.entries(parameters)) {
|
|
479
|
-
if (schema) {
|
|
480
|
-
addParameter(name, schema);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
} else if (parameters) {
|
|
484
|
-
throw new Error(`Invalid parameters definition: ${parameters}`);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const schema = (0, _schema.convertSchema)(properties, options);
|
|
488
|
-
const validate = this.compileValidator(schema, {
|
|
489
|
-
coerceTypes: 'array',
|
|
490
|
-
...options
|
|
491
|
-
});
|
|
492
|
-
const ctx = {
|
|
493
|
-
app: this,
|
|
494
|
-
validator: this.validator,
|
|
495
|
-
options
|
|
496
|
-
};
|
|
497
|
-
return {
|
|
498
|
-
list,
|
|
499
|
-
schema,
|
|
500
|
-
asObject,
|
|
501
|
-
dataName,
|
|
502
|
-
validate: validate ? data => validate.call(ctx, data) : null
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
createValidationError({
|
|
507
|
-
type,
|
|
508
|
-
message,
|
|
509
|
-
errors,
|
|
510
|
-
options,
|
|
511
|
-
json
|
|
512
|
-
}) {
|
|
513
|
-
var _this$config$log$erro;
|
|
514
|
-
|
|
515
|
-
return new _errors.ValidationError({
|
|
516
|
-
type,
|
|
517
|
-
message,
|
|
518
|
-
errors: this.validator.parseErrors(errors, options),
|
|
519
|
-
json: (_this$config$log$erro = this.config.log.errors) != null && _this$config$log$erro.json ? json : undefined
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
createDatabaseError(error) {
|
|
524
|
-
var _this$config$log$erro2;
|
|
525
|
-
|
|
526
|
-
const [, sql, message] = error.message.match(/^([\s\S]*) - ([\s\S]*?)$/) || [null, null, error.message];
|
|
527
|
-
return new _errors.DatabaseError(error, {
|
|
528
|
-
message,
|
|
529
|
-
sql: (_this$config$log$erro2 = this.config.log.errors) != null && _this$config$log$erro2.sql ? sql : undefined
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
setupGlobalMiddleware() {
|
|
534
|
-
const {
|
|
535
|
-
app,
|
|
536
|
-
log
|
|
537
|
-
} = this.config;
|
|
538
|
-
this.use((0, _middleware.attachLogger)(this.logger));
|
|
539
|
-
|
|
540
|
-
if (app.responseTime !== false) {
|
|
541
|
-
this.use((0, _koaResponseTime.default)(getOptions(app.responseTime)));
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
if (log.requests) {
|
|
545
|
-
this.use((0, _middleware.logRequests)());
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
this.use((0, _middleware.handleError)());
|
|
549
|
-
|
|
550
|
-
if (app.helmet !== false) {
|
|
551
|
-
this.use((0, _koaHelmet.default)(getOptions(app.helmet)));
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (app.cors !== false) {
|
|
555
|
-
this.use((0, _cors.default)(getOptions(app.cors)));
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
if (app.compress !== false) {
|
|
559
|
-
this.use((0, _koaCompress.default)((0, _utils2.merge)({
|
|
560
|
-
br: {
|
|
561
|
-
params: {
|
|
562
|
-
[_zlib.default.constants.BROTLI_PARAM_QUALITY]: 4
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}, getOptions(app.compress))));
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
if (app.etag !== false) {
|
|
569
|
-
this.use((0, _koaConditionalGet.default)());
|
|
570
|
-
this.use((0, _koaEtag.default)());
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
setupControllerMiddleware() {
|
|
575
|
-
if (!this.hasControllerMiddleware) {
|
|
576
|
-
const {
|
|
577
|
-
app
|
|
578
|
-
} = this.config;
|
|
579
|
-
this.use((0, _koaBodyparser.default)(getOptions(app.bodyParser)));
|
|
580
|
-
this.use((0, _middleware.findRoute)(this.router));
|
|
581
|
-
this.use((0, _middleware.createTransaction)());
|
|
582
|
-
|
|
583
|
-
if (app.session) {
|
|
584
|
-
const {
|
|
585
|
-
modelClass,
|
|
586
|
-
...options
|
|
587
|
-
} = getOptions(app.session);
|
|
588
|
-
|
|
589
|
-
if (modelClass) {
|
|
590
|
-
options.ContextStore = (0, _SessionStore.default)(modelClass);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
this.use((0, _koaSession.default)(options, this));
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
if (app.passport) {
|
|
597
|
-
this.use(_koaPassport.default.initialize());
|
|
598
|
-
|
|
599
|
-
if (app.session) {
|
|
600
|
-
this.use(_koaPassport.default.session());
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
this.use((0, _middleware.handleUser)());
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
this.use((0, _middleware.handleRoute)());
|
|
607
|
-
this.hasControllerMiddleware = true;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
setupLogger() {
|
|
612
|
-
const {
|
|
613
|
-
err,
|
|
614
|
-
req,
|
|
615
|
-
res
|
|
616
|
-
} = _pino.default.stdSerializers;
|
|
617
|
-
|
|
618
|
-
const user = user => ({
|
|
619
|
-
id: user.id
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
const serializers = {
|
|
623
|
-
err,
|
|
624
|
-
req,
|
|
625
|
-
res,
|
|
626
|
-
user
|
|
627
|
-
};
|
|
628
|
-
const logger = (0, _pino.default)((0, _utils2.merge)({
|
|
629
|
-
level: 'info',
|
|
630
|
-
serializers,
|
|
631
|
-
prettyPrint: {
|
|
632
|
-
ignore: 'req,res,durationMs,user,requestId',
|
|
633
|
-
translateTime: 'SYS:HH:MM:ss.l'
|
|
634
|
-
},
|
|
635
|
-
redact: ['*.headers["cookie"]', '*.headers["set-cookie"]', '*.headers["authorization"]'],
|
|
636
|
-
base: null
|
|
637
|
-
}, getOptions(this.config.logger)));
|
|
638
|
-
this.logger = logger.child({
|
|
639
|
-
name: 'app'
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
setupKnex() {
|
|
644
|
-
var _knex;
|
|
645
|
-
|
|
646
|
-
let {
|
|
647
|
-
knex,
|
|
648
|
-
log
|
|
649
|
-
} = this.config;
|
|
650
|
-
|
|
651
|
-
if ((_knex = knex) != null && _knex.client) {
|
|
652
|
-
const snakeCaseOptions = knex.normalizeDbNames === true ? {} : knex.normalizeDbNames;
|
|
653
|
-
|
|
654
|
-
if (snakeCaseOptions) {
|
|
655
|
-
knex = { ...knex,
|
|
656
|
-
...(0, _objection.knexSnakeCaseMappers)(snakeCaseOptions)
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
this.knex = (0, _knex2.default)(knex);
|
|
661
|
-
|
|
662
|
-
if (log.sql) {
|
|
663
|
-
this.setupKnexLogging();
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
setupKnexLogging() {
|
|
669
|
-
const startTimes = {};
|
|
670
|
-
const logger = this.logger.child({
|
|
671
|
-
name: 'sql'
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
function end(query, {
|
|
675
|
-
response,
|
|
676
|
-
error
|
|
677
|
-
}) {
|
|
678
|
-
const id = query.__knexQueryUid;
|
|
679
|
-
const diff = process.hrtime(startTimes[id]);
|
|
680
|
-
const duration = diff[0] * 1e3 + diff[1] / 1e6;
|
|
681
|
-
delete startTimes[id];
|
|
682
|
-
const {
|
|
683
|
-
sql,
|
|
684
|
-
bindings
|
|
685
|
-
} = query;
|
|
686
|
-
response = Object.fromEntries(Object.entries(response).filter(([key]) => !key.startsWith('_')));
|
|
687
|
-
logger.info({
|
|
688
|
-
duration,
|
|
689
|
-
bindings,
|
|
690
|
-
response,
|
|
691
|
-
error
|
|
692
|
-
}, sql);
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
this.knex.on('query', query => {
|
|
696
|
-
startTimes[query.__knexQueryUid] = process.hrtime();
|
|
697
|
-
}).on('query-response', (response, query) => {
|
|
698
|
-
end(query, {
|
|
699
|
-
response
|
|
700
|
-
});
|
|
701
|
-
}).on('query-error', (error, query) => {
|
|
702
|
-
end(query, {
|
|
703
|
-
error
|
|
704
|
-
});
|
|
705
|
-
});
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
normalizeIdentifier(identifier) {
|
|
709
|
-
return this.knex.client.wrapIdentifier(identifier).replace(/['`"]/g, '');
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
denormalizeIdentifier(identifier) {
|
|
713
|
-
const obj = this.knex.client.postProcessResponse({
|
|
714
|
-
[identifier]: 1
|
|
715
|
-
});
|
|
716
|
-
return Object.keys(obj)[0];
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
normalizePath(path) {
|
|
720
|
-
return this.config.app.normalizePaths ? (0, _utils2.hyphenate)(path) : path;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
formatError(err) {
|
|
724
|
-
var _this$config$log$erro3;
|
|
725
|
-
|
|
726
|
-
const message = err.toJSON ? (0, _utils.formatJson)(err.toJSON()) : err.message || err;
|
|
727
|
-
const str = `${err.name}: ${message}`;
|
|
728
|
-
return err.stack && ((_this$config$log$erro3 = this.config.log.errors) == null ? void 0 : _this$config$log$erro3.stack) !== false ? `${str}\n${err.stack.split(/\n|\r\n|\r/).slice(1).join(_os.default.EOL)}` : str;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
logError(err, ctx) {
|
|
732
|
-
if (!err.expose && !this.silent) {
|
|
733
|
-
try {
|
|
734
|
-
const text = this.formatError(err);
|
|
735
|
-
const level = err instanceof _errors.ResponseError && err.status < 500 ? 'info' : 'error';
|
|
736
|
-
const logger = (ctx == null ? void 0 : ctx.logger) || this.logger;
|
|
737
|
-
logger[level](text);
|
|
738
|
-
} catch (e) {
|
|
739
|
-
console.error('Could not log error', e);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
async start() {
|
|
745
|
-
if (this.config.log.errors !== false) {
|
|
746
|
-
this.on('error', this.logError);
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
await this.emit('before:start');
|
|
750
|
-
await this.forEachService(service => service.start());
|
|
751
|
-
const {
|
|
752
|
-
server: {
|
|
753
|
-
host,
|
|
754
|
-
port
|
|
755
|
-
},
|
|
756
|
-
env
|
|
757
|
-
} = this.config;
|
|
758
|
-
this.server = await new Promise((resolve, reject) => {
|
|
759
|
-
const server = this.listen(port, host, () => {
|
|
760
|
-
const {
|
|
761
|
-
port
|
|
762
|
-
} = server.address();
|
|
763
|
-
console.info(`${env} server started at http://${host}:${port}`);
|
|
764
|
-
resolve(server);
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
if (!server) {
|
|
768
|
-
reject(new Error(`Unable to start server at http://${host}:${port}`));
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
await this.emit('after:start');
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
async stop() {
|
|
775
|
-
await this.emit('before:stop');
|
|
776
|
-
this.server = await new Promise((resolve, reject) => {
|
|
777
|
-
const {
|
|
778
|
-
server
|
|
779
|
-
} = this;
|
|
780
|
-
|
|
781
|
-
if (server) {
|
|
782
|
-
server.close(err => {
|
|
783
|
-
if (err) {
|
|
784
|
-
reject(err);
|
|
785
|
-
} else {
|
|
786
|
-
resolve(null);
|
|
787
|
-
}
|
|
788
|
-
});
|
|
789
|
-
setImmediate(() => server.emit('close'));
|
|
790
|
-
} else {
|
|
791
|
-
reject(new Error('Server is not running'));
|
|
792
|
-
}
|
|
793
|
-
});
|
|
794
|
-
await this.forEachService(service => service.stop());
|
|
795
|
-
await this.emit('after:stop');
|
|
796
|
-
|
|
797
|
-
if (this.config.log.errors !== false) {
|
|
798
|
-
this.off('error', this.logError);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
async startOrExit() {
|
|
803
|
-
try {
|
|
804
|
-
await this.start();
|
|
805
|
-
} catch (err) {
|
|
806
|
-
this.logError(err);
|
|
807
|
-
process.exit(-1);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
async createAssets(storage, files, count = 0, trx = null) {
|
|
812
|
-
const AssetModel = this.getModel('Asset');
|
|
813
|
-
|
|
814
|
-
if (AssetModel) {
|
|
815
|
-
const assets = files.map(file => ({
|
|
816
|
-
key: file.key,
|
|
817
|
-
file,
|
|
818
|
-
storage: storage.name,
|
|
819
|
-
count
|
|
820
|
-
}));
|
|
821
|
-
return AssetModel.query(trx).insert(assets);
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
return null;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
async handleAdddedAndRemovedAssets(storage, addedFiles, removedFiles, trx = null) {
|
|
828
|
-
const {
|
|
829
|
-
assets: {
|
|
830
|
-
cleanupTimeThreshold = 0
|
|
831
|
-
} = {}
|
|
832
|
-
} = this.config;
|
|
833
|
-
const timeThreshold = (0, _utils2.isString)(cleanupTimeThreshold) ? (0, _parseDuration.default)(cleanupTimeThreshold) : cleanupTimeThreshold;
|
|
834
|
-
const importedFiles = [];
|
|
835
|
-
const AssetModel = this.getModel('Asset');
|
|
836
|
-
|
|
837
|
-
if (AssetModel) {
|
|
838
|
-
importedFiles.push(...(await this.addForeignAssets(storage, addedFiles, trx)));
|
|
839
|
-
|
|
840
|
-
if (addedFiles.length > 0 || removedFiles.length > 0) {
|
|
841
|
-
const changeCount = (files, increment) => files.length > 0 && AssetModel.query(trx).whereIn('key', files.map(file => file.key)).increment('count', increment);
|
|
842
|
-
|
|
843
|
-
await Promise.all([changeCount(addedFiles, 1), changeCount(removedFiles, -1)]);
|
|
844
|
-
|
|
845
|
-
if (timeThreshold > 0) {
|
|
846
|
-
setTimeout(() => this.releaseUnusedAssets(timeThreshold), timeThreshold);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
await this.releaseUnusedAssets(timeThreshold, trx);
|
|
851
|
-
return importedFiles;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
async addForeignAssets(storage, files, trx = null) {
|
|
856
|
-
const importedFiles = [];
|
|
857
|
-
const AssetModel = this.getModel('Asset');
|
|
858
|
-
|
|
859
|
-
if (AssetModel) {
|
|
860
|
-
await Promise.all(files.map(async file => {
|
|
861
|
-
const asset = await AssetModel.query(trx).findOne('key', file.key);
|
|
862
|
-
|
|
863
|
-
if (!asset) {
|
|
864
|
-
if (file.data || file.url) {
|
|
865
|
-
let {
|
|
866
|
-
data
|
|
867
|
-
} = file;
|
|
868
|
-
|
|
869
|
-
if (!data) {
|
|
870
|
-
console.info(`${_chalk.default.red('INFO:')} Asset ${_chalk.default.green(`'${file.name}'`)} is from a foreign source, fetching from ${_chalk.default.green(`'${file.url}'`)} and adding to storage ${_chalk.default.green(`'${storage.name}'`)}...`);
|
|
871
|
-
const response = await _axios.default.request({
|
|
872
|
-
method: 'get',
|
|
873
|
-
url: file.url,
|
|
874
|
-
responseType: 'arraybuffer'
|
|
875
|
-
});
|
|
876
|
-
data = response.data;
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
const importedFile = await storage.addFile(file, data);
|
|
880
|
-
await this.createAssets(storage, [importedFile], 0, trx);
|
|
881
|
-
Object.assign(file, importedFile);
|
|
882
|
-
importedFiles.push(importedFile);
|
|
883
|
-
} else {
|
|
884
|
-
throw new _errors.AssetError(`Unable to import asset from foreign source: '${file.name}' ('${file.key}')`);
|
|
885
|
-
}
|
|
886
|
-
} else {
|
|
887
|
-
Object.assign(file, asset.file);
|
|
888
|
-
}
|
|
889
|
-
}));
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
return importedFiles;
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
async handleModifiedAssets(storage, files, trx = null) {
|
|
896
|
-
const modifiedFiles = [];
|
|
897
|
-
const AssetModel = this.getModel('Asset');
|
|
898
|
-
|
|
899
|
-
if (AssetModel) {
|
|
900
|
-
await Promise.all(files.map(async file => {
|
|
901
|
-
if (file.data) {
|
|
902
|
-
const asset = await AssetModel.query(trx).findOne('key', file.key);
|
|
903
|
-
|
|
904
|
-
if (asset) {
|
|
905
|
-
const changedFile = await storage.addFile(file, file.data);
|
|
906
|
-
Object.assign(file, changedFile);
|
|
907
|
-
modifiedFiles.push(changedFile);
|
|
908
|
-
} else {
|
|
909
|
-
throw new _errors.AssetError(`Unable to update modified asset from memory source: '${file.name}' ('${file.key}')`);
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}));
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
return modifiedFiles;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
async releaseUnusedAssets(timeThreshold = 0, trx = null) {
|
|
919
|
-
const AssetModel = this.getModel('Asset');
|
|
920
|
-
|
|
921
|
-
if (AssetModel) {
|
|
922
|
-
return AssetModel.transaction(trx, async trx => {
|
|
923
|
-
const date = new Date();
|
|
924
|
-
date.setMilliseconds(date.getMilliseconds() - timeThreshold);
|
|
925
|
-
const orphanedAssets = await AssetModel.query(trx).where('count', 0).andWhere('updatedAt', '<=', date).andWhere('updatedAt', '>', (0, _objection.ref)('createdAt'));
|
|
926
|
-
|
|
927
|
-
if (orphanedAssets.length > 0) {
|
|
928
|
-
const orphanedKeys = await Promise.all(orphanedAssets.map(async asset => {
|
|
929
|
-
try {
|
|
930
|
-
await this.getStorage(asset.storage).removeFile(asset.file);
|
|
931
|
-
} catch (error) {
|
|
932
|
-
this.emit('error', error);
|
|
933
|
-
asset.error = error;
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
return asset.key;
|
|
937
|
-
}));
|
|
938
|
-
await AssetModel.query(trx).delete().whereIn('key', orphanedKeys);
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
return orphanedAssets;
|
|
942
|
-
});
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
exports.Application = Application;
|
|
949
|
-
|
|
950
|
-
_lib.EventEmitter.mixin(Application.prototype);
|
|
951
|
-
|
|
952
|
-
function getOptions(options) {
|
|
953
|
-
return (0, _utils2.isObject)(options) ? options : {};
|
|
954
|
-
}
|
|
955
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcHAvQXBwbGljYXRpb24uanMiXSwibmFtZXMiOlsiQXBwbGljYXRpb24iLCJLb2EiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsInZhbGlkYXRvciIsInJvdXRlciIsImV2ZW50cyIsIm1pZGRsZXdhcmUiLCJtb2RlbHMiLCJzZXJ2aWNlcyIsImNvbnRyb2xsZXJzIiwiX3NldHVwRW1pdHRlciIsImFwcCIsImtleXMiLCJsb2ciLCJyZXN0Iiwic2lsZW50IiwicHJvY2VzcyIsImVudiIsIkRJVE9fU0lMRU5UIiwicHJveHkiLCJWYWxpZGF0b3IiLCJSb3V0ZXIiLCJzdG9yYWdlcyIsIk9iamVjdCIsImNyZWF0ZSIsImhhc0NvbnRyb2xsZXJNaWRkbGV3YXJlIiwic2V0dXBMb2dnZXIiLCJzZXR1cEtuZXgiLCJzZXR1cEdsb2JhbE1pZGRsZXdhcmUiLCJ1c2UiLCJhZGRTdG9yYWdlcyIsImFkZE1vZGVscyIsImFkZFNlcnZpY2VzIiwiYWRkQ29udHJvbGxlcnMiLCJhZGRSb3V0ZSIsInZlcmIiLCJwYXRoIiwidHJhbnNhY3RlZCIsImhhbmRsZXJzIiwiY29udHJvbGxlciIsImFjdGlvbiIsImhhbmRsZXIiLCJsZW5ndGgiLCJyb3V0ZSIsIm1vZGVsQ2xhc3MiLCJ2YWx1ZXMiLCJhZGRNb2RlbCIsInNvcnRNb2RlbHMiLCJzb3J0ZWRNb2RlbHMiLCJmaWx0ZXIiLCJuYW1lIiwic2V0dXAiLCJrbmV4IiwiaW5pdGlhbGl6ZSIsImFkZFNjaGVtYSIsImdldEpzb25TY2hlbWEiLCJzY2hlbWEiLCJyZWxhdGlvbnMiLCJzaG91bGRMb2ciLCJvcHRpb24iLCJpbmNsdWRlcyIsImRhdGEiLCJyZWxhdGlvbk1hcHBpbmdzIiwidmFsdWUiLCJNb2RlbCIsImlzUHJvdG90eXBlT2YiLCJjb25zb2xlIiwiaW5mbyIsImNoYWxrIiwieWVsbG93IiwiYm9sZCIsInV0aWwiLCJpbnNwZWN0IiwiY29sb3JzIiwiZGVwdGgiLCJtYXhBcnJheUxlbmd0aCIsIkVycm9yIiwic29ydEJ5UmVsYXRpb25zIiwibGlzdCIsImNvbGxlY3RlZCIsImV4Y2x1ZGVkIiwicmVsYXRpb24iLCJnZXRSZWxhdGlvbnMiLCJCZWxvbmdzVG9PbmVSZWxhdGlvbiIsInJlbGF0ZWRNb2RlbENsYXNzIiwiam9pblRhYmxlTW9kZWxDbGFzcyIsInJlbGF0ZWQiLCJyZXZlcnNlIiwicmVkdWNlIiwiZ2V0TW9kZWwiLCJlbmRzV2l0aCIsImZpbmRNb2RlbCIsImNhbGxiYWNrIiwiZmluZCIsInNlcnZpY2UiLCJlbnRyaWVzIiwiYWRkU2VydmljZSIsIlNlcnZpY2UiLCJ1bmRlZmluZWQiLCJnZXRTZXJ2aWNlIiwiZmluZFNlcnZpY2UiLCJmb3JFYWNoU2VydmljZSIsIlByb21pc2UiLCJhbGwiLCJtYXAiLCJuYW1lc3BhY2UiLCJrZXkiLCJhZGRDb250cm9sbGVyIiwic2V0dXBDb250cm9sbGVyTWlkZGxld2FyZSIsIkNvbnRyb2xsZXIiLCJ1cmwiLCJjb21wb3NlIiwiZ2V0Q29udHJvbGxlciIsImZpbmRDb250cm9sbGVyIiwiZ2V0QWRtaW5Db250cm9sbGVyIiwiQWRtaW5Db250cm9sbGVyIiwiZ2V0QWRtaW5WdWVDb25maWciLCJnZXRWdWVDb25maWciLCJnZXRBc3NldENvbmZpZyIsIm5vcm1hbGl6ZURiTmFtZXMiLCJhc3NldENvbmZpZyIsIm1vZGVsTmFtZSIsImFzc2V0cyIsImRlZmluaXRpb24iLCJub3JtYWxpemVkTW9kZWxOYW1lIiwibm9ybWFsaXplSWRlbnRpZmllciIsImNvbnZlcnRlZEFzc2V0cyIsImFzc2V0RGF0YVBhdGgiLCJwcm9wZXJ0eSIsIm5lc3RlZERhdGFQYXRoIiwiaW5kZXgiLCJnZXRQcm9wZXJ0eU9yUmVsYXRpb25BdERhdGFQYXRoIiwibm9ybWFsaXplZE5hbWUiLCJkYXRhUGF0aCIsImFzc2V0Q29uZmlncyIsImFkZFN0b3JhZ2UiLCJzdG9yYWdlIiwic3RvcmFnZUNsYXNzIiwiU3RvcmFnZSIsImdldCIsInR5cGUiLCJnZXRTdG9yYWdlIiwiY29tcGlsZVZhbGlkYXRvciIsImpzb25TY2hlbWEiLCJvcHRpb25zIiwiY29tcGlsZSIsImNvbXBpbGVQYXJhbWV0ZXJzVmFsaWRhdG9yIiwicGFyYW1ldGVycyIsImRhdGFOYW1lIiwicHJvcGVydGllcyIsImFkZFBhcmFtZXRlciIsInB1c2giLCJtZW1iZXIiLCJhc09iamVjdCIsInZhbGlkYXRlIiwiY29lcmNlVHlwZXMiLCJjdHgiLCJjYWxsIiwiY3JlYXRlVmFsaWRhdGlvbkVycm9yIiwibWVzc2FnZSIsImVycm9ycyIsImpzb24iLCJWYWxpZGF0aW9uRXJyb3IiLCJwYXJzZUVycm9ycyIsImNyZWF0ZURhdGFiYXNlRXJyb3IiLCJlcnJvciIsInNxbCIsIm1hdGNoIiwiRGF0YWJhc2VFcnJvciIsImxvZ2dlciIsInJlc3BvbnNlVGltZSIsImdldE9wdGlvbnMiLCJyZXF1ZXN0cyIsImhlbG1ldCIsImNvcnMiLCJjb21wcmVzcyIsImJyIiwicGFyYW1zIiwiemxpYiIsImNvbnN0YW50cyIsIkJST1RMSV9QQVJBTV9RVUFMSVRZIiwiZXRhZyIsImJvZHlQYXJzZXIiLCJzZXNzaW9uIiwiQ29udGV4dFN0b3JlIiwicGFzc3BvcnQiLCJlcnIiLCJyZXEiLCJyZXMiLCJwaW5vIiwic3RkU2VyaWFsaXplcnMiLCJ1c2VyIiwiaWQiLCJzZXJpYWxpemVycyIsImxldmVsIiwicHJldHR5UHJpbnQiLCJpZ25vcmUiLCJ0cmFuc2xhdGVUaW1lIiwicmVkYWN0IiwiYmFzZSIsImNoaWxkIiwiY2xpZW50Iiwic25ha2VDYXNlT3B0aW9ucyIsInNldHVwS25leExvZ2dpbmciLCJzdGFydFRpbWVzIiwiZW5kIiwicXVlcnkiLCJyZXNwb25zZSIsIl9fa25leFF1ZXJ5VWlkIiwiZGlmZiIsImhydGltZSIsImR1cmF0aW9uIiwiYmluZGluZ3MiLCJmcm9tRW50cmllcyIsInN0YXJ0c1dpdGgiLCJvbiIsImlkZW50aWZpZXIiLCJ3cmFwSWRlbnRpZmllciIsInJlcGxhY2UiLCJkZW5vcm1hbGl6ZUlkZW50aWZpZXIiLCJvYmoiLCJwb3N0UHJvY2Vzc1Jlc3BvbnNlIiwibm9ybWFsaXplUGF0aCIsIm5vcm1hbGl6ZVBhdGhzIiwiZm9ybWF0RXJyb3IiLCJ0b0pTT04iLCJzdHIiLCJzdGFjayIsInNwbGl0Iiwic2xpY2UiLCJqb2luIiwib3MiLCJFT0wiLCJsb2dFcnJvciIsImV4cG9zZSIsInRleHQiLCJSZXNwb25zZUVycm9yIiwic3RhdHVzIiwiZSIsInN0YXJ0IiwiZW1pdCIsInNlcnZlciIsImhvc3QiLCJwb3J0IiwicmVzb2x2ZSIsInJlamVjdCIsImxpc3RlbiIsImFkZHJlc3MiLCJzdG9wIiwiY2xvc2UiLCJzZXRJbW1lZGlhdGUiLCJvZmYiLCJzdGFydE9yRXhpdCIsImV4aXQiLCJjcmVhdGVBc3NldHMiLCJmaWxlcyIsImNvdW50IiwidHJ4IiwiQXNzZXRNb2RlbCIsImZpbGUiLCJpbnNlcnQiLCJoYW5kbGVBZGRkZWRBbmRSZW1vdmVkQXNzZXRzIiwiYWRkZWRGaWxlcyIsInJlbW92ZWRGaWxlcyIsImNsZWFudXBUaW1lVGhyZXNob2xkIiwidGltZVRocmVzaG9sZCIsImltcG9ydGVkRmlsZXMiLCJhZGRGb3JlaWduQXNzZXRzIiwiY2hhbmdlQ291bnQiLCJpbmNyZW1lbnQiLCJ3aGVyZUluIiwic2V0VGltZW91dCIsInJlbGVhc2VVbnVzZWRBc3NldHMiLCJhc3NldCIsImZpbmRPbmUiLCJyZWQiLCJncmVlbiIsImF4aW9zIiwicmVxdWVzdCIsIm1ldGhvZCIsInJlc3BvbnNlVHlwZSIsImltcG9ydGVkRmlsZSIsImFkZEZpbGUiLCJhc3NpZ24iLCJBc3NldEVycm9yIiwiaGFuZGxlTW9kaWZpZWRBc3NldHMiLCJtb2RpZmllZEZpbGVzIiwiY2hhbmdlZEZpbGUiLCJ0cmFuc2FjdGlvbiIsImRhdGUiLCJEYXRlIiwic2V0TWlsbGlzZWNvbmRzIiwiZ2V0TWlsbGlzZWNvbmRzIiwib3JwaGFuZWRBc3NldHMiLCJ3aGVyZSIsImFuZFdoZXJlIiwib3JwaGFuZWRLZXlzIiwicmVtb3ZlRmlsZSIsImRlbGV0ZSIsIkV2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QUFOLEdBQWNBLEtBQWQ7QUFDRDs7QUFDRCxtQkFBTzRHLEtBQUssQ0FBQ3ZLLEdBQWI7QUFDRCxXQVJELENBRHlCLENBQTNCO0FBV0EsZ0JBQU13SixVQUFVLENBQ2JwRCxLQURHLENBQ0dtRCxHQURILEVBRUh5QyxNQUZHLEdBR0g1QixPQUhHLENBR0ssS0FITCxFQUdZMEIsWUFIWixDQUFOO0FBSUQ7O0FBQ0QsZUFBT0gsY0FBUDtBQUNELE9BOUJNLENBQVA7QUErQkQ7QUFDRjs7QUF6NEJrQzs7OztBQTg0QnJDTSxrQkFBYUMsS0FBYixDQUFtQjdTLFdBQVcsQ0FBQzhTLFNBQS9COztBQUVBLFNBQVNsSSxVQUFULENBQW9CM0IsT0FBcEIsRUFBNkI7QUFDM0IsU0FBTyxzQkFBU0EsT0FBVCxJQUFvQkEsT0FBcEIsR0FBOEIsRUFBckM7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBLb2EgZnJvbSAna29hJ1xuaW1wb3J0IEtuZXggZnJvbSAna25leCdcbmltcG9ydCB1dGlsIGZyb20gJ3V0aWwnXG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnXG5pbXBvcnQgY2hhbGsgZnJvbSAnY2hhbGsnXG5pbXBvcnQgemxpYiBmcm9tICd6bGliJ1xuaW1wb3J0IHBpbm8gZnJvbSAncGlubydcbmltcG9ydCBvcyBmcm9tICdvcydcbmltcG9ydCBwYXJzZUR1cmF0aW9uIGZyb20gJ3BhcnNlLWR1cmF0aW9uJ1xuaW1wb3J0IGJvZHlQYXJzZXIgZnJvbSAna29hLWJvZHlwYXJzZXInXG5pbXBvcnQgY29ycyBmcm9tICdAa29hL2NvcnMnXG5pbXBvcnQgY29tcG9zZSBmcm9tICdrb2EtY29tcG9zZSdcbmltcG9ydCBjb21wcmVzcyBmcm9tICdrb2EtY29tcHJlc3MnXG5pbXBvcnQgY29uZGl0aW9uYWwgZnJvbSAna29hLWNvbmRpdGlvbmFsLWdldCdcbmltcG9ydCBwYXNzcG9ydCBmcm9tICdrb2EtcGFzc3BvcnQnXG5pbXBvcnQgc2Vzc2lvbiBmcm9tICdrb2Etc2Vzc2lvbidcbmltcG9ydCBldGFnIGZyb20gJ2tvYS1ldGFnJ1xuaW1wb3J0IGhlbG1ldCBmcm9tICdrb2EtaGVsbWV0J1xuaW1wb3J0IHJlc3BvbnNlVGltZSBmcm9tICdrb2EtcmVzcG9uc2UtdGltZSdcbmltcG9ydCBSb3V0ZXIgZnJvbSAnQGRpdG9qcy9yb3V0ZXInXG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdAL2xpYidcbmltcG9ydCB7IENvbnRyb2xsZXIsIEFkbWluQ29udHJvbGxlciB9IGZyb20gJ0AvY29udHJvbGxlcnMnXG5pbXBvcnQgeyBTZXJ2aWNlIH0gZnJvbSAnQC9zZXJ2aWNlcydcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAL3N0b3JhZ2UnXG5pbXBvcnQgeyBjb252ZXJ0U2NoZW1hIH0gZnJvbSAnQC9zY2hlbWEnXG5pbXBvcnQgeyBmb3JtYXRKc29uIH0gZnJvbSAnQC91dGlscydcbmltcG9ydCB7XG4gIFJlc3BvbnNlRXJyb3IsXG4gIFZhbGlkYXRpb25FcnJvcixcbiAgRGF0YWJhc2VFcnJvcixcbiAgQXNzZXRFcnJvclxufSBmcm9tICdAL2Vycm9ycydcbmltcG9ydCBTZXNzaW9uU3RvcmUgZnJvbSAnLi9TZXNzaW9uU3RvcmUnXG5pbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tICcuL1ZhbGlkYXRvcidcbmltcG9ydCB7XG4gIGF0dGFjaExvZ2dlcixcbiAgY3JlYXRlVHJhbnNhY3Rpb24sXG4gIGZpbmRSb3V0ZSxcbiAgaGFuZGxlRXJyb3IsXG4gIGhhbmRsZVJvdXRlLFxuICBoYW5kbGVVc2VyLFxuICBsb2dSZXF1ZXN0c1xufSBmcm9tICdAL21pZGRsZXdhcmUnXG5pbXBvcnQge1xuICBpc0FycmF5LCBpc09iamVjdCwgaXNTdHJpbmcsIGFzQXJyYXksIGlzUGxhaW5PYmplY3QsIGh5cGhlbmF0ZSwgY2xvbmUsIG1lcmdlLFxuICBwYXJzZURhdGFQYXRoLCBub3JtYWxpemVEYXRhUGF0aFxufSBmcm9tICdAZGl0b2pzL3V0aWxzJ1xuaW1wb3J0IHtcbiAgTW9kZWwsXG4gIEJlbG9uZ3NUb09uZVJlbGF0aW9uLFxuICBrbmV4U25ha2VDYXNlTWFwcGVycyxcbiAgcmVmXG59IGZyb20gJ29iamVjdGlvbidcblxuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uIGV4dGVuZHMgS29hIHtcbiAgY29uc3RydWN0b3Ioe1xuICAgIGNvbmZpZyA9IHt9LFxuICAgIHZhbGlkYXRvcixcbiAgICByb3V0ZXIsXG4gICAgZXZlbnRzLFxuICAgIG1pZGRsZXdhcmUsXG4gICAgbW9kZWxzLFxuICAgIHNlcnZpY2VzLFxuICAgIGNvbnRyb2xsZXJzXG4gIH0gPSB7fSkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9zZXR1cEVtaXR0ZXIoZXZlbnRzKVxuICAgIGNvbnN0IHtcbiAgICAgIC8vIFBsdWNrIGtleXMgb3V0IG9mIGBjb25maWcuYXBwYCB0byBrZWVwIHRoZW0gc2VjcmV0XG4gICAgICBhcHA6IHsga2V5cywgLi4uYXBwIH0gPSB7fSxcbiAgICAgIGxvZyA9IHt9LFxuICAgICAgLi4ucmVzdFxuICAgIH0gPSBjb25maWdcbiAgICB0aGlzLmNvbmZpZyA9IHtcbiAgICAgIGFwcCxcbiAgICAgIGxvZzogbG9nLnNpbGVudCB8fCBwcm9jZXNzLmVudi5ESVRPX1NJTEVOVCA/IHt9IDogbG9nLFxuICAgICAgLi4ucmVzdFxuICAgIH1cbiAgICB0aGlzLmtleXMgPSBrZXlzXG4gICAgdGhpcy5wcm94eSA9ICEhYXBwLnByb3h5XG4gICAgdGhpcy52YWxpZGF0b3IgPSB2YWxpZGF0b3IgfHwgbmV3IFZhbGlkYXRvcigpXG4gICAgdGhpcy5yb3V0ZXIgPSByb3V0ZXIgfHwgbmV3IFJvdXRlcigpXG4gICAgdGhpcy52YWxpZGF0b3IuYXBwID0gdGhpc1xuICAgIHRoaXMuc3RvcmFnZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpXG4gICAgdGhpcy5tb2RlbHMgPSBPYmplY3QuY3JlYXRlKG51bGwpXG4gICAgdGhpcy5zZXJ2aWNlcyA9IE9iamVjdC5jcmVhdGUobnVsbClcbiAgICB0aGlzLmNvbnRyb2xsZXJzID0gT2JqZWN0LmNyZWF0ZShudWxsKVxuICAgIHRoaXMuaGFzQ29udHJvbGxlck1pZGRsZXdhcmUgPSBmYWxzZVxuICAgIHRoaXMuc2V0dXBMb2dnZXIoKVxuICAgIHRoaXMuc2V0dXBLbmV4KClcbiAgICB0aGlzLnNldHVwR2xvYmFsTWlkZGxld2FyZSgpXG4gICAgaWYgKG1pZGRsZXdhcmUpIHtcbiAgICAgIHRoaXMudXNlKG1pZGRsZXdhcmUpXG4gICAgfVxuICAgIGlmIChjb25maWcuc3RvcmFnZXMpIHtcbiAgICAgIHRoaXMuYWRkU3RvcmFnZXMoY29uZmlnLnN0b3JhZ2VzKVxuICAgIH1cbiAgICBpZiAobW9kZWxzKSB7XG4gICAgICB0aGlzLmFkZE1vZGVscyhtb2RlbHMpXG4gICAgfVxuICAgIGlmIChzZXJ2aWNlcykge1xuICAgICAgdGhpcy5hZGRTZXJ2aWNlcyhzZXJ2aWNlcylcbiAgICB9XG4gICAgaWYgKGNvbnRyb2xsZXJzKSB7XG4gICAgICB0aGlzLmFkZENvbnRyb2xsZXJzKGNvbnRyb2xsZXJzKVxuICAgIH1cbiAgfVxuXG4gIGFkZFJvdXRlKHZlcmIsIHBhdGgsIHRyYW5zYWN0ZWQsIGhhbmRsZXJzLCBjb250cm9sbGVyID0gbnVsbCwgYWN0aW9uID0gbnVsbCkge1xuICAgIGhhbmRsZXJzID0gYXNBcnJheShoYW5kbGVycylcbiAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnMubGVuZ3RoID4gMSA/IGNvbXBvc2UoaGFuZGxlcnMpIDogaGFuZGxlcnNbMF1cbiAgICAvLyBJbnN0ZWFkIG9mIGRpcmVjdGx5IHBhc3NpbmcgYGhhbmRsZXJgLCBwYXNzIGEgYHJvdXRlYCBvYmplY3QgdGhhdCBhbHNvXG4gICAgLy8gd2lsbCBiZSBleHBvc2VkIHRocm91Z2ggYGN0eC5yb3V0ZWAsIHNlZSBgcm91dGVySGFuZGxlcigpYDpcbiAgICBjb25zdCByb3V0ZSA9IHtcbiAgICAgIHZlcmIsXG4gICAgICBwYXRoLFxuICAgICAgdHJhbnNhY3RlZCxcbiAgICAgIGhhbmRsZXIsXG4gICAgICBjb250cm9sbGVyLFxuICAgICAgYWN0aW9uXG4gICAgfVxuICAgIHRoaXMucm91dGVyW3ZlcmJdKHBhdGgsIHJvdXRlKVxuICB9XG5cbiAgYWRkTW9kZWxzKG1vZGVscykge1xuICAgIC8vIEZpcnN0IGFkZCBhbGwgbW9kZWxzIHRoZW4gY2FsbCBpbml0aWFsaXplKCkgZm9yIGVhY2ggaW4gYSBzZWNvbmQgbG9vcCxcbiAgICAvLyBzaW5jZSB0aGV5IG1heSBiZSByZWZlcmVuY2luZyBlYWNoIG90aGVyIGluIHJlbGF0aW9ucy5cbiAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2YgT2JqZWN0LnZhbHVlcyhtb2RlbHMpKSB7XG4gICAgICB0aGlzLmFkZE1vZGVsKG1vZGVsQ2xhc3MpXG4gICAgfVxuICAgIC8vIE5vdyAocmUtKXNvcnQgYWxsIG1vZGVscyBiYXNlZCBvbiB0aGVpciByZWxhdGlvbnMuXG4gICAgdGhpcy5tb2RlbHMgPSB0aGlzLnNvcnRNb2RlbHModGhpcy5tb2RlbHMpXG4gICAgLy8gRmlsdGVyIHRocm91Z2ggYWxsIHNvcnRlZCBtb2RlbHMsIGtlZXBpbmcgb25seSB0aGUgbmV3bHkgYWRkZWQgb25lcy5cbiAgICBjb25zdCBzb3J0ZWRNb2RlbHMgPSBPYmplY3QudmFsdWVzKHRoaXMubW9kZWxzKS5maWx0ZXIoXG4gICAgICBtb2RlbENsYXNzID0+IG1vZGVsc1ttb2RlbENsYXNzLm5hbWVdID09PSBtb2RlbENsYXNzXG4gICAgKVxuICAgIC8vIEluaXRpYWxpemUgdGhlIGFkZGVkIG1vZGVscyBpbiBjb3JyZWN0IHNvcnRlZCBzZXF1ZW5jZSwgc28gdGhhdCBmb3IgZXZlcnlcbiAgICAvLyBtb2RlbCwgZ2V0UmVsYXRlZFJlbGF0aW9ucygpIHJldHVybnMgdGhlIGZ1bGwgbGlzdCBvZiByZWxhdGluZyByZWxhdGlvbnMuXG4gICAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIHNvcnRlZE1vZGVscykge1xuICAgICAgaWYgKG1vZGVsc1ttb2RlbENsYXNzLm5hbWVdID09PSBtb2RlbENsYXNzKSB7XG4gICAgICAgIG1vZGVsQ2xhc3Muc2V0dXAodGhpcy5rbmV4KVxuICAgICAgICAvLyBOb3cgdGhhdCB0aGUgbW9kZWxDbGFzcyBpcyBzZXQgdXAsIGNhbGwgYGluaXRpYWxpemUoKWAsIHdoaWNoIGNhbiBiZVxuICAgICAgICAvLyBvdmVycmlkZGVuIGJ5IHN1Yi1jbGFzc2VzLHdpdGhvdXQgaGF2aW5nIHRvIGNhbGwgYHN1cGVyLmluaXRpYWxpemUoKWBcbiAgICAgICAgbW9kZWxDbGFzcy5pbml0aWFsaXplKClcbiAgICAgICAgdGhpcy52YWxpZGF0b3IuYWRkU2NoZW1hKG1vZGVsQ2xhc3MuZ2V0SnNvblNjaGVtYSgpKVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB7IGxvZyB9ID0gdGhpcy5jb25maWdcbiAgICBpZiAobG9nLnNjaGVtYSB8fCBsb2cucmVsYXRpb25zKSB7XG4gICAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2Ygc29ydGVkTW9kZWxzKSB7XG4gICAgICAgIGNvbnN0IHNob3VsZExvZyA9IG9wdGlvbiA9PiAoXG4gICAgICAgICAgb3B0aW9uID09PSB0cnVlIHx8XG4gICAgICAgICAgYXNBcnJheShvcHRpb24pLmluY2x1ZGVzKG1vZGVsQ2xhc3MubmFtZSlcbiAgICAgICAgKVxuICAgICAgICBjb25zdCBkYXRhID0ge31cbiAgICAgICAgaWYgKHNob3VsZExvZyhsb2cuc2NoZW1hKSkge1xuICAgICAgICAgIGRhdGEuc2NoZW1hID0gbW9kZWxDbGFzcy5nZXRKc29uU2NoZW1hKClcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2hvdWxkTG9nKGxvZy5yZWxhdGlvbnMpKSB7XG4gICAgICAgICAgZGF0YS5yZWxhdGlvbnMgPSBjbG9uZShtb2RlbENsYXNzLnJlbGF0aW9uTWFwcGluZ3MsIHZhbHVlID0+XG4gICAgICAgICAgICBNb2RlbC5pc1Byb3RvdHlwZU9mKHZhbHVlKSA/IGBbTW9kZWw6ICR7dmFsdWUubmFtZX1dYCA6IHZhbHVlXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhkYXRhKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICAgICAgY2hhbGsueWVsbG93LmJvbGQoYFxcbiR7bW9kZWxDbGFzcy5uYW1lfTpcXG5gKSxcbiAgICAgICAgICAgIHV0aWwuaW5zcGVjdChkYXRhLCB7XG4gICAgICAgICAgICAgIGNvbG9yczogdHJ1ZSxcbiAgICAgICAgICAgICAgZGVwdGg6IG51bGwsXG4gICAgICAgICAgICAgIG1heEFycmF5TGVuZ3RoOiBudWxsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFkZE1vZGVsKG1vZGVsQ2xhc3MpIHtcbiAgICBpZiAoTW9kZWwuaXNQcm90b3R5cGVPZihtb2RlbENsYXNzKSkge1xuICAgICAgbW9kZWxDbGFzcy5hcHAgPSB0aGlzXG4gICAgICB0aGlzLm1vZGVsc1ttb2RlbENsYXNzLm5hbWVdID0gbW9kZWxDbGFzc1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbW9kZWwgY2xhc3M6ICR7bW9kZWxDbGFzc31gKVxuICAgIH1cbiAgfVxuXG4gIHNvcnRNb2RlbHMobW9kZWxzKSB7XG4gICAgY29uc3Qgc29ydEJ5UmVsYXRpb25zID0gKGxpc3QsIGNvbGxlY3RlZCA9IHt9LCBleGNsdWRlZCA9IHt9KSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2YgbGlzdCkge1xuICAgICAgICBjb25zdCB7IG5hbWUgfSA9IG1vZGVsQ2xhc3NcbiAgICAgICAgaWYgKCFjb2xsZWN0ZWRbbmFtZV0gJiYgIWV4Y2x1ZGVkW25hbWVdKSB7XG4gICAgICAgICAgZm9yIChjb25zdCByZWxhdGlvbiBvZiBPYmplY3QudmFsdWVzKG1vZGVsQ2xhc3MuZ2V0UmVsYXRpb25zKCkpKSB7XG4gICAgICAgICAgICBpZiAoIShyZWxhdGlvbiBpbnN0YW5jZW9mIEJlbG9uZ3NUb09uZVJlbGF0aW9uKSkge1xuICAgICAgICAgICAgICBjb25zdCB7IHJlbGF0ZWRNb2RlbENsYXNzLCBqb2luVGFibGVNb2RlbENsYXNzIH0gPSByZWxhdGlvblxuICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlbGF0ZWQgb2YgW2pvaW5UYWJsZU1vZGVsQ2xhc3MsIHJlbGF0ZWRNb2RlbENsYXNzXSkge1xuICAgICAgICAgICAgICAgIC8vIEV4Y2x1ZGUgc2VsZi1yZWZlcmVuY2VzIGFuZCBnZW5lcmF0ZWQgam9pbiBtb2RlbHM6XG4gICAgICAgICAgICAgICAgaWYgKHJlbGF0ZWQgJiYgcmVsYXRlZCAhPT0gbW9kZWxDbGFzcyAmJiBtb2RlbHNbcmVsYXRlZC5uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgc29ydEJ5UmVsYXRpb25zKFtyZWxhdGVkXSwgY29sbGVjdGVkLCB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEV4Y2x1ZGUgbW9kZWxDbGFzcyB0byBwcmV2ZW50IGVuZGxlc3MgcmVjdXJzaW9uczpcbiAgICAgICAgICAgICAgICAgICAgW25hbWVdOiBtb2RlbENsYXNzLFxuICAgICAgICAgICAgICAgICAgICAuLi5leGNsdWRlZFxuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29sbGVjdGVkW25hbWVdID0gbW9kZWxDbGFzc1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhjb2xsZWN0ZWQpXG4gICAgfVxuICAgIC8vIFJldHVybiBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgc29ydGVkIG1vZGVscyBhcyBpdHMga2V5L3ZhbHVlIHBhaXJzLlxuICAgIC8vIE5PVEU6IFdlIG5lZWQgdG8gcmV2ZXJzZSBmb3IgdGhlIGFib3ZlIGFsZ29yaXRobSB0byBzb3J0IHByb3Blcmx5LFxuICAgIC8vIGFuZCB0aGVuIHJldmVyc2UgdGhlIHJlc3VsdCBiYWNrLlxuICAgIHJldHVybiBzb3J0QnlSZWxhdGlvbnMoT2JqZWN0LnZhbHVlcyhtb2RlbHMpLnJldmVyc2UoKSkucmV2ZXJzZSgpLnJlZHVjZShcbiAgICAgIChtb2RlbHMsIG1vZGVsQ2xhc3MpID0+IHtcbiAgICAgICAgbW9kZWxzW21vZGVsQ2xhc3MubmFtZV0gPSBtb2RlbENsYXNzXG4gICAgICAgIHJldHVybiBtb2RlbHNcbiAgICAgIH0sXG4gICAgICBPYmplY3QuY3JlYXRlKG51bGwpXG4gICAgKVxuICB9XG5cbiAgZ2V0TW9kZWwobmFtZSkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLm1vZGVsc1tuYW1lXSB8fFxuICAgICAgIW5hbWUuZW5kc1dpdGgoJ01vZGVsJykgJiYgdGhpcy5tb2RlbHNbYCR7bmFtZX1Nb2RlbGBdIHx8XG4gICAgICBudWxsXG4gICAgKVxuICB9XG5cbiAgZmluZE1vZGVsKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5tb2RlbHMpLmZpbmQoY2FsbGJhY2spXG4gIH1cblxuICBhZGRTZXJ2aWNlcyhzZXJ2aWNlcykge1xuICAgIGZvciAoY29uc3QgW25hbWUsIHNlcnZpY2VdIG9mIE9iamVjdC5lbnRyaWVzKHNlcnZpY2VzKSkge1xuICAgICAgLy8gSGFuZGxlIEVTNiBtb2R1bGUgd2VpcmRuZXNzIHRoYXQgY2FuIGhhcHBlbiwgYXBwYXJlbnRseTpcbiAgICAgIGlmIChuYW1lID09PSAnZGVmYXVsdCcgJiYgaXNQbGFpbk9iamVjdChzZXJ2aWNlKSkge1xuICAgICAgICB0aGlzLmFkZFNlcnZpY2VzKHNlcnZpY2UpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFkZFNlcnZpY2Uoc2VydmljZSwgbmFtZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhZGRTZXJ2aWNlKHNlcnZpY2UsIG5hbWUpIHtcbiAgICAvLyBBdXRvLWluc3RhbnRpYXRlIGNvbnRyb2xsZXIgY2xhc3NlczpcbiAgICBpZiAoU2VydmljZS5pc1Byb3RvdHlwZU9mKHNlcnZpY2UpKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcFxuICAgICAgc2VydmljZSA9IG5ldyBzZXJ2aWNlKHRoaXMsIG5hbWUpXG4gICAgfVxuICAgIGlmICghKHNlcnZpY2UgaW5zdGFuY2VvZiBTZXJ2aWNlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHNlcnZpY2U6ICR7c2VydmljZX1gKVxuICAgIH1cbiAgICAvLyBPbmx5IGFmdGVyIHRoZSBjb25zdHJ1Y3RvciBpcyBjYWxsZWQsIGBzZXJ2aWNlLm5hbWVgIGlzIGd1YXJhbnRlZWQgdG8gYmVcbiAgICAvLyBzZXQgdG8gdGhlIGNvcnJlY3QgdmFsdWUsIGUuZy4gd2l0aCBhbiBhZnRlci1jb25zdHJ1Y3RvciBjbGFzcyBwcm9wZXJ0eS5cbiAgICAoeyBuYW1lIH0gPSBzZXJ2aWNlKVxuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuY29uZmlnLnNlcnZpY2VzW25hbWVdXG4gICAgaWYgKGNvbmZpZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvbmZpZ3VyYXRpb24gbWlzc2luZyBmb3Igc2VydmljZSAnJHtuYW1lfSdgKVxuICAgIH1cbiAgICAvLyBBcyBhIGNvbnZlbnRpb24sIHRoZSBjb25maWd1cmF0aW9uIG9mIGEgc2VydmljZSBjYW4gYmUgc2V0IHRvIGBmYWxzZWBcbiAgICAvLyBpbiBvcmRlciB0byBlbnRpcmVseSBkZWFjdGl2YXRlIHRoZSBzZXJ2aWNlLlxuICAgIGlmIChjb25maWcgIT09IGZhbHNlKSB7XG4gICAgICBzZXJ2aWNlLnNldHVwKGNvbmZpZylcbiAgICAgIHRoaXMuc2VydmljZXNbbmFtZV0gPSBzZXJ2aWNlXG4gICAgICAvLyBOb3cgdGhhdCB0aGUgc2VydmljZSBpcyBzZXQgdXAsIGNhbGwgYGluaXRpYWxpemUoKWAgd2hpY2ggY2FuIGJlXG4gICAgICAvLyBvdmVycmlkZGVuIGJ5IHNlcnZpY2VzLlxuICAgICAgc2VydmljZS5pbml0aWFsaXplKClcbiAgICB9XG4gIH1cblxuICBnZXRTZXJ2aWNlKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2aWNlc1tuYW1lXSB8fCBudWxsXG4gIH1cblxuICBmaW5kU2VydmljZShjYWxsYmFjaykge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuc2VydmljZXMpLmZpbmQoY2FsbGJhY2spXG4gIH1cblxuICBmb3JFYWNoU2VydmljZShjYWxsYmFjaykge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChPYmplY3QudmFsdWVzKHRoaXMuc2VydmljZXMpLm1hcChjYWxsYmFjaykpXG4gIH1cblxuICBhZGRDb250cm9sbGVycyhjb250cm9sbGVycywgbmFtZXNwYWNlKSB7XG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoY29udHJvbGxlcnMpKSB7XG4gICAgICBpZiAoaXNQbGFpbk9iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgdGhpcy5hZGRDb250cm9sbGVycyh2YWx1ZSwgbmFtZXNwYWNlID8gYCR7bmFtZXNwYWNlfS8ke2tleX1gIDoga2V5KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hZGRDb250cm9sbGVyKHZhbHVlLCBuYW1lc3BhY2UpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYWRkQ29udHJvbGxlcihjb250cm9sbGVyLCBuYW1lc3BhY2UpIHtcbiAgICAvLyBDb250cm9sbGVycyByZXF1aXJlIGFkZGl0aW9uYWwgbWlkZGxld2FyZSB0byBiZSBpbnN0YWxsZWQgb25jZS5cbiAgICB0aGlzLnNldHVwQ29udHJvbGxlck1pZGRsZXdhcmUoKVxuICAgIC8vIEF1dG8taW5zdGFudGlhdGUgY29udHJvbGxlciBjbGFzc2VzOlxuICAgIGlmIChDb250cm9sbGVyLmlzUHJvdG90eXBlT2YoY29udHJvbGxlcikpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuZXctY2FwXG4gICAgICBjb250cm9sbGVyID0gbmV3IGNvbnRyb2xsZXIodGhpcywgbmFtZXNwYWNlKVxuICAgIH1cbiAgICBpZiAoIShjb250cm9sbGVyIGluc3RhbmNlb2YgQ29udHJvbGxlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBjb250cm9sbGVyOiAke2NvbnRyb2xsZXJ9YClcbiAgICB9XG4gICAgLy8gSW5oZXJpdGFuY2Ugb2YgYWN0aW9uIG1ldGhvZHMgY2Fubm90IGhhcHBlbiBpbiB0aGUgY29uc3RydWN0b3IgaXRzZWxmLFxuICAgIC8vIHNvIGNhbGwgc2VwYXJhdGUgYHNldHVwKClgIG1ldGhvZCBhZnRlciBpbiBvcmRlciB0byB0YWtlIGNhcmUgb2YgaXQuXG4gICAgY29udHJvbGxlci5zZXR1cCgpXG4gICAgdGhpcy5jb250cm9sbGVyc1tjb250cm9sbGVyLnVybF0gPSBjb250cm9sbGVyXG4gICAgLy8gTm93IHRoYXQgdGhlIGNvbnRyb2xsZXIgaXMgc2V0IHVwLCBjYWxsIGBpbml0aWFsaXplKClgIHdoaWNoIGNhbiBiZVxuICAgIC8vIG92ZXJyaWRkZW4gYnkgY29udHJvbGxlcnMuXG4gICAgY29udHJvbGxlci5pbml0aWFsaXplKClcbiAgICAvLyBFYWNoIGNvbnRyb2xsZXIgY2FuIGFsc28gcHJvdmlkZSBmdXJ0aGVyIG1pZGRsZXdhcmUsIGUuZy5cbiAgICAvLyBgQWRtaW5Db250cm9sbGVyYDpcbiAgICBjb25zdCBtaWRkbGV3YXJlID0gY29udHJvbGxlci5jb21wb3NlKClcbiAgICBpZiAobWlkZGxld2FyZSkge1xuICAgICAgdGhpcy51c2UobWlkZGxld2FyZSlcbiAgICB9XG4gIH1cblxuICBnZXRDb250cm9sbGVyKHVybCkge1xuICAgIHJldHVybiB0aGlzLmNvbnRyb2xsZXJzW3VybF0gfHwgbnVsbFxuICB9XG5cbiAgZmluZENvbnRyb2xsZXIoY2FsbGJhY2spIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLmNvbnRyb2xsZXJzKS5maW5kKGNhbGxiYWNrKVxuICB9XG5cbiAgZ2V0QWRtaW5Db250cm9sbGVyKCkge1xuICAgIHJldHVybiB0aGlzLmZpbmRDb250cm9sbGVyKFxuICAgICAgY29udHJvbGxlciA9PiBjb250cm9sbGVyIGluc3RhbmNlb2YgQWRtaW5Db250cm9sbGVyXG4gICAgKVxuICB9XG5cbiAgZ2V0QWRtaW5WdWVDb25maWcoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QWRtaW5Db250cm9sbGVyKCk/LmdldFZ1ZUNvbmZpZygpIHx8IG51bGxcbiAgfVxuXG4gIGdldEFzc2V0Q29uZmlnKHtcbiAgICBtb2RlbHMgPSBPYmplY3Qua2V5cyh0aGlzLm1vZGVscyksXG4gICAgbm9ybWFsaXplRGJOYW1lcyA9IHRoaXMuY29uZmlnLmtuZXgubm9ybWFsaXplRGJOYW1lc1xuICB9ID0ge30pIHtcbiAgICBjb25zdCBhc3NldENvbmZpZyA9IHt9XG4gICAgZm9yIChjb25zdCBtb2RlbE5hbWUgb2YgbW9kZWxzKSB7XG4gICAgICBjb25zdCBtb2RlbENsYXNzID0gdGhpcy5tb2RlbHNbbW9kZWxOYW1lXVxuICAgICAgY29uc3QgeyBhc3NldHMgfSA9IG1vZGVsQ2xhc3MuZGVmaW5pdGlvblxuICAgICAgaWYgKGFzc2V0cykge1xuICAgICAgICBjb25zdCBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplRGJOYW1lc1xuICAgICAgICAgID8gdGhpcy5ub3JtYWxpemVJZGVudGlmaWVyKG1vZGVsTmFtZSlcbiAgICAgICAgICA6IG1vZGVsTmFtZVxuICAgICAgICBjb25zdCBjb252ZXJ0ZWRBc3NldHMgPSB7fVxuICAgICAgICBmb3IgKGNvbnN0IFthc3NldERhdGFQYXRoLCBjb25maWddIG9mIE9iamVjdC5lbnRyaWVzKGFzc2V0cykpIHtcbiAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgIG5lc3RlZERhdGFQYXRoLFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGluZGV4XG4gICAgICAgICAgfSA9IG1vZGVsQ2xhc3MuZ2V0UHJvcGVydHlPclJlbGF0aW9uQXREYXRhUGF0aChhc3NldERhdGFQYXRoKVxuICAgICAgICAgIGlmIChwcm9wZXJ0eSAmJiBpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZE5hbWUgPSBub3JtYWxpemVEYk5hbWVzXG4gICAgICAgICAgICAgID8gdGhpcy5ub3JtYWxpemVJZGVudGlmaWVyKG5hbWUpXG4gICAgICAgICAgICAgIDogbmFtZVxuICAgICAgICAgICAgY29uc3QgZGF0YVBhdGggPSBub3JtYWxpemVEYXRhUGF0aChbXG4gICAgICAgICAgICAgIG5vcm1hbGl6ZWROYW1lLFxuICAgICAgICAgICAgICAuLi5wYXJzZURhdGFQYXRoKG5lc3RlZERhdGFQYXRoKVxuICAgICAgICAgICAgXSlcbiAgICAgICAgICAgIGNvbnN0IGFzc2V0Q29uZmlncyA9IGNvbnZlcnRlZEFzc2V0c1tub3JtYWxpemVkTmFtZV0gfHw9IHt9XG4gICAgICAgICAgICBhc3NldENvbmZpZ3NbZGF0YVBhdGhdID0gY29uZmlnXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTmVzdGVkIGdyYXBoIHByb3BlcnRpZXMgYXJlIG5vdCBzdXBwb3J0ZWQgeWV0JylcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXNzZXRDb25maWdbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBjb252ZXJ0ZWRBc3NldHNcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFzc2V0Q29uZmlnXG4gIH1cblxuICBhZGRTdG9yYWdlcyhzdG9yYWdlcykge1xuICAgIGZvciAoY29uc3QgW25hbWUsIGNvbmZpZ10gb2YgT2JqZWN0LmVudHJpZXMoc3RvcmFnZXMpKSB7XG4gICAgICB0aGlzLmFkZFN0b3JhZ2UoY29uZmlnLCBuYW1lKVxuICAgIH1cbiAgfVxuXG4gIGFkZFN0b3JhZ2UoY29uZmlnLCBuYW1lKSB7XG4gICAgbGV0IHN0b3JhZ2UgPSBudWxsXG4gICAgaWYgKGlzUGxhaW5PYmplY3QoY29uZmlnKSkge1xuICAgICAgY29uc3Qgc3RvcmFnZUNsYXNzID0gU3RvcmFnZS5nZXQoY29uZmlnLnR5cGUpXG4gICAgICBpZiAoIXN0b3JhZ2VDbGFzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHN0b3JhZ2U6ICR7Y29uZmlnfWApXG4gICAgICB9XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcFxuICAgICAgc3RvcmFnZSA9IG5ldyBzdG9yYWdlQ2xhc3ModGhpcywgY29uZmlnKVxuICAgIH0gZWxzZSBpZiAoY29uZmlnIGluc3RhbmNlb2YgU3RvcmFnZSkge1xuICAgICAgc3RvcmFnZSA9IGNvbmZpZ1xuICAgIH1cbiAgICBpZiAoc3RvcmFnZSkge1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgc3RvcmFnZS5uYW1lID0gbmFtZVxuICAgICAgfVxuICAgICAgdGhpcy5zdG9yYWdlc1tzdG9yYWdlLm5hbWVdID0gc3RvcmFnZVxuICAgIH1cbiAgICByZXR1cm4gc3RvcmFnZVxuICB9XG5cbiAgZ2V0U3RvcmFnZShuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZXNbbmFtZV0gfHwgbnVsbFxuICB9XG5cbiAgY29tcGlsZVZhbGlkYXRvcihqc29uU2NoZW1hLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGpzb25TY2hlbWFcbiAgICAgID8gdGhpcy52YWxpZGF0b3IuY29tcGlsZShqc29uU2NoZW1hLCBvcHRpb25zKVxuICAgICAgOiBudWxsXG4gIH1cblxuICBjb21waWxlUGFyYW1ldGVyc1ZhbGlkYXRvcihwYXJhbWV0ZXJzLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBsaXN0ID0gW11cbiAgICBjb25zdCB7IGRhdGFOYW1lID0gJ2RhdGEnIH0gPSBvcHRpb25zXG5cbiAgICBsZXQgcHJvcGVydGllcyA9IG51bGxcbiAgICBjb25zdCBhZGRQYXJhbWV0ZXIgPSAobmFtZSwgc2NoZW1hKSA9PiB7XG4gICAgICBsaXN0LnB1c2goe1xuICAgICAgICBuYW1lOiBuYW1lID8/IG51bGwsXG4gICAgICAgIC4uLnNjaGVtYVxuICAgICAgfSlcbiAgICAgIGlmICghc2NoZW1hLm1lbWJlcikge1xuICAgICAgICBwcm9wZXJ0aWVzIHx8PSB7fVxuICAgICAgICBwcm9wZXJ0aWVzW25hbWUgfHwgZGF0YU5hbWVdID0gc2NoZW1hXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU3VwcG9ydCB0d28gZm9ybWF0cyBvZiBwYXJhbWV0ZXJzIGRlZmluaXRpb25zOlxuICAgIC8vIC0gQW4gYXJyYXkgb2YgcGFyYW1ldGVyIHNjaGVtYXMsIG5hbWVkIGJ5IHRoZWlyIGBuYW1lYCBrZXkuXG4gICAgLy8gLSBBbiBvYmplY3Qgb2YgcGFyYW1ldGVyIHNjaGVtYXMsIG5hbWVkIGJ5IHRoZSBrZXkgdW5kZXIgd2hpY2ggZWFjaFxuICAgIC8vICAgc2NoZW1hIGlzIHN0b3JlZCBpbiB0aGUgcm9vdCBvYmplY3QuXG4gICAgLy8gSWYgYW4gYXJyYXkgaXMgcGFzc2VkLCB0aGVuIHRoZSBjb250cm9sbGVyIGFjdGlvbnMgcmVjZWl2ZXMgdGhlXG4gICAgLy8gcGFyYW1ldGVycyBhcyBzZXBhcmF0ZSBhcmd1bWVudHMuIElmIGFuIG9iamVjdCBpcyBwYXNzZWQsIHRoZW4gdGhlXG4gICAgLy8gYWN0aW9ucyByZWNlaXZlcyBvbmUgcGFyYW1ldGVyIG9iamVjdCB3aGVyZSB1bmRlciB0aGUgc2FtZSBrZXlzIHRoZVxuICAgIC8vIHNwZWNpZmllZCBwYXJhbWV0ZXIgdmFsdWVzIGFyZSBzdG9yZWQuXG4gICAgbGV0IGFzT2JqZWN0ID0gZmFsc2VcbiAgICBpZiAoaXNBcnJheShwYXJhbWV0ZXJzKSkge1xuICAgICAgZm9yIChjb25zdCB7IG5hbWUsIC4uLnNjaGVtYSB9IG9mIHBhcmFtZXRlcnMpIHtcbiAgICAgICAgYWRkUGFyYW1ldGVyKG5hbWUsIHNjaGVtYSlcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHBhcmFtZXRlcnMpKSB7XG4gICAgICBhc09iamVjdCA9IHRydWVcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIHNjaGVtYV0gb2YgT2JqZWN0LmVudHJpZXMocGFyYW1ldGVycykpIHtcbiAgICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICAgIGFkZFBhcmFtZXRlcihuYW1lLCBzY2hlbWEpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHBhcmFtZXRlcnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwYXJhbWV0ZXJzIGRlZmluaXRpb246ICR7cGFyYW1ldGVyc31gKVxuICAgIH1cbiAgICAvLyBOT1RFOiBJZiBwcm9wZXJ0aWVzIGlzIG51bGwsIHNjaGVtYSBhbmQgdmFsaWRhdGUgd2lsbCBiZWNvbWUgbnVsbCB0b28uXG4gICAgLy8gTk9URTogSWYgaXQgaXMgbm90IG51bGwsIGl0IHdpbGwgZ2V0IGV4cGFuZGVkIHRvIGFuIG9iamVjdCBzY2hlbWEuXG4gICAgY29uc3Qgc2NoZW1hID0gY29udmVydFNjaGVtYShwcm9wZXJ0aWVzLCBvcHRpb25zKVxuICAgIGNvbnN0IHZhbGlkYXRlID0gdGhpcy5jb21waWxlVmFsaWRhdG9yKHNjaGVtYSwge1xuICAgICAgLy8gRm9yIHBhcmFtZXRlcnMsIGFsd2F5cyBjb2VyY2UgdHlwZXMsIGluY2x1ZGluZyBhcnJheXMuXG4gICAgICBjb2VyY2VUeXBlczogJ2FycmF5JyxcbiAgICAgIC4uLm9wdGlvbnNcbiAgICB9KVxuICAgIGNvbnN0IGN0eCA9IHtcbiAgICAgIGFwcDogdGhpcyxcbiAgICAgIHZhbGlkYXRvcjogdGhpcy52YWxpZGF0b3IsXG4gICAgICBvcHRpb25zXG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBsaXN0LFxuICAgICAgc2NoZW1hLFxuICAgICAgYXNPYmplY3QsXG4gICAgICBkYXRhTmFtZSxcbiAgICAgIHZhbGlkYXRlOiB2YWxpZGF0ZVxuICAgICAgICAvLyBVc2UgYGNhbGwoKWAgdG8gcGFzcyBjdHggYXMgY29udGV4dCB0byBBanYsIHNlZSBwYXNzQ29udGV4dDpcbiAgICAgICAgPyBkYXRhID0+IHZhbGlkYXRlLmNhbGwoY3R4LCBkYXRhKVxuICAgICAgICA6IG51bGxcbiAgICB9XG4gIH1cblxuICBjcmVhdGVWYWxpZGF0aW9uRXJyb3IoeyB0eXBlLCBtZXNzYWdlLCBlcnJvcnMsIG9wdGlvbnMsIGpzb24gfSkge1xuICAgIHJldHVybiBuZXcgVmFsaWRhdGlvbkVycm9yKHtcbiAgICAgIHR5cGUsXG4gICAgICBtZXNzYWdlLFxuICAgICAgZXJyb3JzOiB0aGlzLnZhbGlkYXRvci5wYXJzZUVycm9ycyhlcnJvcnMsIG9wdGlvbnMpLFxuICAgICAgLy8gT25seSBpbmNsdWRlIHRoZSBKU09OIGRhdGEgaW4gdGhlIGVycm9yIGlmIGBsb2cuZXJyb3JzLmpzb25gaXMgc2V0LlxuICAgICAganNvbjogdGhpcy5jb25maWcubG9nLmVycm9ycz8uanNvbiA/IGpzb24gOiB1bmRlZmluZWRcbiAgICB9KVxuICB9XG5cbiAgY3JlYXRlRGF0YWJhc2VFcnJvcihlcnJvcikge1xuICAgIC8vIFJlbW92ZSBrbmV4IFNRTCBxdWVyeSBhbmQgbW92ZSB0byBzZXBhcmF0ZSBgc3FsYCBwcm9wZXJ0eS5cbiAgICAvLyBUT0RPOiBGaXggdGhpcyBwcm9wZXJseSBpbiBLbmV4IC8gT2JqZWN0aW9uIGluc3RlYWQsIHNlZTpcbiAgICAvLyBodHRwczovL2dpdHRlci5pbS9WaW5jaXQvb2JqZWN0aW9uLmpzP2F0PTVhNjg3MjhmNWE5ZWJlNGY3NWNhNDBiMFxuICAgIGNvbnN0IFssIHNxbCwgbWVzc2FnZV0gPSBlcnJvci5tZXNzYWdlLm1hdGNoKC9eKFtcXHNcXFNdKikgLSAoW1xcc1xcU10qPykkLykgfHxcbiAgICAgIFtudWxsLCBudWxsLCBlcnJvci5tZXNzYWdlXVxuICAgIHJldHVybiBuZXcgRGF0YWJhc2VFcnJvcihlcnJvciwge1xuICAgICAgbWVzc2FnZSxcbiAgICAgIC8vIE9ubHkgaW5jbHVkZSB0aGUgU1FMIHF1ZXJ5IGluIHRoZSBlcnJvciBpZiBgbG9nLmVycm9ycy5zcWxgaXMgc2V0LlxuICAgICAgc3FsOiB0aGlzLmNvbmZpZy5sb2cuZXJyb3JzPy5zcWwgPyBzcWwgOiB1bmRlZmluZWRcbiAgICB9KVxuICB9XG5cbiAgc2V0dXBHbG9iYWxNaWRkbGV3YXJlKCkge1xuICAgIGNvbnN0IHsgYXBwLCBsb2cgfSA9IHRoaXMuY29uZmlnXG5cbiAgICB0aGlzLnVzZShhdHRhY2hMb2dnZXIodGhpcy5sb2dnZXIpKVxuXG4gICAgaWYgKGFwcC5yZXNwb25zZVRpbWUgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnVzZShyZXNwb25zZVRpbWUoZ2V0T3B0aW9ucyhhcHAucmVzcG9uc2VUaW1lKSkpXG4gICAgfVxuICAgIGlmIChsb2cucmVxdWVzdHMpIHtcbiAgICAgIHRoaXMudXNlKGxvZ1JlcXVlc3RzKCkpXG4gICAgfVxuICAgIC8vIE5lZWRzIHRvIGJlIHBvc2l0aW9uZWQgYWZ0ZXIgdGhlIHJlcXVlc3QgbG9nZ2VyIHRvIGxvZyB0aGUgY29ycmVjdFxuICAgIC8vIHJlc3BvbnNlIHN0YXR1cy5cbiAgICB0aGlzLnVzZShoYW5kbGVFcnJvcigpKVxuICAgIGlmIChhcHAuaGVsbWV0ICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy51c2UoaGVsbWV0KGdldE9wdGlvbnMoYXBwLmhlbG1ldCkpKVxuICAgIH1cbiAgICBpZiAoYXBwLmNvcnMgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnVzZShjb3JzKGdldE9wdGlvbnMoYXBwLmNvcnMpKSlcbiAgICB9XG4gICAgaWYgKGFwcC5jb21wcmVzcyAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMudXNlKGNvbXByZXNzKG1lcmdlKFxuICAgICAgICB7XG4gICAgICAgICAgLy8gVXNlIGEgcmVhc29uYWJsZSBkZWZhdWx0IGZvciBCcm90bGkgY29tcHJlc3Npb24uXG4gICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9rb2Fqcy9jb21wcmVzcy9pc3N1ZXMvMTI2XG4gICAgICAgICAgYnI6IHtcbiAgICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgICBbemxpYi5jb25zdGFudHMuQlJPVExJX1BBUkFNX1FVQUxJVFldOiA0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBnZXRPcHRpb25zKGFwcC5jb21wcmVzcylcbiAgICAgICkpKVxuICAgIH1cbiAgICBpZiAoYXBwLmV0YWcgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnVzZShjb25kaXRpb25hbCgpKVxuICAgICAgdGhpcy51c2UoZXRhZygpKVxuICAgIH1cbiAgfVxuXG4gIHNldHVwQ29udHJvbGxlck1pZGRsZXdhcmUoKSB7XG4gICAgLy8gTk9URTogVGhpcyBpcyBub3QgcGFydCBvZiB0aGUgYXV0b21hdGljIGBzZXR1cEdsb2JhbE1pZGRsZXdhcmUoKWAgc28gdGhhdFxuICAgIC8vIGFwcHMgY2FuIHNldCB1cCB0aGUgc3RhdGljIHNlcnZpbmcgb2YgYXNzZXRzIGJlZm9yZSBpbnN0YWxsaW5nIHRoZVxuICAgIC8vIHNlc3Npb24gYW5kIHBhc3Nwb3J0IG1pZGRsZXdhcmUuIEl0IGlzIGNhbGxlZCBmcm9tIGBhZGRDb250cm9sbGVyKClgLlxuICAgIC8vIFVzZSBhIGZsYWcgdG8gb25seSBpbnN0YWxsIHRoZSBtaWRkbGV3YXJlIG9uY2U6XG4gICAgaWYgKCF0aGlzLmhhc0NvbnRyb2xsZXJNaWRkbGV3YXJlKSB7XG4gICAgICBjb25zdCB7IGFwcCB9ID0gdGhpcy5jb25maWdcbiAgICAgIC8vIFNlcXVlbmNlIGlzIGltcG9ydGFudDpcbiAgICAgIC8vIDEuIGJvZHkgcGFyc2VyXG4gICAgICB0aGlzLnVzZShib2R5UGFyc2VyKGdldE9wdGlvbnMoYXBwLmJvZHlQYXJzZXIpKSlcbiAgICAgIC8vIDIuIGZpbmQgcm91dGUgZnJvbSByb3V0ZXMgaW5zdGFsbGVkIGJ5IGNvbnRyb2xsZXJzLlxuICAgICAgdGhpcy51c2UoZmluZFJvdXRlKHRoaXMucm91dGVyKSlcbiAgICAgIC8vIDMuIHJlc3BlY3QgdHJhbnNhY3RlZCBzZXR0aW5ncywgY3JlYXRlIGFuZCBoYW5kbGUgdHJhbnNhY3Rpb25zLlxuICAgICAgdGhpcy51c2UoY3JlYXRlVHJhbnNhY3Rpb24oKSlcbiAgICAgIC8vIDQuIHNlc3Npb25cbiAgICAgIGlmIChhcHAuc2Vzc2lvbikge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgbW9kZWxDbGFzcyxcbiAgICAgICAgICAuLi5vcHRpb25zXG4gICAgICAgIH0gPSBnZXRPcHRpb25zKGFwcC5zZXNzaW9uKVxuICAgICAgICBpZiAobW9kZWxDbGFzcykge1xuICAgICAgICAgIC8vIENyZWF0ZSBhIENvbnRleHRTdG9yZSB0aGF0IHJlc29sdmVkIHRoZSBzcGVjaWZpZWQgbW9kZWwgY2xhc3MsXG4gICAgICAgICAgLy8gdXNlcyBpdCB0byBwZXJzaXN0IGFuZCByZXRyaWV2ZSB0aGUgc2Vzc2lvbiwgYW5kIGF1dG9tYXRpY2FsbHlcbiAgICAgICAgICAvLyBiaW5kcyBhbGwgZGIgb3BlcmF0aW9ucyB0byBgY3R4LnRyYW5zYWN0aW9uYCwgaWYgaXQgaXMgc2V0LlxuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuZXctY2FwXG4gICAgICAgICAgb3B0aW9ucy5Db250ZXh0U3RvcmUgPSBTZXNzaW9uU3RvcmUobW9kZWxDbGFzcylcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVzZShzZXNzaW9uKG9wdGlvbnMsIHRoaXMpKVxuICAgICAgfVxuICAgICAgLy8gNS4gcGFzc3BvcnRcbiAgICAgIGlmIChhcHAucGFzc3BvcnQpIHtcbiAgICAgICAgdGhpcy51c2UocGFzc3BvcnQuaW5pdGlhbGl6ZSgpKVxuICAgICAgICBpZiAoYXBwLnNlc3Npb24pIHtcbiAgICAgICAgICB0aGlzLnVzZShwYXNzcG9ydC5zZXNzaW9uKCkpXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51c2UoaGFuZGxlVXNlcigpKVxuICAgICAgfVxuXG4gICAgICAvLyA2LiBmaW5hbGx5IGhhbmRsZSB0aGUgZm91bmQgcm91dGUsIG9yIHNldCBzdGF0dXMgLyBhbGxvdyBhY2NvcmRpbmdseS5cbiAgICAgIHRoaXMudXNlKGhhbmRsZVJvdXRlKCkpXG4gICAgICB0aGlzLmhhc0NvbnRyb2xsZXJNaWRkbGV3YXJlID0gdHJ1ZVxuICAgIH1cbiAgfVxuXG4gIHNldHVwTG9nZ2VyKCkge1xuICAgIGNvbnN0IHsgZXJyLCByZXEsIHJlcyB9ID0gcGluby5zdGRTZXJpYWxpemVyc1xuICAgIC8vIE9ubHkgaW5jbHVkZSBgaWRgIGZyb20gdGhlIHVzZXIsIHRvIG5vdCBpbmFkdmVydGVudGx5IGxvZyBQSUkuXG4gICAgY29uc3QgdXNlciA9IHVzZXIgPT4gKHsgaWQ6IHVzZXIuaWQgfSlcbiAgICBjb25zdCBzZXJpYWxpemVycyA9IHsgZXJyLCByZXEsIHJlcywgdXNlciB9XG5cbiAgICBjb25zdCBsb2dnZXIgPSBwaW5vKG1lcmdlKFxuICAgICAge1xuICAgICAgICBsZXZlbDogJ2luZm8nLFxuICAgICAgICBzZXJpYWxpemVycyxcbiAgICAgICAgcHJldHR5UHJpbnQ6IHtcbiAgICAgICAgICAvLyBMaXN0IG9mIGtleXMgdG8gaWdub3JlIGluIHByZXR0eSBtb2RlLlxuICAgICAgICAgIGlnbm9yZTogJ3JlcSxyZXMsZHVyYXRpb25Ncyx1c2VyLHJlcXVlc3RJZCcsXG4gICAgICAgICAgLy8gU1lTIHRvIHVzZSBzeXN0ZW0gdGltZSBhbmQgbm90IFVUQy5cbiAgICAgICAgICB0cmFuc2xhdGVUaW1lOiAnU1lTOkhIOk1NOnNzLmwnXG4gICAgICAgIH0sXG4gICAgICAgIC8vIFJlZGFjdCBjb21tb24gc2Vuc2l0aXZlIGhlYWRlcnMuXG4gICAgICAgIHJlZGFjdDogW1xuICAgICAgICAgICcqLmhlYWRlcnNbXCJjb29raWVcIl0nLFxuICAgICAgICAgICcqLmhlYWRlcnNbXCJzZXQtY29va2llXCJdJyxcbiAgICAgICAgICAnKi5oZWFkZXJzW1wiYXV0aG9yaXphdGlvblwiXSdcbiAgICAgICAgXSxcbiAgICAgICAgYmFzZTogbnVsbCAvLyBubyBwaWQsaG9zdG5hbWUsbmFtZVxuICAgICAgfSxcbiAgICAgIGdldE9wdGlvbnModGhpcy5jb25maWcubG9nZ2VyKVxuICAgICkpXG5cbiAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlci5jaGlsZCh7IG5hbWU6ICdhcHAnIH0pXG4gIH1cblxuICBzZXR1cEtuZXgoKSB7XG4gICAgbGV0IHsga25leCwgbG9nIH0gPSB0aGlzLmNvbmZpZ1xuICAgIGlmIChrbmV4Py5jbGllbnQpIHtcbiAgICAgIGNvbnN0IHNuYWtlQ2FzZU9wdGlvbnMgPSBrbmV4Lm5vcm1hbGl6ZURiTmFtZXMgPT09IHRydWVcbiAgICAgICAgPyB7fVxuICAgICAgICA6IGtuZXgubm9ybWFsaXplRGJOYW1lc1xuICAgICAgaWYgKHNuYWtlQ2FzZU9wdGlvbnMpIHtcbiAgICAgICAga25leCA9IHtcbiAgICAgICAgICAuLi5rbmV4LFxuICAgICAgICAgIC4uLmtuZXhTbmFrZUNhc2VNYXBwZXJzKHNuYWtlQ2FzZU9wdGlvbnMpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMua25leCA9IEtuZXgoa25leClcbiAgICAgIGlmIChsb2cuc3FsKSB7XG4gICAgICAgIHRoaXMuc2V0dXBLbmV4TG9nZ2luZygpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc2V0dXBLbmV4TG9nZ2luZygpIHtcbiAgICBjb25zdCBzdGFydFRpbWVzID0ge31cbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLmxvZ2dlci5jaGlsZCh7IG5hbWU6ICdzcWwnIH0pXG4gICAgZnVuY3Rpb24gZW5kKHF1ZXJ5LCB7IHJlc3BvbnNlLCBlcnJvciB9KSB7XG4gICAgICBjb25zdCBpZCA9IHF1ZXJ5Ll9fa25leFF1ZXJ5VWlkXG4gICAgICBjb25zdCBkaWZmID0gcHJvY2Vzcy5ocnRpbWUoc3RhcnRUaW1lc1tpZF0pXG4gICAgICBjb25zdCBkdXJhdGlvbiA9IGRpZmZbMF0gKiAxZTMgKyBkaWZmWzFdIC8gMWU2XG4gICAgICBkZWxldGUgc3RhcnRUaW1lc1tpZF1cbiAgICAgIGNvbnN0IHsgc3FsLCBiaW5kaW5ncyB9ID0gcXVlcnlcbiAgICAgIHJlc3BvbnNlID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICBPYmplY3QuZW50cmllcyhyZXNwb25zZSkuZmlsdGVyKFxuICAgICAgICAgIChba2V5XSkgPT4gIWtleS5zdGFydHNXaXRoKCdfJylcbiAgICAgICAgKVxuICAgICAgKVxuICAgICAgbG9nZ2VyLmluZm8oeyBkdXJhdGlvbiwgYmluZGluZ3MsIHJlc3BvbnNlLCBlcnJvciB9LCBzcWwpXG4gICAgfVxuXG4gICAgdGhpcy5rbmV4XG4gICAgICAub24oJ3F1ZXJ5JywgcXVlcnkgPT4ge1xuICAgICAgICBzdGFydFRpbWVzW3F1ZXJ5Ll9fa25leFF1ZXJ5VWlkXSA9IHByb2Nlc3MuaHJ0aW1lKClcbiAgICAgIH0pXG4gICAgICAub24oJ3F1ZXJ5LXJlc3BvbnNlJywgKHJlc3BvbnNlLCBxdWVyeSkgPT4ge1xuICAgICAgICBlbmQocXVlcnksIHsgcmVzcG9uc2UgfSlcbiAgICAgIH0pXG4gICAgICAub24oJ3F1ZXJ5LWVycm9yJywgKGVycm9yLCBxdWVyeSkgPT4ge1xuICAgICAgICBlbmQocXVlcnksIHsgZXJyb3IgfSlcbiAgICAgIH0pXG4gIH1cblxuICBub3JtYWxpemVJZGVudGlmaWVyKGlkZW50aWZpZXIpIHtcbiAgICByZXR1cm4gdGhpcy5rbmV4LmNsaWVudC53cmFwSWRlbnRpZmllcihpZGVudGlmaWVyKS5yZXBsYWNlKC9bJ2BcIl0vZywgJycpXG4gIH1cblxuICBkZW5vcm1hbGl6ZUlkZW50aWZpZXIoaWRlbnRpZmllcikge1xuICAgIGNvbnN0IG9iaiA9IHRoaXMua25leC5jbGllbnQucG9zdFByb2Nlc3NSZXNwb25zZSh7IFtpZGVudGlmaWVyXTogMSB9KVxuICAgIHJldHVybiBPYmplY3Qua2V5cyhvYmopWzBdXG4gIH1cblxuICBub3JtYWxpemVQYXRoKHBhdGgpIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuYXBwLm5vcm1hbGl6ZVBhdGhzID8gaHlwaGVuYXRlKHBhdGgpIDogcGF0aFxuICB9XG5cbiAgZm9ybWF0RXJyb3IoZXJyKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9IGVyci50b0pTT05cbiAgICAgID8gZm9ybWF0SnNvbihlcnIudG9KU09OKCkpXG4gICAgICA6IGVyci5tZXNzYWdlIHx8IGVyclxuICAgIGNvbnN0IHN0ciA9IGAke2Vyci5uYW1lfTogJHttZXNzYWdlfWBcbiAgICByZXR1cm4gZXJyLnN0YWNrICYmIHRoaXMuY29uZmlnLmxvZy5lcnJvcnM/LnN0YWNrICE9PSBmYWxzZVxuICAgICAgPyBgJHtzdHJ9XFxuJHtlcnIuc3RhY2suc3BsaXQoL1xcbnxcXHJcXG58XFxyLykuc2xpY2UoMSkuam9pbihvcy5FT0wpfWBcbiAgICAgIDogc3RyXG4gIH1cblxuICBsb2dFcnJvcihlcnIsIGN0eCkge1xuICAgIGlmICghZXJyLmV4cG9zZSAmJiAhdGhpcy5zaWxlbnQpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHRleHQgPSB0aGlzLmZvcm1hdEVycm9yKGVycilcbiAgICAgICAgY29uc3QgbGV2ZWwgPVxuICAgICAgICAgIGVyciBpbnN0YW5jZW9mIFJlc3BvbnNlRXJyb3IgJiYgZXJyLnN0YXR1cyA8IDUwMCA/ICdpbmZvJyA6ICdlcnJvcidcbiAgICAgICAgY29uc3QgbG9nZ2VyID0gY3R4Py5sb2dnZXIgfHwgdGhpcy5sb2dnZXJcbiAgICAgICAgbG9nZ2VyW2xldmVsXSh0ZXh0KVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdDb3VsZCBub3QgbG9nIGVycm9yJywgZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBzdGFydCgpIHtcbiAgICBpZiAodGhpcy5jb25maWcubG9nLmVycm9ycyAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMub24oJ2Vycm9yJywgdGhpcy5sb2dFcnJvcilcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5lbWl0KCdiZWZvcmU6c3RhcnQnKVxuICAgIGF3YWl0IHRoaXMuZm9yRWFjaFNlcnZpY2Uoc2VydmljZSA9PiBzZXJ2aWNlLnN0YXJ0KCkpXG4gICAgY29uc3Qge1xuICAgICAgc2VydmVyOiB7IGhvc3QsIHBvcnQgfSxcbiAgICAgIGVudlxuICAgIH0gPSB0aGlzLmNvbmZpZ1xuICAgIHRoaXMuc2VydmVyID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5saXN0ZW4ocG9ydCwgaG9zdCwgKCkgPT4ge1xuICAgICAgICBjb25zdCB7IHBvcnQgfSA9IHNlcnZlci5hZGRyZXNzKClcbiAgICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICAgIGAke2Vudn0gc2VydmVyIHN0YXJ0ZWQgYXQgaHR0cDovLyR7aG9zdH06JHtwb3J0fWBcbiAgICAgICAgKVxuICAgICAgICByZXNvbHZlKHNlcnZlcilcbiAgICAgIH0pXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBVbmFibGUgdG8gc3RhcnQgc2VydmVyIGF0IGh0dHA6Ly8ke2hvc3R9OiR7cG9ydH1gKSlcbiAgICAgIH1cbiAgICB9KVxuICAgIGF3YWl0IHRoaXMuZW1pdCgnYWZ0ZXI6c3RhcnQnKVxuICB9XG5cbiAgYXN5bmMgc3RvcCgpIHtcbiAgICBhd2FpdCB0aGlzLmVtaXQoJ2JlZm9yZTpzdG9wJylcbiAgICB0aGlzLnNlcnZlciA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHsgc2VydmVyIH0gPSB0aGlzXG4gICAgICBpZiAoc2VydmVyKSB7XG4gICAgICAgIHNlcnZlci5jbG9zZShlcnIgPT4ge1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdChlcnIpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUobnVsbClcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC8vIEhhY2sgdG8gbWFrZSBzdXJlIHRoYXQgd2UgY2xvc2UgdGhlIHNlcnZlcixcbiAgICAgICAgLy8gIGV2ZW4gaWYgc29ja2V0cyBhcmUgc3RpbGwgb3Blbi5cbiAgICAgICAgLy8gIFRha2VuIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM2ODMwMDcyLlxuICAgICAgICAvLyAgQSBwcm9wZXIgc29sdXRpb24gd291bGQgYmUgdG8gdXNlIGEgbGlicmFyeSwgZXg6IGh0dHBzOi8vZ2l0aHViLmNvbS9nb2RhZGR5L3Rlcm1pbnVzXG4gICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiBzZXJ2ZXIuZW1pdCgnY2xvc2UnKSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1NlcnZlciBpcyBub3QgcnVubmluZycpKVxuICAgICAgfVxuICAgIH0pXG4gICAgYXdhaXQgdGhpcy5mb3JFYWNoU2VydmljZShzZXJ2aWNlID0+IHNlcnZpY2Uuc3RvcCgpKVxuICAgIGF3YWl0IHRoaXMuZW1pdCgnYWZ0ZXI6c3RvcCcpXG4gICAgaWYgKHRoaXMuY29uZmlnLmxvZy5lcnJvcnMgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLm9mZignZXJyb3InLCB0aGlzLmxvZ0Vycm9yKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHN0YXJ0T3JFeGl0KCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0KClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMubG9nRXJyb3IoZXJyKVxuICAgICAgcHJvY2Vzcy5leGl0KC0xKVxuICAgIH1cbiAgfVxuXG4gIC8vIEFzc2V0cyBoYW5kbGluZ1xuXG4gIGFzeW5jIGNyZWF0ZUFzc2V0cyhzdG9yYWdlLCBmaWxlcywgY291bnQgPSAwLCB0cnggPSBudWxsKSB7XG4gICAgY29uc3QgQXNzZXRNb2RlbCA9IHRoaXMuZ2V0TW9kZWwoJ0Fzc2V0JylcbiAgICBpZiAoQXNzZXRNb2RlbCkge1xuICAgICAgY29uc3QgYXNzZXRzID0gZmlsZXMubWFwKGZpbGUgPT4gKHtcbiAgICAgICAga2V5OiBmaWxlLmtleSxcbiAgICAgICAgZmlsZSxcbiAgICAgICAgc3RvcmFnZTogc3RvcmFnZS5uYW1lLFxuICAgICAgICBjb3VudFxuICAgICAgfSkpXG4gICAgICByZXR1cm4gQXNzZXRNb2RlbFxuICAgICAgICAucXVlcnkodHJ4KVxuICAgICAgICAuaW5zZXJ0KGFzc2V0cylcbiAgICB9XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGFzeW5jIGhhbmRsZUFkZGRlZEFuZFJlbW92ZWRBc3NldHMoXG4gICAgc3RvcmFnZSxcbiAgICBhZGRlZEZpbGVzLFxuICAgIHJlbW92ZWRGaWxlcyxcbiAgICB0cnggPSBudWxsXG4gICkge1xuICAgIGNvbnN0IHtcbiAgICAgIGFzc2V0czoge1xuICAgICAgICBjbGVhbnVwVGltZVRocmVzaG9sZCA9IDBcbiAgICAgIH0gPSB7fVxuICAgIH0gPSB0aGlzLmNvbmZpZ1xuICAgIC8vIE9ubHkgcmVtb3ZlIHVudXNlZCBhc3NldHMgdGhhdCBoYXZlbid0IHNlZW4gY2hhbmdlcyBmb3IgZ2l2ZW4gdGltZWZyYW1lLlxuICAgIGNvbnN0IHRpbWVUaHJlc2hvbGQgPSBpc1N0cmluZyhjbGVhbnVwVGltZVRocmVzaG9sZClcbiAgICAgID8gcGFyc2VEdXJhdGlvbihjbGVhbnVwVGltZVRocmVzaG9sZClcbiAgICAgIDogY2xlYW51cFRpbWVUaHJlc2hvbGRcblxuICAgIGNvbnN0IGltcG9ydGVkRmlsZXMgPSBbXVxuICAgIGNvbnN0IEFzc2V0TW9kZWwgPSB0aGlzLmdldE1vZGVsKCdBc3NldCcpXG4gICAgaWYgKEFzc2V0TW9kZWwpIHtcbiAgICAgIGltcG9ydGVkRmlsZXMucHVzaChcbiAgICAgICAgLi4uYXdhaXQgdGhpcy5hZGRGb3JlaWduQXNzZXRzKHN0b3JhZ2UsIGFkZGVkRmlsZXMsIHRyeClcbiAgICAgIClcbiAgICAgIGlmIChcbiAgICAgICAgYWRkZWRGaWxlcy5sZW5ndGggPiAwIHx8XG4gICAgICAgIHJlbW92ZWRGaWxlcy5sZW5ndGggPiAwXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgY2hhbmdlQ291bnQgPSAoZmlsZXMsIGluY3JlbWVudCkgPT4gKFxuICAgICAgICAgIGZpbGVzLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICBBc3NldE1vZGVsLnF1ZXJ5KHRyeClcbiAgICAgICAgICAgIC53aGVyZUluKCdrZXknLCBmaWxlcy5tYXAoZmlsZSA9PiBmaWxlLmtleSkpXG4gICAgICAgICAgICAuaW5jcmVtZW50KCdjb3VudCcsIGluY3JlbWVudClcbiAgICAgICAgKVxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgY2hhbmdlQ291bnQoYWRkZWRGaWxlcywgMSksXG4gICAgICAgICAgY2hhbmdlQ291bnQocmVtb3ZlZEZpbGVzLCAtMSlcbiAgICAgICAgXSlcbiAgICAgICAgaWYgKHRpbWVUaHJlc2hvbGQgPiAwKSB7XG4gICAgICAgICAgc2V0VGltZW91dChcbiAgICAgICAgICAgIC8vIERvbid0IHBhc3MgYHRyeGAgaGVyZSwgYXMgd2Ugd2FudCB0aGlzIGRlbGF5ZWQgZXhlY3V0aW9uIHRvXG4gICAgICAgICAgICAvLyBjcmVhdGUgaXRzIG93biB0cmFuc2FjdGlvbi5cbiAgICAgICAgICAgICgpID0+IHRoaXMucmVsZWFzZVVudXNlZEFzc2V0cyh0aW1lVGhyZXNob2xkKSxcbiAgICAgICAgICAgIHRpbWVUaHJlc2hvbGRcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEFsc28gZXhlY3V0ZSByZWxlYXNlVW51c2VkQXNzZXRzKCkgaW1tZWRpYXRlbHkgaW4gdGhlIHNhbWVcbiAgICAgIC8vIHRyYW5zYWN0aW9uLCB0byBwb3RlbnRpYWxseSBjbGVhbiB1cCBvdGhlciBwZW5kaW5nIGFzc2V0cy5cbiAgICAgIGF3YWl0IHRoaXMucmVsZWFzZVVudXNlZEFzc2V0cyh0aW1lVGhyZXNob2xkLCB0cngpXG4gICAgICByZXR1cm4gaW1wb3J0ZWRGaWxlc1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFkZEZvcmVpZ25Bc3NldHMoc3RvcmFnZSwgZmlsZXMsIHRyeCA9IG51bGwpIHtcbiAgICBjb25zdCBpbXBvcnRlZEZpbGVzID0gW11cbiAgICBjb25zdCBBc3NldE1vZGVsID0gdGhpcy5nZXRNb2RlbCgnQXNzZXQnKVxuICAgIGlmIChBc3NldE1vZGVsKSB7XG4gICAgICAvLyBGaW5kIG1pc3NpbmcgYXNzZXRzIChjb3BpZWQgZnJvbSBhbm90aGVyIHN5c3RlbSksIGFuZCBhZGQgdGhlbS5cbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWxlcy5tYXAoYXN5bmMgZmlsZSA9PiB7XG4gICAgICAgICAgY29uc3QgYXNzZXQgPSBhd2FpdCBBc3NldE1vZGVsLnF1ZXJ5KHRyeCkuZmluZE9uZSgna2V5JywgZmlsZS5rZXkpXG4gICAgICAgICAgaWYgKCFhc3NldCkge1xuICAgICAgICAgICAgaWYgKGZpbGUuZGF0YSB8fCBmaWxlLnVybCkge1xuICAgICAgICAgICAgICBsZXQgeyBkYXRhIH0gPSBmaWxlXG4gICAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcbiAgICAgICAgICAgICAgICAgIGAke1xuICAgICAgICAgICAgICAgICAgICBjaGFsay5yZWQoJ0lORk86JylcbiAgICAgICAgICAgICAgICAgIH0gQXNzZXQgJHtcbiAgICAgICAgICAgICAgICAgICAgY2hhbGsuZ3JlZW4oYCcke2ZpbGUubmFtZX0nYClcbiAgICAgICAgICAgICAgICAgIH0gaXMgZnJvbSBhIGZvcmVpZ24gc291cmNlLCBmZXRjaGluZyBmcm9tICR7XG4gICAgICAgICAgICAgICAgICAgIGNoYWxrLmdyZWVuKGAnJHtmaWxlLnVybH0nYClcbiAgICAgICAgICAgICAgICAgIH0gYW5kIGFkZGluZyB0byBzdG9yYWdlICR7XG4gICAgICAgICAgICAgICAgICAgIGNoYWxrLmdyZWVuKGAnJHtzdG9yYWdlLm5hbWV9J2ApXG4gICAgICAgICAgICAgICAgICB9Li4uYFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnZ2V0JyxcbiAgICAgICAgICAgICAgICAgIHVybDogZmlsZS51cmwsXG4gICAgICAgICAgICAgICAgICByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcidcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIGRhdGEgPSByZXNwb25zZS5kYXRhXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3QgaW1wb3J0ZWRGaWxlID0gYXdhaXQgc3RvcmFnZS5hZGRGaWxlKGZpbGUsIGRhdGEpXG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQXNzZXRzKHN0b3JhZ2UsIFtpbXBvcnRlZEZpbGVdLCAwLCB0cngpXG4gICAgICAgICAgICAgIC8vIE1lcmdlIGJhY2sgdGhlIGNoYW5nZWQgZmlsZSBwcm9wZXJ0aWVzIGludG8gdGhlIGFjdHVhbCBmaWxlc1xuICAgICAgICAgICAgICAvLyBvYmplY3QsIHNvIHRoYXQgdGhlIGRhdGEgZnJvbSB0aGUgc3RhdGljIG1vZGVsIGhvb2sgY2FuIGJlIHVzZWRcbiAgICAgICAgICAgICAgLy8gZGlyZWN0bHkgZm9yIHRoZSBhY3R1YWwgcnVubmluZyBxdWVyeS5cbiAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihmaWxlLCBpbXBvcnRlZEZpbGUpXG4gICAgICAgICAgICAgIGltcG9ydGVkRmlsZXMucHVzaChpbXBvcnRlZEZpbGUpXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXRFcnJvcihcbiAgICAgICAgICAgICAgICBgVW5hYmxlIHRvIGltcG9ydCBhc3NldCBmcm9tIGZvcmVpZ24gc291cmNlOiAnJHtcbiAgICAgICAgICAgICAgICAgIGZpbGUubmFtZVxuICAgICAgICAgICAgICAgIH0nICgnJHtcbiAgICAgICAgICAgICAgICAgIGZpbGUua2V5XG4gICAgICAgICAgICAgICAgfScpYFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEFzc2V0IGlzIGZyb20gYSBmb3JlaWduIHNvdXJjZSwgYnV0IHdhcyBhbHJlYWR5IGltcG9ydGVkIGFuZCBjYW5cbiAgICAgICAgICAgIC8vIGJlIHJldXNlZC4gU2VlIGFib3ZlIGZvciBhbiBleHBsYW5hdGlvbiBvZiB0aGlzIG1lcmdlLlxuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihmaWxlLCBhc3NldC5maWxlKVxuICAgICAgICAgICAgLy8gTk9URTogTm8gbmVlZCB0byBhZGQgYGZpbGVgIHRvIGBpbXBvcnRlZEZpbGVzYCwgc2luY2UgaXQnc1xuICAgICAgICAgICAgLy8gYWxyZWFkeSBiZWVuIGltcG9ydGVkIHRvIHRoZSBzdG9yYWdlIGJlZm9yZS5cbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgfVxuICAgIHJldHVybiBpbXBvcnRlZEZpbGVzXG4gIH1cblxuICBhc3luYyBoYW5kbGVNb2RpZmllZEFzc2V0cyhzdG9yYWdlLCBmaWxlcywgdHJ4ID0gbnVsbCkge1xuICAgIGNvbnN0IG1vZGlmaWVkRmlsZXMgPSBbXVxuICAgIGNvbnN0IEFzc2V0TW9kZWwgPSB0aGlzLmdldE1vZGVsKCdBc3NldCcpXG4gICAgaWYgKEFzc2V0TW9kZWwpIHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWxlcy5tYXAoYXN5bmMgZmlsZSA9PiB7XG4gICAgICAgICAgaWYgKGZpbGUuZGF0YSkge1xuICAgICAgICAgICAgY29uc3QgYXNzZXQgPSBhd2FpdCBBc3NldE1vZGVsLnF1ZXJ5KHRyeCkuZmluZE9uZSgna2V5JywgZmlsZS5rZXkpXG4gICAgICAgICAgICBpZiAoYXNzZXQpIHtcbiAgICAgICAgICAgICAgY29uc3QgY2hhbmdlZEZpbGUgPSBhd2FpdCBzdG9yYWdlLmFkZEZpbGUoZmlsZSwgZmlsZS5kYXRhKVxuICAgICAgICAgICAgICAvLyBNZXJnZSBiYWNrIHRoZSBjaGFuZ2VkIGZpbGUgcHJvcGVydGllcyBpbnRvIHRoZSBhY3R1YWwgZmlsZXNcbiAgICAgICAgICAgICAgLy8gb2JqZWN0LCBzbyB0aGF0IHRoZSBkYXRhIGZyb20gdGhlIHN0YXRpYyBtb2RlbCBob29rIGNhbiBiZSB1c2VkXG4gICAgICAgICAgICAgIC8vIGRpcmVjdGx5IGZvciB0aGUgYWN0dWFsIHJ1bm5pbmcgcXVlcnkuXG4gICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZmlsZSwgY2hhbmdlZEZpbGUpXG4gICAgICAgICAgICAgIG1vZGlmaWVkRmlsZXMucHVzaChjaGFuZ2VkRmlsZSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBBc3NldEVycm9yKFxuICAgICAgICAgICAgICAgIGBVbmFibGUgdG8gdXBkYXRlIG1vZGlmaWVkIGFzc2V0IGZyb20gbWVtb3J5IHNvdXJjZTogJyR7XG4gICAgICAgICAgICAgICAgICBmaWxlLm5hbWVcbiAgICAgICAgICAgICAgICB9JyAoJyR7XG4gICAgICAgICAgICAgICAgICBmaWxlLmtleVxuICAgICAgICAgICAgICAgIH0nKWBcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIG1vZGlmaWVkRmlsZXNcbiAgfVxuXG4gIGFzeW5jIHJlbGVhc2VVbnVzZWRBc3NldHModGltZVRocmVzaG9sZCA9IDAsIHRyeCA9IG51bGwpIHtcbiAgICBjb25zdCBBc3NldE1vZGVsID0gdGhpcy5nZXRNb2RlbCgnQXNzZXQnKVxuICAgIGlmIChBc3NldE1vZGVsKSB7XG4gICAgICByZXR1cm4gQXNzZXRNb2RlbC50cmFuc2FjdGlvbih0cngsIGFzeW5jIHRyeCA9PiB7XG4gICAgICAgIC8vIERldGVybWluZSB0aGUgdGltZSB0aHJlc2hvbGQgaW4gSlMgaW5zdGVhZCBvZiBTUUwsIGFzIHRoZXJlIGlzIG5vXG4gICAgICAgIC8vIGVhc3kgY3Jvc3MtU1FMIHdheSB0byBkbyBgbm93KCkgLSBpbnRlcnZhbCBYIGhvdXJzYDpcbiAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKClcbiAgICAgICAgZGF0ZS5zZXRNaWxsaXNlY29uZHMoZGF0ZS5nZXRNaWxsaXNlY29uZHMoKSAtIHRpbWVUaHJlc2hvbGQpXG4gICAgICAgIGNvbnN0IG9ycGhhbmVkQXNzZXRzID0gYXdhaXQgQXNzZXRNb2RlbFxuICAgICAgICAgIC5xdWVyeSh0cngpXG4gICAgICAgICAgLndoZXJlKCdjb3VudCcsIDApXG4gICAgICAgICAgLmFuZFdoZXJlKCd1cGRhdGVkQXQnLCAnPD0nLCBkYXRlKVxuICAgICAgICAgIC8vIFByb3RlY3QgZnJlc2hseSBjcmVhdGVkIGFzc2V0cyBmcm9tIGJlaW5nIGRlbGV0ZWQgYWdhaW4gcmlnaHQgYXdheSxcbiAgICAgICAgICAvLyAuZS5nLiB3aGVuIGBjb25maWcuYXNzZXRzLmNsZWFudXBUaW1lVGhyZXNob2xkID0gMGBcbiAgICAgICAgICAuYW5kV2hlcmUoJ3VwZGF0ZWRBdCcsICc+JywgcmVmKCdjcmVhdGVkQXQnKSlcbiAgICAgICAgaWYgKG9ycGhhbmVkQXNzZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zdCBvcnBoYW5lZEtleXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIG9ycGhhbmVkQXNzZXRzLm1hcChhc3luYyBhc3NldCA9PiB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5nZXRTdG9yYWdlKGFzc2V0LnN0b3JhZ2UpLnJlbW92ZUZpbGUoYXNzZXQuZmlsZSlcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IpXG4gICAgICAgICAgICAgICAgYXNzZXQuZXJyb3IgPSBlcnJvclxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBhc3NldC5rZXlcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKVxuICAgICAgICAgIGF3YWl0IEFzc2V0TW9kZWxcbiAgICAgICAgICAgIC5xdWVyeSh0cngpXG4gICAgICAgICAgICAuZGVsZXRlKClcbiAgICAgICAgICAgIC53aGVyZUluKCdrZXknLCBvcnBoYW5lZEtleXMpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9ycGhhbmVkQXNzZXRzXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG4vLyBPdmVycmlkZSBLb2EncyBldmVudHMgd2l0aCBvdXIgb3duIEV2ZW50RW1pdHRlciB0aGF0IGFkZHMgc3VwcG9ydCBmb3Jcbi8vIGFzeW5jaHJvbm91cyBldmVudHMuXG5FdmVudEVtaXR0ZXIubWl4aW4oQXBwbGljYXRpb24ucHJvdG90eXBlKVxuXG5mdW5jdGlvbiBnZXRPcHRpb25zKG9wdGlvbnMpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KG9wdGlvbnMpID8gb3B0aW9ucyA6IHt9XG59XG4iXX0=
|