@navios/di 0.1.12 → 0.2.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.
@@ -1,5 +1,5 @@
1
1
  import { expectTypeOf, test } from 'vitest'
2
- import { z } from 'zod'
2
+ import { z } from 'zod/v4'
3
3
 
4
4
  import { Injectable } from '../decorators/index.mjs'
5
5
  import { InjectableType } from '../enums/index.mjs'
@@ -17,8 +17,8 @@ const simpleOptionalObjectSchema = z
17
17
  foo: z.string(),
18
18
  })
19
19
  .optional()
20
- const simpleRecordSchema = z.record(z.string())
21
- const simpleOptionalRecordSchema = z.record(z.string()).optional()
20
+ const simpleRecordSchema = z.record(z.string(), z.string())
21
+ const simpleOptionalRecordSchema = z.record(z.string(), z.string()).optional()
22
22
 
23
23
  const typelessObjectToken = InjectionToken.create(
24
24
  Symbol.for('Typeless object token'),
@@ -286,4 +286,259 @@ test('Injectable types', () => {
286
286
  }
287
287
  },
288
288
  )
289
+
290
+ // #1 Injectable w/o decorators enabled in project
291
+ expectTypeOf(
292
+ Injectable({
293
+ token: typedObjectToken,
294
+ })(
295
+ class {
296
+ constructor() {}
297
+ makeFoo() {
298
+ return 'foo'
299
+ }
300
+ },
301
+ ),
302
+ ).toBeConstructibleWith()
303
+ expectTypeOf(
304
+ Injectable({
305
+ type: InjectableType.Factory,
306
+ })(
307
+ class {
308
+ create() {}
309
+ },
310
+ ),
311
+ ).toBeConstructibleWith()
312
+ expectTypeOf(
313
+ Injectable({
314
+ type: InjectableType.Factory,
315
+ })(
316
+ // @ts-expect-error should check that the class implements the factory
317
+ class {},
318
+ ),
319
+ ).toBeConstructibleWith()
320
+
321
+ // #3 required argument
322
+ expectTypeOf(
323
+ Injectable({
324
+ token: typelessObjectToken,
325
+ })(
326
+ class {
327
+ constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
328
+ },
329
+ ),
330
+ ).toBeConstructibleWith({
331
+ foo: 'something',
332
+ })
333
+ // #3 it's required in token but optional in class allowed
334
+ expectTypeOf(
335
+ Injectable({
336
+ token: typelessObjectToken,
337
+ })(
338
+ class {
339
+ constructor(public arg?: z.infer<typeof simpleObjectSchema>) {}
340
+ },
341
+ ),
342
+ ).toBeConstructibleWith({
343
+ foo: 'something',
344
+ })
345
+ // #3 optional value but class accepts it
346
+ expectTypeOf(
347
+ Injectable({
348
+ token: typelessOptionalObjectToken,
349
+ })(
350
+ class {
351
+ constructor(public arg: z.infer<typeof simpleOptionalObjectSchema>) {}
352
+ },
353
+ ),
354
+ ).toBeConstructibleWith({
355
+ foo: 'something',
356
+ })
357
+ // #3 optional value and class accepts it
358
+ expectTypeOf(
359
+ Injectable({
360
+ token: typelessOptionalObjectToken,
361
+ })(
362
+ class {
363
+ constructor(public arg: z.infer<typeof simpleOptionalObjectSchema>) {}
364
+ },
365
+ ),
366
+ ).toBeConstructibleWith(undefined)
367
+ // #3 compatible schemas
368
+ expectTypeOf(
369
+ Injectable({
370
+ token: typelessOptionalObjectToken,
371
+ })(
372
+ class {
373
+ constructor(public arg?: z.infer<typeof simpleObjectSchema>) {}
374
+ },
375
+ ),
376
+ ).toBeConstructibleWith(undefined)
377
+ // #3 compatible schemas
378
+ expectTypeOf(
379
+ Injectable({
380
+ token: typelessOptionalObjectToken,
381
+ })(
382
+ // @ts-expect-error token has optional schema, but Class has required, should fail
383
+ class {
384
+ constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
385
+ },
386
+ ),
387
+ ).toBeConstructibleWith({
388
+ foo: 'something',
389
+ })
390
+
391
+ // #3 typed token and required argument
392
+ expectTypeOf(
393
+ Injectable({
394
+ token: typedObjectToken,
395
+ })(
396
+ class {
397
+ constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
398
+
399
+ makeFoo() {
400
+ return this.arg.foo
401
+ }
402
+ },
403
+ ),
404
+ ).toBeConstructibleWith({
405
+ foo: 'something',
406
+ })
407
+ // #3 typed token and required argument
408
+ expectTypeOf(
409
+ Injectable({
410
+ token: typedOptionalObjectToken,
411
+ })(
412
+ class {
413
+ constructor(public arg?: z.infer<typeof simpleObjectSchema>) {}
414
+
415
+ makeFoo() {
416
+ return this.arg?.foo ?? 'default'
417
+ }
418
+ },
419
+ ),
420
+ ).toBeConstructibleWith({
421
+ foo: 'something',
422
+ })
423
+ // #3 should fail if not compatible
424
+ expectTypeOf(
425
+ Injectable({
426
+ token: typedOptionalObjectToken,
427
+ })(
428
+ // @ts-expect-error class doesn't implement the token type
429
+ class {
430
+ constructor(public arg?: z.infer<typeof simpleObjectSchema>) {}
431
+ },
432
+ ),
433
+ ).toBeConstructibleWith({
434
+ foo: 'something',
435
+ })
436
+ // #3 should fail if not compatible
437
+ expectTypeOf(
438
+ Injectable({
439
+ token: typedOptionalObjectToken,
440
+ })(
441
+ // @ts-expect-error class doesn't implement the token type
442
+ class {
443
+ constructor(public arg?: z.infer<typeof simpleObjectSchema>) {}
444
+
445
+ makeFoo() {
446
+ return this.arg?.foo
447
+ }
448
+ },
449
+ ),
450
+ ).toBeConstructibleWith({
451
+ foo: 'something',
452
+ })
453
+ // #3 typed token without schema
454
+ expectTypeOf(
455
+ Injectable({
456
+ token: typedToken,
457
+ })(
458
+ class {
459
+ constructor() {}
460
+ makeFoo() {
461
+ return 'foo'
462
+ }
463
+ },
464
+ ),
465
+ ).toBeConstructibleWith()
466
+ // #3 typed token without schema fail if not compatible
467
+ expectTypeOf(
468
+ Injectable({
469
+ token: typedToken,
470
+ })(
471
+ // @ts-expect-error class doesn't implement the token type
472
+ class {
473
+ constructor() {}
474
+ },
475
+ ),
476
+ ).toBeConstructibleWith()
477
+
478
+ // #4 factory with typed token
479
+ expectTypeOf(
480
+ Injectable({
481
+ type: InjectableType.Factory,
482
+ token: typedToken,
483
+ })(
484
+ class {
485
+ constructor() {}
486
+ create() {
487
+ return {
488
+ makeFoo: () => 'foo',
489
+ }
490
+ }
491
+ },
492
+ ),
493
+ ).toBeConstructibleWith()
494
+ // #4 factory with typed token without schema should fail if not compatible
495
+ expectTypeOf(
496
+ Injectable({
497
+ type: InjectableType.Factory,
498
+ token: typedToken,
499
+ })(
500
+ // @ts-expect-error factory doesn't implement the token type
501
+ class {
502
+ constructor() {}
503
+ create(ctx: any, arg: z.infer<typeof simpleObjectSchema>) {
504
+ return {
505
+ makeFoo: () => 'foo',
506
+ }
507
+ }
508
+ },
509
+ ),
510
+ ).toBeConstructibleWith()
511
+ // #4 factory with typed token fail if not compatible
512
+ expectTypeOf(
513
+ Injectable({
514
+ type: InjectableType.Factory,
515
+ token: typedToken,
516
+ })(
517
+ // @ts-expect-error class doesn't implement the token type
518
+ class {
519
+ constructor() {}
520
+ create() {
521
+ return {
522
+ // makeFoo: () => 'foo',
523
+ }
524
+ }
525
+ },
526
+ ),
527
+ ).toBeConstructibleWith()
528
+ // #4 factory with typed token and schema
529
+ expectTypeOf(
530
+ Injectable({
531
+ type: InjectableType.Factory,
532
+ token: typedObjectToken,
533
+ })(
534
+ class {
535
+ constructor() {}
536
+ create(ctx: any, arg: z.infer<typeof simpleObjectSchema>) {
537
+ return {
538
+ makeFoo: () => 'foo',
539
+ }
540
+ }
541
+ },
542
+ ),
543
+ )
289
544
  })
