@navios/core 0.1.15 → 0.2.1
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/dist/_tsup-dts-rollup.d.mts +96 -425
- package/dist/_tsup-dts-rollup.d.ts +96 -425
- package/dist/index.d.mts +54 -44
- package/dist/index.d.ts +54 -44
- package/dist/index.js +111 -1023
- package/dist/index.mjs +113 -982
- package/package.json +5 -4
- package/src/adapters/endpoint-adapter.service.mts +3 -6
- package/src/adapters/handler-adapter.interface.mts +1 -1
- package/src/adapters/multipart-adapter.service.mts +2 -1
- package/src/adapters/stream-adapter.service.mts +3 -7
- package/src/attribute.factory.mts +1 -1
- package/src/config/config.provider.mts +13 -11
- package/src/decorators/controller.decorator.mts +3 -6
- package/src/decorators/endpoint.decorator.mts +17 -10
- package/src/decorators/module.decorator.mts +3 -6
- package/src/decorators/multipart.decorator.mts +17 -10
- package/src/decorators/stream.decorator.mts +17 -10
- package/src/decorators/use-guards.decorator.mts +3 -2
- package/src/index.mts +1 -1
- package/src/logger/console-logger.service.mts +3 -2
- package/src/logger/logger.factory.mts +4 -5
- package/src/logger/logger.service.mts +2 -1
- package/src/metadata/controller.metadata.mts +3 -2
- package/src/metadata/handler.metadata.mts +1 -4
- package/src/metadata/index.mts +0 -1
- package/src/metadata/module.metadata.mts +3 -2
- package/src/navios.application.mts +9 -8
- package/src/navios.factory.mts +4 -2
- package/src/services/controller-adapter.service.mts +13 -12
- package/src/services/guard-runner.service.mts +4 -6
- package/src/services/module-loader.service.mts +4 -2
- package/src/tokens/application.token.mts +1 -1
- package/src/tokens/execution-context.token.mts +2 -1
- package/src/tokens/reply.token.mts +1 -1
- package/src/tokens/request.token.mts +1 -1
- package/src/metadata/injectable.metadata.mts +0 -11
- package/src/service-locator/__tests__/injectable.spec.mts +0 -171
- package/src/service-locator/__tests__/injection-token.spec.mts +0 -129
- package/src/service-locator/decorators/get-injectable-token.mts +0 -19
- package/src/service-locator/decorators/index.mts +0 -2
- package/src/service-locator/decorators/injectable.decorator.mts +0 -113
- package/src/service-locator/enums/index.mts +0 -1
- package/src/service-locator/enums/injectable-scope.enum.mts +0 -10
- package/src/service-locator/errors/errors.enum.mts +0 -8
- package/src/service-locator/errors/factory-not-found.mts +0 -8
- package/src/service-locator/errors/factory-token-not-resolved.mts +0 -10
- package/src/service-locator/errors/index.mts +0 -7
- package/src/service-locator/errors/instance-destroying.mts +0 -8
- package/src/service-locator/errors/instance-expired.mts +0 -8
- package/src/service-locator/errors/instance-not-found.mts +0 -8
- package/src/service-locator/errors/unknown-error.mts +0 -15
- package/src/service-locator/event-emitter.mts +0 -107
- package/src/service-locator/index.mts +0 -15
- package/src/service-locator/inject.mts +0 -42
- package/src/service-locator/injection-token.mts +0 -92
- package/src/service-locator/injector.mts +0 -18
- package/src/service-locator/interfaces/factory.interface.mts +0 -11
- package/src/service-locator/override.mts +0 -22
- package/src/service-locator/proxy-service-locator.mts +0 -99
- package/src/service-locator/resolve-service.mts +0 -46
- package/src/service-locator/service-locator-abstract-factory-context.mts +0 -23
- package/src/service-locator/service-locator-event-bus.mts +0 -96
- package/src/service-locator/service-locator-instance-holder.mts +0 -63
- package/src/service-locator/service-locator-manager.mts +0 -89
- package/src/service-locator/service-locator.mts +0 -535
- package/src/service-locator/sync-injector.mts +0 -66
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { AnyZodObject, z, ZodOptional } from 'zod'
|
|
2
|
-
|
|
3
|
-
import type { ClassType } from './injection-token.mjs'
|
|
4
|
-
|
|
5
|
-
import { getInjectableToken } from './decorators/index.mjs'
|
|
6
|
-
import { InjectionToken } from './injection-token.mjs'
|
|
7
|
-
import { getServiceLocator } from './injector.mjs'
|
|
8
|
-
|
|
9
|
-
export function inject<T extends ClassType>(token: T): Promise<InstanceType<T>>
|
|
10
|
-
// Not supported by TypeScript yet
|
|
11
|
-
// export function inject<
|
|
12
|
-
// R,
|
|
13
|
-
// T extends ClassType & {
|
|
14
|
-
// [InjectableTokenMeta]: InjectionToken<R, undefined>
|
|
15
|
-
// },
|
|
16
|
-
// >(token: T): Promise<R>
|
|
17
|
-
// export function inject<
|
|
18
|
-
// R,
|
|
19
|
-
// S extends AnyZodObject,
|
|
20
|
-
// T extends ClassType & {
|
|
21
|
-
// [InjectableTokenMeta]: InjectionToken<R, S>
|
|
22
|
-
// },
|
|
23
|
-
// >(token: T, args: z.input<S>): Promise<R>
|
|
24
|
-
export function inject<T, S extends AnyZodObject>(
|
|
25
|
-
token: InjectionToken<T, S>,
|
|
26
|
-
args: z.input<S>,
|
|
27
|
-
): Promise<T>
|
|
28
|
-
export function inject<T, S extends ZodOptional<AnyZodObject>>(
|
|
29
|
-
token: InjectionToken<T, S>,
|
|
30
|
-
args?: z.input<S>,
|
|
31
|
-
): Promise<T>
|
|
32
|
-
|
|
33
|
-
export function inject<T>(token: InjectionToken<T, undefined>): Promise<T>
|
|
34
|
-
export function inject(token: InjectionToken<any>, args?: unknown) {
|
|
35
|
-
let realToken = token
|
|
36
|
-
if (!(token instanceof InjectionToken)) {
|
|
37
|
-
realToken = getInjectableToken(token)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// @ts-expect-error We chek the type in overload
|
|
41
|
-
return getServiceLocator().getOrThrowInstance(realToken, args)
|
|
42
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import type { AnyZodObject } from 'zod'
|
|
2
|
-
|
|
3
|
-
import { randomUUID } from 'crypto'
|
|
4
|
-
|
|
5
|
-
import { z, ZodOptional } from 'zod'
|
|
6
|
-
|
|
7
|
-
export type ClassType = new (...args: any[]) => any
|
|
8
|
-
|
|
9
|
-
export type ClassTypeWithInstance<T> = new (...args: any[]) => T
|
|
10
|
-
|
|
11
|
-
export class InjectionToken<
|
|
12
|
-
T,
|
|
13
|
-
S extends AnyZodObject | ZodOptional<AnyZodObject> | unknown = unknown,
|
|
14
|
-
> {
|
|
15
|
-
public id = randomUUID()
|
|
16
|
-
constructor(
|
|
17
|
-
public readonly name: string | symbol | ClassType,
|
|
18
|
-
public readonly schema: AnyZodObject | undefined,
|
|
19
|
-
) {}
|
|
20
|
-
|
|
21
|
-
static create<T extends ClassType>(
|
|
22
|
-
name: T,
|
|
23
|
-
): InjectionToken<InstanceType<T>, undefined>
|
|
24
|
-
static create<
|
|
25
|
-
T extends ClassType,
|
|
26
|
-
Schema extends AnyZodObject | ZodOptional<AnyZodObject>,
|
|
27
|
-
>(name: T, schema: Schema): InjectionToken<InstanceType<T>, Schema>
|
|
28
|
-
static create<T>(name: string | symbol): InjectionToken<T, undefined>
|
|
29
|
-
static create<T, Schema extends AnyZodObject | ZodOptional<AnyZodObject>>(
|
|
30
|
-
name: string | any,
|
|
31
|
-
schema: Schema,
|
|
32
|
-
): InjectionToken<T, Schema>
|
|
33
|
-
static create(name: string | symbol, schema?: unknown) {
|
|
34
|
-
// @ts-expect-error
|
|
35
|
-
return new InjectionToken(name, schema)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
static bound<T, S extends AnyZodObject | ZodOptional<AnyZodObject>>(
|
|
39
|
-
token: InjectionToken<T, S>,
|
|
40
|
-
value: z.input<S>,
|
|
41
|
-
): BoundInjectionToken<T, S> {
|
|
42
|
-
return new BoundInjectionToken(token, value)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static factory<T, S extends AnyZodObject | ZodOptional<AnyZodObject>>(
|
|
46
|
-
token: InjectionToken<T, S>,
|
|
47
|
-
factory: () => Promise<z.input<S>>,
|
|
48
|
-
): FactoryInjectionToken<T, S> {
|
|
49
|
-
return new FactoryInjectionToken(token, factory)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
static refineType<T>(
|
|
53
|
-
token: BoundInjectionToken<any, any>,
|
|
54
|
-
): BoundInjectionToken<T, any> {
|
|
55
|
-
return token as BoundInjectionToken<T, any>
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export class BoundInjectionToken<
|
|
60
|
-
T,
|
|
61
|
-
S extends AnyZodObject | ZodOptional<AnyZodObject>,
|
|
62
|
-
> extends InjectionToken<T, undefined> {
|
|
63
|
-
constructor(
|
|
64
|
-
public readonly token: InjectionToken<T, S>,
|
|
65
|
-
public readonly value: z.input<S>,
|
|
66
|
-
) {
|
|
67
|
-
super(token.name, token.schema)
|
|
68
|
-
this.id = token.id
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export class FactoryInjectionToken<
|
|
73
|
-
T,
|
|
74
|
-
S extends AnyZodObject | ZodOptional<AnyZodObject>,
|
|
75
|
-
> extends InjectionToken<T, S> {
|
|
76
|
-
public value?: z.input<S>
|
|
77
|
-
public resolved = false
|
|
78
|
-
constructor(
|
|
79
|
-
public readonly token: InjectionToken<T, S>,
|
|
80
|
-
public readonly factory: () => Promise<z.input<S>>,
|
|
81
|
-
) {
|
|
82
|
-
super(token.name, token.schema)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async resolve(): Promise<z.input<S>> {
|
|
86
|
-
if (!this.value) {
|
|
87
|
-
this.value = await this.factory()
|
|
88
|
-
this.resolved = true
|
|
89
|
-
}
|
|
90
|
-
return this.value
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { ServiceLocator } from './service-locator.mjs'
|
|
2
|
-
|
|
3
|
-
let serviceLocator: ServiceLocator = new ServiceLocator()
|
|
4
|
-
|
|
5
|
-
export function provideServiceLocator(locator: ServiceLocator): ServiceLocator {
|
|
6
|
-
const original = serviceLocator
|
|
7
|
-
serviceLocator = locator
|
|
8
|
-
return original
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function getServiceLocator(): ServiceLocator {
|
|
12
|
-
if (!serviceLocator) {
|
|
13
|
-
throw new Error(
|
|
14
|
-
'[ServiceLocator] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator.',
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
return serviceLocator
|
|
18
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { AnyZodObject } from 'zod'
|
|
2
|
-
|
|
3
|
-
import { z } from 'zod'
|
|
4
|
-
|
|
5
|
-
export interface Factory<T> {
|
|
6
|
-
create(ctx?: any): Promise<T> | T
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface FactoryWithArgs<T, A extends AnyZodObject> {
|
|
10
|
-
create(ctx: any, args: z.output<A>): Promise<T> | T
|
|
11
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { ClassType, InjectionToken } from './injection-token.mjs'
|
|
2
|
-
|
|
3
|
-
import { getServiceLocator } from './injector.mjs'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Useful for tests or when you want to override a service
|
|
7
|
-
* with a different implementation.
|
|
8
|
-
*/
|
|
9
|
-
export function override<T>(token: InjectionToken<T>, target: ClassType) {
|
|
10
|
-
const serviceLocator = getServiceLocator()
|
|
11
|
-
const originalDefinition = serviceLocator['abstractFactories'].get(token)
|
|
12
|
-
serviceLocator.registerAbstractFactory(token, async (ctx, args: any) => {
|
|
13
|
-
const builder = new target()
|
|
14
|
-
return builder.create(ctx, args)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
return () => {
|
|
18
|
-
if (originalDefinition) {
|
|
19
|
-
serviceLocator.registerAbstractFactory(token, originalDefinition)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import type { AnyZodObject, output, z, ZodOptional } from 'zod'
|
|
2
|
-
|
|
3
|
-
import type { FactoryNotFound, UnknownError } from './index.mjs'
|
|
4
|
-
import type { InjectionToken } from './injection-token.mjs'
|
|
5
|
-
import type { ServiceLocatorAbstractFactoryContext } from './service-locator-abstract-factory-context.mjs'
|
|
6
|
-
import type { ServiceLocatorEventBus } from './service-locator-event-bus.mjs'
|
|
7
|
-
import type { ServiceLocator } from './service-locator.mjs'
|
|
8
|
-
|
|
9
|
-
// @ts-expect-error We don't need all the properties of the class
|
|
10
|
-
export class ProxyServiceLocator implements ServiceLocator {
|
|
11
|
-
constructor(
|
|
12
|
-
private readonly serviceLocator: ServiceLocator,
|
|
13
|
-
private readonly ctx: ServiceLocatorAbstractFactoryContext,
|
|
14
|
-
) {}
|
|
15
|
-
get abstractFactories(): Map<
|
|
16
|
-
InjectionToken<any, any>,
|
|
17
|
-
(ctx: ServiceLocatorAbstractFactoryContext, args: any) => Promise<any>
|
|
18
|
-
> {
|
|
19
|
-
return this.serviceLocator['abstractFactories']
|
|
20
|
-
}
|
|
21
|
-
getEventBus(): ServiceLocatorEventBus {
|
|
22
|
-
return this.serviceLocator.getEventBus()
|
|
23
|
-
}
|
|
24
|
-
public registerAbstractFactory<
|
|
25
|
-
Instance,
|
|
26
|
-
Schema extends AnyZodObject | undefined,
|
|
27
|
-
>(
|
|
28
|
-
token: InjectionToken<Instance, Schema>,
|
|
29
|
-
factory: (
|
|
30
|
-
ctx: ServiceLocatorAbstractFactoryContext,
|
|
31
|
-
values: Schema extends AnyZodObject ? output<Schema> : undefined,
|
|
32
|
-
) => Promise<Instance>,
|
|
33
|
-
): void {
|
|
34
|
-
return this.serviceLocator.registerAbstractFactory(token, factory)
|
|
35
|
-
}
|
|
36
|
-
public getInstance<
|
|
37
|
-
Instance,
|
|
38
|
-
Schema extends AnyZodObject | ZodOptional<AnyZodObject> | undefined,
|
|
39
|
-
>(
|
|
40
|
-
token: InjectionToken<Instance, Schema>,
|
|
41
|
-
args: Schema extends AnyZodObject
|
|
42
|
-
? z.input<Schema>
|
|
43
|
-
: Schema extends ZodOptional<AnyZodObject>
|
|
44
|
-
? z.input<Schema> | undefined
|
|
45
|
-
: undefined,
|
|
46
|
-
): Promise<[undefined, Instance] | [UnknownError | FactoryNotFound]> {
|
|
47
|
-
return this.ctx.inject(token, args).then(
|
|
48
|
-
(instance) => {
|
|
49
|
-
return [undefined, instance]
|
|
50
|
-
},
|
|
51
|
-
(error) => {
|
|
52
|
-
return [error]
|
|
53
|
-
},
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
public getOrThrowInstance<
|
|
57
|
-
Instance,
|
|
58
|
-
Schema extends AnyZodObject | ZodOptional<AnyZodObject> | undefined,
|
|
59
|
-
>(
|
|
60
|
-
token: InjectionToken<Instance, Schema>,
|
|
61
|
-
args: Schema extends AnyZodObject
|
|
62
|
-
? z.input<Schema>
|
|
63
|
-
: Schema extends ZodOptional<AnyZodObject>
|
|
64
|
-
? z.input<Schema> | undefined
|
|
65
|
-
: undefined,
|
|
66
|
-
): Promise<Instance> {
|
|
67
|
-
return this.ctx.inject(token, args)
|
|
68
|
-
}
|
|
69
|
-
public getSyncInstance<
|
|
70
|
-
Instance,
|
|
71
|
-
Schema extends AnyZodObject | ZodOptional<AnyZodObject> | undefined,
|
|
72
|
-
>(
|
|
73
|
-
token: InjectionToken<Instance, Schema>,
|
|
74
|
-
args: Schema extends AnyZodObject
|
|
75
|
-
? z.input<Schema>
|
|
76
|
-
: Schema extends ZodOptional<AnyZodObject>
|
|
77
|
-
? z.input<Schema> | undefined
|
|
78
|
-
: undefined,
|
|
79
|
-
): Instance | null {
|
|
80
|
-
return this.serviceLocator.getSyncInstance(token, args)
|
|
81
|
-
}
|
|
82
|
-
invalidate(service: string, round?: number): Promise<any> {
|
|
83
|
-
return this.serviceLocator.invalidate(service, round)
|
|
84
|
-
}
|
|
85
|
-
ready(): Promise<null> {
|
|
86
|
-
return this.serviceLocator.ready()
|
|
87
|
-
}
|
|
88
|
-
makeInstanceName(token: InjectionToken<any, any>, args: any): string {
|
|
89
|
-
return this.serviceLocator.makeInstanceName(token, args)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function makeProxyServiceLocator(
|
|
94
|
-
serviceLocator: ServiceLocator,
|
|
95
|
-
ctx: ServiceLocatorAbstractFactoryContext,
|
|
96
|
-
): ServiceLocator {
|
|
97
|
-
// @ts-expect-error We don't need all the properties of the class
|
|
98
|
-
return new ProxyServiceLocator(serviceLocator, ctx)
|
|
99
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { NaviosException } from '@navios/common'
|
|
2
|
-
|
|
3
|
-
import type { ClassType } from './injection-token.mjs'
|
|
4
|
-
import type { ServiceLocatorAbstractFactoryContext } from './service-locator-abstract-factory-context.mjs'
|
|
5
|
-
|
|
6
|
-
import { getServiceLocator, provideServiceLocator } from './injector.mjs'
|
|
7
|
-
import { makeProxyServiceLocator } from './proxy-service-locator.mjs'
|
|
8
|
-
import { setPromiseCollector } from './sync-injector.mjs'
|
|
9
|
-
|
|
10
|
-
export async function resolveService<T extends ClassType>(
|
|
11
|
-
ctx: ServiceLocatorAbstractFactoryContext,
|
|
12
|
-
target: T,
|
|
13
|
-
args: any[] = [],
|
|
14
|
-
): Promise<InstanceType<T>> {
|
|
15
|
-
const proxyServiceLocator = makeProxyServiceLocator(getServiceLocator(), ctx)
|
|
16
|
-
let promises: Promise<any>[] = []
|
|
17
|
-
const promiseCollector = (promise: Promise<any>) => {
|
|
18
|
-
promises.push(promise)
|
|
19
|
-
}
|
|
20
|
-
const originalPromiseCollector = setPromiseCollector(promiseCollector)
|
|
21
|
-
const tryLoad = () => {
|
|
22
|
-
const original = provideServiceLocator(proxyServiceLocator)
|
|
23
|
-
let result = new target(...args)
|
|
24
|
-
provideServiceLocator(original)
|
|
25
|
-
return result
|
|
26
|
-
}
|
|
27
|
-
let instance = tryLoad()
|
|
28
|
-
setPromiseCollector(originalPromiseCollector)
|
|
29
|
-
if (promises.length > 0) {
|
|
30
|
-
await Promise.all(promises)
|
|
31
|
-
promises = []
|
|
32
|
-
instance = tryLoad()
|
|
33
|
-
}
|
|
34
|
-
if (promises.length > 0) {
|
|
35
|
-
console.error(`[ServiceLocator] ${target.name} has problem with it's definition.
|
|
36
|
-
|
|
37
|
-
One or more of the dependencies are registered as a InjectableScope.Instance and are used with syncInject.
|
|
38
|
-
|
|
39
|
-
Please use inject instead of syncInject to load those dependencies.`)
|
|
40
|
-
throw new NaviosException(
|
|
41
|
-
`[ServiceLocator] Service ${target.name} cannot be instantiated.`,
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return instance
|
|
46
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
-
import type { AnyZodObject, z } from 'zod'
|
|
3
|
-
|
|
4
|
-
import type { inject } from './inject.mjs'
|
|
5
|
-
import type { InjectionToken } from './injection-token.mjs'
|
|
6
|
-
import type { ServiceLocatorEventBus } from './service-locator-event-bus.mjs'
|
|
7
|
-
|
|
8
|
-
export interface ServiceLocatorAbstractFactoryContext {
|
|
9
|
-
inject: typeof inject
|
|
10
|
-
addDependency:
|
|
11
|
-
| ((token: InjectionToken<any, undefined>) => void)
|
|
12
|
-
| (<S extends AnyZodObject>(
|
|
13
|
-
token: InjectionToken<any, S>,
|
|
14
|
-
args: z.input<S>,
|
|
15
|
-
) => void)
|
|
16
|
-
on: ServiceLocatorEventBus['on']
|
|
17
|
-
getDependencies: () => string[]
|
|
18
|
-
invalidate: () => void
|
|
19
|
-
addEffect: (listener: () => void) => void
|
|
20
|
-
getDestroyListeners: () => (() => void)[]
|
|
21
|
-
setTtl: (ttl: number) => void
|
|
22
|
-
getTtl: () => number
|
|
23
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
|
3
|
-
|
|
4
|
-
type ListenersMap = Map<string, Map<string, Set<Function>>>
|
|
5
|
-
|
|
6
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
7
|
-
export class ServiceLocatorEventBus {
|
|
8
|
-
private listeners: ListenersMap = new Map()
|
|
9
|
-
constructor(private readonly logger: Console | null = null) {}
|
|
10
|
-
|
|
11
|
-
on<Event extends string | `pre:${string}` | `post:${string}`>(
|
|
12
|
-
ns: string,
|
|
13
|
-
event: Event,
|
|
14
|
-
listener: (event: Event) => void,
|
|
15
|
-
) {
|
|
16
|
-
this.logger?.debug(`[ServiceLocatorEventBus]#on(): ns:${ns} event:${event}`)
|
|
17
|
-
if (!this.listeners.has(ns)) {
|
|
18
|
-
this.listeners.set(ns, new Map())
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const nsEvents = this.listeners.get(ns)!
|
|
22
|
-
if (!nsEvents.has(event)) {
|
|
23
|
-
nsEvents.set(event, new Set())
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
nsEvents.get(event)!.add(listener)
|
|
27
|
-
|
|
28
|
-
return () => {
|
|
29
|
-
nsEvents.get(event)!.delete(listener)
|
|
30
|
-
if (nsEvents.get(event)?.size === 0) {
|
|
31
|
-
nsEvents.delete(event)
|
|
32
|
-
}
|
|
33
|
-
if (nsEvents.size === 0) {
|
|
34
|
-
this.listeners.delete(ns)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async emit(key: string, event: string) {
|
|
40
|
-
if (!this.listeners.has(key)) {
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const events = this.listeners.get(key)!
|
|
45
|
-
|
|
46
|
-
const preEvent = `pre:${event}`
|
|
47
|
-
const postEvent = `post:${event}`
|
|
48
|
-
this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent}`)
|
|
49
|
-
await Promise.allSettled(
|
|
50
|
-
[...(events.get(preEvent) ?? [])].map((listener) => listener(preEvent)),
|
|
51
|
-
).then((results) => {
|
|
52
|
-
results
|
|
53
|
-
.filter((result) => result.status === 'rejected')
|
|
54
|
-
.forEach((result: PromiseRejectedResult) => {
|
|
55
|
-
this.logger?.warn(
|
|
56
|
-
`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent} rejected with`,
|
|
57
|
-
result.reason,
|
|
58
|
-
)
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${event}`)
|
|
62
|
-
|
|
63
|
-
const res = await Promise.allSettled(
|
|
64
|
-
[...(events.get(event) ?? [])!].map((listener) => listener(event)),
|
|
65
|
-
).then((results) => {
|
|
66
|
-
const res = results
|
|
67
|
-
.filter((result) => result.status === 'rejected')
|
|
68
|
-
.map((result: PromiseRejectedResult) => {
|
|
69
|
-
this.logger?.warn(
|
|
70
|
-
`[ServiceLocatorEventBus]#emit(): ${key}:${event} rejected with`,
|
|
71
|
-
result.reason,
|
|
72
|
-
)
|
|
73
|
-
return result
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
if (res.length > 0) {
|
|
77
|
-
return Promise.reject(res)
|
|
78
|
-
}
|
|
79
|
-
return results
|
|
80
|
-
})
|
|
81
|
-
this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent}`)
|
|
82
|
-
await Promise.allSettled(
|
|
83
|
-
[...(events.get(postEvent) ?? [])].map((listener) => listener(postEvent)),
|
|
84
|
-
).then((results) => {
|
|
85
|
-
results
|
|
86
|
-
.filter((result) => result.status === 'rejected')
|
|
87
|
-
.forEach((result: PromiseRejectedResult) => {
|
|
88
|
-
this.logger?.warn(
|
|
89
|
-
`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent} rejected with`,
|
|
90
|
-
result.reason,
|
|
91
|
-
)
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
return res
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
-
|
|
3
|
-
export enum ServiceLocatorInstanceHolderKind {
|
|
4
|
-
Instance = 'instance',
|
|
5
|
-
Factory = 'factory',
|
|
6
|
-
AbstractFactory = 'abstractFactory',
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export enum ServiceLocatorInstanceHolderStatus {
|
|
10
|
-
Created = 'created',
|
|
11
|
-
Creating = 'creating',
|
|
12
|
-
Destroying = 'destroying',
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type ServiceLocatorInstanceEffect = () => void
|
|
16
|
-
export type ServiceLocatorInstanceDestroyListener = () => void | Promise<void>
|
|
17
|
-
|
|
18
|
-
export interface ServiceLocatorInstanceHolderCreating<Instance> {
|
|
19
|
-
status: ServiceLocatorInstanceHolderStatus.Creating
|
|
20
|
-
name: string
|
|
21
|
-
instance: null
|
|
22
|
-
creationPromise: Promise<[undefined, Instance]> | null
|
|
23
|
-
destroyPromise: null
|
|
24
|
-
kind: ServiceLocatorInstanceHolderKind
|
|
25
|
-
effects: ServiceLocatorInstanceEffect[]
|
|
26
|
-
deps: string[]
|
|
27
|
-
destroyListeners: ServiceLocatorInstanceDestroyListener[]
|
|
28
|
-
createdAt: number
|
|
29
|
-
ttl: number
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface ServiceLocatorInstanceHolderCreated<Instance> {
|
|
33
|
-
status: ServiceLocatorInstanceHolderStatus.Created
|
|
34
|
-
name: string
|
|
35
|
-
instance: Instance
|
|
36
|
-
creationPromise: null
|
|
37
|
-
destroyPromise: null
|
|
38
|
-
kind: ServiceLocatorInstanceHolderKind
|
|
39
|
-
effects: ServiceLocatorInstanceEffect[]
|
|
40
|
-
deps: string[]
|
|
41
|
-
destroyListeners: ServiceLocatorInstanceDestroyListener[]
|
|
42
|
-
createdAt: number
|
|
43
|
-
ttl: number
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface ServiceLocatorInstanceHolderDestroying<Instance> {
|
|
47
|
-
status: ServiceLocatorInstanceHolderStatus.Destroying
|
|
48
|
-
name: string
|
|
49
|
-
instance: Instance | null
|
|
50
|
-
creationPromise: null
|
|
51
|
-
destroyPromise: Promise<void>
|
|
52
|
-
kind: ServiceLocatorInstanceHolderKind
|
|
53
|
-
effects: ServiceLocatorInstanceEffect[]
|
|
54
|
-
deps: string[]
|
|
55
|
-
destroyListeners: ServiceLocatorInstanceDestroyListener[]
|
|
56
|
-
createdAt: number
|
|
57
|
-
ttl: number
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export type ServiceLocatorInstanceHolder<Instance = unknown> =
|
|
61
|
-
| ServiceLocatorInstanceHolderCreating<Instance>
|
|
62
|
-
| ServiceLocatorInstanceHolderCreated<Instance>
|
|
63
|
-
| ServiceLocatorInstanceHolderDestroying<Instance>
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
-
import type { ServiceLocatorInstanceHolder } from './service-locator-instance-holder.mjs'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
ErrorsEnum,
|
|
6
|
-
InstanceDestroying,
|
|
7
|
-
InstanceExpired,
|
|
8
|
-
InstanceNotFound,
|
|
9
|
-
} from './errors/index.mjs'
|
|
10
|
-
import { ServiceLocatorInstanceHolderStatus } from './service-locator-instance-holder.mjs'
|
|
11
|
-
|
|
12
|
-
export class ServiceLocatorManager {
|
|
13
|
-
private readonly instancesHolders: Map<string, ServiceLocatorInstanceHolder> =
|
|
14
|
-
new Map()
|
|
15
|
-
|
|
16
|
-
constructor(private readonly logger: Console | null = null) {}
|
|
17
|
-
|
|
18
|
-
get(
|
|
19
|
-
name: string,
|
|
20
|
-
):
|
|
21
|
-
| [InstanceExpired | InstanceDestroying, ServiceLocatorInstanceHolder]
|
|
22
|
-
| [InstanceNotFound]
|
|
23
|
-
| [undefined, ServiceLocatorInstanceHolder] {
|
|
24
|
-
const holder = this.instancesHolders.get(name)
|
|
25
|
-
if (holder) {
|
|
26
|
-
if (holder.ttl !== Infinity) {
|
|
27
|
-
const now = Date.now()
|
|
28
|
-
if (now - holder.createdAt > holder.ttl) {
|
|
29
|
-
this.logger?.log(
|
|
30
|
-
`[ServiceLocatorManager]#getInstanceHolder() TTL expired for ${holder.name}`,
|
|
31
|
-
)
|
|
32
|
-
return [new InstanceExpired(holder.name), holder]
|
|
33
|
-
}
|
|
34
|
-
} else if (
|
|
35
|
-
holder.status === ServiceLocatorInstanceHolderStatus.Destroying
|
|
36
|
-
) {
|
|
37
|
-
this.logger?.log(
|
|
38
|
-
`[ServiceLocatorManager]#getInstanceHolder() Instance ${holder.name} is destroying`,
|
|
39
|
-
)
|
|
40
|
-
return [new InstanceDestroying(holder.name), holder]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return [undefined, holder]
|
|
44
|
-
} else {
|
|
45
|
-
this.logger?.log(
|
|
46
|
-
`[ServiceLocatorManager]#getInstanceHolder() Instance ${name} not found`,
|
|
47
|
-
)
|
|
48
|
-
return [new InstanceNotFound(name)]
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
set(name: string, holder: ServiceLocatorInstanceHolder): void {
|
|
53
|
-
this.instancesHolders.set(name, holder)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
has(
|
|
57
|
-
name: string,
|
|
58
|
-
): [InstanceExpired | InstanceDestroying] | [undefined, boolean] {
|
|
59
|
-
const [error, holder] = this.get(name)
|
|
60
|
-
if (!error) {
|
|
61
|
-
return [undefined, true]
|
|
62
|
-
}
|
|
63
|
-
if (
|
|
64
|
-
[ErrorsEnum.InstanceExpired, ErrorsEnum.InstanceDestroying].includes(
|
|
65
|
-
error.code,
|
|
66
|
-
)
|
|
67
|
-
) {
|
|
68
|
-
return [error]
|
|
69
|
-
}
|
|
70
|
-
return [undefined, !!holder]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
delete(name: string): boolean {
|
|
74
|
-
return this.instancesHolders.delete(name)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
filter(
|
|
78
|
-
predicate: (
|
|
79
|
-
value: ServiceLocatorInstanceHolder<any>,
|
|
80
|
-
key: string,
|
|
81
|
-
) => boolean,
|
|
82
|
-
): Map<string, ServiceLocatorInstanceHolder> {
|
|
83
|
-
return new Map(
|
|
84
|
-
[...this.instancesHolders].filter(([key, value]) =>
|
|
85
|
-
predicate(value, key),
|
|
86
|
-
),
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
}
|