@navios/di 0.1.12 → 0.1.13

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.
@@ -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
  })
@@ -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
  )