@decohere/crucible 0.0.1-dev.12 → 0.0.1-dev.121

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.
Files changed (47) hide show
  1. package/README.md +354 -0
  2. package/commonjs/src/const.js +5 -7
  3. package/commonjs/src/decorators/index.js +0 -2
  4. package/commonjs/src/decorators/inject.decorator.js +28 -15
  5. package/commonjs/src/decorators/injectable.dectorator.js +0 -2
  6. package/commonjs/src/index.js +0 -2
  7. package/commonjs/src/models/service-key.js +20 -0
  8. package/commonjs/src/models/service-registration.model.js +1 -6
  9. package/commonjs/src/services/container.js +207 -0
  10. package/commonjs/src/services/index.js +2 -4
  11. package/commonjs/src/services/service-container-builder.js +67 -0
  12. package/commonjs/src/services/service-registry.js +29 -22
  13. package/commonjs/src/types/errors.js +0 -2
  14. package/commonjs/src/types/index.js +1 -2
  15. package/commonjs/src/types/types.js +0 -2
  16. package/es6/src/const.js +3 -5
  17. package/es6/src/decorators/index.js +0 -2
  18. package/es6/src/decorators/inject.decorator.js +27 -14
  19. package/es6/src/decorators/injectable.dectorator.js +0 -2
  20. package/es6/src/index.js +0 -2
  21. package/es6/src/models/service-key.js +10 -0
  22. package/es6/src/models/service-registration.model.js +1 -6
  23. package/es6/src/services/container.js +197 -0
  24. package/es6/src/services/index.js +2 -4
  25. package/es6/src/services/service-container-builder.js +57 -0
  26. package/es6/src/services/service-registry.js +34 -23
  27. package/es6/src/types/errors.js +0 -2
  28. package/es6/src/types/index.js +1 -2
  29. package/es6/src/types/types.js +0 -2
  30. package/package.json +2 -3
  31. package/types/src/const.d.ts +1 -1
  32. package/types/src/decorators/inject.decorator.d.ts +17 -2
  33. package/types/src/models/service-key.d.ts +9 -0
  34. package/types/src/models/service-registration.model.d.ts +5 -4
  35. package/types/src/services/{crucible.d.ts → container.d.ts} +16 -5
  36. package/types/src/services/index.d.ts +2 -2
  37. package/types/src/services/{crucible-builder.d.ts → service-container-builder.d.ts} +9 -5
  38. package/types/src/services/service-registry.d.ts +12 -6
  39. package/types/src/types/index.d.ts +1 -0
  40. package/types/src/types/types.d.ts +1 -1
  41. package/commonjs/src/models/registration-key.model.js +0 -31
  42. package/commonjs/src/services/crucible-builder.js +0 -68
  43. package/commonjs/src/services/crucible.js +0 -165
  44. package/es6/src/models/registration-key.model.js +0 -21
  45. package/es6/src/services/crucible-builder.js +0 -58
  46. package/es6/src/services/crucible.js +0 -155
  47. package/types/src/models/registration-key.model.d.ts +0 -7
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "Container", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Container;
9
+ }
10
+ });
11
+ const _reflection = require("@decohere/core/reflection");
12
+ const _const = require("../const.js");
13
+ const _servicekey = require("../models/service-key.js");
14
+ const _errors = require("../types/errors.js");
15
+ const _serviceregistry = require("./service-registry.js");
16
+ function describePath(path, last) {
17
+ const keys = path.map((registration)=>registration.key);
18
+ return [
19
+ ...keys,
20
+ ...last == null ? [] : [
21
+ last
22
+ ]
23
+ ].map(_servicekey.describeKey).join(" → ");
24
+ }
25
+ class Container {
26
+ key;
27
+ instances = new Map();
28
+ serviceRegistry;
29
+ parent;
30
+ rootScope;
31
+ scopes = new Map();
32
+ isDisposed = false;
33
+ constructor(options){
34
+ this.key = options?.key;
35
+ this.serviceRegistry = new _serviceregistry.ServiceRegistry(options?.serviceRegistry);
36
+ this.registerLifetimeScope();
37
+ this.parent = options?.parent;
38
+ this.rootScope = options?.parent?.rootScope ?? this;
39
+ }
40
+ resolveMany(resolveRequest) {
41
+ return this.resolveAll(resolveRequest, []);
42
+ }
43
+ /** Throws {@link ResolveError} when nothing is registered for the key. */ resolve(resolveRequest) {
44
+ return this.resolveOne(resolveRequest, [], false);
45
+ }
46
+ resolveAll(key, path) {
47
+ const registrations = this.serviceRegistry.getRegistration(key) ?? [];
48
+ return registrations.map((registration)=>this.resolveRegistration(registration, path));
49
+ }
50
+ resolveOne(key, path, optional) {
51
+ const registrations = this.serviceRegistry.getRegistration(key);
52
+ if (registrations == null || registrations.length === 0) {
53
+ if (optional) return undefined;
54
+ const requiredBy = path.length === 0 ? "" : ` (required by ${describePath(path, key)})`;
55
+ throw new _errors.ResolveError(`Nothing is registered for ${(0, _servicekey.describeKey)(key)}${requiredBy}. Register it, or mark the parameter @optional().`);
56
+ }
57
+ if (registrations.length > 1) {
58
+ throw new _errors.ResolveError(`There are multiple services registered with key ${(0, _servicekey.describeKey)(key)}. Use resolveMany to resolve all implementations.`);
59
+ }
60
+ return this.resolveRegistration(registrations[0], path);
61
+ }
62
+ beginScope(name) {
63
+ if (this.isDisposed) {
64
+ throw new Error("This container has been disposed");
65
+ }
66
+ if (name != null && this.scopes.has(name)) {
67
+ throw new _errors.DuplicateScopeError(`Cannot create duplicate scope. Scope with ${name} is already created and has not been disposed.`);
68
+ }
69
+ const scope = new Container({
70
+ key: name,
71
+ serviceRegistry: this.serviceRegistry,
72
+ parent: this
73
+ });
74
+ if (name != null) {
75
+ this.scopes.set(name, scope);
76
+ }
77
+ return scope;
78
+ }
79
+ [Symbol.dispose]() {
80
+ if (this.isDisposed) {
81
+ return;
82
+ }
83
+ this.disposeSync();
84
+ }
85
+ async [Symbol.asyncDispose]() {
86
+ if (this.isDisposed) {
87
+ return;
88
+ }
89
+ await this.disposeAsync();
90
+ }
91
+ disposeSync() {
92
+ if (this.isDisposed) {
93
+ return;
94
+ }
95
+ this.isDisposed = true;
96
+ this.parent?.releaseScope(this.key);
97
+ this.scopes.clear();
98
+ // Reverse creation order: dependents are cleaned up before what they depend on.
99
+ for (const inst of [
100
+ ...this.instances.values()
101
+ ].reverse()){
102
+ if (inst === this) {
103
+ continue;
104
+ }
105
+ inst[Symbol.dispose]?.();
106
+ }
107
+ }
108
+ async disposeAsync() {
109
+ if (this.isDisposed) {
110
+ return;
111
+ }
112
+ this.isDisposed = true;
113
+ this.parent?.releaseScope(this.key);
114
+ this.scopes.clear();
115
+ // Reverse creation order: dependents are cleaned up before what they depend on.
116
+ for (const inst of [
117
+ ...this.instances.values()
118
+ ].reverse()){
119
+ if (inst === this) {
120
+ continue;
121
+ }
122
+ if (Symbol.asyncDispose in inst) {
123
+ await inst[Symbol.asyncDispose]();
124
+ } else {
125
+ inst[Symbol.dispose]?.();
126
+ }
127
+ }
128
+ }
129
+ resolveRegistration(registration, path) {
130
+ this.assertNoCycle(registration, path);
131
+ this.assertNotCaptive(registration, path);
132
+ const { scope } = registration;
133
+ switch(scope){
134
+ case _const.Scopes.transient:
135
+ return this.createInstance(registration, path);
136
+ case _const.Scopes.singleton:
137
+ return this.rootScope.getOrCreateInstance(registration, path);
138
+ case _const.Scopes.request:
139
+ return this.getOrCreateInstance(registration, path);
140
+ }
141
+ }
142
+ assertNoCycle(registration, path) {
143
+ if (!path.includes(registration)) return;
144
+ throw new _errors.ResolveError(`Circular dependency: ${describePath(path, registration.key)}. Break the cycle, e.g. by resolving one side lazily from the LifetimeScope.`);
145
+ }
146
+ /**
147
+ * A singleton lives for the whole process, so a request-scoped service it depends on (directly
148
+ * or through transients) would be created once and then shared by every request, e.g. one
149
+ * QueryRunner for the life of the process. The container's own lifetime scope is exempt: a
150
+ * singleton asking for it gets the root, which is the scope it lives in.
151
+ */ assertNotCaptive(registration, path) {
152
+ if (registration.scope !== _const.Scopes.request || registration.key === _const.LifetimeScopeToken) return;
153
+ const singleton = path.find((owner)=>owner.scope === _const.Scopes.singleton);
154
+ if (singleton == null) return;
155
+ throw new _errors.ResolveError(`Singleton ${(0, _servicekey.describeKey)(singleton.key)} depends on request-scoped ${(0, _servicekey.describeKey)(registration.key)} (${describePath(path, registration.key)}). A singleton would keep the first request's instance forever: make ${(0, _servicekey.describeKey)(singleton.key)} request-scoped, or resolve ${(0, _servicekey.describeKey)(registration.key)} per request from the LifetimeScope.`);
156
+ }
157
+ getOrCreateInstance(registration, path) {
158
+ if (this.isDisposed) {
159
+ throw new Error("This container has been disposed");
160
+ }
161
+ const { type, isInstance } = registration;
162
+ // One cache entry per registration: an instance registration is its own entry.
163
+ const cacheKey = type;
164
+ const existingInstance = this.instances.get(cacheKey);
165
+ if (existingInstance != null) {
166
+ return existingInstance;
167
+ }
168
+ const instance = isInstance ? type : this.createInstance(registration, path);
169
+ this.instances.set(cacheKey, instance);
170
+ return instance;
171
+ }
172
+ createInstance(registration, path) {
173
+ const type = registration.type;
174
+ const canConstruct = (0, _reflection.isConstructable)(type);
175
+ const deps = this.resolveDependencies(type, [
176
+ ...path,
177
+ registration
178
+ ]);
179
+ const inst = canConstruct ? new type(...deps) : type();
180
+ return inst;
181
+ }
182
+ resolveDependencies(type, path) {
183
+ const params = (0, _reflection.getMeta)(_reflection.ReflectionMeta.paramtypes, type) ?? [];
184
+ const injectTokens = (0, _reflection.getMeta)(_const.ContainerMeta.injecttoken, type) ?? new Map();
185
+ return params.map((param, index)=>{
186
+ const token = injectTokens.get(index);
187
+ const key = token?.key ?? param;
188
+ if (key == null || key === Object || token?.key == null && (0, _reflection.isArrayType)(param)) {
189
+ if (token?.optional) return undefined;
190
+ throw new _errors.ResolveError(`Cannot tell what to inject for constructor parameter ${index} of ${describePath(path)}: its type is not a class at run time (an interface, an array, or a type-only import). Add @inject(token) to the parameter.`);
191
+ }
192
+ return (0, _reflection.isArrayType)(param) ? this.resolveAll(key, path) : this.resolveOne(key, path, token?.optional === true);
193
+ });
194
+ }
195
+ releaseScope(name) {
196
+ if (name == null) {
197
+ return;
198
+ }
199
+ this.scopes.delete(name);
200
+ }
201
+ registerLifetimeScope() {
202
+ this.serviceRegistry.replaceType(_const.Scopes.request, {
203
+ typeOrKey: _const.LifetimeScopeToken,
204
+ typeOrInstance: this
205
+ });
206
+ }
207
+ }
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- _export_star(require("./crucible.js"), exports);
6
- _export_star(require("./crucible-builder.js"), exports);
5
+ _export_star(require("./container.js"), exports);
6
+ _export_star(require("./service-container-builder.js"), exports);
7
7
  function _export_star(from, to) {
8
8
  Object.keys(from).forEach(function(k) {
9
9
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
@@ -17,5 +17,3 @@ function _export_star(from, to) {
17
17
  });
18
18
  return from;
19
19
  }
20
-
21
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9zZXJ2aWNlcy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9jcnVjaWJsZS5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vY3J1Y2libGUtYnVpbGRlci5qc1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7cUJBQWM7cUJBQ0EifQ==
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "ServiceContainerBuilder", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return ServiceContainerBuilder;
9
+ }
10
+ });
11
+ const _const = require("../const.js");
12
+ const _container = require("./container.js");
13
+ const _serviceregistry = require("./service-registry.js");
14
+ class ServiceContainerBuilder {
15
+ serviceRegistry;
16
+ constructor(options){
17
+ this.serviceRegistry = options?.serviceRegistry ?? new _serviceregistry.ServiceRegistry();
18
+ }
19
+ get override() {
20
+ return this.createRegistrar(true);
21
+ }
22
+ registerType(type, scope = _const.Scopes.transient) {
23
+ return this.register(false)(scope)(type, type);
24
+ }
25
+ registerTypes(scopeOrType, ...types) {
26
+ return this.registerMany(false, scopeOrType, types);
27
+ }
28
+ registerTransient(typeOrKey, type) {
29
+ return this.register(false)(_const.Scopes.transient)(typeOrKey, type);
30
+ }
31
+ registerSingleton(typeOrKey, typeOrInstance) {
32
+ return this.register(false)(_const.Scopes.singleton)(typeOrKey, typeOrInstance);
33
+ }
34
+ registerRequestScoped(typeOrKey, type) {
35
+ return this.register(false)(_const.Scopes.request)(typeOrKey, type);
36
+ }
37
+ build() {
38
+ return new _container.Container({
39
+ serviceRegistry: this.serviceRegistry
40
+ });
41
+ }
42
+ register = (override)=>(scope)=>(typeOrKey, typeOrInstance)=>this.serviceRegistry.registerType(scope, {
43
+ typeOrKey,
44
+ typeOrInstance,
45
+ override
46
+ });
47
+ registerMany(override, scopeOrType, types) {
48
+ const bind = this.register(override);
49
+ const isScope = typeof scopeOrType !== "function";
50
+ const scope = isScope ? scopeOrType : _const.Scopes.transient;
51
+ const allTypes = isScope ? types : [
52
+ scopeOrType,
53
+ ...types
54
+ ];
55
+ return allTypes.map((type)=>bind(scope)(type, type));
56
+ }
57
+ createRegistrar(override) {
58
+ const bind = this.register(override);
59
+ return {
60
+ registerType: (type, scope = _const.Scopes.transient)=>bind(scope)(type, type),
61
+ registerTypes: (scopeOrType, ...types)=>this.registerMany(override, scopeOrType, types),
62
+ registerTransient: (typeOrKey, type)=>bind(_const.Scopes.transient)(typeOrKey, type),
63
+ registerSingleton: (typeOrKey, typeOrInstance)=>bind(_const.Scopes.singleton)(typeOrKey, typeOrInstance),
64
+ registerRequestScoped: (typeOrKey, type)=>bind(_const.Scopes.request)(typeOrKey, type)
65
+ };
66
+ }
67
+ }
@@ -8,43 +8,50 @@ Object.defineProperty(exports, "ServiceRegistry", {
8
8
  return ServiceRegistry;
9
9
  }
10
10
  });
