opinionated-machine 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -86,18 +86,27 @@ const contract = buildDeleteRoute({
86
86
 
87
87
  export class MyController extends AbstractController<typeof MyController.contracts> {
88
88
  public static contracts = { deleteItem: contract } as const
89
+ private readonly service: Service
89
90
 
90
- public buildRoutes() {
91
- return {
92
- deleteItem: buildFastifyNoPayloadRoute(
93
- MyController.contracts.deleteItem,
91
+ constructor({ service }: ModuleDependencies) {
92
+ super()
93
+ this.service = testService
94
+ }
95
+
96
+ private deleteItem = buildFastifyNoPayloadRoute(
97
+ TestController.contracts.deleteItem,
94
98
  async (req, reply) => {
95
- req.log.info(req.params.userId)
96
- await reply.status(204).send()
99
+ req.log.info(req.params.userId)
100
+ this.service.execute()
101
+ await reply.status(204).send()
97
102
  },
98
- ),
103
+ )
104
+
105
+ public buildRoutes() {
106
+ return {
107
+ deleteItem: this.deleteItem,
108
+ }
99
109
  }
100
- }
101
110
  }
102
111
  ```
103
112
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { DIContext, type DependencyInjectionOptions, type registerDependenciesParams, } from './lib/DIContext.js';
2
- export { AbstractModule, type MandatoryNameAndRegistrationPair } from './lib/AbstractModule.js';
1
+ export { DIContext, type DependencyInjectionOptions, type RegisterDependenciesParams, } from './lib/DIContext.js';
2
+ export { AbstractModule, type MandatoryNameAndRegistrationPair, type UnionToIntersection, } from './lib/AbstractModule.js';
3
3
  export { ENABLE_ALL, resolveJobQueuesEnabled, isJobQueueEnabled, isMessageQueueConsumerEnabled, isJobWorkersEnabled, isPeriodicJobEnabled, } from './lib/diConfigUtils.js';
4
4
  export { AbstractController } from './lib/AbstractController.js';
5
- export { asJobQueueClass, asJobWorkerClass, asMessageQueueHandlerClass, asControllerClass, asSingletonClass, asPeriodicJobClass, } from './lib/resolverFunctions.js';
5
+ export { asJobQueueClass, asJobWorkerClass, asMessageQueueHandlerClass, asControllerClass, asSingletonClass, asPeriodicJobClass, asSingletonFunction, asServiceClass, asRepositoryClass, asUseCaseClass, } from './lib/resolverFunctions.js';
6
6
  export type { PeriodicJobOptions, JobQueueModuleOptions, MessageQueueConsumerModuleOptions, JobWorkerModuleOptions, } from './lib/resolverFunctions.js';
7
- export type { InferRequestFromContract } from './lib/typeUtils.js';
7
+ export { AbstractTestContextFactory, type CreateTestContextParams, type ConfigOverrides, } from './lib/AbstractTestContextFactory.js';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { DIContext, } from './lib/DIContext.js';
2
- export { AbstractModule } from './lib/AbstractModule.js';
2
+ export { AbstractModule, } from './lib/AbstractModule.js';
3
3
  export { ENABLE_ALL, resolveJobQueuesEnabled, isJobQueueEnabled, isMessageQueueConsumerEnabled, isJobWorkersEnabled, isPeriodicJobEnabled, } from './lib/diConfigUtils.js';
4
4
  export { AbstractController } from './lib/AbstractController.js';
5
- export { asJobQueueClass, asJobWorkerClass, asMessageQueueHandlerClass, asControllerClass, asSingletonClass, asPeriodicJobClass, } from './lib/resolverFunctions.js';
5
+ export { asJobQueueClass, asJobWorkerClass, asMessageQueueHandlerClass, asControllerClass, asSingletonClass, asPeriodicJobClass, asSingletonFunction, asServiceClass, asRepositoryClass, asUseCaseClass, } from './lib/resolverFunctions.js';
6
+ export { AbstractTestContextFactory, } from './lib/AbstractTestContextFactory.js';
6
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GAGV,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,cAAc,EAAyC,MAAM,yBAAyB,CAAA;AAC/F,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,6BAA6B,EAC7B,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GAGV,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,cAAc,GAGf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,6BAA6B,EAC7B,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,4BAA4B,CAAA;AASnC,OAAO,EACL,0BAA0B,GAG3B,MAAM,qCAAqC,CAAA"}
@@ -3,6 +3,10 @@ import type { DependencyInjectionOptions } from './DIContext.js';
3
3
  export type MandatoryNameAndRegistrationPair<T> = {
4
4
  [U in keyof T]: Resolver<T[U]>;
5
5
  };
6
+ /**
7
+ * Use this utility type to combine dependencies from multiple modules into full context list of dependencies
8
+ */
9
+ export type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
6
10
  export declare abstract class AbstractModule<ModuleDependencies, ExternalDependencies = never> {
7
11
  abstract resolveDependencies(diOptions: DependencyInjectionOptions, externalDependencies: ExternalDependencies): MandatoryNameAndRegistrationPair<ModuleDependencies>;
8
12
  abstract resolveControllers(): MandatoryNameAndRegistrationPair<unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractModule.js","sourceRoot":"","sources":["../../lib/AbstractModule.ts"],"names":[],"mappings":"AAOA,MAAM,OAAgB,cAAc;CAOnC"}
1
+ {"version":3,"file":"AbstractModule.js","sourceRoot":"","sources":["../../lib/AbstractModule.ts"],"names":[],"mappings":"AAcA,MAAM,OAAgB,cAAc;CAOnC"}
@@ -0,0 +1,23 @@
1
+ import { type NameAndRegistrationPair } from 'awilix';
2
+ import type { AbstractModule } from './AbstractModule.js';
3
+ import { DIContext, type DependencyInjectionOptions } from './DIContext.js';
4
+ type NestedPartial<T> = {
5
+ [P in keyof T]?: NestedPartial<T[P]>;
6
+ };
7
+ export type ConfigOverrides<Config> = NestedPartial<Config>;
8
+ export type CreateTestContextParams<Dependencies, Config extends object> = {
9
+ modules?: readonly AbstractModule<unknown>[];
10
+ diOptions?: DependencyInjectionOptions;
11
+ dependencyOverrides?: NameAndRegistrationPair<Dependencies>;
12
+ configOverrides?: ConfigOverrides<Config>;
13
+ };
14
+ export declare abstract class AbstractTestContextFactory<Dependencies extends object, ExternalDependencies, Config extends object> {
15
+ private readonly externalDependencies;
16
+ protected configDependencyId: string;
17
+ private readonly allModules;
18
+ constructor(externalDependencies: ExternalDependencies, allModules: readonly AbstractModule<unknown>[]);
19
+ resetExternalDependencies(): void;
20
+ abstract resolveBaseAppConfig(): Config;
21
+ createTestContext(params?: CreateTestContextParams<Dependencies, Config>): Promise<DIContext<Dependencies, ExternalDependencies>>;
22
+ }
23
+ export {};
@@ -0,0 +1,39 @@
1
+ import { createContainer } from 'awilix';
2
+ import { merge } from 'ts-deepmerge';
3
+ import { DIContext } from './DIContext.js';
4
+ import { asSingletonFunction } from './resolverFunctions.js';
5
+ export class AbstractTestContextFactory {
6
+ externalDependencies;
7
+ configDependencyId = 'config'; // override in subclass if different
8
+ allModules;
9
+ constructor(externalDependencies, allModules) {
10
+ this.externalDependencies = externalDependencies;
11
+ this.allModules = allModules;
12
+ }
13
+ resetExternalDependencies() {
14
+ // Override if necessary
15
+ }
16
+ async createTestContext(params = {}) {
17
+ const diContainer = createContainer({
18
+ injectionMode: 'PROXY',
19
+ });
20
+ const context = new DIContext(diContainer, params.diOptions ?? {});
21
+ const dependencyOverrides = params.configOverrides
22
+ ? {
23
+ ...params.dependencyOverrides,
24
+ [this.configDependencyId]: asSingletonFunction(() => {
25
+ // biome-ignore lint/style/noNonNullAssertion: there is a ternary condition above
26
+ return merge(this.resolveBaseAppConfig(), params.configOverrides);
27
+ }),
28
+ }
29
+ : params.dependencyOverrides;
30
+ const modules = params.modules ?? this.allModules;
31
+ context.registerDependencies({
32
+ dependencyOverrides,
33
+ modules,
34
+ }, this.externalDependencies, false);
35
+ await context.init();
36
+ return context;
37
+ }
38
+ }
39
+ //# sourceMappingURL=AbstractTestContextFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbstractTestContextFactory.js","sourceRoot":"","sources":["../../lib/AbstractTestContextFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,eAAe,EAAE,MAAM,QAAQ,CAAA;AACtE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEpC,OAAO,EAAE,SAAS,EAAmC,MAAM,gBAAgB,CAAA;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAe5D,MAAM,OAAgB,0BAA0B;IAK7B,oBAAoB,CAAsB;IACjD,kBAAkB,GAAG,QAAQ,CAAA,CAAC,oCAAoC;IAC3D,UAAU,CAAoC;IAE/D,YACE,oBAA0C,EAC1C,UAA8C;QAE9C,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAA;QAChD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,yBAAyB;QACvB,wBAAwB;IAC1B,CAAC;IAID,KAAK,CAAC,iBAAiB,CACrB,SAAwD,EAAE;QAE1D,MAAM,WAAW,GAAG,eAAe,CAAC;YAClC,aAAa,EAAE,OAAO;SACvB,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,IAAI,SAAS,CAC3B,WAAW,EACX,MAAM,CAAC,SAAS,IAAI,EAAE,CACvB,CAAA;QAED,MAAM,mBAAmB,GAAG,MAAM,CAAC,eAAe;YAChD,CAAC,CAAE;gBACC,GAAG,MAAM,CAAC,mBAAmB;gBAC7B,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,GAAG,EAAE;oBAClD,iFAAiF;oBACjF,OAAO,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,MAAM,CAAC,eAAgB,CAAC,CAAA;gBACpE,CAAC,CAAC;aACuC;YAC7C,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAA;QAE9B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,CAAA;QACjD,OAAO,CAAC,oBAAoB,CAC1B;YACE,mBAAmB;YACnB,OAAO;SACR,EACD,IAAI,CAAC,oBAAoB,EACzB,KAAK,CACN,CAAA;QAED,MAAM,OAAO,CAAC,IAAI,EAAE,CAAA;QAEpB,OAAO,OAAO,CAAA;IAChB,CAAC;CACF"}
@@ -3,23 +3,25 @@ import { AwilixManager } from 'awilix-manager';
3
3
  import type { FastifyInstance } from 'fastify';
4
4
  import type { AbstractModule } from './AbstractModule.js';
5
5
  import type { ENABLE_ALL } from './diConfigUtils.js';
6
- export type registerDependenciesParams<Dependencies, ExternalDependencies> = {
6
+ export type RegisterDependenciesParams<Dependencies, ExternalDependencies> = {
7
7
  modules: readonly AbstractModule<unknown, ExternalDependencies>[];
8
+ secondaryModules?: readonly AbstractModule<unknown, ExternalDependencies>[];
8
9
  dependencyOverrides?: NameAndRegistrationPair<Dependencies>;
9
10
  };
10
11
  export type DependencyInjectionOptions = {
11
12
  jobQueuesEnabled?: false | typeof ENABLE_ALL | string[];
12
13
  jobWorkersEnabled?: false | typeof ENABLE_ALL | string[];
13
14
  messageQueueConsumersEnabled?: false | typeof ENABLE_ALL | string[];
14
- periodicJobsEnabled?: false | typeof ENABLE_ALL;
15
+ periodicJobsEnabled?: false | typeof ENABLE_ALL | string[];
15
16
  };
16
- export declare class DIContext<Dependencies extends object, ExternalDependencies = {}> {
17
+ export declare class DIContext<Dependencies extends object, ExternalDependencies = undefined> {
17
18
  private readonly options;
18
19
  readonly awilixManager: AwilixManager;
19
20
  readonly diContainer: AwilixContainer<Dependencies>;
20
21
  private readonly controllerResolvers;
21
22
  constructor(diContainer: AwilixContainer, options: DependencyInjectionOptions);
22
- registerDependencies(params: registerDependenciesParams<Dependencies, ExternalDependencies>, externalDependencies: ExternalDependencies): void;
23
+ private registerModule;
24
+ registerDependencies(params: RegisterDependenciesParams<Dependencies, ExternalDependencies>, externalDependencies: ExternalDependencies, resolveControllers?: boolean): void;
23
25
  registerRoutes(app: FastifyInstance): void;
24
26
  destroy(): Promise<void>;
25
27
  init(): Promise<void>;
@@ -1,5 +1,4 @@
1
1
  import { AwilixManager } from 'awilix-manager';
2
- // biome-ignore lint/complexity/noBannedTypes: default is empty object
3
2
  export class DIContext {
4
3
  options;
5
4
  awilixManager;
@@ -18,18 +17,31 @@ export class DIContext {
18
17
  });
19
18
  this.controllerResolvers = [];
20
19
  }
21
- registerDependencies(params, externalDependencies) {
22
- const _dependencyOverrides = params.dependencyOverrides ?? {};
23
- const diConfig = {};
24
- for (const module of params.modules) {
25
- const resolvedDIConfig = module.resolveDependencies(this.options, externalDependencies);
26
- for (const key in resolvedDIConfig) {
20
+ registerModule(module, targetDiConfig, externalDependencies, resolveControllers, isPrimaryModule) {
21
+ const resolvedDIConfig = module.resolveDependencies(this.options, externalDependencies);
22
+ for (const key in resolvedDIConfig) {
23
+ // @ts-expect-error we can't really ensure type-safety here
24
+ if (isPrimaryModule || resolvedDIConfig[key].public) {
27
25
  // @ts-expect-error we can't really ensure type-safety here
28
- diConfig[key] = resolvedDIConfig[key];
26
+ targetDiConfig[key] = resolvedDIConfig[key];
29
27
  }
28
+ }
29
+ if (isPrimaryModule && resolveControllers) {
30
30
  this.controllerResolvers.push(...Object.values(module.resolveControllers()));
31
31
  }
32
- this.diContainer.register(diConfig);
32
+ }
33
+ registerDependencies(params, externalDependencies, resolveControllers = true) {
34
+ const _dependencyOverrides = params.dependencyOverrides ?? {};
35
+ const targetDiConfig = {};
36
+ for (const primaryModule of params.modules) {
37
+ this.registerModule(primaryModule, targetDiConfig, externalDependencies, resolveControllers, true);
38
+ }
39
+ if (params.secondaryModules) {
40
+ for (const secondaryModule of params.secondaryModules) {
41
+ this.registerModule(secondaryModule, targetDiConfig, externalDependencies, resolveControllers, false);
42
+ }
43
+ }
44
+ this.diContainer.register(targetDiConfig);
33
45
  for (const [dependencyKey, _dependencyValue] of Object.entries(_dependencyOverrides)) {
34
46
  const dependencyValue = { ..._dependencyValue };
35
47
  // preserve lifetime from original resolver
@@ -1 +1 @@
1
- {"version":3,"file":"DIContext.js","sourceRoot":"","sources":["../../lib/DIContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAkB9C,sEAAsE;AACtE,MAAM,OAAO,SAAS;IACH,OAAO,CAA4B;IACpC,aAAa,CAAe;IAC5B,WAAW,CAA+B;IAC1D,8EAA8E;IAC7D,mBAAmB,CAAiB;IAErD,YAAY,WAA4B,EAAE,OAAmC;QAC3E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;QAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC;YACrC,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,IAAI;YACf,WAAW;YACX,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE,IAAI;SAC5B,CAAC,CAAA;QACF,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAA;IAC/B,CAAC;IAED,oBAAoB,CAClB,MAAsE,EACtE,oBAA0C;QAE1C,MAAM,oBAAoB,GAAG,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAA;QAC7D,MAAM,QAAQ,GAA0C,EAAE,CAAA;QAE1D,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,gBAAgB,GAAG,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;YAEvF,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;gBACnC,2DAA2D;gBAC3D,QAAQ,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;YACvC,CAAC;YAED,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAC3B,GAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAyB,CACvE,CAAA;QACH,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAEnC,KAAK,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACrF,MAAM,eAAe,GAAG,EAAE,GAAI,gBAAsC,EAAE,CAAA;YAEtE,2CAA2C;YAC3C,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,aAAa,CAAC,CAAA;YACxE,aAAa;YACb,IAAI,eAAe,CAAC,QAAQ,KAAK,gBAAgB,CAAC,QAAQ,EAAE,CAAC;gBAC3D,aAAa;gBACb,eAAe,CAAC,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAA;YACtD,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IAED,cAAc,CAAC,GAAoB;QACjC,KAAK,MAAM,kBAAkB,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1D,wEAAwE;YACxE,MAAM,UAAU,GAA4B,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YACxF,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAA;YACvC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1C,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAA;QACzC,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,CAAA;IACxC,CAAC;CACF"}
1
+ {"version":3,"file":"DIContext.js","sourceRoot":"","sources":["../../lib/DIContext.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,16 @@
1
1
  import type { BuildResolver, BuildResolverOptions, Constructor, DisposableResolver } from 'awilix';
2
+ import type { FunctionReturning } from 'awilix/lib/container';
2
3
  import type { DependencyInjectionOptions } from './DIContext.js';
4
+ declare module 'awilix' {
5
+ interface ResolverOptions<T> {
6
+ public?: boolean;
7
+ }
8
+ }
3
9
  export declare function asSingletonClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
10
+ export declare function asSingletonFunction<T>(fn: FunctionReturning<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
11
+ export declare function asServiceClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
12
+ export declare function asUseCaseClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
13
+ export declare function asRepositoryClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
4
14
  export declare function asControllerClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
5
15
  export type MessageQueueConsumerModuleOptions = {
6
16
  queueName: string;
@@ -1,4 +1,4 @@
1
- import { asClass } from 'awilix';
1
+ import { asClass, asFunction } from 'awilix';
2
2
  import { isJobQueueEnabled, isJobWorkersEnabled, isMessageQueueConsumerEnabled, isPeriodicJobEnabled, } from './diConfigUtils.js';
3
3
  export function asSingletonClass(Type, opts) {
4
4
  return asClass(Type, {
@@ -6,8 +6,36 @@ export function asSingletonClass(Type, opts) {
6
6
  lifetime: 'SINGLETON',
7
7
  });
8
8
  }
9
+ export function asSingletonFunction(fn, opts) {
10
+ return asFunction(fn, {
11
+ ...opts,
12
+ lifetime: 'SINGLETON',
13
+ });
14
+ }
15
+ export function asServiceClass(Type, opts) {
16
+ return asClass(Type, {
17
+ public: true,
18
+ ...opts,
19
+ lifetime: 'SINGLETON',
20
+ });
21
+ }
22
+ export function asUseCaseClass(Type, opts) {
23
+ return asClass(Type, {
24
+ public: true,
25
+ ...opts,
26
+ lifetime: 'SINGLETON',
27
+ });
28
+ }
29
+ export function asRepositoryClass(Type, opts) {
30
+ return asClass(Type, {
31
+ public: false,
32
+ ...opts,
33
+ lifetime: 'SINGLETON',
34
+ });
35
+ }
9
36
  export function asControllerClass(Type, opts) {
10
37
  return asClass(Type, {
38
+ public: false,
11
39
  ...opts,
12
40
  lifetime: 'SINGLETON',
13
41
  });
@@ -20,6 +48,7 @@ export function asMessageQueueHandlerClass(Type, mqOptions, opts) {
20
48
  asyncDisposePriority: 10,
21
49
  enabled: isMessageQueueConsumerEnabled(mqOptions.diOptions.messageQueueConsumersEnabled, mqOptions.queueName),
22
50
  lifetime: 'SINGLETON',
51
+ public: false,
23
52
  ...opts,
24
53
  });
25
54
  }
@@ -28,7 +57,8 @@ export function asJobWorkerClass(Type, workerOptions, opts) {
28
57
  // these follow background-jobs-common conventions
29
58
  asyncInit: 'start',
30
59
  asyncDispose: 'dispose',
31
- asyncDisposePriority: 10,
60
+ asyncDisposePriority: 15,
61
+ public: false,
32
62
  enabled: isJobWorkersEnabled(workerOptions.diOptions.jobWorkersEnabled, workerOptions.queueName),
33
63
  lifetime: 'SINGLETON',
34
64
  ...opts,
@@ -38,6 +68,8 @@ export function asPeriodicJobClass(Type, workerOptions, opts) {
38
68
  return asClass(Type, {
39
69
  // this follows background-jobs-common conventions
40
70
  eagerInject: 'register',
71
+ asyncDispose: 'dispose',
72
+ public: false,
41
73
  enabled: isPeriodicJobEnabled(workerOptions.diOptions.periodicJobsEnabled, workerOptions.jobName),
42
74
  lifetime: 'SINGLETON',
43
75
  ...opts,
@@ -49,6 +81,7 @@ export function asJobQueueClass(Type, queueOptions, opts) {
49
81
  asyncInit: 'start',
50
82
  asyncDispose: 'dispose',
51
83
  asyncDisposePriority: 20,
84
+ public: true,
52
85
  enabled: isJobQueueEnabled(queueOptions.diOptions.jobQueuesEnabled, queueOptions.queueName),
53
86
  lifetime: 'SINGLETON',
54
87
  ...opts,
@@ -1 +1 @@
1
- {"version":3,"file":"resolverFunctions.js","sourceRoot":"","sources":["../../lib/resolverFunctions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAGhC,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,6BAA6B,EAC7B,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAE3B,MAAM,UAAU,gBAAgB,CAC9B,IAAoB,EACpB,IAA8B;IAE9B,OAAO,OAAO,CAAC,IAAI,EAAE;QACnB,GAAG,IAAI;QACP,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAoB,EACpB,IAA8B;IAE9B,OAAO,OAAO,CAAC,IAAI,EAAE;QACnB,GAAG,IAAI;QACP,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAA;AACJ,CAAC;AAOD,MAAM,UAAU,0BAA0B,CACxC,IAAoB,EACpB,SAA4C,EAC5C,IAA8B;IAE9B,OAAO,OAAO,CAAC,IAAI,EAAE;QACnB,iDAAiD;QACjD,SAAS,EAAE,OAAO;QAClB,YAAY,EAAE,OAAO;QACrB,oBAAoB,EAAE,EAAE;QAExB,OAAO,EAAE,6BAA6B,CACpC,SAAS,CAAC,SAAS,CAAC,4BAA4B,EAChD,SAAS,CAAC,SAAS,CACpB;QACD,QAAQ,EAAE,WAAW;QACrB,GAAG,IAAI;KACR,CAAC,CAAA;AACJ,CAAC;AAOD,MAAM,UAAU,gBAAgB,CAC9B,IAAoB,EACpB,aAAqC,EACrC,IAA8B;IAE9B,OAAO,OAAO,CAAC,IAAI,EAAE;QACnB,kDAAkD;QAClD,SAAS,EAAE,OAAO;QAClB,YAAY,EAAE,SAAS;QACvB,oBAAoB,EAAE,EAAE;QAExB,OAAO,EAAE,mBAAmB,CAC1B,aAAa,CAAC,SAAS,CAAC,iBAAiB,EACzC,aAAa,CAAC,SAAS,CACxB;QACD,QAAQ,EAAE,WAAW;QACrB,GAAG,IAAI;KACR,CAAC,CAAA;AACJ,CAAC;AAOD,MAAM,UAAU,kBAAkB,CAChC,IAAoB,EACpB,aAAiC,EACjC,IAA8B;IAE9B,OAAO,OAAO,CAAC,IAAI,EAAE;QACnB,kDAAkD;QAClD,WAAW,EAAE,UAAU;QAEvB,OAAO,EAAE,oBAAoB,CAC3B,aAAa,CAAC,SAAS,CAAC,mBAAmB,EAC3C,aAAa,CAAC,OAAO,CACtB;QACD,QAAQ,EAAE,WAAW;QACrB,GAAG,IAAI;KACR,CAAC,CAAA;AACJ,CAAC;AAOD,MAAM,UAAU,eAAe,CAC7B,IAAoB,EACpB,YAAmC,EACnC,IAA8B;IAE9B,OAAO,OAAO,CAAC,IAAI,EAAE;QACnB,kDAAkD;QAClD,SAAS,EAAE,OAAO;QAClB,YAAY,EAAE,SAAS;QACvB,oBAAoB,EAAE,EAAE;QAExB,OAAO,EAAE,iBAAiB,CAAC,YAAY,CAAC,SAAS,CAAC,gBAAgB,EAAE,YAAY,CAAC,SAAS,CAAC;QAC3F,QAAQ,EAAE,WAAW;QACrB,GAAG,IAAI;KACR,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"resolverFunctions.js","sourceRoot":"","sources":["../../lib/resolverFunctions.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "opinionated-machine",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Very opinionated DI framework for fastify, built on top of awilix ",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./package.json": "./package.json"
11
+ },
8
12
  "maintainers": [
9
13
  {
10
14
  "name": "Igor Savin",
@@ -12,7 +16,7 @@
12
16
  }
13
17
  ],
14
18
  "scripts": {
15
- "build": "tsc -p tsconfig.build.json",
19
+ "build": "rimraf dist && tsc -p tsconfig.build.json",
16
20
  "lint": "biome check . && tsc",
17
21
  "lint:fix": "biome check --write .",
18
22
  "test": "vitest --coverage",
@@ -22,6 +26,9 @@
22
26
  "type": "git",
23
27
  "url": "git+https://github.com/kibertoad/opinionated-machine.git"
24
28
  },
29
+ "dependencies": {
30
+ "ts-deepmerge": "^7.0.2"
31
+ },
25
32
  "peerDependencies": {
26
33
  "@lokalise/fastify-api-contracts": ">=1.4.4",
27
34
  "@lokalise/universal-ts-utils": ">=4.2.0",
@@ -44,6 +51,7 @@
44
51
  "fastify": "^5.2.2",
45
52
  "fastify-type-provider-zod": "^4.0.2",
46
53
  "vitest": "^3.0.9",
54
+ "rimraf": "^6.0.1",
47
55
  "typescript": "^5.8.2",
48
56
  "zod": "^3.24.2"
49
57
  },
@@ -1,19 +0,0 @@
1
- import type { FastifyRequest } from 'fastify';
2
- import type { z } from 'zod';
3
- type InferredOptionalSchema<Schema> = Schema extends z.Schema ? z.infer<Schema> : never;
4
- /**
5
- * Infer fastify request type from a contract
6
- */
7
- export type InferRequestFromContract<Contract extends {
8
- requestHeaderSchema?: z.Schema;
9
- requestPathParamsSchema?: z.Schema;
10
- requestQuerySchema?: z.Schema;
11
- successResponseBodySchema: z.Schema;
12
- }> = FastifyRequest<{
13
- Body: never;
14
- Headers: InferredOptionalSchema<Contract['requestHeaderSchema']>;
15
- Params: InferredOptionalSchema<Contract['requestPathParamsSchema']>;
16
- Querystring: InferredOptionalSchema<Contract['requestQuerySchema']>;
17
- Reply: InferredOptionalSchema<Contract['successResponseBodySchema']>;
18
- }>;
19
- export {};
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=typeUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"typeUtils.js","sourceRoot":"","sources":["../../lib/typeUtils.ts"],"names":[],"mappings":""}