@declaro/core 2.0.0-beta.99 → 2.1.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.
Files changed (60) hide show
  1. package/dist/browser/index.js +21 -27
  2. package/dist/browser/index.js.map +37 -27
  3. package/dist/browser/scope/index.js +1 -2
  4. package/dist/browser/scope/index.js.map +1 -1
  5. package/dist/bun/index.js +19011 -0
  6. package/dist/bun/index.js.map +132 -0
  7. package/dist/bun/scope/index.js +4 -0
  8. package/dist/bun/scope/index.js.map +9 -0
  9. package/dist/node/index.cjs +2581 -874
  10. package/dist/node/index.cjs.map +36 -27
  11. package/dist/node/index.js +2572 -868
  12. package/dist/node/index.js.map +36 -27
  13. package/dist/node/scope/index.cjs +31 -10
  14. package/dist/node/scope/index.cjs.map +1 -1
  15. package/dist/node/scope/index.js +1 -27
  16. package/dist/node/scope/index.js.map +1 -1
  17. package/dist/ts/context/async-context.d.ts +54 -0
  18. package/dist/ts/context/async-context.d.ts.map +1 -0
  19. package/dist/ts/context/async-context.test.d.ts +2 -0
  20. package/dist/ts/context/async-context.test.d.ts.map +1 -0
  21. package/dist/ts/context/context.circular-deps.test.d.ts +2 -0
  22. package/dist/ts/context/context.circular-deps.test.d.ts.map +1 -0
  23. package/dist/ts/context/context.d.ts +297 -38
  24. package/dist/ts/context/context.d.ts.map +1 -1
  25. package/dist/ts/http/request-context.d.ts.map +1 -1
  26. package/dist/ts/index.d.ts +2 -0
  27. package/dist/ts/index.d.ts.map +1 -1
  28. package/dist/ts/schema/json-schema.d.ts +9 -1
  29. package/dist/ts/schema/json-schema.d.ts.map +1 -1
  30. package/dist/ts/schema/model.d.ts +6 -1
  31. package/dist/ts/schema/model.d.ts.map +1 -1
  32. package/dist/ts/schema/test/mock-model.d.ts +2 -2
  33. package/dist/ts/schema/test/mock-model.d.ts.map +1 -1
  34. package/dist/ts/shared/utils/schema-utils.d.ts +3 -0
  35. package/dist/ts/shared/utils/schema-utils.d.ts.map +1 -0
  36. package/dist/ts/shared/utils/schema-utils.test.d.ts +2 -0
  37. package/dist/ts/shared/utils/schema-utils.test.d.ts.map +1 -0
  38. package/dist/ts/shims/async-local-storage.d.ts +36 -0
  39. package/dist/ts/shims/async-local-storage.d.ts.map +1 -0
  40. package/dist/ts/shims/async-local-storage.test.d.ts +2 -0
  41. package/dist/ts/shims/async-local-storage.test.d.ts.map +1 -0
  42. package/package.json +17 -9
  43. package/src/context/async-context.test.ts +348 -0
  44. package/src/context/async-context.ts +129 -0
  45. package/src/context/context.circular-deps.test.ts +1047 -0
  46. package/src/context/context.test.ts +150 -0
  47. package/src/context/context.ts +493 -55
  48. package/src/http/request-context.ts +1 -3
  49. package/src/index.ts +2 -0
  50. package/src/schema/json-schema.ts +14 -1
  51. package/src/schema/model-schema.test.ts +155 -1
  52. package/src/schema/model.ts +34 -3
  53. package/src/schema/test/mock-model.ts +6 -2
  54. package/src/shared/utils/schema-utils.test.ts +33 -0
  55. package/src/shared/utils/schema-utils.ts +17 -0
  56. package/src/shims/async-local-storage.test.ts +258 -0
  57. package/src/shims/async-local-storage.ts +82 -0
  58. package/dist/ts/schema/entity-schema.test.d.ts +0 -1
  59. package/dist/ts/schema/entity-schema.test.d.ts.map +0 -1
  60. package/src/schema/entity-schema.test.ts +0 -0
@@ -899,4 +899,154 @@ describe('Context', () => {
899
899
  // Both references point to the same instance
900
900
  expect(partialContext).toBe(context)
901
901
  })