11
- const _registrationkeymodel = require("../models/registration-key.model.js");
11
+ const _servicekey = require("../models/service-key.js");
12
12
  const _serviceregistrationmodel = require("../models/service-registration.model.js");
13
+ const _errors = require("../types/errors.js");
13
14
  class ServiceRegistry {
14
- registrations;
15
+ #registrations = new Map();
16
+ #parent;
15
17
  constructor(parent){
16
- this.registrations = new Map(parent?.registrations);
18
+ this.#parent = parent;
17
19
  }
18
20
  registerType(scope, options) {
19
21
  const registration = this.createRegistrationFrom(scope, options);
20
- const existingRegistration = this.getRegistrations(registration.key)?.filter((reg)=>!reg.isEqual(registration)) ?? [];
21
- this.setRegistration(registration.key, [
22
- registration,
23
- ...existingRegistration
22
+ // Override means "this key now resolves to this", e.g. a test fake: replace every binding.
23
+ if (options.override) {
24
+ this.#registrations.set(registration.key, [
25
+ registration
26
+ ]);
27
+ return registration;
28
+ }
29
+ const existing = this.getRegistration(registration.key) ?? [];
30
+ const duplicate = existing.find((reg)=>reg.isEqual(registration));
31
+ if (duplicate != null) {
32
+ throw new _errors.RegistrationError(`A service is already registered for key ${(0, _servicekey.describeKey)(registration.key)}. Use builder.override.registerSingleton() (or the matching register* method) to replace it.`);
33
+ }
34
+ this.#registrations.set(registration.key, [
35
+ ...existing,
36
+ registration
24
37
  ]);
