atomic-di 0.9.1-beta.3 → 0.9.1-beta.4

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.d.mts CHANGED
@@ -85,8 +85,11 @@ declare const createScope: () => Scope;
85
85
  * A wrapper around the resolver(factory) for contextual dependency resolution.
86
86
  *
87
87
  * Resolves an instance by calling a resolver
88
- * with a resolution context that will be propagated
88
+ * with an **optional** resolution context that will be propagated
89
89
  * throughout a dependency tree.
90
+ * ```ts
91
+ * provider({ scope, mocks })
92
+ * ```
90
93
  *
91
94
  * When passing a scope it will try to get an instance from it
92
95
  * or create a new one and put it there.
@@ -127,6 +130,13 @@ type ResolutionContext = {
127
130
  /**
128
131
  * Creates a provider instance,
129
132
  * a wrapper around a resolver(factory) for contextual dependency resolution.
133
+ * ```ts
134
+ * const getInstance = provide("transient", () =>
135
+ * createInstance(
136
+ * getOtherInstance(context)
137
+ * )
138
+ * )
139
+ * ```
130
140
  *
131
141
  * @param lifetime
132
142
  * A resolution lifetime.
@@ -143,14 +153,24 @@ type ResolutionContext = {
143
153
  *
144
154
  * @param resolver
145
155
  * The function that creates an instance using a resolution context.
156
+ * If the function calls other providers,
157
+ * the context **must** be passed to their calls.
146
158
  *
147
159
  * @returns The provider instance.
148
160
  */
149
161
  declare const provide: <T>(lifetime: Lifetime, resolver: Resolver<T>) => Provider<T>;
150
162
  /**
163
+ * An alias for `provide("transient", ...)`.
151
164
  * Creates a transient provider instance,
152
165
  * a wrapper around a resolver(factory) for contextual dependency resolution
153
166
  * that will create a new instance on each request.
167
+ * ```ts
168
+ * const getInstance = transient((context) =>
169
+ * createInstance(...)
170
+ * )
171
+ *
172
+ * getInstance() !== getInstance()
173
+ * ```
154
174
  *
155
175
  * @param resolver
156
176
  * The function that creates an instance using a resolution context.
@@ -159,9 +179,17 @@ declare const provide: <T>(lifetime: Lifetime, resolver: Resolver<T>) => Provide
159
179
  */
160
180
  declare const transient: <T>(resolver: Resolver<T>) => Provider<T>;
161
181
  /**
182
+ * An alias for `provide("singleton", ...)`.
162
183
  * Creates a transient provider instance,
163
184
  * a wrapper around a resolver(factory) for contextual dependency resolution
164
185
  * that will create an instance once and return it in subsequent requests.
186
+ * ```ts
187
+ * const getInstance = singleton((context) =>
188
+ * createInstance(...)
189
+ * )
190
+ *
191
+ * getInstance() === getInstance()
192
+ * ```
165
193
  *
166
194
  * @param resolver
167
195
  * The function that creates an instance using a resolution context.
@@ -170,11 +198,20 @@ declare const transient: <T>(resolver: Resolver<T>) => Provider<T>;
170
198
  */
171
199
  declare const singleton: <T>(resolver: Resolver<T>) => Provider<T>;
172
200
  /**
201
+ * An alias for `provide("scoped", ...)`.
173
202
  * Creates a transient provider instance,
174
203
  * a wrapper around a resolver(factory) for contextual dependency resolution
175
204
  * that will take its resolution from a provided scope
176
205
  * or create a new one and save it if there is none.
177
206
  * If no scope is passed, it will create a new instance on each request.
207
+ * ```ts
208
+ * const getInstance = scoped((context) =>
209
+ * createInstance(...)
210
+ * )
211
+ *
212
+ * getInstance() !== getInstance()
213
+ * getInstance({ scope }) === getInstance({ scope })
214
+ * ```
178
215
  *
179
216
  * @param resolver
180
217
  * The function that creates an instance using a resolution context.
@@ -200,6 +237,12 @@ type AwaitAllValuesInCollection<T extends any[] | Record<any, any>> = Promise<an
200
237
  * Calls every provider in a list with a provided resolution context
201
238
  * and returns a list of resolutions. Returns a promise of a list
202
239
  * of awaited resolutions if there's at least one promise in the resolutions.
240
+ * ```ts
241
+ * const resolutions = resolveList(
242
+ * [getA, getB, getC],
243
+ * { scope, mocks }
244
+ * )
245
+ * ```
203
246
  *
204
247
  * @param providers - The list of providers.
205
248
  * @param context - The resolution context.
@@ -212,6 +255,12 @@ declare const resolveList: <const Providers extends ProviderList>(providers: Pro
212
255
  * and returns a map with identical keys but with resolutions in values instead.
213
256
  * Returns a promise of a map of awaited resolutions if there's at least one
214
257
  * promise in the resolutions.
258
+ * ```ts
259
+ * const resolutionMap = resolveMap(
260
+ * { a: getA, b: getB, c: getC },
261
+ * { scope, mocks }
262
+ * )
263
+ * ```
215
264
  *
216
265
  * @param providers - The map of providers.
217
266
  * @param context - The resolution context.
package/dist/index.d.ts CHANGED
@@ -85,8 +85,11 @@ declare const createScope: () => Scope;
85
85
  * A wrapper around the resolver(factory) for contextual dependency resolution.
86
86
  *
87
87
  * Resolves an instance by calling a resolver
88
- * with a resolution context that will be propagated
88
+ * with an **optional** resolution context that will be propagated
89
89
  * throughout a dependency tree.
90
+ * ```ts
91
+ * provider({ scope, mocks })
92
+ * ```
90
93
  *
91
94
  * When passing a scope it will try to get an instance from it
92
95
  * or create a new one and put it there.
@@ -127,6 +130,13 @@ type ResolutionContext = {
127
130
  /**
128
131
  * Creates a provider instance,
129
132
  * a wrapper around a resolver(factory) for contextual dependency resolution.
133
+ * ```ts
134
+ * const getInstance = provide("transient", () =>
135
+ * createInstance(
136
+ * getOtherInstance(context)
137
+ * )
138
+ * )
139
+ * ```
130
140
  *
131
141
  * @param lifetime
132
142
  * A resolution lifetime.
@@ -143,14 +153,24 @@ type ResolutionContext = {
143
153
  *
144
154
  * @param resolver
145
155
  * The function that creates an instance using a resolution context.
156
+ * If the function calls other providers,
157
+ * the context **must** be passed to their calls.
146
158
  *
147
159
  * @returns The provider instance.
148
160
  */
149
161
  declare const provide: <T>(lifetime: Lifetime, resolver: Resolver<T>) => Provider<T>;
150
162
  /**
163
+ * An alias for `provide("transient", ...)`.
151
164
  * Creates a transient provider instance,
152
165
  * a wrapper around a resolver(factory) for contextual dependency resolution
153
166
  * that will create a new instance on each request.
167
+ * ```ts
168
+ * const getInstance = transient((context) =>
169
+ * createInstance(...)
170
+ * )
171
+ *
172
+ * getInstance() !== getInstance()
173
+ * ```
154
174
  *
155
175
  * @param resolver
156
176
  * The function that creates an instance using a resolution context.
@@ -159,9 +179,17 @@ declare const provide: <T>(lifetime: Lifetime, resolver: Resolver<T>) => Provide
159
179
  */
160
180
  declare const transient: <T>(resolver: Resolver<T>) => Provider<T>;
161
181
  /**
182
+ * An alias for `provide("singleton", ...)`.
162
183
  * Creates a transient provider instance,
163
184
  * a wrapper around a resolver(factory) for contextual dependency resolution
164
185
  * that will create an instance once and return it in subsequent requests.
186
+ * ```ts
187
+ * const getInstance = singleton((context) =>
188
+ * createInstance(...)
189
+ * )
190
+ *
191
+ * getInstance() === getInstance()
192
+ * ```
165
193
  *
166
194
  * @param resolver
167
195
  * The function that creates an instance using a resolution context.
@@ -170,11 +198,20 @@ declare const transient: <T>(resolver: Resolver<T>) => Provider<T>;
170
198
  */
171
199
  declare const singleton: <T>(resolver: Resolver<T>) => Provider<T>;
172
200
  /**
201
+ * An alias for `provide("scoped", ...)`.
173
202
  * Creates a transient provider instance,
174
203
  * a wrapper around a resolver(factory) for contextual dependency resolution
175
204
  * that will take its resolution from a provided scope
176
205
  * or create a new one and save it if there is none.
177
206
  * If no scope is passed, it will create a new instance on each request.
207
+ * ```ts
208
+ * const getInstance = scoped((context) =>
209
+ * createInstance(...)
210
+ * )
211
+ *
212
+ * getInstance() !== getInstance()
213
+ * getInstance({ scope }) === getInstance({ scope })
214
+ * ```
178
215
  *
179
216
  * @param resolver
180
217
  * The function that creates an instance using a resolution context.
@@ -200,6 +237,12 @@ type AwaitAllValuesInCollection<T extends any[] | Record<any, any>> = Promise<an
200
237
  * Calls every provider in a list with a provided resolution context
201
238
  * and returns a list of resolutions. Returns a promise of a list
202
239
  * of awaited resolutions if there's at least one promise in the resolutions.
240
+ * ```ts
241
+ * const resolutions = resolveList(
242
+ * [getA, getB, getC],
243
+ * { scope, mocks }
244
+ * )
245
+ * ```
203
246
  *
204
247
  * @param providers - The list of providers.
205
248
  * @param context - The resolution context.
@@ -212,6 +255,12 @@ declare const resolveList: <const Providers extends ProviderList>(providers: Pro
212
255
  * and returns a map with identical keys but with resolutions in values instead.
213
256
  * Returns a promise of a map of awaited resolutions if there's at least one
214
257
  * promise in the resolutions.
258
+ * ```ts
259
+ * const resolutionMap = resolveMap(
260
+ * { a: getA, b: getB, c: getC },
261
+ * { scope, mocks }
262
+ * )
263
+ * ```
215
264
  *
216
265
  * @param providers - The map of providers.
217
266
  * @param context - The resolution context.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/helpers.ts","../src/provider.ts","../src/scope.ts","../src/mock-map.ts","../src/collection-resolution.ts"],"sourcesContent":["export * from \"./provider\";\nexport * from \"./scope\";\nexport * from \"./mock-map\";\nexport * from \"./collection-resolution\";\n","/**\n * Creates a function that will invoke the provided function `fn` only once,\n * caching the result for subsequent calls with the same arguments.\n *\n * @returns A new function that returns the cached result after the first call.\n */\nexport const once = <A extends any[], R>(\n /**\n * The function to invoke once and cache the result.\n */\n fn: (...args: A) => R,\n) => {\n let returned = false;\n let result: R | undefined;\n\n return Object.assign((...args: A): R => {\n if (returned) return result!;\n\n result = fn(...args);\n returned = true;\n\n return result;\n }, fn);\n};\n","import { once } from \"./helpers\";\nimport { MockMap } from \"./mock-map\";\nimport { Scope } from \"./scope\";\n\n/**\n * A wrapper around the resolver(factory) for contextual dependency resolution.\n *\n * Resolves an instance by calling a resolver\n * with a resolution context that will be propagated\n * throughout a dependency tree.\n *\n * When passing a scope it will try to get an instance from it\n * or create a new one and put it there.\n *\n * When passing mocks, it will try to get its own mock version,\n * and if there is one, it will use it instead of itself.\n */\nexport type Provider<T> = (context?: ResolutionContext) => T;\n\n/**\n * A resolution lifetime.\n *\n * Passed when creating a provider to determine its behavior.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its instance from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n */\nexport type Lifetime = \"transient\" | \"singleton\" | \"scoped\";\n\n/**\n * A function that creates an instance using a resolution context.\n */\nexport type Resolver<T> = (context?: ResolutionContext) => T;\n\n/**\n * An object that holds information about a scope and provider mocks.\n *\n * Passed to the provider call to resolve scope instances and mock providers.\n */\nexport type ResolutionContext = {\n scope?: Scope;\n mocks?: MockMap;\n};\n\n/**\n * Creates a provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution.\n *\n * @param lifetime\n * A resolution lifetime.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The provider instance.\n */\nexport const provide = <T>(\n lifetime: Lifetime,\n resolver: Resolver<T>,\n): Provider<T> => {\n resolver = lifetime === \"singleton\" ? once(resolver) : resolver;\n\n const resolve: Provider<T> = (context) => {\n const maybeOwnMock = context?.mocks?.get(resolve);\n if (maybeOwnMock) return maybeOwnMock(context);\n\n if (lifetime !== \"scoped\" || !context?.scope) return resolver(context);\n\n const resolution = context.scope.has(resolve)\n ? context.scope.get(resolve)\n : resolver(context);\n context.scope.set(resolve, resolution);\n\n return resolution;\n };\n\n return resolve;\n};\n\n/**\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The transient provider instance.\n */\nexport const transient = <T>(resolver: Resolver<T>) =>\n provide(\"transient\", resolver);\n\n/**\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create an instance once and return it in subsequent requests.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The singleton provider instance.\n */\nexport const singleton = <T>(resolver: Resolver<T>) =>\n provide(\"singleton\", resolver);\n\n/**\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The scoped provider instance.\n */\nexport const scoped = <T>(resolver: Resolver<T>) => provide(\"scoped\", resolver);\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to their instances.\n *\n * Passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n */\nexport type Scope = Map<Provider<any>, any>;\n\n/**\n * Creates a scope instance.\n *\n * Scope is passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n *\n * @returns The scope instance.\n */\nexport const createScope = (): Scope => new Map();\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n */\nexport type MockMap = Omit<Map<Provider<any>, Provider<any>>, \"set\" | \"get\"> & {\n /**\n * Sets a mock for a provider.\n *\n * @param provider - The original provider.\n * @param mock - The mock provider.\n */\n set<T>(provider: Provider<T>, mock: Provider<T>): MockMap;\n /**\n * Retrieves a mock of a provider. Returns undefined if there's none.\n *\n * @param provider - The provider.\n */\n get<T>(provider: Provider<T>): Provider<T> | undefined;\n};\n\n/**\n * Creates a mock map instance,\n * a map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n *\n * @returns The mock map instance.\n */\nexport const createMockMap = (): MockMap => new Map();\n","import { Provider, ResolutionContext } from \"./provider\";\n\ntype ProviderList = Provider<any>[];\ntype ProviderRecord = Record<string, Provider<any>>;\n\ntype InferProviderCollectionResolutions<\n Providers extends ProviderList | ProviderRecord,\n> = {\n [K in keyof Providers]: Providers[K] extends Provider<infer T> ? T : never;\n};\n\n/**\n * Awaits all promises and wraps the collection in a promise\n * if there'ss at least one `Promise` in the collection,\n * otherwise returns an untouched type.\n */\ntype AwaitAllValuesInCollection<T extends any[] | Record<any, any>> =\n Promise<any> extends T[keyof T]\n ? Promise<{\n [I in keyof T]: T[I] extends Promise<infer T> ? T : T[I];\n }>\n : T;\n\n/**\n * Calls every provider in a list with a provided resolution context\n * and returns a list of resolutions. Returns a promise of a list\n * of awaited resolutions if there's at least one promise in the resolutions.\n *\n * @param providers - The list of providers.\n * @param context - The resolution context.\n *\n * @returns The list of resolutions.\n */\nexport const resolveList = <const Providers extends ProviderList>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n const resolutions = providers.map((provider) => provider(context));\n\n return (\n resolutions.some((resolution) => resolution instanceof Promise)\n ? Promise.all(resolutions)\n : resolutions\n ) as any;\n};\n\n/**\n * Calls every provider in a map with a provided resolution context\n * and returns a map with identical keys but with resolutions in values instead.\n * Returns a promise of a map of awaited resolutions if there's at least one\n * promise in the resolutions.\n *\n * @param providers - The map of providers.\n * @param context - The resolution context.\n *\n * @returns The map of resolutions.\n */\nexport const resolveMap = <const Providers extends ProviderRecord>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n let resolutionMapEntries = Object.entries(providers).map(\n ([key, provider]) => [key, provider(context)],\n );\n\n if (\n resolutionMapEntries.some(\n ([, resolution]) => resolution instanceof Promise,\n )\n ) {\n return (async () => {\n resolutionMapEntries = await Promise.all(\n resolutionMapEntries.map(async ([key, resolution]) => [\n key,\n await resolution,\n ]),\n );\n\n return Object.fromEntries(resolutionMapEntries);\n })() as any;\n }\n\n return Object.fromEntries(resolutionMapEntries);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMO,IAAM,OAAO,CAIhB,OACC;AACD,MAAI,WAAW;AACf,MAAI;AAEJ,SAAO,OAAO,OAAO,IAAI,SAAe;AACpC,QAAI,SAAU,QAAO;AAErB,aAAS,GAAG,GAAG,IAAI;AACnB,eAAW;AAEX,WAAO;AAAA,EACX,GAAG,EAAE;AACT;;;ACkDO,IAAM,UAAU,CACnB,UACA,aACc;AACd,aAAW,aAAa,cAAc,KAAK,QAAQ,IAAI;AAEvD,QAAM,UAAuB,CAAC,YAAY;AA/E9C;AAgFQ,UAAM,gBAAe,wCAAS,UAAT,mBAAgB,IAAI;AACzC,QAAI,aAAc,QAAO,aAAa,OAAO;AAE7C,QAAI,aAAa,YAAY,EAAC,mCAAS,OAAO,QAAO,SAAS,OAAO;AAErE,UAAM,aAAa,QAAQ,MAAM,IAAI,OAAO,IACtC,QAAQ,MAAM,IAAI,OAAO,IACzB,SAAS,OAAO;AACtB,YAAQ,MAAM,IAAI,SAAS,UAAU;AAErC,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAYO,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAY1B,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAc1B,IAAM,SAAS,CAAI,aAA0B,QAAQ,UAAU,QAAQ;;;AC5GvE,IAAM,cAAc,MAAa,oBAAI,IAAI;;;ACiCzC,IAAM,gBAAgB,MAAe,oBAAI,IAAI;;;AC1B7C,IAAM,cAAc,CACvB,WACA,YAGC;AACD,QAAM,cAAc,UAAU,IAAI,CAAC,aAAa,SAAS,OAAO,CAAC;AAEjE,SACI,YAAY,KAAK,CAAC,eAAe,sBAAsB,OAAO,IACxD,QAAQ,IAAI,WAAW,IACvB;AAEd;AAaO,IAAM,aAAa,CACtB,WACA,YAGC;AACD,MAAI,uBAAuB,OAAO,QAAQ,SAAS,EAAE;AAAA,IACjD,CAAC,CAAC,KAAK,QAAQ,MAAM,CAAC,KAAK,SAAS,OAAO,CAAC;AAAA,EAChD;AAEA,MACI,qBAAqB;AAAA,IACjB,CAAC,CAAC,EAAE,UAAU,MAAM,sBAAsB;AAAA,EAC9C,GACF;AACE,YAAQ,YAAY;AAChB,6BAAuB,MAAM,QAAQ;AAAA,QACjC,qBAAqB,IAAI,OAAO,CAAC,KAAK,UAAU,MAAM;AAAA,UAClD;AAAA,UACA,MAAM;AAAA,QACV,CAAC;AAAA,MACL;AAEA,aAAO,OAAO,YAAY,oBAAoB;AAAA,IAClD,GAAG;AAAA,EACP;AAEA,SAAO,OAAO,YAAY,oBAAoB;AAClD;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/helpers.ts","../src/provider.ts","../src/scope.ts","../src/mock-map.ts","../src/collection-resolution.ts"],"sourcesContent":["export * from \"./provider\";\nexport * from \"./scope\";\nexport * from \"./mock-map\";\nexport * from \"./collection-resolution\";\n","/**\n * Creates a function that will invoke the provided function `fn` only once,\n * caching the result for subsequent calls with the same arguments.\n *\n * @param fn - The function to invoke once and cache the result.\n *\n * @returns A new function that returns the cached result after the first call.\n */\nexport const once = <A extends any[], R>(fn: (...args: A) => R) => {\n let returned = false;\n let result: R | undefined;\n\n return Object.assign((...args: A): R => {\n if (returned) return result!;\n\n result = fn(...args);\n returned = true;\n\n return result;\n }, fn);\n};\n","import { once } from \"./helpers\";\nimport { MockMap } from \"./mock-map\";\nimport { Scope } from \"./scope\";\n\n/**\n * A wrapper around the resolver(factory) for contextual dependency resolution.\n *\n * Resolves an instance by calling a resolver\n * with an **optional** resolution context that will be propagated\n * throughout a dependency tree.\n * ```ts\n * provider({ scope, mocks })\n * ```\n *\n * When passing a scope it will try to get an instance from it\n * or create a new one and put it there.\n *\n * When passing mocks, it will try to get its own mock version,\n * and if there is one, it will use it instead of itself.\n */\nexport type Provider<T> = (context?: ResolutionContext) => T;\n\n/**\n * A resolution lifetime.\n *\n * Passed when creating a provider to determine its behavior.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its instance from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n */\nexport type Lifetime = \"transient\" | \"singleton\" | \"scoped\";\n\n/**\n * A function that creates an instance using a resolution context.\n */\nexport type Resolver<T> = (context?: ResolutionContext) => T;\n\n/**\n * An object that holds information about a scope and provider mocks.\n *\n * Passed to the provider call to resolve scope instances and mock providers.\n */\nexport type ResolutionContext = {\n scope?: Scope;\n mocks?: MockMap;\n};\n\n/**\n * Creates a provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution.\n * ```ts\n * const getInstance = provide(\"transient\", () =>\n * createInstance(\n * getOtherInstance(context)\n * )\n * )\n * ```\n *\n * @param lifetime\n * A resolution lifetime.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n * If the function calls other providers,\n * the context **must** be passed to their calls.\n *\n * @returns The provider instance.\n */\nexport const provide = <T>(\n lifetime: Lifetime,\n resolver: Resolver<T>,\n): Provider<T> => {\n resolver = lifetime === \"singleton\" ? once(resolver) : resolver;\n\n const resolve: Provider<T> = (context) => {\n const maybeOwnMock = context?.mocks?.get(resolve);\n if (maybeOwnMock) return maybeOwnMock(context);\n\n if (lifetime !== \"scoped\" || !context?.scope) return resolver(context);\n\n const resolution = context.scope.has(resolve)\n ? context.scope.get(resolve)\n : resolver(context);\n context.scope.set(resolve, resolution);\n\n return resolution;\n };\n\n return resolve;\n};\n\n/**\n * An alias for `provide(\"transient\", ...)`.\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create a new instance on each request.\n * ```ts\n * const getInstance = transient((context) =>\n * createInstance(...)\n * )\n *\n * getInstance() !== getInstance()\n * ```\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The transient provider instance.\n */\nexport const transient = <T>(resolver: Resolver<T>): Provider<T> =>\n provide(\"transient\", resolver);\n\n/**\n * An alias for `provide(\"singleton\", ...)`.\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create an instance once and return it in subsequent requests.\n * ```ts\n * const getInstance = singleton((context) =>\n * createInstance(...)\n * )\n *\n * getInstance() === getInstance()\n * ```\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The singleton provider instance.\n */\nexport const singleton = <T>(resolver: Resolver<T>): Provider<T> =>\n provide(\"singleton\", resolver);\n\n/**\n * An alias for `provide(\"scoped\", ...)`.\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n * ```ts\n * const getInstance = scoped((context) =>\n * createInstance(...)\n * )\n *\n * getInstance() !== getInstance()\n * getInstance({ scope }) === getInstance({ scope })\n * ```\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The scoped provider instance.\n */\nexport const scoped = <T>(resolver: Resolver<T>): Provider<T> =>\n provide(\"scoped\", resolver);\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to their instances.\n *\n * Passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n */\nexport type Scope = Map<Provider<any>, any>;\n\n/**\n * Creates a scope instance.\n *\n * Scope is passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n *\n * @returns The scope instance.\n */\nexport const createScope = (): Scope => new Map();\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n */\nexport type MockMap = Omit<Map<Provider<any>, Provider<any>>, \"set\" | \"get\"> & {\n /**\n * Sets a mock for a provider.\n *\n * @param provider - The original provider.\n * @param mock - The mock provider.\n */\n set<T>(provider: Provider<T>, mock: Provider<T>): MockMap;\n /**\n * Retrieves a mock of a provider. Returns undefined if there's none.\n *\n * @param provider - The provider.\n */\n get<T>(provider: Provider<T>): Provider<T> | undefined;\n};\n\n/**\n * Creates a mock map instance,\n * a map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n *\n * @returns The mock map instance.\n */\nexport const createMockMap = (): MockMap => new Map();\n","import { Provider, ResolutionContext } from \"./provider\";\n\ntype ProviderList = Provider<any>[];\ntype ProviderRecord = Record<string, Provider<any>>;\n\ntype InferProviderCollectionResolutions<\n Providers extends ProviderList | ProviderRecord,\n> = {\n [K in keyof Providers]: Providers[K] extends Provider<infer T> ? T : never;\n};\n\n/**\n * Awaits all promises and wraps the collection in a promise\n * if there'ss at least one `Promise` in the collection,\n * otherwise returns an untouched type.\n */\ntype AwaitAllValuesInCollection<T extends any[] | Record<any, any>> =\n Promise<any> extends T[keyof T]\n ? Promise<{\n [I in keyof T]: T[I] extends Promise<infer T> ? T : T[I];\n }>\n : T;\n\n/**\n * Calls every provider in a list with a provided resolution context\n * and returns a list of resolutions. Returns a promise of a list\n * of awaited resolutions if there's at least one promise in the resolutions.\n * ```ts\n * const resolutions = resolveList(\n * [getA, getB, getC],\n * { scope, mocks }\n * )\n * ```\n *\n * @param providers - The list of providers.\n * @param context - The resolution context.\n *\n * @returns The list of resolutions.\n */\nexport const resolveList = <const Providers extends ProviderList>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n const resolutions = providers.map((provider) => provider(context));\n\n return (\n resolutions.some((resolution) => resolution instanceof Promise)\n ? Promise.all(resolutions)\n : resolutions\n ) as any;\n};\n\n/**\n * Calls every provider in a map with a provided resolution context\n * and returns a map with identical keys but with resolutions in values instead.\n * Returns a promise of a map of awaited resolutions if there's at least one\n * promise in the resolutions.\n * ```ts\n * const resolutionMap = resolveMap(\n * { a: getA, b: getB, c: getC },\n * { scope, mocks }\n * )\n * ```\n *\n * @param providers - The map of providers.\n * @param context - The resolution context.\n *\n * @returns The map of resolutions.\n */\nexport const resolveMap = <const Providers extends ProviderRecord>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n let resolutionMapEntries = Object.entries(providers).map(\n ([key, provider]) => [key, provider(context)],\n );\n\n if (\n resolutionMapEntries.some(\n ([, resolution]) => resolution instanceof Promise,\n )\n ) {\n return (async () => {\n resolutionMapEntries = await Promise.all(\n resolutionMapEntries.map(async ([key, resolution]) => [\n key,\n await resolution,\n ]),\n );\n\n return Object.fromEntries(resolutionMapEntries);\n })() as any;\n }\n\n return Object.fromEntries(resolutionMapEntries);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAM,OAAO,CAAqB,OAA0B;AAC/D,MAAI,WAAW;AACf,MAAI;AAEJ,SAAO,OAAO,OAAO,IAAI,SAAe;AACpC,QAAI,SAAU,QAAO;AAErB,aAAS,GAAG,GAAG,IAAI;AACnB,eAAW;AAEX,WAAO;AAAA,EACX,GAAG,EAAE;AACT;;;ACiEO,IAAM,UAAU,CACnB,UACA,aACc;AACd,aAAW,aAAa,cAAc,KAAK,QAAQ,IAAI;AAEvD,QAAM,UAAuB,CAAC,YAAY;AA3F9C;AA4FQ,UAAM,gBAAe,wCAAS,UAAT,mBAAgB,IAAI;AACzC,QAAI,aAAc,QAAO,aAAa,OAAO;AAE7C,QAAI,aAAa,YAAY,EAAC,mCAAS,OAAO,QAAO,SAAS,OAAO;AAErE,UAAM,aAAa,QAAQ,MAAM,IAAI,OAAO,IACtC,QAAQ,MAAM,IAAI,OAAO,IACzB,SAAS,OAAO;AACtB,YAAQ,MAAM,IAAI,SAAS,UAAU;AAErC,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAoBO,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAoB1B,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAuB1B,IAAM,SAAS,CAAI,aACtB,QAAQ,UAAU,QAAQ;;;AClJvB,IAAM,cAAc,MAAa,oBAAI,IAAI;;;ACiCzC,IAAM,gBAAgB,MAAe,oBAAI,IAAI;;;ACpB7C,IAAM,cAAc,CACvB,WACA,YAGC;AACD,QAAM,cAAc,UAAU,IAAI,CAAC,aAAa,SAAS,OAAO,CAAC;AAEjE,SACI,YAAY,KAAK,CAAC,eAAe,sBAAsB,OAAO,IACxD,QAAQ,IAAI,WAAW,IACvB;AAEd;AAmBO,IAAM,aAAa,CACtB,WACA,YAGC;AACD,MAAI,uBAAuB,OAAO,QAAQ,SAAS,EAAE;AAAA,IACjD,CAAC,CAAC,KAAK,QAAQ,MAAM,CAAC,KAAK,SAAS,OAAO,CAAC;AAAA,EAChD;AAEA,MACI,qBAAqB;AAAA,IACjB,CAAC,CAAC,EAAE,UAAU,MAAM,sBAAsB;AAAA,EAC9C,GACF;AACE,YAAQ,YAAY;AAChB,6BAAuB,MAAM,QAAQ;AAAA,QACjC,qBAAqB,IAAI,OAAO,CAAC,KAAK,UAAU,MAAM;AAAA,UAClD;AAAA,UACA,MAAM;AAAA,QACV,CAAC;AAAA,MACL;AAEA,aAAO,OAAO,YAAY,oBAAoB;AAAA,IAClD,GAAG;AAAA,EACP;AAEA,SAAO,OAAO,YAAY,oBAAoB;AAClD;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/helpers.ts","../src/provider.ts","../src/scope.ts","../src/mock-map.ts","../src/collection-resolution.ts"],"sourcesContent":["/**\n * Creates a function that will invoke the provided function `fn` only once,\n * caching the result for subsequent calls with the same arguments.\n *\n * @returns A new function that returns the cached result after the first call.\n */\nexport const once = <A extends any[], R>(\n /**\n * The function to invoke once and cache the result.\n */\n fn: (...args: A) => R,\n) => {\n let returned = false;\n let result: R | undefined;\n\n return Object.assign((...args: A): R => {\n if (returned) return result!;\n\n result = fn(...args);\n returned = true;\n\n return result;\n }, fn);\n};\n","import { once } from \"./helpers\";\nimport { MockMap } from \"./mock-map\";\nimport { Scope } from \"./scope\";\n\n/**\n * A wrapper around the resolver(factory) for contextual dependency resolution.\n *\n * Resolves an instance by calling a resolver\n * with a resolution context that will be propagated\n * throughout a dependency tree.\n *\n * When passing a scope it will try to get an instance from it\n * or create a new one and put it there.\n *\n * When passing mocks, it will try to get its own mock version,\n * and if there is one, it will use it instead of itself.\n */\nexport type Provider<T> = (context?: ResolutionContext) => T;\n\n/**\n * A resolution lifetime.\n *\n * Passed when creating a provider to determine its behavior.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its instance from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n */\nexport type Lifetime = \"transient\" | \"singleton\" | \"scoped\";\n\n/**\n * A function that creates an instance using a resolution context.\n */\nexport type Resolver<T> = (context?: ResolutionContext) => T;\n\n/**\n * An object that holds information about a scope and provider mocks.\n *\n * Passed to the provider call to resolve scope instances and mock providers.\n */\nexport type ResolutionContext = {\n scope?: Scope;\n mocks?: MockMap;\n};\n\n/**\n * Creates a provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution.\n *\n * @param lifetime\n * A resolution lifetime.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The provider instance.\n */\nexport const provide = <T>(\n lifetime: Lifetime,\n resolver: Resolver<T>,\n): Provider<T> => {\n resolver = lifetime === \"singleton\" ? once(resolver) : resolver;\n\n const resolve: Provider<T> = (context) => {\n const maybeOwnMock = context?.mocks?.get(resolve);\n if (maybeOwnMock) return maybeOwnMock(context);\n\n if (lifetime !== \"scoped\" || !context?.scope) return resolver(context);\n\n const resolution = context.scope.has(resolve)\n ? context.scope.get(resolve)\n : resolver(context);\n context.scope.set(resolve, resolution);\n\n return resolution;\n };\n\n return resolve;\n};\n\n/**\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The transient provider instance.\n */\nexport const transient = <T>(resolver: Resolver<T>) =>\n provide(\"transient\", resolver);\n\n/**\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create an instance once and return it in subsequent requests.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The singleton provider instance.\n */\nexport const singleton = <T>(resolver: Resolver<T>) =>\n provide(\"singleton\", resolver);\n\n/**\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The scoped provider instance.\n */\nexport const scoped = <T>(resolver: Resolver<T>) => provide(\"scoped\", resolver);\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to their instances.\n *\n * Passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n */\nexport type Scope = Map<Provider<any>, any>;\n\n/**\n * Creates a scope instance.\n *\n * Scope is passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n *\n * @returns The scope instance.\n */\nexport const createScope = (): Scope => new Map();\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n */\nexport type MockMap = Omit<Map<Provider<any>, Provider<any>>, \"set\" | \"get\"> & {\n /**\n * Sets a mock for a provider.\n *\n * @param provider - The original provider.\n * @param mock - The mock provider.\n */\n set<T>(provider: Provider<T>, mock: Provider<T>): MockMap;\n /**\n * Retrieves a mock of a provider. Returns undefined if there's none.\n *\n * @param provider - The provider.\n */\n get<T>(provider: Provider<T>): Provider<T> | undefined;\n};\n\n/**\n * Creates a mock map instance,\n * a map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n *\n * @returns The mock map instance.\n */\nexport const createMockMap = (): MockMap => new Map();\n","import { Provider, ResolutionContext } from \"./provider\";\n\ntype ProviderList = Provider<any>[];\ntype ProviderRecord = Record<string, Provider<any>>;\n\ntype InferProviderCollectionResolutions<\n Providers extends ProviderList | ProviderRecord,\n> = {\n [K in keyof Providers]: Providers[K] extends Provider<infer T> ? T : never;\n};\n\n/**\n * Awaits all promises and wraps the collection in a promise\n * if there'ss at least one `Promise` in the collection,\n * otherwise returns an untouched type.\n */\ntype AwaitAllValuesInCollection<T extends any[] | Record<any, any>> =\n Promise<any> extends T[keyof T]\n ? Promise<{\n [I in keyof T]: T[I] extends Promise<infer T> ? T : T[I];\n }>\n : T;\n\n/**\n * Calls every provider in a list with a provided resolution context\n * and returns a list of resolutions. Returns a promise of a list\n * of awaited resolutions if there's at least one promise in the resolutions.\n *\n * @param providers - The list of providers.\n * @param context - The resolution context.\n *\n * @returns The list of resolutions.\n */\nexport const resolveList = <const Providers extends ProviderList>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n const resolutions = providers.map((provider) => provider(context));\n\n return (\n resolutions.some((resolution) => resolution instanceof Promise)\n ? Promise.all(resolutions)\n : resolutions\n ) as any;\n};\n\n/**\n * Calls every provider in a map with a provided resolution context\n * and returns a map with identical keys but with resolutions in values instead.\n * Returns a promise of a map of awaited resolutions if there's at least one\n * promise in the resolutions.\n *\n * @param providers - The map of providers.\n * @param context - The resolution context.\n *\n * @returns The map of resolutions.\n */\nexport const resolveMap = <const Providers extends ProviderRecord>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n let resolutionMapEntries = Object.entries(providers).map(\n ([key, provider]) => [key, provider(context)],\n );\n\n if (\n resolutionMapEntries.some(\n ([, resolution]) => resolution instanceof Promise,\n )\n ) {\n return (async () => {\n resolutionMapEntries = await Promise.all(\n resolutionMapEntries.map(async ([key, resolution]) => [\n key,\n await resolution,\n ]),\n );\n\n return Object.fromEntries(resolutionMapEntries);\n })() as any;\n }\n\n return Object.fromEntries(resolutionMapEntries);\n};\n"],"mappings":";AAMO,IAAM,OAAO,CAIhB,OACC;AACD,MAAI,WAAW;AACf,MAAI;AAEJ,SAAO,OAAO,OAAO,IAAI,SAAe;AACpC,QAAI,SAAU,QAAO;AAErB,aAAS,GAAG,GAAG,IAAI;AACnB,eAAW;AAEX,WAAO;AAAA,EACX,GAAG,EAAE;AACT;;;ACkDO,IAAM,UAAU,CACnB,UACA,aACc;AACd,aAAW,aAAa,cAAc,KAAK,QAAQ,IAAI;AAEvD,QAAM,UAAuB,CAAC,YAAY;AA/E9C;AAgFQ,UAAM,gBAAe,wCAAS,UAAT,mBAAgB,IAAI;AACzC,QAAI,aAAc,QAAO,aAAa,OAAO;AAE7C,QAAI,aAAa,YAAY,EAAC,mCAAS,OAAO,QAAO,SAAS,OAAO;AAErE,UAAM,aAAa,QAAQ,MAAM,IAAI,OAAO,IACtC,QAAQ,MAAM,IAAI,OAAO,IACzB,SAAS,OAAO;AACtB,YAAQ,MAAM,IAAI,SAAS,UAAU;AAErC,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAYO,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAY1B,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAc1B,IAAM,SAAS,CAAI,aAA0B,QAAQ,UAAU,QAAQ;;;AC5GvE,IAAM,cAAc,MAAa,oBAAI,IAAI;;;ACiCzC,IAAM,gBAAgB,MAAe,oBAAI,IAAI;;;AC1B7C,IAAM,cAAc,CACvB,WACA,YAGC;AACD,QAAM,cAAc,UAAU,IAAI,CAAC,aAAa,SAAS,OAAO,CAAC;AAEjE,SACI,YAAY,KAAK,CAAC,eAAe,sBAAsB,OAAO,IACxD,QAAQ,IAAI,WAAW,IACvB;AAEd;AAaO,IAAM,aAAa,CACtB,WACA,YAGC;AACD,MAAI,uBAAuB,OAAO,QAAQ,SAAS,EAAE;AAAA,IACjD,CAAC,CAAC,KAAK,QAAQ,MAAM,CAAC,KAAK,SAAS,OAAO,CAAC;AAAA,EAChD;AAEA,MACI,qBAAqB;AAAA,IACjB,CAAC,CAAC,EAAE,UAAU,MAAM,sBAAsB;AAAA,EAC9C,GACF;AACE,YAAQ,YAAY;AAChB,6BAAuB,MAAM,QAAQ;AAAA,QACjC,qBAAqB,IAAI,OAAO,CAAC,KAAK,UAAU,MAAM;AAAA,UAClD;AAAA,UACA,MAAM;AAAA,QACV,CAAC;AAAA,MACL;AAEA,aAAO,OAAO,YAAY,oBAAoB;AAAA,IAClD,GAAG;AAAA,EACP;AAEA,SAAO,OAAO,YAAY,oBAAoB;AAClD;","names":[]}