902
+
903
+ it('should cache singleton dependencies of dependencies correctly', async () => {
904
+ interface ServiceA {
905
+ id: string
906
+ message: string
907
+ }
908
+
909
+ interface ServiceB {
910
+ id: string
911
+ serviceA: ServiceA
912
+ }
913
+
914
+ interface ServiceC {
915
+ id: string
916
+ serviceA: ServiceA
917
+ serviceB: ServiceB
918
+ }
919
+
920
+ interface ServiceD {
921
+ id: string
922
+ serviceA: ServiceA
923
+ serviceB: ServiceB
924
+ serviceC: ServiceC
925
+ }
926
+
927
+ type Scope = {
928
+ serviceA: Promise<ServiceA>
929
+ serviceB: Promise<ServiceB>
930
+ serviceC: Promise<ServiceC>
931
+ serviceD: Promise<ServiceD>
932
+ }
933
+
934
+ const context = new Context<Scope>()
935
+
936
+ let serviceAInstances = 0
937
+ let serviceBInstances = 0
938
+ let serviceCInstances = 0
939
+ let serviceDInstances = 0
940
+
941
+ // ServiceA - async factory - singleton
942
+ context.registerAsyncFactory(
943
+ 'serviceA',
944
+ async (): Promise<ServiceA> => {
945
+ serviceAInstances++
946
+ return {
947
+ id: `serviceA-${serviceAInstances}`,
948
+ message: 'I am Service A',
949
+ }
950
+ },
951
+ [],
952
+ { singleton: true },
953
+ )
954
+
955
+ // ServiceB - async factory depends on ServiceA - singleton
956
+ context.registerAsyncFactory(
957
+ 'serviceB',
958
+ async (serviceA: ServiceA): Promise<ServiceB> => {
959
+ serviceBInstances++
960
+ return {
961
+ id: `serviceB-${serviceBInstances}`,
962
+ serviceA,
963
+ }
964
+ },
965
+ ['serviceA'],
966
+ { singleton: true },
967
+ )
968
+
969
+ // ServiceC - async factory depends on ServiceB and ServiceA - singleton
970
+ context.registerAsyncFactory(
971
+ 'serviceC',
972
+ async (serviceA: ServiceA, serviceB: ServiceB): Promise<ServiceC> => {
973
+ serviceCInstances++
974
+ return {
975
+ id: `serviceC-${serviceCInstances}`,
976
+ serviceA,
977
+ serviceB,
978
+ }
979
+ },
980
+ ['serviceA', 'serviceB'],
981
+ { singleton: true },
982
+ )
983
+
984
+ // ServiceD - async factory depends on ServiceA, ServiceB, and ServiceC - NOT a singleton
985
+ context.registerAsyncFactory(
986
+ 'serviceD',
987
+ async (serviceA: ServiceA, serviceB: ServiceB, serviceC: ServiceC): Promise<ServiceD> => {
988
+ serviceDInstances++
989
+ return {
990
+ id: `serviceD-${serviceDInstances}`,
991
+ serviceA,
992
+ serviceB,
993
+ serviceC,
994
+ }
995
+ },
996
+ ['serviceA', 'serviceB', 'serviceC'],
997
+ )
998
+
999
+ // First resolution - all should be created
1000
+ const serviceD1 = await context.resolve('serviceD')
1001
+
1002
+ expect(serviceAInstances).toBe(1) // ServiceA should only be created once
1003
+ expect(serviceBInstances).toBe(1) // ServiceB should only be created once
1004
+ expect(serviceCInstances).toBe(1) // ServiceC should only be created once
1005
+ expect(serviceDInstances).toBe(1) // ServiceD should be created
1006
+
1007
+ // Second resolution - only ServiceD should be recreated
1008
+ const serviceD2 = await context.resolve('serviceD')
1009
+
1010
+ expect(serviceAInstances).toBe(1) // ServiceA should still be only created once
1011
+ expect(serviceBInstances).toBe(1) // ServiceB should still be only created once
1012
+ expect(serviceCInstances).toBe(1) // ServiceC should still be only created once
1013
+ expect(serviceDInstances).toBe(2) // ServiceD should be created again
1014
+
1015
+ // Third resolution - again only ServiceD should be recreated
1016
+ const serviceD3 = await context.resolve('serviceD')
1017
+
1018
+ expect(serviceAInstances).toBe(1) // ServiceA should still be only created once
1019
+ expect(serviceBInstances).toBe(1) // ServiceB should still be only created once
1020
+ expect(serviceCInstances).toBe(1) // ServiceC should still be only created once
1021
+ expect(serviceDInstances).toBe(3) // ServiceD should be created again
1022
+
1023
+ // Verify that singleton dependencies are the same instances (use toEqual since we have proxy objects)
1024
+ expect(serviceD1.serviceA).toEqual(serviceD2.serviceA)
1025
+ expect(serviceD1.serviceA).toEqual(serviceD3.serviceA)
1026
+ expect(serviceD1.serviceB).toEqual(serviceD2.serviceB)
1027
+ expect(serviceD1.serviceB).toEqual(serviceD3.serviceB)
1028
+ expect(serviceD1.serviceC).toEqual(serviceD2.serviceC)
1029
+ expect(serviceD1.serviceC).toEqual(serviceD3.serviceC)
1030
+
1031
+ // Verify nested dependencies are also the same
1032
+ expect(serviceD1.serviceB.serviceA).toEqual(serviceD2.serviceB.serviceA)
1033
+ expect(serviceD1.serviceC.serviceA).toEqual(serviceD2.serviceC.serviceA)
1034
+ expect(serviceD1.serviceC.serviceB).toEqual(serviceD2.serviceC.serviceB)
1035
+
1036
+ // Verify the IDs to confirm singletons were reused
1037
+ expect(serviceD1.serviceA.id).toBe('serviceA-1')
1038
+ expect(serviceD1.serviceB.id).toBe('serviceB-1')
1039
+ expect(serviceD1.serviceC.id).toBe('serviceC-1')
1040
+ expect(serviceD1.id).toBe('serviceD-1')
1041
+
1042
+ expect(serviceD2.serviceA.id).toBe('serviceA-1') // Same instance
1043
+ expect(serviceD2.serviceB.id).toBe('serviceB-1') // Same instance
1044
+ expect(serviceD2.serviceC.id).toBe('serviceC-1') // Same instance
1045
+ expect(serviceD2.id).toBe('serviceD-2') // New instance
1046
+
1047
+ expect(serviceD3.serviceA.id).toBe('serviceA-1') // Same instance
1048
+ expect(serviceD3.serviceB.id).toBe('serviceB-1') // Same instance
1049
+ expect(serviceD3.serviceC.id).toBe('serviceC-1') // Same instance
1050
+ expect(serviceD3.id).toBe('serviceD-3') // New instance
1051
+ })
902
1052
  })