@@ -1,4 +1,4 @@
1
- import { z } from 'zod'
1
+ import { z } from 'zod/v4'
2
2
 
3
3
  import type {
4
4
  BaseInjectionTokenSchemaType,
@@ -29,11 +29,11 @@ export interface InjectableOptions {
29
29
  // #1 Simple constructorless class
30
30
  export function Injectable(): <T extends ClassType>(
31
31
  target: T,
32
- context: ClassDecoratorContext,
32
+ context?: ClassDecoratorContext,
33
33
  ) => T
34
34
  export function Injectable(options: {
35
35
  registry: Registry
36
- }): <T extends ClassType>(target: T, context: ClassDecoratorContext) => T
36
+ }): <T extends ClassType>(target: T, context?: ClassDecoratorContext) => T
37
37
 
38
38
  // #2 Factory without arguments
39
39
  export function Injectable<R>(options: {
@@ -42,7 +42,7 @@ export function Injectable<R>(options: {
42
42
  registry?: Registry
43
43
  }): <T extends ClassTypeWithInstance<Factory<R>>>(
44
44
  target: T,
45
- context: ClassDecoratorContext,
45
+ context?: ClassDecoratorContext,
46
46
  ) => T
47
47
 
48
48
  // #3 Class with typeless token and schema
@@ -55,17 +55,17 @@ export function Injectable<Type, Schema>(options: {
55
55
  ? Type extends undefined
56
56
  ? <T extends ClassTypeWithArgument<z.output<Schema>>>( // #3.1.1 Typeless token
57
57
  target: T,
58
- context: ClassDecoratorContext,
58
+ context?: ClassDecoratorContext,
59
59
  ) => T
60
60
  : <T extends ClassTypeWithInstanceAndArgument<Type, z.output<Schema>>>( // #3.1.2 Typed token
61
61
  target: T,
62
- context: ClassDecoratorContext,
62
+ context?: ClassDecoratorContext,
63
63
  ) => T
64
64
  : Schema extends OptionalInjectionTokenSchemaType // #3.2 Check that schema is an optional object or a record
65
65
  ? Type extends undefined
66
66
  ? <T extends ClassTypeWithOptionalArgument<z.output<Schema>>>( // #3.2.1 Typeless token
67
67
  target: T,
68
- context: ClassDecoratorContext,
68
+ context?: ClassDecoratorContext,
69
69
  ) => T
70
70
  : <
71
71
  // #3.2.2 Typed token
@@ -75,12 +75,12 @@ export function Injectable<Type, Schema>(options: {
75
75
  >,
76
76
  >(
77
77
  target: T,
78
- context: ClassDecoratorContext,
78
+ context?: ClassDecoratorContext,
79
79
  ) => T
80
80
  : Schema extends undefined // #3.3 Check that schema is undefined
81
81
  ? <R extends ClassTypeWithInstance<Type>>( // #3.3.1 Token must have a type
82
82
  target: R,
83
- context: ClassDecoratorContext,
83
+ context?: ClassDecoratorContext,
84
84
  ) => R
85
85
  : never // #3.4 Cannot use a token without a type and schema
86
86
 
@@ -95,12 +95,12 @@ export function Injectable<R, S>(options: {
95
95
  : S extends InjectionTokenSchemaType // #4.2 Check that schema is an object or a record
96
96
  ? <T extends ClassTypeWithInstance<FactoryWithArgs<R, S>>>( // #4.2.1 Token have a schema
97
97
  target: T,
98
- context: ClassDecoratorContext,
98
+ context?: ClassDecoratorContext,
99
99
  ) => T
100
100
  : S extends undefined // #4.3 For a factory without schema
101
101
  ? <T extends ClassTypeWithInstance<Factory<R>>>( // #4.3.1 Token without a schema
102
102
  target: T,
103
- context: ClassDecoratorContext,
103
+ context?: ClassDecoratorContext,
104
104
  ) => T
105
105
  : never // #4.4 Cannot use a token without a type and schema
106
106
  export function Injectable({
@@ -111,9 +111,12 @@ export function Injectable({
111
111
  }: InjectableOptions = {}) {
112
112
  return <T extends ClassType>(
113
113
  target: T,
114
- context: ClassDecoratorContext,
114
+ context?: ClassDecoratorContext,
115
115
  ): T => {
116
- if (context.kind !== 'class') {
116
+ if (
117
+ (context && context.kind !== 'class') ||
118
+ (target instanceof Function && !context)
119
+ ) {
117
120
  throw new Error(
118
121
  '[ServiceLocator] @Injectable decorator can only be used on classes.',
119
122
  )
@@ -1,6 +1,4 @@
1
- import type { AnyZodObject } from 'zod'
2
-
3
- import { z, ZodOptional, ZodRecord } from 'zod'
1
+ import type { z, ZodObject, ZodOptional, ZodRecord } from 'zod/v4'
4
2
 
5
3
  export type ClassType = new (...args: any[]) => any
6
4
  export type ClassTypeWithArgument<Arg> = new (arg: Arg) => any
@@ -12,10 +10,10 @@ export type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (
12
10
  arg?: Arg,
13
11
  ) => T
14
12
 
15
- export type BaseInjectionTokenSchemaType = AnyZodObject | ZodRecord
13
+ export type BaseInjectionTokenSchemaType = ZodObject<any> | ZodRecord
16
14
 
17
15
  export type OptionalInjectionTokenSchemaType =
18
- | ZodOptional<AnyZodObject>
16
+ | ZodOptional<ZodObject<any>>
19
17
  | ZodOptional<ZodRecord>
20
18
 
21
19
  export type InjectionTokenSchemaType =
@@ -25,11 +23,11 @@ export type InjectionTokenSchemaType =
25
23
  export class InjectionToken<
26
24
  T,
27
25
  S extends InjectionTokenSchemaType | unknown = unknown,
28
- Required extends boolean = S extends ZodOptional<AnyZodObject>
26
+ Required extends boolean = S extends ZodOptional<ZodObject<any>>
29
27
  ? false
30
28
  : S extends ZodOptional<ZodRecord>
31
29
  ? false
32
- : S extends AnyZodObject
30
+ : S extends ZodObject<any>
33
31
  ? true
34
32
  : S extends ZodRecord
35
33
  ? true
@@ -40,7 +38,7 @@ export class InjectionToken<
40
38
 
41
39
  constructor(
42
40
  public readonly name: string | symbol | ClassType,
43
- public readonly schema: AnyZodObject | undefined,
41
+ public readonly schema: ZodObject<any> | undefined,
44
42
  ) {}
45
43
 
46
44
  static create<T extends ClassType>(
@@ -49,7 +47,7 @@ export class InjectionToken<
49
47
  static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(
50
48
  name: T,
51
49
  schema: Schema,
52
- ): Schema['_def']['typeName'] extends 'ZodOptional'
50
+ ): Schema['_def']['type'] extends 'ZodOptional'
53
51
  ? InjectionToken<InstanceType<T>, Schema, false>
54
52
  : InjectionToken<InstanceType<T>, Schema, true>
55
53
  static create<T>(name: string | symbol): InjectionToken<T, undefined>
@@ -1,4 +1,4 @@
1
- import { z } from 'zod'
1
+ import { z } from 'zod/v4'
2
2
 
3
3
  import type { FactoryContext } from '../factory-context.mjs'
4
4
  import type { InjectionTokenSchemaType } from '../injection-token.mjs'
@@ -1,4 +1,4 @@
1
- import type { AnyZodObject, z, ZodOptional } from 'zod'
1
+ import type { z, ZodObject, ZodOptional } from 'zod/v4'
2
2
 
3
3
  import type { FactoryContext } from './factory-context.mjs'
4
4
  import type {
@@ -39,12 +39,12 @@ export class ProxyServiceLocator implements ServiceLocator {
39
39
  }
40
40
  public getOrThrowInstance<
41
41
  Instance,
42
- Schema extends AnyZodObject | ZodOptional<AnyZodObject> | undefined,
42
+ Schema extends ZodObject<any> | ZodOptional<ZodObject<any>> | undefined,
43
43
  >(
44
44
  token: InjectionToken<Instance, Schema>,
45
- args: Schema extends AnyZodObject
45
+ args: Schema extends ZodObject<any>
46
46
  ? z.input<Schema>
47
- : Schema extends ZodOptional<AnyZodObject>
47
+ : Schema extends ZodOptional<ZodObject<any>>
48
48
  ? z.input<Schema> | undefined
49
49
  : undefined,
50
50
  ): Promise<Instance> {
@@ -52,16 +52,16 @@ export class ProxyServiceLocator implements ServiceLocator {
52
52
  }
53
53
  public getSyncInstance<
54
54
  Instance,
55
- Schema extends AnyZodObject | ZodOptional<AnyZodObject> | undefined,
55
+ Schema extends ZodObject<any> | ZodOptional<ZodObject<any>> | undefined,
56
56
  >(
57
57
  token: InjectionToken<Instance, Schema>,
58
- args: Schema extends AnyZodObject
58
+ args: Schema extends ZodObject<any>
59
59
  ? z.input<Schema>
60
- : Schema extends ZodOptional<AnyZodObject>
60
+ : Schema extends ZodOptional<ZodObject<any>>
61
61
  ? z.input<Schema> | undefined
62
62
  : undefined,
63
63
  ): Instance | null {
64
- return this.serviceLocator.getSyncInstance(token, args)
64
+ return this.serviceLocator.getSyncInstance<Instance, Schema>(token, args)
65
65
  }
66
66
  invalidate(service: string, round?: number): Promise<any> {
67
67
  return this.serviceLocator.invalidate(service, round)
package/src/registry.mts CHANGED
@@ -1,6 +1,4 @@
1
- import type { AnyZodObject } from 'zod'
2
-
3
- import { z } from 'zod'
1
+ import type { z, ZodObject } from 'zod/v4'
4
2
 
5
3
  import type { FactoryContext } from './factory-context.mjs'
6
4
  import type { InjectionToken } from './injection-token.mjs'
@@ -17,7 +15,7 @@ export type FactoryRecord<Instance = any, Schema = any> = {
17
15
  originalToken: InjectionToken<Instance, Schema>
18
16
  factory: InjectionFactory<
19
17
  Instance,
20
- Schema extends AnyZodObject ? z.input<Schema> : unknown
18
+ Schema extends ZodObject<any> ? z.input<Schema> : unknown
21
19
  >
22
20
  }
23
21
 
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  /* eslint-disable @typescript-eslint/no-empty-object-type */
3
- import type { AnyZodObject, z, ZodOptional } from 'zod'
3
+ import type { z, ZodObject, ZodOptional } from 'zod/v4'
4
4
 
5
5
  import type { FactoryContext } from './factory-context.mjs'
6
6
  import type {
@@ -62,7 +62,7 @@ export class ServiceLocator {
62
62
  ): void
63
63
  public storeInstance<
64
64
  Instance,
65
- Schema extends AnyZodObject | ZodOptional<AnyZodObject>,
65
+ Schema extends ZodObject<any> | ZodOptional<ZodObject<any>>,
66
66
  >(
67
67
  instance: Instance,
68
68
  token: InjectionToken<Instance, Schema>,
@@ -292,9 +292,9 @@ export class ServiceLocator {
292
292
  Schema extends InjectionTokenSchemaType | undefined,
293
293
  >(
294
294
  token: InjectionToken<Instance, Schema>,
295
- args: Schema extends AnyZodObject
295
+ args: Schema extends ZodObject<any>
296
296
  ? z.input<Schema>
297
- : Schema extends ZodOptional<AnyZodObject>
297
+ : Schema extends ZodOptional<ZodObject<any>>
298
298
  ? z.input<Schema> | undefined
299
299
  : undefined,
300
300
  ): Promise<Instance> {
@@ -321,9 +321,9 @@ export class ServiceLocator {
321
321
  >(
322
322
  instanceName: string,
323
323
  token: InjectionToken<Instance, Schema>,
324
- args: Schema extends AnyZodObject
324
+ args: Schema extends ZodObject<any>
325
325
  ? z.input<Schema>
326
- : Schema extends ZodOptional<AnyZodObject>
326
+ : Schema extends ZodOptional<ZodObject<any>>
327
327
  ? z.input<Schema> | undefined
328
328
  : undefined,
329
329
  ): Promise<[undefined, Instance] | [FactoryNotFound | UnknownError]> {
@@ -481,9 +481,9 @@ export class ServiceLocator {
481
481
  Schema extends InjectionTokenSchemaType | undefined,
482
482
  >(
483
483
  token: InjectionToken<Instance, Schema>,
484
- args: Schema extends AnyZodObject
484
+ args: Schema extends ZodObject<any>
485
485
  ? z.input<Schema>
486
- : Schema extends ZodOptional<AnyZodObject>
486
+ : Schema extends ZodOptional<ZodObject<any>>
487
487
  ? z.input<Schema> | undefined
488
488
  : undefined,
489
489
  ): Instance | null {
@@ -1,4 +1,4 @@
1
- import type { AnyZodObject, z, ZodType } from 'zod'
1
+ import type { z, ZodObject, ZodType } from 'zod/v4'
2
2
 
3
3
  import type {
4
4
  BoundInjectionToken,
@@ -150,8 +150,8 @@ export function getInjectors({ baseLocator }: CreateInjectorsOptions) {
150
150
  | InjectionToken<T>
151
151
  | BoundInjectionToken<T, any>
152
152
  | FactoryInjectionToken<T, any>,
153
- S extends AnyZodObject | unknown = Token['schema'],
154
- >(token: Token, args?: S extends AnyZodObject ? z.input<S> : never): T {
153
+ S extends ZodObject<any> | unknown = Token['schema'],
154
+ >(token: Token, args?: S extends ZodObject<any> ? z.input<S> : never): T {
155
155
  // @ts-expect-error In case we have a class
156
156
  const realToken = token[InjectableTokenMeta] ?? token
157
157