25
38
  return registration;
26
39
  }
27
- getRegistration(key) {
28
- const keyVal = new _registrationkeymodel.RegistrationKey(key).value;
29
- const registration = this.registrations.get(keyVal);
40
+ replaceType(scope, options) {
41
+ const registration = this.createRegistrationFrom(scope, options);
42
+ this.#registrations.set(registration.key, [
43
+ registration
44
+ ]);
30
45
  return registration;
31
46
  }
47
+ getRegistration(key) {
48
+ return this.#registrations.get(key) ?? this.#parent?.getRegistration(key);
49
+ }
32
50
  createRegistrationFrom(scope, options) {
33
51
  const { typeOrKey, typeOrInstance } = options;
34
52
  const isKey = typeof typeOrKey === "string" || typeof typeOrKey === "symbol";
35
53
  const isInstance = typeof typeOrInstance === "object";
36
- const key = new _registrationkeymodel.RegistrationKey(!isKey ? typeOrKey.name : typeOrKey);
37
54
  const type = isInstance ? typeOrInstance : isKey ? typeOrInstance : typeOrKey;
38
- const registration = new _serviceregistrationmodel.ServiceRegistration(key, type, scope, isInstance);
39
- return registration;
40
- }
41
- getRegistrations(key) {
42
- const value = key.value;
43
- return this.registrations.get(value);
44
- }
45
- setRegistration(key, registrations) {
46
- this.registrations.set(key.value, registrations);
55
+ return new _serviceregistrationmodel.ServiceRegistration(typeOrKey, type, scope, isInstance);
47
56
  }
