composed-di 0.0.3 → 0.0.5-alpha

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/README.md CHANGED
@@ -4,8 +4,8 @@ A tiny, type-friendly dependency injection helper for composing services via key
4
4
 
5
5
  It provides:
6
6
  - ServiceKey<T>: a typed token used to identify a service
7
- - ServiceFactory<T>: a contract to create a service (with helpers singletonFactory and oneShotFactory)
8
- - ServiceModule: a resolver that wires factories, validates dependencies, and injects services
7
+ - ServiceFactory<T>: a contract to create a service (with static methods `singleton` and `oneShot`)
8
+ - ServiceModule: a resolver that wires factories, validates dependencies, and provides services
9
9
 
10
10
  ServiceModule will:
11
11
  - detect recursive dependencies (a factory that depends on its own key)
@@ -13,7 +13,13 @@ ServiceModule will:
13
13
 
14
14
  ## Install
15
15
 
16
- This repository is set up as a library. Build artifacts are generated under `dist/` by running:
16
+ Install from npm:
17
+
18
+ - npm: `npm install composed-di`
19
+ - pnpm: `pnpm add composed-di`
20
+ - yarn: `yarn add composed-di`
21
+
22
+ If you're working on this repo locally, build artifacts are generated under `dist/` by running:
17
23
 
18
24
  ```
19
25
  npm run build
@@ -21,15 +27,14 @@ npm run build
21
27
 
22
28
  ## Usage
23
29
 
24
- Below is an example based on the previous sample `main.ts` usage pattern.
30
+ Below is a minimal example using the public API.
25
31
 
26
32
  ```ts
27
33
  import {
28
34
  ServiceKey,
29
35
  ServiceModule,
30
- singletonFactory,
31
- oneShotFactory,
32
- } from 'composed-di'; // if used locally, import from the relative path to `src/index`
36
+ ServiceFactory,
37
+ } from 'composed-di'; // when developing this repo locally, import from './src'
33
38
 
34
39
  // 1) Define service types