1
+ {"version":3,"sources":["../src/helpers.ts","../src/provider.ts","../src/scope.ts","../src/mock-map.ts","../src/collection-resolution.ts"],"sourcesContent":["/**\n * Creates a function that will invoke the provided function `fn` only once,\n * caching the result for subsequent calls with the same arguments.\n *\n * @param fn - The function to invoke once and cache the result.\n *\n * @returns A new function that returns the cached result after the first call.\n */\nexport const once = <A extends any[], R>(fn: (...args: A) => R) => {\n let returned = false;\n let result: R | undefined;\n\n return Object.assign((...args: A): R => {\n if (returned) return result!;\n\n result = fn(...args);\n returned = true;\n\n return result;\n }, fn);\n};\n","import { once } from \"./helpers\";\nimport { MockMap } from \"./mock-map\";\nimport { Scope } from \"./scope\";\n\n/**\n * A wrapper around the resolver(factory) for contextual dependency resolution.\n *\n * Resolves an instance by calling a resolver\n * with an **optional** resolution context that will be propagated\n * throughout a dependency tree.\n * ```ts\n * provider({ scope, mocks })\n * ```\n *\n * When passing a scope it will try to get an instance from it\n * or create a new one and put it there.\n *\n * When passing mocks, it will try to get its own mock version,\n * and if there is one, it will use it instead of itself.\n */\nexport type Provider<T> = (context?: ResolutionContext) => T;\n\n/**\n * A resolution lifetime.\n *\n * Passed when creating a provider to determine its behavior.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its instance from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n */\nexport type Lifetime = \"transient\" | \"singleton\" | \"scoped\";\n\n/**\n * A function that creates an instance using a resolution context.\n */\nexport type Resolver<T> = (context?: ResolutionContext) => T;\n\n/**\n * An object that holds information about a scope and provider mocks.\n *\n * Passed to the provider call to resolve scope instances and mock providers.\n */\nexport type ResolutionContext = {\n scope?: Scope;\n mocks?: MockMap;\n};\n\n/**\n * Creates a provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution.\n * ```ts\n * const getInstance = provide(\"transient\", () =>\n * createInstance(\n * getOtherInstance(context)\n * )\n * )\n * ```\n *\n * @param lifetime\n * A resolution lifetime.\n *\n * `\"transient\"` doesn't provide any modifications to a resolver behaviour,\n * so the resolver will create a new instance on each request.\n *\n * `\"singleton\"` forces the resolver to create an instance once\n * and return it in subsequent requests.\n *\n * `\"scoped\"` forces the resolver to take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n * If the function calls other providers,\n * the context **must** be passed to their calls.\n *\n * @returns The provider instance.\n */\nexport const provide = <T>(\n lifetime: Lifetime,\n resolver: Resolver<T>,\n): Provider<T> => {\n resolver = lifetime === \"singleton\" ? once(resolver) : resolver;\n\n const resolve: Provider<T> = (context) => {\n const maybeOwnMock = context?.mocks?.get(resolve);\n if (maybeOwnMock) return maybeOwnMock(context);\n\n if (lifetime !== \"scoped\" || !context?.scope) return resolver(context);\n\n const resolution = context.scope.has(resolve)\n ? context.scope.get(resolve)\n : resolver(context);\n context.scope.set(resolve, resolution);\n\n return resolution;\n };\n\n return resolve;\n};\n\n/**\n * An alias for `provide(\"transient\", ...)`.\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create a new instance on each request.\n * ```ts\n * const getInstance = transient((context) =>\n * createInstance(...)\n * )\n *\n * getInstance() !== getInstance()\n * ```\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The transient provider instance.\n */\nexport const transient = <T>(resolver: Resolver<T>): Provider<T> =>\n provide(\"transient\", resolver);\n\n/**\n * An alias for `provide(\"singleton\", ...)`.\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will create an instance once and return it in subsequent requests.\n * ```ts\n * const getInstance = singleton((context) =>\n * createInstance(...)\n * )\n *\n * getInstance() === getInstance()\n * ```\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The singleton provider instance.\n */\nexport const singleton = <T>(resolver: Resolver<T>): Provider<T> =>\n provide(\"singleton\", resolver);\n\n/**\n * An alias for `provide(\"scoped\", ...)`.\n * Creates a transient provider instance,\n * a wrapper around a resolver(factory) for contextual dependency resolution\n * that will take its resolution from a provided scope\n * or create a new one and save it if there is none.\n * If no scope is passed, it will create a new instance on each request.\n * ```ts\n * const getInstance = scoped((context) =>\n * createInstance(...)\n * )\n *\n * getInstance() !== getInstance()\n * getInstance({ scope }) === getInstance({ scope })\n * ```\n *\n * @param resolver\n * The function that creates an instance using a resolution context.\n *\n * @returns The scoped provider instance.\n */\nexport const scoped = <T>(resolver: Resolver<T>): Provider<T> =>\n provide(\"scoped\", resolver);\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to their instances.\n *\n * Passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n */\nexport type Scope = Map<Provider<any>, any>;\n\n/**\n * Creates a scope instance.\n *\n * Scope is passed to a provider call in a resolution context object\n * to resolve instances of scoped providers within it.\n * ```ts\n * const scope = createScope()\n * provider({ scope })\n * ```\n *\n * @returns The scope instance.\n */\nexport const createScope = (): Scope => new Map();\n","import { Provider } from \"./provider\";\n\n/**\n * A map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n */\nexport type MockMap = Omit<Map<Provider<any>, Provider<any>>, \"set\" | \"get\"> & {\n /**\n * Sets a mock for a provider.\n *\n * @param provider - The original provider.\n * @param mock - The mock provider.\n */\n set<T>(provider: Provider<T>, mock: Provider<T>): MockMap;\n /**\n * Retrieves a mock of a provider. Returns undefined if there's none.\n *\n * @param provider - The provider.\n */\n get<T>(provider: Provider<T>): Provider<T> | undefined;\n};\n\n/**\n * Creates a mock map instance,\n * a map of providers to providers of the same type.\n * Lifetime is not a part of `Provider` type, so you can use\n * a different one if necessary.\n *\n * Passed to a provider call in a resolution context object\n * in order to replace providers with their mocks.\n * ```ts\n * const otherProvider =\n * transitive(() => ...)\n * const otherProviderMock: typeof otherProvider =\n * scoped(() => ...)\n *\n * const mocks = createMockMap()\n * mocks.set(otherProvider, otherProviderMock)\n *\n * provider({ mocks })\n * ```\n *\n * @returns The mock map instance.\n */\nexport const createMockMap = (): MockMap => new Map();\n","import { Provider, ResolutionContext } from \"./provider\";\n\ntype ProviderList = Provider<any>[];\ntype ProviderRecord = Record<string, Provider<any>>;\n\ntype InferProviderCollectionResolutions<\n Providers extends ProviderList | ProviderRecord,\n> = {\n [K in keyof Providers]: Providers[K] extends Provider<infer T> ? T : never;\n};\n\n/**\n * Awaits all promises and wraps the collection in a promise\n * if there'ss at least one `Promise` in the collection,\n * otherwise returns an untouched type.\n */\ntype AwaitAllValuesInCollection<T extends any[] | Record<any, any>> =\n Promise<any> extends T[keyof T]\n ? Promise<{\n [I in keyof T]: T[I] extends Promise<infer T> ? T : T[I];\n }>\n : T;\n\n/**\n * Calls every provider in a list with a provided resolution context\n * and returns a list of resolutions. Returns a promise of a list\n * of awaited resolutions if there's at least one promise in the resolutions.\n * ```ts\n * const resolutions = resolveList(\n * [getA, getB, getC],\n * { scope, mocks }\n * )\n * ```\n *\n * @param providers - The list of providers.\n * @param context - The resolution context.\n *\n * @returns The list of resolutions.\n */\nexport const resolveList = <const Providers extends ProviderList>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n const resolutions = providers.map((provider) => provider(context));\n\n return (\n resolutions.some((resolution) => resolution instanceof Promise)\n ? Promise.all(resolutions)\n : resolutions\n ) as any;\n};\n\n/**\n * Calls every provider in a map with a provided resolution context\n * and returns a map with identical keys but with resolutions in values instead.\n * Returns a promise of a map of awaited resolutions if there's at least one\n * promise in the resolutions.\n * ```ts\n * const resolutionMap = resolveMap(\n * { a: getA, b: getB, c: getC },\n * { scope, mocks }\n * )\n * ```\n *\n * @param providers - The map of providers.\n * @param context - The resolution context.\n *\n * @returns The map of resolutions.\n */\nexport const resolveMap = <const Providers extends ProviderRecord>(\n providers: Providers,\n context?: ResolutionContext,\n): AwaitAllValuesInCollection<\n InferProviderCollectionResolutions<Providers>\n> => {\n let resolutionMapEntries = Object.entries(providers).map(\n ([key, provider]) => [key, provider(context)],\n );\n\n if (\n resolutionMapEntries.some(\n ([, resolution]) => resolution instanceof Promise,\n )\n ) {\n return (async () => {\n resolutionMapEntries = await Promise.all(\n resolutionMapEntries.map(async ([key, resolution]) => [\n key,\n await resolution,\n ]),\n );\n\n return Object.fromEntries(resolutionMapEntries);\n })() as any;\n }\n\n return Object.fromEntries(resolutionMapEntries);\n};\n"],"mappings":";AAQO,IAAM,OAAO,CAAqB,OAA0B;AAC/D,MAAI,WAAW;AACf,MAAI;AAEJ,SAAO,OAAO,OAAO,IAAI,SAAe;AACpC,QAAI,SAAU,QAAO;AAErB,aAAS,GAAG,GAAG,IAAI;AACnB,eAAW;AAEX,WAAO;AAAA,EACX,GAAG,EAAE;AACT;;;ACiEO,IAAM,UAAU,CACnB,UACA,aACc;AACd,aAAW,aAAa,cAAc,KAAK,QAAQ,IAAI;AAEvD,QAAM,UAAuB,CAAC,YAAY;AA3F9C;AA4FQ,UAAM,gBAAe,wCAAS,UAAT,mBAAgB,IAAI;AACzC,QAAI,aAAc,QAAO,aAAa,OAAO;AAE7C,QAAI,aAAa,YAAY,EAAC,mCAAS,OAAO,QAAO,SAAS,OAAO;AAErE,UAAM,aAAa,QAAQ,MAAM,IAAI,OAAO,IACtC,QAAQ,MAAM,IAAI,OAAO,IACzB,SAAS,OAAO;AACtB,YAAQ,MAAM,IAAI,SAAS,UAAU;AAErC,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAoBO,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAoB1B,IAAM,YAAY,CAAI,aACzB,QAAQ,aAAa,QAAQ;AAuB1B,IAAM,SAAS,CAAI,aACtB,QAAQ,UAAU,QAAQ;;;AClJvB,IAAM,cAAc,MAAa,oBAAI,IAAI;;;ACiCzC,IAAM,gBAAgB,MAAe,oBAAI,IAAI;;;ACpB7C,IAAM,cAAc,CACvB,WACA,YAGC;AACD,QAAM,cAAc,UAAU,IAAI,CAAC,aAAa,SAAS,OAAO,CAAC;AAEjE,SACI,YAAY,KAAK,CAAC,eAAe,sBAAsB,OAAO,IACxD,QAAQ,IAAI,WAAW,IACvB;AAEd;AAmBO,IAAM,aAAa,CACtB,WACA,YAGC;AACD,MAAI,uBAAuB,OAAO,QAAQ,SAAS,EAAE;AAAA,IACjD,CAAC,CAAC,KAAK,QAAQ,MAAM,CAAC,KAAK,SAAS,OAAO,CAAC;AAAA,EAChD;AAEA,MACI,qBAAqB;AAAA,IACjB,CAAC,CAAC,EAAE,UAAU,MAAM,sBAAsB;AAAA,EAC9C,GACF;AACE,YAAQ,YAAY;AAChB,6BAAuB,MAAM,QAAQ;AAAA,QACjC,qBAAqB,IAAI,OAAO,CAAC,KAAK,UAAU,MAAM;AAAA,UAClD;AAAA,UACA,MAAM;AAAA,QACV,CAAC;AAAA,MACL;AAEA,aAAO,OAAO,YAAY,oBAAoB;AAAA,IAClD,GAAG;AAAA,EACP;AAEA,SAAO,OAAO,YAAY,oBAAoB;AAClD;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atomic-di",
3
- "version": "0.9.1-beta.3",
3
+ "version": "0.9.1-beta.4",
4
4
  "description": "A toolset for containerless dependency injection.",
5
5
  "repository": "https://github.com/ncor/atomic-di",
6
6
  "bugs": "https://github.com/ncor/atomic-di/issues",