48
57
  }
49
-
50
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlLXJlZ2lzdHJ5LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgQ29uc3RydWN0YWJsZSwgRnVuY3Rpb25UeXBlIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBSZWdpc3RyYXRpb25LZXkgfSBmcm9tIFwiLi4vbW9kZWxzL3JlZ2lzdHJhdGlvbi1rZXkubW9kZWwuanNcIjtcbmltcG9ydCB7IFNlcnZpY2VSZWdpc3RyYXRpb24gfSBmcm9tIFwiLi4vbW9kZWxzL3NlcnZpY2UtcmVnaXN0cmF0aW9uLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFNjb3BlIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzLmpzXCI7XG5cbmV4cG9ydCB0eXBlIFJlZ2lzdGVyVHlwZU9wdGlvbnMgPSB7XG5cdHR5cGVPcktleTogc3RyaW5nIHwgc3ltYm9sIHwgQ29uc3RydWN0YWJsZSB8IEZ1bmN0aW9uVHlwZTtcblx0dHlwZU9ySW5zdGFuY2U/OiBDb25zdHJ1Y3RhYmxlIHwgRnVuY3Rpb25UeXBlIHwgb2JqZWN0O1xufTtcblxuZXhwb3J0IGNsYXNzIFNlcnZpY2VSZWdpc3RyeSB7XG5cdHByaXZhdGUgcmVhZG9ubHkgcmVnaXN0cmF0aW9uczogTWFwPHN0cmluZywgU2VydmljZVJlZ2lzdHJhdGlvbltdPjtcblx0cHVibGljIGNvbnN0cnVjdG9yKHBhcmVudD86IFNlcnZpY2VSZWdpc3RyeSkge1xuXHRcdHRoaXMucmVnaXN0cmF0aW9ucyA9IG5ldyBNYXAocGFyZW50Py5yZWdpc3RyYXRpb25zKTtcblx0fVxuXG5cdHB1YmxpYyByZWdpc3RlclR5cGUoc2NvcGU6IFNjb3BlLCBvcHRpb25zOiBSZWdpc3RlclR5cGVPcHRpb25zKSB7XG5cdFx0Y29uc3QgcmVnaXN0cmF0aW9uID0gdGhpcy5jcmVhdGVSZWdpc3RyYXRpb25Gcm9tKHNjb3BlLCBvcHRpb25zKTtcblx0XHRjb25zdCBleGlzdGluZ1JlZ2lzdHJhdGlvbiA9XG5cdFx0XHR0aGlzLmdldFJlZ2lzdHJhdGlvbnMocmVnaXN0cmF0aW9uLmtleSk/LmZpbHRlcigocmVnKSA9PiAhcmVnLmlzRXF1YWwocmVnaXN0cmF0aW9uKSkgPz9cblx0XHRcdFtdO1xuXG5cdFx0dGhpcy5zZXRSZWdpc3RyYXRpb24ocmVnaXN0cmF0aW9uLmtleSwgW3JlZ2lzdHJhdGlvbiwgLi4uZXhpc3RpbmdSZWdpc3RyYXRpb25dKTtcblx0XHRyZXR1cm4gcmVnaXN0cmF0aW9uO1xuXHR9XG5cblx0cHVibGljIGdldFJlZ2lzdHJhdGlvbihrZXk6IHN0cmluZyB8IHN5bWJvbCB8IENvbnN0cnVjdGFibGUpOiBTZXJ2aWNlUmVnaXN0cmF0aW9uW10ge1xuXHRcdGNvbnN0IGtleVZhbCA9IG5ldyBSZWdpc3RyYXRpb25LZXkoa2V5KS52YWx1ZTtcblx0XHRjb25zdCByZWdpc3RyYXRpb24gPSB0aGlzLnJlZ2lzdHJhdGlvbnMuZ2V0KGtleVZhbCk7XG5cdFx0cmV0dXJuIHJlZ2lzdHJhdGlvbjtcblx0fVxuXG5cdHByaXZhdGUgY3JlYXRlUmVnaXN0cmF0aW9uRnJvbShzY29wZTogU2NvcGUsIG9wdGlvbnM6IFJlZ2lzdGVyVHlwZU9wdGlvbnMpIHtcblx0XHRjb25zdCB7IHR5cGVPcktleSwgdHlwZU9ySW5zdGFuY2UgfSA9IG9wdGlvbnM7XG5cdFx0Y29uc3QgaXNLZXkgPSB0eXBlb2YgdHlwZU9yS2V5ID09PSBcInN0cmluZ1wiIHx8IHR5cGVvZiB0eXBlT3JLZXkgPT09IFwic3ltYm9sXCI7XG5cdFx0Y29uc3QgaXNJbnN0YW5jZSA9IHR5cGVvZiB0eXBlT3JJbnN0YW5jZSA9PT0gXCJvYmplY3RcIjtcblx0XHRjb25zdCBrZXkgPSBuZXcgUmVnaXN0cmF0aW9uS2V5KCFpc0tleSA/IHR5cGVPcktleS5uYW1lIDogdHlwZU9yS2V5KTtcblx0XHRjb25zdCB0eXBlID0gaXNJbnN0YW5jZSA/IHR5cGVPckluc3RhbmNlIDogaXNLZXkgPyB0eXBlT3JJbnN0YW5jZSA6IHR5cGVPcktleTtcblx0XHRjb25zdCByZWdpc3RyYXRpb24gPSBuZXcgU2VydmljZVJlZ2lzdHJhdGlvbihrZXksIHR5cGUsIHNjb3BlLCBpc0luc3RhbmNlKTtcblx0XHRyZXR1cm4gcmVnaXN0cmF0aW9uO1xuXHR9XG5cblx0cHJpdmF0ZSBnZXRSZWdpc3RyYXRpb25zKGtleTogUmVnaXN0cmF0aW9uS2V5KSB7XG5cdFx0Y29uc3QgdmFsdWUgPSBrZXkudmFsdWU7XG5cdFx0cmV0dXJuIHRoaXMucmVnaXN0cmF0aW9ucy5nZXQodmFsdWUpO1xuXHR9XG5cblx0cHJpdmF0ZSBzZXRSZWdpc3RyYXRpb24oa2V5OiBSZWdpc3RyYXRpb25LZXksIHJlZ2lzdHJhdGlvbnM6IFNlcnZpY2VSZWdpc3RyYXRpb25bXSkge1xuXHRcdHRoaXMucmVnaXN0cmF0aW9ucy5zZXQoa2V5LnZhbHVlLCByZWdpc3RyYXRpb25zKTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIlNlcnZpY2VSZWdpc3RyeSIsInJlZ2lzdHJhdGlvbnMiLCJwYXJlbnQiLCJNYXAiLCJyZWdpc3RlclR5cGUiLCJzY29wZSIsIm9wdGlvbnMiLCJyZWdpc3RyYXRpb24iLCJjcmVhdGVSZWdpc3RyYXRpb25Gcm9tIiwiZXhpc3RpbmdSZWdpc3RyYXRpb24iLCJnZXRSZWdpc3RyYXRpb25zIiwia2V5IiwiZmlsdGVyIiwicmVnIiwiaXNFcXVhbCIsInNldFJlZ2lzdHJhdGlvbiIsImdldFJlZ2lzdHJhdGlvbiIsImtleVZhbCIsIlJlZ2lzdHJhdGlvbktleSIsInZhbHVlIiwiZ2V0IiwidHlwZU9yS2V5IiwidHlwZU9ySW5zdGFuY2UiLCJpc0tleSIsImlzSW5zdGFuY2UiLCJuYW1lIiwidHlwZSIsIlNlcnZpY2VSZWdpc3RyYXRpb24iLCJzZXQiXSwibWFwcGluZ3MiOiI7Ozs7K0JBVWFBOzs7ZUFBQUE7OztzQ0FUbUI7MENBQ0k7QUFRN0IsTUFBTUE7SUFDS0MsY0FBa0Q7SUFDbkUsWUFBbUJDLE1BQXdCLENBQUU7UUFDNUMsSUFBSSxDQUFDRCxhQUFhLEdBQUcsSUFBSUUsSUFBSUQsUUFBUUQ7SUFDdEM7SUFFT0csYUFBYUMsS0FBWSxFQUFFQyxPQUE0QixFQUFFO1FBQy9ELE1BQU1DLGVBQWUsSUFBSSxDQUFDQyxzQkFBc0IsQ0FBQ0gsT0FBT0M7UUFDeEQsTUFBTUcsdUJBQ0wsSUFBSSxDQUFDQyxnQkFBZ0IsQ0FBQ0gsYUFBYUksR0FBRyxHQUFHQyxPQUFPLENBQUNDLE1BQVEsQ0FBQ0EsSUFBSUMsT0FBTyxDQUFDUCxrQkFDdEUsRUFBRTtRQUVILElBQUksQ0FBQ1EsZUFBZSxDQUFDUixhQUFhSSxHQUFHLEVBQUU7WUFBQ0o7ZUFBaUJFO1NBQXFCO1FBQzlFLE9BQU9GO0lBQ1I7SUFFT1MsZ0JBQWdCTCxHQUFvQyxFQUF5QjtRQUNuRixNQUFNTSxTQUFTLElBQUlDLHFDQUFlLENBQUNQLEtBQUtRLEtBQUs7UUFDN0MsTUFBTVosZUFBZSxJQUFJLENBQUNOLGFBQWEsQ0FBQ21CLEdBQUcsQ0FBQ0g7UUFDNUMsT0FBT1Y7SUFDUjtJQUVRQyx1QkFBdUJILEtBQVksRUFBRUMsT0FBNEIsRUFBRTtRQUMxRSxNQUFNLEVBQUVlLFNBQVMsRUFBRUMsY0FBYyxFQUFFLEdBQUdoQjtRQUN0QyxNQUFNaUIsUUFBUSxPQUFPRixjQUFjLFlBQVksT0FBT0EsY0FBYztRQUNwRSxNQUFNRyxhQUFhLE9BQU9GLG1CQUFtQjtRQUM3QyxNQUFNWCxNQUFNLElBQUlPLHFDQUFlLENBQUMsQ0FBQ0ssUUFBUUYsVUFBVUksSUFBSSxHQUFHSjtRQUMxRCxNQUFNSyxPQUFPRixhQUFhRixpQkFBaUJDLFFBQVFELGlCQUFpQkQ7UUFDcEUsTUFBTWQsZUFBZSxJQUFJb0IsNkNBQW1CLENBQUNoQixLQUFLZSxNQUFNckIsT0FBT21CO1FBQy9ELE9BQU9qQjtJQUNSO0lBRVFHLGlCQUFpQkMsR0FBb0IsRUFBRTtRQUM5QyxNQUFNUSxRQUFRUixJQUFJUSxLQUFLO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDbEIsYUFBYSxDQUFDbUIsR0FBRyxDQUFDRDtJQUMvQjtJQUVRSixnQkFBZ0JKLEdBQW9CLEVBQUVWLGFBQW9DLEVBQUU7UUFDbkYsSUFBSSxDQUFDQSxhQUFhLENBQUMyQixHQUFHLENBQUNqQixJQUFJUSxLQUFLLEVBQUVsQjtJQUNuQztBQUNEIn0=
@@ -25,5 +25,3 @@ class DuplicateScopeError extends Error {
25
25
  }