35
40
  interface Config {
@@ -53,50 +58,84 @@ const LoggerKey = new ServiceKey<Logger>('Logger');
53
58
  const AppKey = new ServiceKey<App>('App');
54
59
 
55
60
  // 3) Create factories (singleton or one-shot)
56
- const configFactory = singletonFactory({
61
+ const configFactory = ServiceFactory.singleton({
57
62
  provides: ConfigKey,
58
- dependsOn: [] as const,
59
- async initialize() {
63
+ dependsOn: [],
64
+ initialize: () => {
60
65
  return { baseUrl: 'https://api.example.com' } satisfies Config;
61
66
  },
62
67
  });
63
68
 
64
- const loggerFactory = singletonFactory({
69
+ const loggerFactory = ServiceFactory.singleton({
65
70
  provides: LoggerKey,
66
- dependsOn: [] as const,
67
- async initialize() {
71
+ dependsOn: [],
72
+ initialize: () => {
68
73
  return console as unknown as Logger;
69
74
  },
70
75
  });
71
76
 
72
- const appFactory = oneShotFactory({
77
+ const appFactory = ServiceFactory.oneShot({
73
78
  provides: AppKey,
74
- dependsOn: [ConfigKey, LoggerKey] as const,
75
- async initialize(config, logger) {
79
+ dependsOn: [ConfigKey, LoggerKey],
80
+ initialize: (config, logger) => {
76
81
  return new App(config, logger);
77
82
  },
78
83
  });
79
84
 
80
- // 4) Compose a module
85
+ // 4) Compose a module (you can pass factories and/or other ServiceModule instances)
81
86
  const module = ServiceModule.from([configFactory, loggerFactory, appFactory]);
82
87
 
83
- // 5) Inject and use
88
+ // 5) Resolve and use
84
89
  (async () => {
85
- const app = await module.inject(AppKey);
90
+ const app = await module.get(AppKey);
86
91
  app.start();
87
92
  })();
88
93
  ```
89
94
 
90
95
  Notes:
91
- - Use `as const` on your `dependsOn` list to preserve tuple types and keep constructor parameters strongly typed.
92
- - `ServiceModule.inject` resolves dependencies recursively, so factories can depend on other services.
96
+ - `ServiceModule.get` resolves dependencies recursively, so factories can depend on other services.
93
97
  - If a dependency is missing or recursive, `ServiceModule` throws with a helpful error message.
94
98
 
99
+ ## Visualizing Dependencies
100
+
101
+ The library includes utilities to generate a DOT graph representation of your service dependencies, which can be visualized using Graphviz tools.
102
+
103
+ ```ts
104
+ import { ServiceModule, printDotGraph, createDotGraph } from 'composed-di';
105
+
106
+ // After creating your ServiceModule
107
+ const module = ServiceModule.from([configFactory, loggerFactory, appFactory]);
108
+
109
+ // Option 1: Print the DOT graph to console with instructions
110
+ printDotGraph(module);
111
+
112
+ // Option 2: Generate DOT graph with custom options
113
+ const dotGraph = createDotGraph(module, {
114
+ direction: 'LR', // 'TB' (top-bottom), 'LR' (left-right), 'BT', 'RL'
115
+ title: 'My Service Dependencies',
116
+ highlightLeaves: true, // Highlight services with no dependencies (green)
117
+ highlightRoots: true, // Highlight services with no dependents (orange)
118
+ });
119
+ console.log(dotGraph);
120
+ ```
121
+
122
+ The generated DOT notation can be visualized using:
123
+ - [GraphvizOnline](https://dreampuf.github.io/GraphvizOnline/)
124
+ - [Edotor](https://edotor.net/)
125
+
95
126
  ## API
96
127
 
97
- - `class ServiceKey<T>(name: string)`
98
- - `interface ServiceFactory<T, D extends ServiceKey<unknown>[]>` with `provides`, `dependsOn`, `initialize`, `dispose`
99
- - `singletonFactory({ provides, dependsOn?, initialize, dispose? })`
100
- - `oneShotFactory({ provides, dependsOn, initialize, dispose? })`
101
- - `class ServiceModule` with `static from(factories)`, `inject(key)`
128
+ - `class ServiceKey<T>(name: string)` - Creates a typed token to identify a service
129
+ - `abstract class ServiceFactory<T, D extends readonly ServiceKey<unknown>[]>` with:
130
+ - `provides: ServiceKey<T>` - The service key this factory provides
131
+ - `dependsOn: D` - Array of service keys this factory depends on
132
+ - `initialize(...dependencies)` - Creates the service instance
133
+ - `dispose(instance)` - Cleans up the service instance
134
+ - `static singleton({ provides, dependsOn?, initialize, dispose? })` - Creates a singleton factory
135
+ - `static oneShot({ provides, dependsOn, initialize, dispose? })` - Creates a one-shot factory
136
+ - `class ServiceModule` with:
137
+ - `static from(factoriesOrModules)` - Creates a module from factories and/or other modules
138
+ - `async get(key)` - Resolves and returns a service by its key
139
+ - `createDotGraph(module, options?)` - Generates DOT notation graph from a ServiceModule
140
+ - `printDotGraph(module)` - Prints DOT graph to console with visualization instructions
102
141
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { ServiceKey } from './serviceKey';
2
- export { ServiceModule } from './serviceModule';
3
- export { type ServiceFactory, singletonFactory, oneShotFactory } from './serviceFactory';
4
- export { type ServiceProvider } from './serviceProvider';
1
+ export * from './ServiceKey';
2
+ export * from './ServiceModule';
3
+ export * from './ServiceFactory';
4
+ export * from './utils';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,KAAK,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAA"}
package/dist/index.js CHANGED
@@ -1,11 +1,21 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.oneShotFactory = exports.singletonFactory = exports.ServiceModule = exports.ServiceKey = void 0;
4
- var serviceKey_1 = require("./serviceKey");
5
- Object.defineProperty(exports, "ServiceKey", { enumerable: true, get: function () { return serviceKey_1.ServiceKey; } });
6
- var serviceModule_1 = require("./serviceModule");
7
- Object.defineProperty(exports, "ServiceModule", { enumerable: true, get: function () { return serviceModule_1.ServiceModule; } });
8
- var serviceFactory_1 = require("./serviceFactory");
9
- Object.defineProperty(exports, "singletonFactory", { enumerable: true, get: function () { return serviceFactory_1.singletonFactory; } });
10
- Object.defineProperty(exports, "oneShotFactory", { enumerable: true, get: function () { return serviceFactory_1.oneShotFactory; } });
17
+ __exportStar(require("./ServiceKey"), exports);
18
+ __exportStar(require("./ServiceModule"), exports);
19
+ __exportStar(require("./ServiceFactory"), exports);
20
+ __exportStar(require("./utils"), exports);
11
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,mDAAyF;AAA3D,kHAAA,gBAAgB,OAAA;AAAE,gHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,kDAAgC;AAChC,mDAAiC;AACjC,0CAAuB"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
package/dist/main.js CHANGED
@@ -1,284 +1,15 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (let key of __getOwnPropNames(from))
11
- if (!__hasOwnProp.call(to, key) && key !== except)
12
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
- }
14
- return to;
15
- };
16
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
- // If the importer is in node compatibility mode or this is not an ESM
18
- // file that has been converted to a CommonJS file using a Babel-
19
- // compatible transform (i.e. "__esModule" has not been set), then set
20
- // "default" to the CommonJS "module.exports" for node compatibility.
21
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
- mod
23
- ));
24
-
25
- // src/lib/serviceModule.ts
26
- var ServiceModule = class _ServiceModule {
27
- constructor(factories) {
28
- this.factories = [];
29
- this.factories = Array.from(factories);
30
- this.factories.forEach((factory) => {
31
- checkRecursiveDependencies(factory);
32
- checkMissingDependencies(factory, this.factories);
33
- });
34
- }
35
- async inject(key) {
36
- const factory = this.factories.find((factory2) => {
37
- return isSuitable(key, factory2);
38
- });
39
- if (!factory) {
40
- throw new Error(`Could not find a suitable factory for ${key.name}`);
41
- }
42
- const dependencies = await Promise.all(
43
- factory.dependsOn.map((dependencyKey) => {
44
- return this.inject(dependencyKey);
45
- })
46
- );
47
- return factory.initialize(...dependencies);
48
- }
49
- static from(factories) {
50
- return new _ServiceModule(new Set(factories));
51
- }
52
- };
53
- function checkRecursiveDependencies(factory) {
54
- const recursive = factory.dependsOn.some((dependencyKey) => {
55
- return dependencyKey === factory.provides;
56
- });
57
- if (recursive) {
58
- throw new Error(
59
- "Recursive dependency detected on: " + factory.provides.name
60
- );
61
- }
62
- }
63
- function checkMissingDependencies(factory, factories) {
64
- const missingDependencies = factory.dependsOn.filter(
65
- (dependencyKey) => {
66
- return !isRegistered(dependencyKey, factories);
67
- }
68
- );
69
- if (missingDependencies.length === 0) {
70
- return;
71
- }
72
- const dependencyList = missingDependencies.map((dependencyKey) => ` -> ${dependencyKey.name}`).join("\n");
73
- throw new Error(
74
- `${factory.provides.name} will fail because it depends on:
75
- ${dependencyList}`
76
- );
77
- }
78
- function isRegistered(key, factories) {
79
- return factories.some((factory) => factory.provides === key);
80
- }
81
- function isSuitable(key, factory) {
82
- return factory?.provides === key;
83
- }
84
-
85
- // src/lib/serviceKey.ts
86
- var ServiceKey = class {
87
- constructor(name) {
88
- this.name = name;
89
- this.symbol = Symbol(name);
90
- }
91
- };
92
-
93
- // src/lib/serviceFactory.ts
94
- function singletonFactory({
95
- provides,
96
- dependsOn = [],
97
- initialize,
98
- dispose = () => {
99
- }
100
- }) {
101
- let instance;
102
- return {
103
- provides,
104
- dependsOn,
105
- async initialize(...dependencies) {
106
- if (instance) {
107
- return instance;
108
- }
109
- instance = await initialize(...dependencies);
110
- return instance;
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const serviceKey_1 = require("./serviceKey");
4
+ const serviceFactory_1 = require("./serviceFactory");
5
+ const TEST_SERVICE_KEY = new serviceKey_1.ServiceKey('testService');
6
+ const FOO_KEY = new serviceKey_1.ServiceKey('foo');
7
+ const BAR_KEY = new serviceKey_1.ServiceKey('bar');
8
+ const TestServiceFactory = (0, serviceFactory_1.singletonFactory)({
9
+ provides: TEST_SERVICE_KEY,
10
+ dependsOn: [FOO_KEY, BAR_KEY],
11
+ initialize: (foo, bar) => {
12
+ return { foo, bar };
111
13
  },
112
- dispose(serviceInstance) {
113
- if (instance === serviceInstance) {
114
- dispose(serviceInstance);
115
- instance = void 0;
116
- }
117
- }
118
- };
119
- }
120
-
121
- // src/core/sms/di/smsModule.ts
122
- var import_node_process = __toESM(require("node:process"));
123
-
124
- // src/core/sms/noOpSmsService.ts
125
- var NoOpSmsService = class {
126
- send(recipient, text) {
127
- console.warn(`NoOpSmsService: Sending sms to ${recipient}: ${text}`);
128
- }
129
- };
130
-
131
- // src/core/sms/tigoSmsService.ts
132
- var TigoSmsService = class {
133
- send(_recipient, _text) {
134
- throw new Error("Not yet implemented");
135
- }
136
- };
137
-
138
- // src/core/logger/emailAlertLogger.ts
139
- var EmailAlertLogger = class {
140
- constructor(bufferSize = 50, recipients = []) {
141
- this.buffer = [];
142
- this.emailQueue = [];
143
- this.bufferSize = bufferSize;
144
- this.recipients = recipients;
145
- }
146
- addToBuffer(event) {
147
- if (this.buffer.length >= this.bufferSize) {
148
- this.buffer.shift();
149
- }
150
- this.buffer.push({ ...event, date: /* @__PURE__ */ new Date() });
151
- }
152
- info(message, payload) {
153
- this.addToBuffer({ level: "INFO", message, payload });
154
- }
155
- error(message, error, payload) {
156
- this.addToBuffer({ level: "ERROR", message, payload });
157
- this.emailQueue.push(createTableString(this.buffer, error));
158
- this.buffer.length = 0;
159
- }
160
- debug(message, payload) {
161
- this.addToBuffer({ level: "DEBUG", message, payload });
162
- }
163
- async flush() {
164
- for (const email of this.emailQueue) {
165
- console.error(email);
166
- }
167
- this.buffer.length = 0;
168
- this.emailQueue.length = 0;
169
- }
170
- };
171
- function createTableString(events, error) {
172
- if (events.length === 0) {
173
- return "No events to display";
174
- }
175
- const dateWidth = Math.max(
176
- 4,
177
- ...events.map((e) => e.date.toISOString().length)
178
- );
179
- const levelWidth = Math.max(
180
- 5,
181
- ...events.map((e) => e.level.length)
182
- );
183
- const messageWidth = Math.max(7, ...events.map((e) => e.message.length));
184
- const payloadWidth = Math.max(
185
- 7,
186
- ...events.map((e) => e.payload ? JSON.stringify(e.payload).length : 0)
187
- );
188
- const header = [
189
- "DATE".padEnd(dateWidth),
190
- "LEVEL".padEnd(levelWidth),
191
- "MESSAGE".padEnd(messageWidth),
192
- "PAYLOAD".padEnd(payloadWidth)
193
- ].join(" | ");
194
- const separator = [
195
- "-".repeat(dateWidth),
196
- "-".repeat(levelWidth),
197
- "-".repeat(messageWidth),
198
- "-".repeat(payloadWidth)
199
- ].join("-|-");
200
- const rows = events.map((event) => {
201
- const date = event.date.toISOString().padEnd(dateWidth);
202
- const level = event.level.padEnd(levelWidth);
203
- const message = event.message.padEnd(messageWidth);
204
- const payload = (event.payload ? JSON.stringify(event.payload) : "").padEnd(
205
- payloadWidth
206
- );
207
- return [date, level, message, payload].join(" | ");
208
- });
209
- const errorSection = error ? "\n\nError Details:\n" + "-".repeat(20) + "\n" + (error instanceof Error ? `${error.name}: ${error.message}
210
- ${error.stack || ""}` : String(error)) : "";
211
- return [header, separator, ...rows].join("\n") + errorSection;
212
- }
213
-
214
- // src/core/logger/di/loggerModule.ts
215
- var LOGGER = new ServiceKey("Logger");
216
- var LoggerFactory = singletonFactory({
217
- provides: LOGGER,
218
- dependsOn: [],
219
- initialize: () => {
220
- return Promise.resolve(new EmailAlertLogger(100, ["juanhr454@gmail.com"]));
221
- }
222
14
  });
223
-
224
- // src/core/sms/di/smsModule.ts
225
- var SMS_SERVICE = new ServiceKey("SmsService");
226
- var SmsServiceFactory = singletonFactory({
227
- provides: SMS_SERVICE,
228
- dependsOn: [LOGGER],
229
- initialize(logger) {
230
- logger.info("Initializing SmsService");
231
- if (import_node_process.default.env.environment === "dev") {
232
- return Promise.resolve(new NoOpSmsService());
233
- } else {
234
- return Promise.resolve(new TigoSmsService());
235
- }
236
- }
237
- });
238
- var SmsServiceTestFactory = singletonFactory({
239
- provides: SMS_SERVICE,
240
- dependsOn: [],
241
- initialize() {
242
- return Promise.resolve(new NoOpSmsService());
243
- }
244
- });
245
-
246
- // src/main.ts
247
- var authModule = ServiceModule.from([SmsServiceFactory, LoggerFactory]);
248
- function module2(module3, fn) {
249
- return (event, context) => {
250
- fn(event, { services: module3, ...context });
251
- };
252
- }
253
- var handler = module2(authModule, login);
254
- (async function() {
255
- await deeplyNestedFunction({ services: authModule });
256
- const logger = await authModule.inject(LOGGER);
257
- if (logger instanceof EmailAlertLogger) {
258
- await logger.flush();
259
- }
260
- console.log("Done");
261
- })();
262
- async function deeplyNestedFunction(context) {
263
- await login({}, context);
264
- }
265
- async function login(event, context) {
266
- const state = authorize(event);
267
- const logger = await context.services.inject(LOGGER);
268
- if (state === "DEVICE_CHANGED") {
269
- logger.info("Device changed", { "user": "asad" });
270
- const sms = await context.services.inject(SMS_SERVICE);
271
- logger.debug("Sending sms");
272
- try {
273
- sms.send(971233149, "Hola Juan, tu pin es 22222");
274
- } catch (e) {
275
- logger.error("Error sending sms", e);
276
- }
277
- const sms1 = await context.services.inject(SMS_SERVICE);
278
- }
279
- return;
280
- }
281
- function authorize(_request) {
282
- return "DEVICE_CHANGED";
283
- }
284
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2xpYi9zZXJ2aWNlTW9kdWxlLnRzIiwgIi4uL3NyYy9saWIvc2VydmljZUtleS50cyIsICIuLi9zcmMvbGliL3NlcnZpY2VGYWN0b3J5LnRzIiwgIi4uL3NyYy9jb3JlL3Ntcy9kaS9zbXNNb2R1bGUudHMiLCAiLi4vc3JjL2NvcmUvc21zL25vT3BTbXNTZXJ2aWNlLnRzIiwgIi4uL3NyYy9jb3JlL3Ntcy90aWdvU21zU2VydmljZS50cyIsICIuLi9zcmMvY29yZS9sb2dnZXIvZW1haWxBbGVydExvZ2dlci50cyIsICIuLi9zcmMvY29yZS9sb2dnZXIvZGkvbG9nZ2VyTW9kdWxlLnRzIiwgIi4uL3NyYy9tYWluLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBTZXJ2aWNlS2V5IH0gZnJvbSAnLi9zZXJ2aWNlS2V5JztcclxuaW1wb3J0IHsgU2VydmljZUZhY3RvcnkgfSBmcm9tICcuL3NlcnZpY2VGYWN0b3J5JztcclxuaW1wb3J0IHsgU2VydmljZVByb3ZpZGVyIH0gZnJvbSAnLi9zZXJ2aWNlUHJvdmlkZXInO1xyXG5cclxuZXhwb3J0IGNsYXNzIFNlcnZpY2VNb2R1bGUgaW1wbGVtZW50cyBTZXJ2aWNlUHJvdmlkZXIge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZmFjdG9yaWVzOiBTZXJ2aWNlRmFjdG9yeTxhbnksIGFueT5bXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcihmYWN0b3JpZXM6IFNldDxTZXJ2aWNlRmFjdG9yeTx1bmtub3duLCBTZXJ2aWNlS2V5PHVua25vd24+W10+Pikge1xyXG4gICAgdGhpcy5mYWN0b3JpZXMgPSBBcnJheS5mcm9tKGZhY3Rvcmllcyk7XHJcbiAgICB0aGlzLmZhY3Rvcmllcy5mb3JFYWNoKChmYWN0b3J5KSA9PiB7XHJcbiAgICAgIGNoZWNrUmVjdXJzaXZlRGVwZW5kZW5jaWVzKGZhY3RvcnkpO1xyXG4gICAgICBjaGVja01pc3NpbmdEZXBlbmRlbmNpZXMoZmFjdG9yeSwgdGhpcy5mYWN0b3JpZXMpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgaW5qZWN0PFQ+KGtleTogU2VydmljZUtleTxUPik6IFByb21pc2U8VD4ge1xyXG4gICAgY29uc3QgZmFjdG9yeSA9IHRoaXMuZmFjdG9yaWVzLmZpbmQoKGZhY3RvcnkpID0+IHtcclxuICAgICAgcmV0dXJuIGlzU3VpdGFibGUoa2V5LCBmYWN0b3J5KTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIGEgZmFjdG9yeSB0byBzdXBwbHkgdGhlIHJlcXVlc3RlZCBrZXkgd2FzIG5vdCBmb3VuZFxyXG4gICAgaWYgKCFmYWN0b3J5KSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgYSBzdWl0YWJsZSBmYWN0b3J5IGZvciAke2tleS5uYW1lfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlc29sdmUgYWxsIGRlcGVuZGVuY2llcyBmaXJzdFxyXG4gICAgY29uc3QgZGVwZW5kZW5jaWVzID0gYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgIGZhY3RvcnkuZGVwZW5kc09uLm1hcCgoZGVwZW5kZW5jeUtleTogU2VydmljZUtleTx1bmtub3duPikgPT4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmluamVjdChkZXBlbmRlbmN5S2V5KTtcclxuICAgICAgfSksXHJcbiAgICApO1xyXG5cclxuICAgIC8vIENhbGwgdGhlIGZhY3RvcnkgdG8gcmV0cmlldmUgdGhlIGRlcGVuZGVuY3lcclxuICAgIHJldHVybiBmYWN0b3J5LmluaXRpYWxpemUoLi4uZGVwZW5kZW5jaWVzKTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBmcm9tKFxyXG4gICAgZmFjdG9yaWVzOiBTZXJ2aWNlRmFjdG9yeTx1bmtub3duLCBTZXJ2aWNlS2V5PHVua25vd24+W10+W10sXHJcbiAgKTogU2VydmljZU1vZHVsZSB7XHJcbiAgICByZXR1cm4gbmV3IFNlcnZpY2VNb2R1bGUobmV3IFNldChmYWN0b3JpZXMpKTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNoZWNrUmVjdXJzaXZlRGVwZW5kZW5jaWVzKFxyXG4gIGZhY3Rvcnk6IFNlcnZpY2VGYWN0b3J5PHVua25vd24sIFNlcnZpY2VLZXk8dW5rbm93bj5bXT4sXHJcbikge1xyXG4gIGNvbnN0IHJlY3Vyc2l2ZSA9IGZhY3RvcnkuZGVwZW5kc09uLnNvbWUoKGRlcGVuZGVuY3lLZXkpID0+IHtcclxuICAgIHJldHVybiBkZXBlbmRlbmN5S2V5ID09PSBmYWN0b3J5LnByb3ZpZGVzO1xyXG4gIH0pO1xyXG5cclxuICBpZiAocmVjdXJzaXZlKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgICdSZWN1cnNpdmUgZGVwZW5kZW5jeSBkZXRlY3RlZCBvbjogJyArIGZhY3RvcnkucHJvdmlkZXMubmFtZSxcclxuICAgICk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBjaGVja01pc3NpbmdEZXBlbmRlbmNpZXMoXHJcbiAgZmFjdG9yeTogU2VydmljZUZhY3Rvcnk8dW5rbm93biwgU2VydmljZUtleTx1bmtub3duPltdPixcclxuICBmYWN0b3JpZXM6IFNlcnZpY2VGYWN0b3J5PHVua25vd24+W10sXHJcbikge1xyXG4gIGNvbnN0IG1pc3NpbmdEZXBlbmRlbmNpZXMgPSBmYWN0b3J5LmRlcGVuZHNPbi5maWx0ZXIoXHJcbiAgICAoZGVwZW5kZW5jeUtleTogU2VydmljZUtleTxhbnk+KSA9PiB7XHJcbiAgICAgIHJldHVybiAhaXNSZWdpc3RlcmVkKGRlcGVuZGVuY3lLZXksIGZhY3Rvcmllcyk7XHJcbiAgICB9LFxyXG4gICk7XHJcbiAgaWYgKG1pc3NpbmdEZXBlbmRlbmNpZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG5cclxuICBjb25zdCBkZXBlbmRlbmN5TGlzdCA9IG1pc3NpbmdEZXBlbmRlbmNpZXNcclxuICAgIC5tYXAoKGRlcGVuZGVuY3lLZXkpID0+IGAgLT4gJHtkZXBlbmRlbmN5S2V5Lm5hbWV9YClcclxuICAgIC5qb2luKCdcXG4nKTtcclxuICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICBgJHtmYWN0b3J5LnByb3ZpZGVzLm5hbWV9IHdpbGwgZmFpbCBiZWNhdXNlIGl0IGRlcGVuZHMgb246XFxuICR7ZGVwZW5kZW5jeUxpc3R9YCxcclxuICApO1xyXG59XHJcblxyXG5mdW5jdGlvbiBpc1JlZ2lzdGVyZWQoXHJcbiAga2V5OiBTZXJ2aWNlS2V5PHVua25vd24+LFxyXG4gIGZhY3RvcmllczogU2VydmljZUZhY3Rvcnk8dW5rbm93bj5bXSxcclxuKSB7XHJcbiAgcmV0dXJuIGZhY3Rvcmllcy5zb21lKChmYWN0b3J5KSA9PiBmYWN0b3J5LnByb3ZpZGVzID09PSBrZXkpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBpc1N1aXRhYmxlPFQsIEQgZXh0ZW5kcyBTZXJ2aWNlS2V5PHVua25vd24+W10+KFxyXG4gIGtleTogU2VydmljZUtleTxUPixcclxuICBmYWN0b3J5OiBTZXJ2aWNlRmFjdG9yeTx1bmtub3duLCBEPixcclxuKTogZmFjdG9yeSBpcyBTZXJ2aWNlRmFjdG9yeTxULCBEPiB7XHJcbiAgcmV0dXJuIGZhY3Rvcnk/LnByb3ZpZGVzID09PSBrZXk7XHJcbn1cclxuIiwgIi8vIEB0cy1pZ25vcmVcclxuZXhwb3J0IGNsYXNzIFNlcnZpY2VLZXk8VD4ge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgc3ltYm9sOiBzeW1ib2w7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuc3ltYm9sID0gU3ltYm9sKG5hbWUpO1xyXG4gIH1cclxufVxyXG4iLCAiaW1wb3J0IHsgU2VydmljZUtleSB9IGZyb20gJy4vc2VydmljZUtleSc7XHJcblxyXG4vLyBIZWxwZXIgdHlwZXMgdG8gZXh0cmFjdCB0aGUgdHlwZSBmcm9tIFNlcnZpY2VLZXlcclxudHlwZSBTZXJ2aWNlVHlwZTxUPiA9IFQgZXh0ZW5kcyBTZXJ2aWNlS2V5PGluZmVyIFU+ID8gVSA6IG5ldmVyO1xyXG5cclxuLy8gSGVscGVyIHR5cGVzIHRvIGNvbnZlcnQgYW4gYXJyYXkgb2YgU2VydmljZUtleSB0byB0dXBsZSBvZiB0aGVpciB0eXBlc1xyXG50eXBlIERlcGVuZGVuY3lUeXBlczxUIGV4dGVuZHMgU2VydmljZUtleTx1bmtub3duPltdPiA9IHtcclxuICBbSyBpbiBrZXlvZiBUXTogU2VydmljZVR5cGU8VFtLXT47XHJcbn07XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VGYWN0b3J5PFQsIEQgZXh0ZW5kcyBTZXJ2aWNlS2V5PHVua25vd24+W10gPSBbXT4ge1xyXG4gIHByb3ZpZGVzOiBTZXJ2aWNlS2V5PFQ+O1xyXG4gIGRlcGVuZHNPbjogRDtcclxuXHJcbiAgaW5pdGlhbGl6ZSguLi5kZXBlbmRlbmNpZXM6IERlcGVuZGVuY3lUeXBlczxEPik6IFByb21pc2U8VD47XHJcblxyXG4gIGRpc3Bvc2UoaW5zdGFuY2U6IFQpOiB2b2lkO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gc2luZ2xldG9uRmFjdG9yeTxULCBEIGV4dGVuZHMgU2VydmljZUtleTx1bmtub3duPltdID0gW10+KHtcclxuICBwcm92aWRlcyxcclxuICBkZXBlbmRzT24gPSBbXSBhcyB1bmtub3duIGFzIEQsXHJcbiAgaW5pdGlhbGl6ZSxcclxuICBkaXNwb3NlID0gKCkgPT4ge30sXHJcbn06IHtcclxuICBwcm92aWRlczogU2VydmljZUtleTxUPjtcclxuICBkZXBlbmRzT24/OiBEO1xyXG4gIGluaXRpYWxpemU6ICguLi5kZXBlbmRlbmNpZXM6IERlcGVuZGVuY3lUeXBlczxEPikgPT4gUHJvbWlzZTxUPjtcclxuICBkaXNwb3NlPzogKGluc3RhbmNlOiBUKSA9PiB2b2lkO1xyXG59KTogU2VydmljZUZhY3Rvcnk8VCwgRD4ge1xyXG4gIGxldCBpbnN0YW5jZTogVCB8IHVuZGVmaW5lZDtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIHByb3ZpZGVzLFxyXG4gICAgZGVwZW5kc09uLFxyXG4gICAgYXN5bmMgaW5pdGlhbGl6ZSguLi5kZXBlbmRlbmNpZXM6IERlcGVuZGVuY3lUeXBlczxEPik6IFByb21pc2U8VD4ge1xyXG4gICAgICBpZiAoaW5zdGFuY2UpIHtcclxuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XHJcbiAgICAgIH1cclxuICAgICAgaW5zdGFuY2UgPSBhd2FpdCBpbml0aWFsaXplKC4uLmRlcGVuZGVuY2llcyk7XHJcbiAgICAgIHJldHVybiBpbnN0YW5jZTtcclxuICAgIH0sXHJcbiAgICBkaXNwb3NlKHNlcnZpY2VJbnN0YW5jZTogVCk6IHZvaWQge1xyXG4gICAgICBpZiAoaW5zdGFuY2UgPT09IHNlcnZpY2VJbnN0YW5jZSkge1xyXG4gICAgICAgIGRpc3Bvc2Uoc2VydmljZUluc3RhbmNlKTtcclxuICAgICAgICBpbnN0YW5jZSA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG4gICAgfSxcclxuICB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gb25lU2hvdEZhY3Rvcnk8VCwgRCBleHRlbmRzIFNlcnZpY2VLZXk8dW5rbm93bj5bXSA9IFtdPih7XHJcbiAgcHJvdmlkZXMsXHJcbiAgZGVwZW5kc09uLFxyXG4gIGluaXRpYWxpemUsXHJcbiAgZGlzcG9zZSA9ICgpID0+IHt9LFxyXG59OiB7XHJcbiAgcHJvdmlkZXM6IFNlcnZpY2VLZXk8VD47XHJcbiAgZGVwZW5kc09uOiBEO1xyXG4gIGluaXRpYWxpemU6ICguLi5kZXBlbmRlbmNpZXM6IERlcGVuZGVuY3lUeXBlczxEPikgPT4gUHJvbWlzZTxUPjtcclxuICBkaXNwb3NlPzogKGluc3RhbmNlOiBUKSA9PiB2b2lkO1xyXG59KTogU2VydmljZUZhY3Rvcnk8VCwgRD4ge1xyXG4gIHJldHVybiB7XHJcbiAgICBwcm92aWRlcyxcclxuICAgIGRlcGVuZHNPbixcclxuICAgIGluaXRpYWxpemUsXHJcbiAgICBkaXNwb3NlLFxyXG4gIH07XHJcbn1cclxuIiwgImltcG9ydCB7IFNlcnZpY2VLZXkgfSBmcm9tICcuLi8uLi8uLi9saWIvc2VydmljZUtleSc7XG5pbXBvcnQgeyBTbXNTZXJ2aWNlIH0gZnJvbSAnLi4vc21zU2VydmljZSc7XG5pbXBvcnQgeyBzaW5nbGV0b25GYWN0b3J5IH0gZnJvbSAnLi4vLi4vLi4vbGliL3NlcnZpY2VGYWN0b3J5JztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5pbXBvcnQgeyBOb09wU21zU2VydmljZSB9IGZyb20gJy4uL25vT3BTbXNTZXJ2aWNlJztcbmltcG9ydCB7IFRpZ29TbXNTZXJ2aWNlIH0gZnJvbSAnLi4vdGlnb1Ntc1NlcnZpY2UnO1xuaW1wb3J0IHsgTE9HR0VSIH0gZnJvbSAnLi4vLi4vbG9nZ2VyL2RpL2xvZ2dlck1vZHVsZSc7XG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi8uLi9sb2dnZXIvbG9nZ2VyJztcblxuZXhwb3J0IGNvbnN0IFNNU19TRVJWSUNFID0gbmV3IFNlcnZpY2VLZXk8U21zU2VydmljZT4oJ1Ntc1NlcnZpY2UnKTtcblxuZXhwb3J0IGNvbnN0IFNtc1NlcnZpY2VGYWN0b3J5ID0gc2luZ2xldG9uRmFjdG9yeSh7XG4gIHByb3ZpZGVzOiBTTVNfU0VSVklDRSxcbiAgZGVwZW5kc09uOiBbTE9HR0VSXSxcbiAgaW5pdGlhbGl6ZShsb2dnZXI6IExvZ2dlcik6IFByb21pc2U8U21zU2VydmljZT4ge1xuICAgIGxvZ2dlci5pbmZvKCdJbml0aWFsaXppbmcgU21zU2VydmljZScpO1xuICAgIC8vIFNpbmNlIHRoZSBjcmVhdGUgbWV0aG9kIGlzIGFzeW5jLCB3ZSBjb3VsZCBpbnN0YW50aWF0ZSBhIGRpZmZlcmVudFxuICAgIC8vIGltcGxlbWVudGF0aW9uIG9uIGRlbWFuZCBieSByZXRyaWV2aW5nIHNvbWUgY29uZmlndXJhdGlvbiBmcm9tIGEgZGJcbiAgICAvLyBvciBhIGNvbmZpZyBmaWxlLlxuICAgIGlmIChwcm9jZXNzLmVudi5lbnZpcm9ubWVudCA9PT0gJ2RldicpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IE5vT3BTbXNTZXJ2aWNlKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBUaWdvU21zU2VydmljZSgpKTtcbiAgICB9XG4gIH0sXG59KTtcblxuZXhwb3J0IGNvbnN0IFNtc1NlcnZpY2VUZXN0RmFjdG9yeSA9IHNpbmdsZXRvbkZhY3Rvcnkoe1xuICBwcm92aWRlczogU01TX1NFUlZJQ0UsXG4gIGRlcGVuZHNPbjogW10sXG4gIGluaXRpYWxpemUoKTogUHJvbWlzZTxTbXNTZXJ2aWNlPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgTm9PcFNtc1NlcnZpY2UoKSk7XG4gIH0sXG59KSIsICJpbXBvcnQgeyBTbXNTZXJ2aWNlIH0gZnJvbSAnLi9zbXNTZXJ2aWNlJztcclxuXHJcbmV4cG9ydCBjbGFzcyBOb09wU21zU2VydmljZSBpbXBsZW1lbnRzIFNtc1NlcnZpY2Uge1xyXG4gIHNlbmQocmVjaXBpZW50OiBudW1iZXIsIHRleHQ6IHN0cmluZykge1xyXG4gICAgY29uc29sZS53YXJuKGBOb09wU21zU2VydmljZTogU2VuZGluZyBzbXMgdG8gJHtyZWNpcGllbnR9OiAke3RleHR9YCk7XHJcbiAgfVxyXG59XHJcbiIsICJpbXBvcnQgeyBTbXNTZXJ2aWNlIH0gZnJvbSAnLi9zbXNTZXJ2aWNlJztcclxuXHJcbmV4cG9ydCBjbGFzcyBUaWdvU21zU2VydmljZSBpbXBsZW1lbnRzIFNtc1NlcnZpY2Uge1xyXG4gIHNlbmQoX3JlY2lwaWVudDogbnVtYmVyLCBfdGV4dDogc3RyaW5nKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCB5ZXQgaW1wbGVtZW50ZWQnKTtcclxuICB9XHJcbn1cclxuIiwgImltcG9ydCB7IExvZ2dlciwgTG9nRXZlbnQsIExvZ0V2ZW50UGF5bG9hZCB9IGZyb20gJy4vbG9nZ2VyJztcclxuXHJcbmV4cG9ydCBjbGFzcyBFbWFpbEFsZXJ0TG9nZ2VyIGltcGxlbWVudHMgTG9nZ2VyIHtcclxuICBwcml2YXRlIHJlYWRvbmx5IGJ1ZmZlcjogTG9nRXZlbnRbXSA9IFtdO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgYnVmZmVyU2l6ZTogbnVtYmVyO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjaXBpZW50czogc3RyaW5nW107XHJcbiAgcHJpdmF0ZSByZWFkb25seSBlbWFpbFF1ZXVlOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcihidWZmZXJTaXplOiBudW1iZXIgPSA1MCwgcmVjaXBpZW50czogc3RyaW5nW10gPSBbXSkge1xyXG4gICAgdGhpcy5idWZmZXJTaXplID0gYnVmZmVyU2l6ZTtcclxuICAgIHRoaXMucmVjaXBpZW50cyA9IHJlY2lwaWVudHM7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFkZFRvQnVmZmVyKGV2ZW50OiBPbWl0PExvZ0V2ZW50LCAnZGF0ZSc+KTogdm9pZCB7XHJcbiAgICAvLyBLZWVwIHRoZSBidWZmZXIgdG8gdGhlIHNwZWNpZmllZCBzaXplXHJcbiAgICBpZiAodGhpcy5idWZmZXIubGVuZ3RoID49IHRoaXMuYnVmZmVyU2l6ZSkge1xyXG4gICAgICB0aGlzLmJ1ZmZlci5zaGlmdCgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5idWZmZXIucHVzaCh7IC4uLmV2ZW50LCBkYXRlOiBuZXcgRGF0ZSgpIH0pO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGluZm8obWVzc2FnZTogc3RyaW5nLCBwYXlsb2FkPzogTG9nRXZlbnRQYXlsb2FkKTogdm9pZCB7XHJcbiAgICB0aGlzLmFkZFRvQnVmZmVyKHsgbGV2ZWw6ICdJTkZPJywgbWVzc2FnZSwgcGF5bG9hZCB9KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBlcnJvcihcclxuICAgIG1lc3NhZ2U6IHN0cmluZyxcclxuICAgIGVycm9yPzogdW5rbm93bixcclxuICAgIHBheWxvYWQ/OiBMb2dFdmVudFBheWxvYWQsXHJcbiAgKTogdm9pZCB7XHJcbiAgICB0aGlzLmFkZFRvQnVmZmVyKHsgbGV2ZWw6ICdFUlJPUicsIG1lc3NhZ2UsIHBheWxvYWQgfSk7XHJcbiAgICB0aGlzLmVtYWlsUXVldWUucHVzaChjcmVhdGVUYWJsZVN0cmluZyh0aGlzLmJ1ZmZlciwgZXJyb3IpKTtcclxuICAgIHRoaXMuYnVmZmVyLmxlbmd0aCA9IDA7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZGVidWcobWVzc2FnZTogc3RyaW5nLCBwYXlsb2FkPzogTG9nRXZlbnRQYXlsb2FkKTogdm9pZCB7XHJcbiAgICB0aGlzLmFkZFRvQnVmZmVyKHsgbGV2ZWw6ICdERUJVRycsIG1lc3NhZ2UsIHBheWxvYWQgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZmx1c2goKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBmb3IgKGNvbnN0IGVtYWlsIG9mIHRoaXMuZW1haWxRdWV1ZSkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGVtYWlsKTtcclxuICAgIH1cclxuICAgIC8vIENsZWFyIGFsbCBidWZmZXJzXHJcbiAgICB0aGlzLmJ1ZmZlci5sZW5ndGggPSAwO1xyXG4gICAgdGhpcy5lbWFpbFF1ZXVlLmxlbmd0aCA9IDA7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVUYWJsZVN0cmluZyhldmVudHM6IExvZ0V2ZW50W10sIGVycm9yPzogdW5rbm93bik6IHN0cmluZyB7XHJcbiAgaWYgKGV2ZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgIHJldHVybiAnTm8gZXZlbnRzIHRvIGRpc3BsYXknO1xyXG4gIH1cclxuXHJcbiAgLy8gQ2FsY3VsYXRlIGNvbHVtbiB3aWR0aHNcclxuICBjb25zdCBkYXRlV2lkdGggPSBNYXRoLm1heChcclxuICAgIDQsXHJcbiAgICAuLi5ldmVudHMubWFwKChlKSA9PiBlLmRhdGUudG9JU09TdHJpbmcoKS5sZW5ndGgpLFxyXG4gICk7XHJcbiAgY29uc3QgbGV2ZWxXaWR0aCA9IE1hdGgubWF4KFxyXG4gICAgNSwgLy8gXCJMZXZlbFwiIGhlYWRlciBsZW5ndGhcclxuICAgIC4uLmV2ZW50cy5tYXAoKGUpID0+IGUubGV2ZWwubGVuZ3RoKSxcclxuICApO1xyXG4gIGNvbnN0IG1lc3NhZ2VXaWR0aCA9IE1hdGgubWF4KDcsIC4uLmV2ZW50cy5tYXAoKGUpID0+IGUubWVzc2FnZS5sZW5ndGgpKTtcclxuICBjb25zdCBwYXlsb2FkV2lkdGggPSBNYXRoLm1heChcclxuICAgIDcsXHJcbiAgICAuLi5ldmVudHMubWFwKChlKSA9PiAoZS5wYXlsb2FkID8gSlNPTi5zdHJpbmdpZnkoZS5wYXlsb2FkKS5sZW5ndGggOiAwKSksXHJcbiAgKTtcclxuXHJcbiAgLy8gQ3JlYXRlIGhlYWRlclxyXG4gIGNvbnN0IGhlYWRlciA9IFtcclxuICAgICdEQVRFJy5wYWRFbmQoZGF0ZVdpZHRoKSxcclxuICAgICdMRVZFTCcucGFkRW5kKGxldmVsV2lkdGgpLFxyXG4gICAgJ01FU1NBR0UnLnBhZEVuZChtZXNzYWdlV2lkdGgpLFxyXG4gICAgJ1BBWUxPQUQnLnBhZEVuZChwYXlsb2FkV2lkdGgpLFxyXG4gIF0uam9pbignIHwgJyk7XHJcblxyXG4gIC8vIENyZWF0ZSBzZXBhcmF0b3JcclxuICBjb25zdCBzZXBhcmF0b3IgPSBbXHJcbiAgICAnLScucmVwZWF0KGRhdGVXaWR0aCksXHJcbiAgICAnLScucmVwZWF0KGxldmVsV2lkdGgpLFxyXG4gICAgJy0nLnJlcGVhdChtZXNzYWdlV2lkdGgpLFxyXG4gICAgJy0nLnJlcGVhdChwYXlsb2FkV2lkdGgpLFxyXG4gIF0uam9pbignLXwtJyk7XHJcblxyXG4gIC8vIENyZWF0ZSByb3dzXHJcbiAgY29uc3Qgcm93cyA9IGV2ZW50cy5tYXAoKGV2ZW50KSA9PiB7XHJcbiAgICBjb25zdCBkYXRlID0gZXZlbnQuZGF0ZS50b0lTT1N0cmluZygpLnBhZEVuZChkYXRlV2lkdGgpO1xyXG4gICAgY29uc3QgbGV2ZWwgPSBldmVudC5sZXZlbC5wYWRFbmQobGV2ZWxXaWR0aCk7XHJcbiAgICBjb25zdCBtZXNzYWdlID0gZXZlbnQubWVzc2FnZS5wYWRFbmQobWVzc2FnZVdpZHRoKTtcclxuICAgIGNvbnN0IHBheWxvYWQgPSAoZXZlbnQucGF5bG9hZCA/IEpTT04uc3RyaW5naWZ5KGV2ZW50LnBheWxvYWQpIDogJycpLnBhZEVuZChcclxuICAgICAgcGF5bG9hZFdpZHRoLFxyXG4gICAgKTtcclxuICAgIHJldHVybiBbZGF0ZSwgbGV2ZWwsIG1lc3NhZ2UsIHBheWxvYWRdLmpvaW4oJyB8ICcpO1xyXG4gIH0pO1xyXG5cclxuICAvLyBDcmVhdGUgZXJyb3Igc2VjdGlvbiBpZiBlcnJvciBleGlzdHNcclxuICBjb25zdCBlcnJvclNlY3Rpb24gPSBlcnJvclxyXG4gICAgPyAnXFxuXFxuRXJyb3IgRGV0YWlsczpcXG4nICtcclxuICAgICAgJy0nLnJlcGVhdCgyMCkgK1xyXG4gICAgICAnXFxuJyArXHJcbiAgICAgIChlcnJvciBpbnN0YW5jZW9mIEVycm9yXHJcbiAgICAgICAgPyBgJHtlcnJvci5uYW1lfTogJHtlcnJvci5tZXNzYWdlfVxcbiR7ZXJyb3Iuc3RhY2sgfHwgJyd9YFxyXG4gICAgICAgIDogU3RyaW5nKGVycm9yKSlcclxuICAgIDogJyc7XHJcblxyXG4gIC8vIENvbWJpbmUgYWxsIHBhcnRzXHJcbiAgcmV0dXJuIFtoZWFkZXIsIHNlcGFyYXRvciwgLi4ucm93c10uam9pbignXFxuJykgKyBlcnJvclNlY3Rpb247XHJcbn1cclxuIiwgImltcG9ydCB7IHNpbmdsZXRvbkZhY3RvcnkgfSBmcm9tICcuLi8uLi8uLi9saWIvc2VydmljZUZhY3RvcnknO1xyXG5pbXBvcnQgeyBTZXJ2aWNlS2V5IH0gZnJvbSAnLi4vLi4vLi4vbGliL3NlcnZpY2VLZXknO1xyXG5pbXBvcnQgeyBFbWFpbEFsZXJ0TG9nZ2VyIH0gZnJvbSAnLi4vZW1haWxBbGVydExvZ2dlcic7XHJcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL2xvZ2dlcic7XHJcbmltcG9ydCB7IFNNU19TRVJWSUNFIH0gZnJvbSAnLi4vLi4vc21zL2RpL3Ntc01vZHVsZSc7XHJcbmltcG9ydCB7IFNtc1NlcnZpY2UgfSBmcm9tICcuLi8uLi9zbXMvc21zU2VydmljZSc7XHJcblxyXG5leHBvcnQgY29uc3QgTE9HR0VSID0gbmV3IFNlcnZpY2VLZXk8TG9nZ2VyPignTG9nZ2VyJyk7XHJcblxyXG5leHBvcnQgY29uc3QgTG9nZ2VyRmFjdG9yeSA9IHNpbmdsZXRvbkZhY3Rvcnkoe1xyXG4gIHByb3ZpZGVzOiBMT0dHRVIsXHJcbiAgZGVwZW5kc09uOiBbXSxcclxuICBpbml0aWFsaXplOiAoKSA9PiB7XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBFbWFpbEFsZXJ0TG9nZ2VyKDEwMCwgWydqdWFuaHI0NTRAZ21haWwuY29tJ10pKTtcclxuICB9LFxyXG59KTtcclxuIiwgImltcG9ydCB7IFNlcnZpY2VNb2R1bGUgfSBmcm9tICcuL2xpYi9zZXJ2aWNlTW9kdWxlJztcclxuaW1wb3J0IHsgU2VydmljZVByb3ZpZGVyIH0gZnJvbSAnLi9saWIvc2VydmljZVByb3ZpZGVyJztcclxuaW1wb3J0IHsgU01TX1NFUlZJQ0UsIFNtc1NlcnZpY2VGYWN0b3J5IH0gZnJvbSAnLi9jb3JlL3Ntcy9kaS9zbXNNb2R1bGUnO1xyXG5pbXBvcnQgeyBMT0dHRVIsIExvZ2dlckZhY3RvcnkgfSBmcm9tICcuL2NvcmUvbG9nZ2VyL2RpL2xvZ2dlck1vZHVsZSc7XHJcbmltcG9ydCB7IEVtYWlsQWxlcnRMb2dnZXIgfSBmcm9tICcuL2NvcmUvbG9nZ2VyL2VtYWlsQWxlcnRMb2dnZXInO1xyXG5cclxuY29uc3QgYXV0aE1vZHVsZSA9IFNlcnZpY2VNb2R1bGUuZnJvbShbU21zU2VydmljZUZhY3RvcnksIExvZ2dlckZhY3RvcnldKTtcclxuXHJcbmZ1bmN0aW9uIG1vZHVsZShcclxuICBtb2R1bGU6IFNlcnZpY2VNb2R1bGUsXHJcbiAgZm46IChldmVudDogb2JqZWN0LCBjb250ZXh0OiBDb250ZXh0KSA9PiB2b2lkLFxyXG4pIHtcclxuICByZXR1cm4gKGV2ZW50OiBvYmplY3QsIGNvbnRleHQ6IG9iamVjdCkgPT4ge1xyXG4gICAgZm4oZXZlbnQsIHsgc2VydmljZXM6IG1vZHVsZSwgLi4uY29udGV4dCB9KTtcclxuICB9O1xyXG59XHJcblxyXG5jb25zdCBoYW5kbGVyID0gbW9kdWxlKGF1dGhNb2R1bGUsIGxvZ2luKTtcclxuXHJcbihhc3luYyBmdW5jdGlvbiAoKSB7XHJcbiAgYXdhaXQgZGVlcGx5TmVzdGVkRnVuY3Rpb24oeyBzZXJ2aWNlczogYXV0aE1vZHVsZSB9KTtcclxuICBjb25zdCBsb2dnZXIgPSBhd2FpdCBhdXRoTW9kdWxlLmluamVjdChMT0dHRVIpO1xyXG4gIGlmIChsb2dnZXIgaW5zdGFuY2VvZiBFbWFpbEFsZXJ0TG9nZ2VyKSB7XHJcbiAgICBhd2FpdCBsb2dnZXIuZmx1c2goKTtcclxuICB9XHJcbiAgY29uc29sZS5sb2coJ0RvbmUnKTtcclxufSkoKTtcclxuXHJcbmFzeW5jIGZ1bmN0aW9uIGRlZXBseU5lc3RlZEZ1bmN0aW9uKGNvbnRleHQ6IENvbnRleHQpIHtcclxuICBhd2FpdCBsb2dpbih7fSwgY29udGV4dCk7XHJcbn1cclxuXHJcbmludGVyZmFjZSBDb250ZXh0IHtcclxuICBzZXJ2aWNlczogU2VydmljZVByb3ZpZGVyO1xyXG59XHJcblxyXG5hc3luYyBmdW5jdGlvbiBsb2dpbihldmVudDogYW55LCBjb250ZXh0OiBDb250ZXh0KSB7XHJcbiAgY29uc3Qgc3RhdGUgPSBhdXRob3JpemUoZXZlbnQpO1xyXG4gIGNvbnN0IGxvZ2dlciA9IGF3YWl0IGNvbnRleHQuc2VydmljZXMuaW5qZWN0KExPR0dFUik7XHJcbiAgaWYgKHN0YXRlID09PSAnREVWSUNFX0NIQU5HRUQnKSB7XHJcbiAgICBsb2dnZXIuaW5mbygnRGV2aWNlIGNoYW5nZWQnLCB7J3VzZXInOiAnYXNhZCd9KTtcclxuICAgIC8vIFdpdGggdGhlIHNlcnZpY2Uga2V5IHdlIGdldCB0eXBlIHNhZmV0eS9pbmZlcmVuY2UgYW5kIG5hdmlnYXRlIHRvIGRlZmluaXRpb24gZm9yIGZyZWUsXHJcbiAgICAvLyB0aGVyZSBpcyBubyBtYWdpYyBubyBhbm5vdGF0aW9ucywgd2UgY2FuIHNlZSBhbGwgdGhlXHJcbiAgICAvLyBmYWN0b3JpZXMgdGhhdCBwcm92aWRlIHRoaXMgZGVwZW5kZW5jeSBhbmQgc2VlIGFsbCBwbGFjZXMgd2hlcmUgdGhpcyBpcyByZXRyaWV2ZWQuXHJcbiAgICBjb25zdCBzbXMgPSBhd2FpdCBjb250ZXh0LnNlcnZpY2VzLmluamVjdChTTVNfU0VSVklDRSk7XHJcbiAgICBsb2dnZXIuZGVidWcoJ1NlbmRpbmcgc21zJyk7XHJcbiAgICB0cnkge1xyXG4gICAgICBzbXMuc2VuZCg5NzEyMzMxNDksICdIb2xhIEp1YW4sIHR1IHBpbiBlcyAyMjIyMicpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgc21zJywgZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0cmlldmluZyB0aGUgc2VydmljZSBhIHNlY29uZCB0aW1lIHdvdWxkIGhhdmUgdmlydHVhbGx5IHplcm8gY29zdCBpZiB0aGVcclxuICAgIC8vIHVuZGVybHlpbmcgZmFjdG9yeSBwcm92aWRlcyBhIHNpbmdsZXRvbi5cclxuICAgIGNvbnN0IHNtczEgPSBhd2FpdCBjb250ZXh0LnNlcnZpY2VzLmluamVjdChTTVNfU0VSVklDRSk7XHJcbiAgfVxyXG5cclxuICByZXR1cm47XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGF1dGhvcml6ZShfcmVxdWVzdDogYW55KTogJ09LJyB8ICdERVZJQ0VfQ0hBTkdFRCcge1xyXG4gIHJldHVybiAnREVWSUNFX0NIQU5HRUQnO1xyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFJTyxJQUFNLGdCQUFOLE1BQU0sZUFBeUM7QUFBQSxFQUdwRCxZQUFZLFdBQWdFO0FBRjVFLFNBQWlCLFlBQXdDLENBQUM7QUFH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
15
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,6CAA0C;AAC1C,qDAAoD;AAEpD,MAAM,gBAAgB,GAAG,IAAI,uBAAU,CAAc,aAAa,CAAC,CAAC;AACpE,MAAM,OAAO,GAAG,IAAI,uBAAU,CAAS,KAAK,CAAC,CAAC;AAC9C,MAAM,OAAO,GAAG,IAAI,uBAAU,CAAS,KAAK,CAAC,CAAC;AAO9C,MAAM,kBAAkB,GAAG,IAAA,iCAAgB,EAAC;IAC1C,QAAQ,EAAE,gBAAgB;IAC1B,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAU;IACtC,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvB,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACtB,CAAC;CACF,CAAC,CAAC"}
@@ -1,25 +1,33 @@
1
- import { ServiceKey } from './serviceKey';
1
+ import { ServiceKey } from './ServiceKey';
2
2
  type ServiceType<T> = T extends ServiceKey<infer U> ? U : never;
3
- type DependencyTypes<T extends ServiceKey<unknown>[]> = {
3
+ type DependencyTypes<T extends readonly ServiceKey<unknown>[]> = {
4
4
  [K in keyof T]: ServiceType<T[K]>;
5
5
  };
6
- export interface ServiceFactory<T, D extends ServiceKey<unknown>[] = []> {
7
- provides: ServiceKey<T>;
8
- dependsOn: D;
9
- initialize(...dependencies: DependencyTypes<D>): Promise<T>;
10
- dispose(instance: T): void;
6
+ export declare abstract class ServiceFactory<const T, const D extends readonly ServiceKey<unknown>[] = []> {
7
+ abstract provides: ServiceKey<T>;
8
+ abstract dependsOn: D;
9
+ abstract initialize(...dependencies: DependencyTypes<D>): T | Promise<T>;
10
+ abstract dispose(instance: T): void;
11
+ /**
12
+ * Creates a singleton service factory that ensures a single instance of the provided service is initialized
13
+ * and used throughout its lifecycle.
14
+ */
15
+ static singleton<const T, const D extends readonly ServiceKey<unknown>[] = []>({ provides, dependsOn, initialize, dispose, }: {
16
+ provides: ServiceKey<T>;
17
+ dependsOn?: D;
18
+ initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
19
+ dispose?: (instance: T) => void;
20
+ }): ServiceFactory<T, D>;
21
+ /**
22
+ * Creates a one-shot service factory that initializes a new instance of the provided service
23
+ * every time it is requested.
24
+ */
25
+ static oneShot<const T, const D extends readonly ServiceKey<unknown>[] = []>({ provides, dependsOn, initialize, dispose, }: {
26
+ provides: ServiceKey<T>;
27
+ dependsOn: D;
28
+ initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
29
+ dispose?: (instance: T) => void;
30
+ }): ServiceFactory<T, D>;
11
31
  }
12
- export declare function singletonFactory<T, D extends ServiceKey<unknown>[] = []>({ provides, dependsOn, initialize, dispose, }: {
13
- provides: ServiceKey<T>;
14
- dependsOn?: D;
15
- initialize: (...dependencies: DependencyTypes<D>) => Promise<T>;
16
- dispose?: (instance: T) => void;
17
- }): ServiceFactory<T, D>;
18
- export declare function oneShotFactory<T, D extends ServiceKey<unknown>[] = []>({ provides, dependsOn, initialize, dispose, }: {
19
- provides: ServiceKey<T>;
20
- dependsOn: D;
21
- initialize: (...dependencies: DependencyTypes<D>) => Promise<T>;
22
- dispose?: (instance: T) => void;
23
- }): ServiceFactory<T, D>;
24
32
  export {};
25
- //# sourceMappingURL=serviceFactory.d.ts.map
33
+ //# sourceMappingURL=ServiceFactory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serviceFactory.d.ts","sourceRoot":"","sources":["../src/serviceFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAGhE,KAAK,eAAe,CAAC,CAAC,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI;KACrD,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,WAAW,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE;IACrE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,CAAC,CAAC;IAEb,UAAU,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE5D,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EACxE,QAAQ,EACR,SAA8B,EAC9B,UAAU,EACV,OAAkB,GACnB,EAAE;IACD,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACxB,SAAS,CAAC,EAAE,CAAC,CAAC;IACd,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;CACjC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAoBvB;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EACtE,QAAQ,EACR,SAAS,EACT,UAAU,EACV,OAAkB,GACnB,EAAE;IACD,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,CAAC,CAAC;IACb,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;CACjC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAOvB"}
1
+ {"version":3,"file":"ServiceFactory.d.ts","sourceRoot":"","sources":["../src/ServiceFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAGhE,KAAK,eAAe,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI;KAC9D,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC,CAAC;AAEF,8BAAsB,cAAc,CAClC,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE;IAEnD,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IAEtB,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAExE,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;IAEnC;;;OAGG;IACH,MAAM,CAAC,SAAS,CACd,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EACnD,EACA,QAAQ,EACR,SAA8B,EAC9B,UAAU,EACV,OAAkB,GACnB,EAAE;QACD,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;KACjC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAsBxB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EAC3E,QAAQ,EACR,SAAS,EACT,UAAU,EACV,OAAkB,GACnB,EAAE;QACD,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,SAAS,EAAE,CAAC,CAAC;QACb,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;KACjC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;CAQzB"}