26
26
  class RegistrationError extends Error {
27
27
  }
28
-
29
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy90eXBlcy9lcnJvcnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNsYXNzIFJlc29sdmVFcnJvciBleHRlbmRzIEVycm9yIHt9XG5leHBvcnQgY2xhc3MgRHVwbGljYXRlU2NvcGVFcnJvciBleHRlbmRzIEVycm9yIHt9XG5leHBvcnQgY2xhc3MgUmVnaXN0cmF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuIl0sIm5hbWVzIjpbIkR1cGxpY2F0ZVNjb3BlRXJyb3IiLCJSZWdpc3RyYXRpb25FcnJvciIsIlJlc29sdmVFcnJvciIsIkVycm9yIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztRQUNhQTtlQUFBQTs7UUFDQUM7ZUFBQUE7O1FBRkFDO2VBQUFBOzs7QUFBTixNQUFNQSxxQkFBcUJDO0FBQU87QUFDbEMsTUFBTUgsNEJBQTRCRztBQUFPO0FBQ3pDLE1BQU1GLDBCQUEwQkU7QUFBTyJ9
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
+ _export_star(require("./errors.js"), exports);
5
6
  _export_star(require("./types.js"), exports);
6
7
  function _export_star(from, to) {
7
8
  Object.keys(from).forEach(function(k) {
@@ -16,5 +17,3 @@ function _export_star(from, to) {
16
17
  });
17
18
  return from;
18
19
  }
19
-
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy90eXBlcy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi90eXBlcy5qc1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7cUJBQWMifQ==
@@ -2,5 +2,3 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
-
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
package/es6/src/const.js CHANGED
@@ -1,12 +1,10 @@
1
- const Crucible = "Crucible";
1
+ const Container = "Container";
2
2
  export const LifetimeScopeToken = Symbol("LifetimeScope");
3
- export const CrucibleMeta = {
4
- injecttoken: `${Crucible}:injecttoken`
3
+ export const ContainerMeta = {
4
+ injecttoken: `${Container}:injecttoken`
5
5
  };
6
6
  export const Scopes = {
7
7
  request: "request",
8
8
  singleton: "single-instance",
9
9
  transient: "transient"
10
10
  };
11
-
12
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9jb25zdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNjb3BlIH0gZnJvbSBcIi4vdHlwZXMvdHlwZXMuanNcIjtcblxuY29uc3QgQ3J1Y2libGUgPSBcIkNydWNpYmxlXCI7XG50eXBlIENydWNpYmxlTWV0YSA9IFwiaW5qZWN0dG9rZW5cIjtcblxuZXhwb3J0IGNvbnN0IExpZmV0aW1lU2NvcGVUb2tlbiA9IFN5bWJvbChcIkxpZmV0aW1lU2NvcGVcIik7XG5cbmV4cG9ydCBjb25zdCBDcnVjaWJsZU1ldGEgPSB7XG5cdGluamVjdHRva2VuOiBgJHtDcnVjaWJsZX06aW5qZWN0dG9rZW5gLFxufSBzYXRpc2ZpZXMgUmVjb3JkPENydWNpYmxlTWV0YSwgc3RyaW5nPjtcblxuZXhwb3J0IGNvbnN0IFNjb3BlcyA9IHtcblx0cmVxdWVzdDogXCJyZXF1ZXN0XCIsXG5cdHNpbmdsZXRvbjogXCJzaW5nbGUtaW5zdGFuY2VcIixcblx0dHJhbnNpZW50OiBcInRyYW5zaWVudFwiLFxufSBzYXRpc2ZpZXMgUmVjb3JkPHN0cmluZywgU2NvcGU+O1xuIl0sIm5hbWVzIjpbIkNydWNpYmxlIiwiTGlmZXRpbWVTY29wZVRva2VuIiwiU3ltYm9sIiwiQ3J1Y2libGVNZXRhIiwiaW5qZWN0dG9rZW4iLCJTY29wZXMiLCJyZXF1ZXN0Iiwic2luZ2xldG9uIiwidHJhbnNpZW50Il0sIm1hcHBpbmdzIjoiQUFFQSxNQUFNQSxXQUFXO0FBR2pCLE9BQU8sTUFBTUMscUJBQXFCQyxPQUFPLGlCQUFpQjtBQUUxRCxPQUFPLE1BQU1DLGVBQWU7SUFDM0JDLGFBQWEsR0FBR0osU0FBUyxZQUFZLENBQUM7QUFDdkMsRUFBeUM7QUFFekMsT0FBTyxNQUFNSyxTQUFTO0lBQ3JCQyxTQUFTO0lBQ1RDLFdBQVc7SUFDWEMsV0FBVztBQUNaLEVBQWtDIn0=
@@ -1,4 +1,2 @@
1
1
  export * from "./inject.decorator.js";
2
2
  export * from "./injectable.dectorator.js";
3
-
4
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9kZWNvcmF0b3JzL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gXCIuL2luamVjdC5kZWNvcmF0b3IuanNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2luamVjdGFibGUuZGVjdG9yYXRvci5qc1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsd0JBQXdCO0FBQ3RDLGNBQWMsNkJBQTZCIn0=
@@ -1,17 +1,30 @@
1
- import { defineMeta, getMeta } from "@decohere/nexus/reflection";
2
- import { CrucibleMeta } from "../const.js";
3
- export function inject(key) {
4
- return (target, _propertyKey, idx)=>{
5
- const metadata = getExistingMeta(target);
6
- metadata.set(idx, {
1
+ import { defineMeta, getMeta } from "@decohere/core/reflection";
2
+ import { ContainerMeta } from "../const.js";
3
+ /**
4
+ * Bind a constructor parameter to a registration key. Keys match by identity: a class matches only
5
+ * itself (not a string of its name), and a symbol only itself. Prefer the class; use a symbol for an
6
+ * interface or several implementations. `@inject(SomeClass)` also keeps SomeClass's import, which
7
+ * a parameter used only as a type can lose (its run-time type then collapses to `Object`).
8
+ */ export function inject(key) {
9
+ return updateToken((token)=>({
10
+ ...token,
7
11
  key
8
- });
9
- defineMeta(CrucibleMeta.injecttoken, metadata, target);
10
- };
12
+ }));
13
+ }
14
+ /**
15
+ * Mark a constructor parameter as optional: when nothing is registered for it, the container
16
+ * passes `undefined` (so a default value applies) instead of throwing.
17
+ */ export function optional() {
18
+ return updateToken((token)=>({
19
+ ...token,
20
+ optional: true
21
+ }));
11
22
  }
12
- function getExistingMeta(target) {
13
- const meta = getMeta(CrucibleMeta.injecttoken, target) ?? new Map();
14
- return meta;
23
+ function updateToken(update) {
24
+ return (target, _propertyKey, idx)=>{
25
+ // Copy: the metadata can be inherited from a base class, which must not change.
26
+ const metadata = new Map(getMeta(ContainerMeta.injecttoken, target));
27
+ metadata.set(idx, update(metadata.get(idx)));
28
+ defineMeta(ContainerMeta.injecttoken, metadata, target);
29
+ };
15
30
  }
16
-
17
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9kZWNvcmF0b3JzL2luamVjdC5kZWNvcmF0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZGVmaW5lTWV0YSwgZ2V0TWV0YSB9IGZyb20gXCJAZGVjb2hlcmUvbmV4dXMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgQ3J1Y2libGVNZXRhIH0gZnJvbSBcIi4uL2NvbnN0LmpzXCI7XG5cbmV4cG9ydCB0eXBlIEluamVjdGlvbk1ldGFkYXRhID0gTWFwPG51bWJlciwgSW5qZWN0aW9uVG9rZW4+O1xuXG5leHBvcnQgdHlwZSBJbmplY3Rpb25Ub2tlbiA9IHtcblx0a2V5OiBzdHJpbmcgfCBzeW1ib2w7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gaW5qZWN0KGtleTogc3RyaW5nIHwgc3ltYm9sKSB7XG5cdHJldHVybiAodGFyZ2V0OiBvYmplY3QsIF9wcm9wZXJ0eUtleTogc3RyaW5nIHwgc3ltYm9sIHwgdW5kZWZpbmVkLCBpZHg6IG51bWJlcikgPT4ge1xuXHRcdGNvbnN0IG1ldGFkYXRhID0gZ2V0RXhpc3RpbmdNZXRhKHRhcmdldCk7XG5cdFx0bWV0YWRhdGEuc2V0KGlkeCwgeyBrZXkgfSk7XG5cdFx0ZGVmaW5lTWV0YShDcnVjaWJsZU1ldGEuaW5qZWN0dG9rZW4sIG1ldGFkYXRhLCB0YXJnZXQpO1xuXHR9O1xufVxuXG5mdW5jdGlvbiBnZXRFeGlzdGluZ01ldGEodGFyZ2V0OiBvYmplY3QpIHtcblx0Y29uc3QgbWV0YSA9XG5cdFx0Z2V0TWV0YTxNYXA8bnVtYmVyLCBJbmplY3Rpb25Ub2tlbj4+KENydWNpYmxlTWV0YS5pbmplY3R0b2tlbiwgdGFyZ2V0KSA/P1xuXHRcdG5ldyBNYXA8bnVtYmVyLCBJbmplY3Rpb25Ub2tlbj4oKTtcblx0cmV0dXJuIG1ldGE7XG59XG4iXSwibmFtZXMiOlsiZGVmaW5lTWV0YSIsImdldE1ldGEiLCJDcnVjaWJsZU1ldGEiLCJpbmplY3QiLCJrZXkiLCJ0YXJnZXQiLCJfcHJvcGVydHlLZXkiLCJpZHgiLCJtZXRhZGF0YSIsImdldEV4aXN0aW5nTWV0YSIsInNldCIsImluamVjdHRva2VuIiwibWV0YSIsIk1hcCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsVUFBVSxFQUFFQyxPQUFPLFFBQVEsNkJBQTZCO0FBQ2pFLFNBQVNDLFlBQVksUUFBUSxjQUFjO0FBUTNDLE9BQU8sU0FBU0MsT0FBT0MsR0FBb0I7SUFDMUMsT0FBTyxDQUFDQyxRQUFnQkMsY0FBMkNDO1FBQ2xFLE1BQU1DLFdBQVdDLGdCQUFnQko7UUFDakNHLFNBQVNFLEdBQUcsQ0FBQ0gsS0FBSztZQUFFSDtRQUFJO1FBQ3hCSixXQUFXRSxhQUFhUyxXQUFXLEVBQUVILFVBQVVIO0lBQ2hEO0FBQ0Q7QUFFQSxTQUFTSSxnQkFBZ0JKLE1BQWM7SUFDdEMsTUFBTU8sT0FDTFgsUUFBcUNDLGFBQWFTLFdBQVcsRUFBRU4sV0FDL0QsSUFBSVE7SUFDTCxPQUFPRDtBQUNSIn0=
@@ -2,5 +2,3 @@ export function injectable() {
2
2
  // no implementation for now. Just used to ensure reflect metadata is generated
3
3
  return ()=>{};
4
4
  }
5
-
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9kZWNvcmF0b3JzL2luamVjdGFibGUuZGVjdG9yYXRvci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gaW5qZWN0YWJsZSgpOiBDbGFzc0RlY29yYXRvciB7XG5cdC8vIG5vIGltcGxlbWVudGF0aW9uIGZvciBub3cuIEp1c3QgdXNlZCB0byBlbnN1cmUgcmVmbGVjdCBtZXRhZGF0YSBpcyBnZW5lcmF0ZWRcblx0cmV0dXJuICgpID0+IHt9O1xufVxuIl0sIm5hbWVzIjpbImluamVjdGFibGUiXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sU0FBU0E7SUFDZiwrRUFBK0U7SUFDL0UsT0FBTyxLQUFPO0FBQ2YifQ==
package/es6/src/index.js CHANGED
@@ -1,5 +1,3 @@
1
1
  export * from "./const.js";
2
2
  export * from "./services/index.js";
3
3
  export * from "./types/index.js";
4
-
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9jb25zdC5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vc2VydmljZXMvaW5kZXguanNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3R5cGVzL2luZGV4LmpzXCI7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxhQUFhO0FBQzNCLGNBQWMsc0JBQXNCO0FBQ3BDLGNBQWMsbUJBQW1CIn0=
@@ -0,0 +1,10 @@
1
+ /** A readable name for a key, for error messages. */ export function describeKey(key) {
2
+ switch(typeof key){
3
+ case "string":
4
+ return `"${key}"`;
5
+ case "symbol":
6
+ return key.toString();
7
+ default:
8
+ return key.name || "(anonymous factory)";
9
+ }
10
+ }
@@ -9,12 +9,7 @@ export class ServiceRegistration {
9
9
  this.scope = scope;
10
10
  this.isInstance = isInstance;
11
11
  }
12
- isEqual(other) {
13
- if (other.isInstance) {
14
- return false;
15
- }
12
+ /** Same class, or the same instance object. */ isEqual(other) {
16
13
  return this.type === other.type;
17
14
  }
18
15
  }
19
-
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9tb2RlbHMvc2VydmljZS1yZWdpc3RyYXRpb24ubW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBDb25zdHJ1Y3RhYmxlLCBGdW5jdGlvblR5cGUgfSBmcm9tIFwiQGRlY29oZXJlL25leHVzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgU2NvcGUgfSBmcm9tIFwiLi4vdHlwZXMvdHlwZXMuanNcIjtcbmltcG9ydCB0eXBlIHsgUmVnaXN0cmF0aW9uS2V5IH0gZnJvbSBcIi4vcmVnaXN0cmF0aW9uLWtleS5tb2RlbC5qc1wiO1xuXG5leHBvcnQgY2xhc3MgU2VydmljZVJlZ2lzdHJhdGlvbiB7XG5cdHB1YmxpYyBrZXk6IFJlZ2lzdHJhdGlvbktleTtcblx0cHVibGljIHNjb3BlOiBTY29wZTtcblx0cHVibGljIHR5cGU6IENvbnN0cnVjdGFibGUgfCBGdW5jdGlvblR5cGUgfCBvYmplY3Q7XG5cdHB1YmxpYyBpc0luc3RhbmNlOiBib29sZWFuO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRrZXk6IFJlZ2lzdHJhdGlvbktleSxcblx0XHR0eXBlOiBDb25zdHJ1Y3RhYmxlIHwgRnVuY3Rpb25UeXBlIHwgb2JqZWN0LFxuXHRcdHNjb3BlOiBTY29wZSxcblx0XHRpc0luc3RhbmNlOiBib29sZWFuLFxuXHQpIHtcblx0XHR0aGlzLmtleSA9IGtleTtcblx0XHR0aGlzLnR5cGUgPSB0eXBlO1xuXHRcdHRoaXMuc2NvcGUgPSBzY29wZTtcblx0XHR0aGlzLmlzSW5zdGFuY2UgPSBpc0luc3RhbmNlO1xuXHR9XG5cblx0cHVibGljIGlzRXF1YWwob3RoZXI6IFNlcnZpY2VSZWdpc3RyYXRpb24pIHtcblx0XHRpZiAob3RoZXIuaXNJbnN0YW5jZSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLnR5cGUgPT09IG90aGVyLnR5cGU7XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJTZXJ2aWNlUmVnaXN0cmF0aW9uIiwia2V5Iiwic2NvcGUiLCJ0eXBlIiwiaXNJbnN0YW5jZSIsImlzRXF1YWwiLCJvdGhlciJdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxNQUFNQTtJQUNMQyxJQUFxQjtJQUNyQkMsTUFBYTtJQUNiQyxLQUE0QztJQUM1Q0MsV0FBb0I7SUFFM0IsWUFDQ0gsR0FBb0IsRUFDcEJFLElBQTJDLEVBQzNDRCxLQUFZLEVBQ1pFLFVBQW1CLENBQ2xCO1FBQ0QsSUFBSSxDQUFDSCxHQUFHLEdBQUdBO1FBQ1gsSUFBSSxDQUFDRSxJQUFJLEdBQUdBO1FBQ1osSUFBSSxDQUFDRCxLQUFLLEdBQUdBO1FBQ2IsSUFBSSxDQUFDRSxVQUFVLEdBQUdBO0lBQ25CO0lBRU9DLFFBQVFDLEtBQTBCLEVBQUU7UUFDMUMsSUFBSUEsTUFBTUYsVUFBVSxFQUFFO1lBQ3JCLE9BQU87UUFDUjtRQUVBLE9BQU8sSUFBSSxDQUFDRCxJQUFJLEtBQUtHLE1BQU1ILElBQUk7SUFDaEM7QUFDRCJ9