react-obsidian 0.0.10 → 0.0.14

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 (135) hide show
  1. package/README.md +82 -7
  2. package/babel.config.js +3 -2
  3. package/dist/src/GraphProperties.d.ts +1 -0
  4. package/dist/src/GraphProperties.d.ts.map +1 -1
  5. package/dist/src/GraphProperties.js +3 -0
  6. package/dist/src/GraphProperties.js.map +1 -1
  7. package/dist/src/ProvidedPropertiesStore.d.ts +1 -0
  8. package/dist/src/ProvidedPropertiesStore.d.ts.map +1 -1
  9. package/dist/src/ProvidedPropertiesStore.js +4 -0
  10. package/dist/src/ProvidedPropertiesStore.js.map +1 -1
  11. package/dist/src/decorators/Graph.d.ts +2 -3
  12. package/dist/src/decorators/Graph.d.ts.map +1 -1
  13. package/dist/src/decorators/Graph.js +2 -3
  14. package/dist/src/decorators/Graph.js.map +1 -1
  15. package/dist/src/decorators/Singleton.d.ts +4 -0
  16. package/dist/src/decorators/Singleton.d.ts.map +1 -0
  17. package/dist/src/decorators/Singleton.js +12 -0
  18. package/dist/src/decorators/Singleton.js.map +1 -0
  19. package/dist/src/decorators/inject/Inject.d.ts +2 -0
  20. package/dist/src/decorators/inject/Inject.d.ts.map +1 -0
  21. package/dist/src/decorators/inject/Inject.js +21 -0
  22. package/dist/src/decorators/inject/Inject.js.map +1 -0
  23. package/dist/src/decorators/inject/Injectable.d.ts +4 -0
  24. package/dist/src/decorators/inject/Injectable.d.ts.map +1 -0
  25. package/dist/src/decorators/inject/Injectable.js +13 -0
  26. package/dist/src/decorators/inject/Injectable.js.map +1 -0
  27. package/dist/src/decorators/provides/MemoizeDescriptor.d.ts.map +1 -1
  28. package/dist/src/decorators/provides/MemoizeDescriptor.js +4 -4
  29. package/dist/src/decorators/provides/MemoizeDescriptor.js.map +1 -1
  30. package/dist/src/decorators/provides/Provides.d.ts +0 -2
  31. package/dist/src/decorators/provides/Provides.d.ts.map +1 -1
  32. package/dist/src/decorators/provides/Provides.js.map +1 -1
  33. package/dist/src/graph/ObjectGraph.d.ts +0 -2
  34. package/dist/src/graph/ObjectGraph.d.ts.map +1 -1
  35. package/dist/src/graph/ObjectGraph.js +2 -2
  36. package/dist/src/graph/ObjectGraph.js.map +1 -1
  37. package/dist/src/graph/ProviderBinder.d.ts +3 -0
  38. package/dist/src/graph/ProviderBinder.d.ts.map +1 -0
  39. package/dist/src/graph/ProviderBinder.js +18 -0
  40. package/dist/src/graph/ProviderBinder.js.map +1 -0
  41. package/dist/src/graph/registry/GraphRegistry.d.ts +8 -8
  42. package/dist/src/graph/registry/GraphRegistry.d.ts.map +1 -1
  43. package/dist/src/graph/registry/GraphRegistry.js +23 -22
  44. package/dist/src/graph/registry/GraphRegistry.js.map +1 -1
  45. package/dist/src/index.d.ts +3 -2
  46. package/dist/src/index.d.ts.map +1 -1
  47. package/dist/src/index.js +7 -5
  48. package/dist/src/index.js.map +1 -1
  49. package/dist/src/injectors/class/ClassInjector.d.ts +12 -0
  50. package/dist/src/injectors/class/ClassInjector.d.ts.map +1 -0
  51. package/dist/src/injectors/class/ClassInjector.js +58 -0
  52. package/dist/src/injectors/class/ClassInjector.js.map +1 -0
  53. package/dist/src/injectors/class/ConstructorArgs.d.ts +8 -0
  54. package/dist/src/injectors/class/ConstructorArgs.d.ts.map +1 -0
  55. package/dist/src/injectors/class/ConstructorArgs.js +25 -0
  56. package/dist/src/injectors/class/ConstructorArgs.js.map +1 -0
  57. package/dist/src/injectors/class/InjectionMetadata.d.ts +10 -0
  58. package/dist/src/injectors/class/InjectionMetadata.d.ts.map +1 -0
  59. package/dist/src/injectors/class/InjectionMetadata.js +28 -0
  60. package/dist/src/injectors/class/InjectionMetadata.js.map +1 -0
  61. package/dist/src/injectors/components/ComponentInjector.d.ts +0 -1
  62. package/dist/src/injectors/components/ComponentInjector.d.ts.map +1 -1
  63. package/dist/src/injectors/components/ComponentInjector.js +0 -1
  64. package/dist/src/injectors/components/ComponentInjector.js.map +1 -1
  65. package/dist/src/types/index.d.ts +0 -1
  66. package/dist/src/types/index.d.ts.map +1 -1
  67. package/dist/test/integration/fixtures/MainGraph.d.ts +1 -0
  68. package/dist/test/integration/fixtures/MainGraph.d.ts.map +1 -1
  69. package/dist/test/integration/fixtures/MainGraph.js +10 -0
  70. package/dist/test/integration/fixtures/MainGraph.js.map +1 -1
  71. package/dist/test/integration/fixtures/SingletonGraph.d.ts +6 -0
  72. package/dist/test/integration/fixtures/SingletonGraph.d.ts.map +1 -0
  73. package/dist/test/integration/fixtures/SingletonGraph.js +53 -0
  74. package/dist/test/integration/fixtures/SingletonGraph.js.map +1 -0
  75. package/dist/test/integration/fixtures/UniqueNumberGraph.d.ts +8 -0
  76. package/dist/test/integration/fixtures/UniqueNumberGraph.d.ts.map +1 -0
  77. package/dist/test/integration/fixtures/UniqueNumberGraph.js +62 -0
  78. package/dist/test/integration/fixtures/UniqueNumberGraph.js.map +1 -0
  79. package/dist/test/integration/fixtures/injectedValues.d.ts +1 -0
  80. package/dist/test/integration/fixtures/injectedValues.d.ts.map +1 -1
  81. package/dist/test/integration/fixtures/injectedValues.js +1 -0
  82. package/dist/test/integration/fixtures/injectedValues.js.map +1 -1
  83. package/dist/transformers/{babel-plugin-obsidian-provide → babel-plugin-obsidian}/helpers/index.d.ts +3 -2
  84. package/dist/transformers/babel-plugin-obsidian/helpers/index.d.ts.map +1 -0
  85. package/dist/transformers/{babel-plugin-obsidian-provide → babel-plugin-obsidian}/helpers/index.js +22 -4
  86. package/dist/transformers/babel-plugin-obsidian/helpers/index.js.map +1 -0
  87. package/dist/transformers/{babel-plugin-obsidian-provide → babel-plugin-obsidian}/index.d.ts +0 -0
  88. package/dist/transformers/babel-plugin-obsidian/index.d.ts.map +1 -0
  89. package/dist/transformers/{babel-plugin-obsidian-provide → babel-plugin-obsidian}/index.js +27 -1
  90. package/dist/transformers/babel-plugin-obsidian/index.js.map +1 -0
  91. package/example/babel.config.js +1 -1
  92. package/example/ios/example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  93. package/jest.config.js +4 -0
  94. package/jest.setup-after-env.js +1 -0
  95. package/jest.setup.ts +1 -0
  96. package/package.json +5 -3
  97. package/src/GraphProperties.ts +4 -0
  98. package/src/ProvidedPropertiesStore.ts +4 -0
  99. package/src/decorators/Graph.ts +2 -5
  100. package/src/decorators/Singleton.ts +14 -0
  101. package/src/decorators/inject/Inject.ts +17 -0
  102. package/src/decorators/inject/Injectable.ts +8 -0
  103. package/src/decorators/provides/MemoizeDescriptor.ts +3 -4
  104. package/src/decorators/provides/Provides.ts +0 -2
  105. package/src/graph/ObjectGraph.ts +2 -5
  106. package/src/graph/ProviderBinder.ts +12 -0
  107. package/src/graph/registry/GraphRegistry.ts +27 -32
  108. package/src/index.ts +3 -2
  109. package/src/injectors/class/ClassInjector.ts +49 -0
  110. package/src/injectors/class/ConstructorArgs.ts +20 -0
  111. package/src/injectors/class/InjectionMetadata.ts +32 -0
  112. package/src/injectors/components/ComponentInjector.tsx +0 -1
  113. package/src/types/index.ts +0 -2
  114. package/testkit/index.ts +1 -1
  115. package/transformers/{babel-plugin-obsidian-provide → babel-plugin-obsidian}/helpers/index.ts +26 -2
  116. package/transformers/{babel-plugin-obsidian-provide → babel-plugin-obsidian}/index.ts +37 -3
  117. package/dist/src/ScopedValuesRegistry.d.ts +0 -11
  118. package/dist/src/ScopedValuesRegistry.d.ts.map +0 -1
  119. package/dist/src/ScopedValuesRegistry.js +0 -25
  120. package/dist/src/ScopedValuesRegistry.js.map +0 -1
  121. package/dist/src/decorators/injectClass.d.ts +0 -7
  122. package/dist/src/decorators/injectClass.d.ts.map +0 -1
  123. package/dist/src/decorators/injectClass.js +0 -34
  124. package/dist/src/decorators/injectClass.js.map +0 -1
  125. package/dist/src/graph/autobind.d.ts +0 -2
  126. package/dist/src/graph/autobind.d.ts.map +0 -1
  127. package/dist/src/graph/autobind.js +0 -12
  128. package/dist/src/graph/autobind.js.map +0 -1
  129. package/dist/transformers/babel-plugin-obsidian-provide/helpers/index.d.ts.map +0 -1
  130. package/dist/transformers/babel-plugin-obsidian-provide/helpers/index.js.map +0 -1
  131. package/dist/transformers/babel-plugin-obsidian-provide/index.d.ts.map +0 -1
  132. package/dist/transformers/babel-plugin-obsidian-provide/index.js.map +0 -1
  133. package/src/ScopedValuesRegistry.ts +0 -26
  134. package/src/decorators/injectClass.ts +0 -28
  135. package/src/graph/autobind.ts +0 -7
@@ -12,14 +12,40 @@ var internalVisitor = {
12
12
  ClassMethod: {
13
13
  enter: function (_a) {
14
14
  var node = _a.node;
15
- var decorator = (0, helpers_1.getProviderDecorator)(node.decorators);
15
+ var decorator = (0, helpers_1.getDecoratorByName)(node.decorators, 'Provides');
16
16
  if ((0, helpers_1.getDecoratorName)(decorator) === 'Provides') {
17
17
  convertProviderParamsToDestructuringAssignment(node);
18
18
  saveUnmangledMethodNameInProviderArguments(node, decorator);
19
19
  }
20
20
  },
21
21
  },
22
+ Identifier: {
23
+ enter: function (_a) {
24
+ var node = _a.node;
25
+ var decorator = (0, helpers_1.getDecoratorByName)(node.decorators, 'Inject');
26
+ if ((0, helpers_1.getDecoratorName)(decorator) === 'Inject') {
27
+ saveUnmangledParamName(node, decorator);
28
+ }
29
+ },
30
+ },
31
+ TSParameterProperty: {
32
+ enter: function (_a) {
33
+ var node = _a.node;
34
+ var decorator = (0, helpers_1.getDecoratorByName)(node.decorators, 'Inject');
35
+ if ((0, helpers_1.getDecoratorName)(decorator) === 'Inject') {
36
+ saveUnmangledParamName(node, decorator);
37
+ }
38
+ },
39
+ },
22
40
  };
41
+ function saveUnmangledParamName(node, decorator) {
42
+ if (injectIsNotNamed(decorator)) {
43
+ (0, helpers_1.passParamNameAsInjectArgument)(node, decorator);
44
+ }
45
+ }
46
+ function injectIsNotNamed(decorator) {
47
+ return (0, helpers_1.getDecoratorArgument)(decorator) === undefined;
48
+ }
23
49
  function convertProviderParamsToDestructuringAssignment(node) {
24
50
  if (node.params.length === 0)
25
51
  return;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../transformers/babel-plugin-obsidian/index.ts"],"names":[],"mappings":";;AASA,qCAQmB;AAEnB,IAAM,4BAA4B,GAAc;IAC9C,OAAO,EAAE;QACP,OAAO,EAAP,UAAQ,IAAuB;YAC7B,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACjC,CAAC;KACF;CACF,CAAC;AAEF,IAAM,eAAe,GAAG;IACtB,WAAW,EAAE;QACX,KAAK,EAAL,UAAM,EAA+B;gBAA7B,IAAI,UAAA;YACV,IAAM,SAAS,GAAG,IAAA,4BAAkB,EAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAClE,IAAI,IAAA,0BAAgB,EAAC,SAAS,CAAC,KAAK,UAAU,EAAE;gBAC9C,8CAA8C,CAAC,IAAI,CAAC,CAAC;gBACrD,0CAA0C,CAAC,IAAI,EAAE,SAAU,CAAC,CAAC;aAC9D;QACH,CAAC;KACF;IACD,UAAU,EAAE;QACV,KAAK,EAAL,UAAM,EAA8B;gBAA5B,IAAI,UAAA;YACV,IAAM,SAAS,GAAG,IAAA,4BAAkB,EAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAChE,IAAI,IAAA,0BAAgB,EAAC,SAAS,CAAC,KAAK,QAAQ,EAAE;gBAC5C,sBAAsB,CAAC,IAAI,EAAE,SAAU,CAAC,CAAC;aAC1C;QACH,CAAC;KACF;IACD,mBAAmB,EAAE;QACnB,KAAK,EAAL,UAAM,EAAuC;gBAArC,IAAI,UAAA;YACV,IAAM,SAAS,GAAG,IAAA,4BAAkB,EAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAChE,IAAI,IAAA,0BAAgB,EAAC,SAAS,CAAC,KAAK,QAAQ,EAAE;gBAC5C,sBAAsB,CAAC,IAAI,EAAE,SAAU,CAAC,CAAC;aAC1C;QACH,CAAC;KACF;CACF,CAAC;AAEF,SAAS,sBAAsB,CAAC,IAAsC,EAAE,SAAoB;IAC1F,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE;QAC/B,IAAA,uCAA6B,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;KAChD;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAoB;IAC5C,OAAO,IAAA,8BAAoB,EAAC,SAAS,CAAC,KAAK,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,8CAA8C,CAAC,IAAiB;IACvE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACrC,IAAM,kBAAkB,GAAG,IAAA,yCAA+B,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxE,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,0CAA0C,CAAC,IAAiB,EAAE,SAAoB;IACzF,IAAI,IAAA,4BAAkB,EAAC,SAAS,CAAC,EAAE;QACjC,IAAA,oCAA0B,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;KAC7C;AACH,CAAC;AAED,SAAwB,MAAM;IAC5B,OAAO,4BAA4B,CAAC;AACtC,CAAC;AAFD,yBAEC"}
@@ -3,6 +3,6 @@ module.exports = {
3
3
  plugins: [
4
4
  ['@babel/plugin-proposal-decorators', {legacy: true}],
5
5
  ['@babel/plugin-proposal-class-properties', {legacy: true}],
6
- [`${__dirname}/../dist/transformers/babel-plugin-obsidian-provide`],
6
+ [`${__dirname}/../dist/transformers/babel-plugin-obsidian`],
7
7
  ],
8
8
  };
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
package/jest.config.js CHANGED
@@ -7,6 +7,10 @@ const config = {
7
7
  'transformers',
8
8
  'test',
9
9
  ],
10
+ setupFilesAfterEnv: [
11
+ './jest.setup-after-env.js'
12
+ ],
13
+ testEnvironment: 'jsdom'
10
14
  };
11
15
 
12
16
  module.exports = config;
@@ -0,0 +1 @@
1
+ require('setimmediate');
package/jest.setup.ts ADDED
@@ -0,0 +1 @@
1
+ import 'reflect-metadata';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-obsidian",
3
- "version": "0.0.10",
3
+ "version": "0.0.14",
4
4
  "description": "Dependency injection framework for React and React Native applications",
5
5
  "main": "src/index.ts",
6
6
  "directories": {
@@ -19,6 +19,7 @@
19
19
  "@babel/plugin-proposal-class-properties": "7.16.x",
20
20
  "@babel/plugin-proposal-decorators": "7.16.x",
21
21
  "@babel/preset-env": "7.16.x",
22
+ "babel-plugin-parameter-decorator": "1.x.x",
22
23
  "@babel/preset-react": "7.16.x",
23
24
  "@babel/preset-typescript": "7.16.x",
24
25
  "@babel/types": "7.16.x",
@@ -40,11 +41,12 @@
40
41
  "eslint-plugin-jsx-a11y": "^6.4.1",
41
42
  "eslint-plugin-react": "^7.26.1",
42
43
  "eslint-plugin-react-hooks": "^4.2.0",
43
- "jest": "26.x.x",
44
+ "jest": "27.x.x",
44
45
  "lodash": "^4.17.21",
45
46
  "react": "17.0.2",
46
47
  "react-dom": "17.0.2",
47
- "typescript": "^4.4.4"
48
+ "typescript": "^4.5.4",
49
+ "setimmediate": "^1.0.5"
48
50
  },
49
51
  "scripts": {
50
52
  "prepack": "npm run lint && tsc --project tsconfig.prod.json",
@@ -8,4 +8,8 @@ export default class GraphProperties {
8
8
  getMangledProperty(unmangledProperty: string): string | undefined {
9
9
  return this.unmangledToMangledPropKeys.get(unmangledProperty);
10
10
  }
11
+
12
+ getMangledProperties(): string[] {
13
+ return Array.from(this.unmangledToMangledPropKeys.values());
14
+ }
11
15
  }
@@ -14,6 +14,10 @@ class ProvidedPropertiesStore {
14
14
  this.providedPropertiesForGraph.set(graph.name, graphProperties);
15
15
  }
16
16
 
17
+ getMangledProperties(graph: Graph): string[] {
18
+ return this.providedPropertiesForGraph.get(graph.name)?.getMangledProperties() ?? [];
19
+ }
20
+
17
21
  clear(graph: Graph) {
18
22
  this.providedPropertiesForGraph.delete(graph.name);
19
23
  }
@@ -1,20 +1,17 @@
1
- import { Constructable, Scope } from '../types';
1
+ import { Constructable } from '../types';
2
2
  import 'reflect-metadata';
3
3
  import graphRegistry from '../graph/registry/GraphRegistry';
4
4
  import { ObjectGraph } from '../graph/ObjectGraph';
5
5
 
6
6
  interface GraphParams {
7
- scope: Scope | undefined;
8
7
  subgraphs: Constructable<ObjectGraph>[];
9
8
  }
10
9
 
11
10
  export function Graph({
12
- scope,
13
11
  subgraphs = [],
14
12
  }: Partial<GraphParams> = {}) {
15
13
  return <T extends ObjectGraph>(constructor: Constructable<T>) => {
16
- Reflect.defineMetadata('scope', scope, constructor);
17
- graphRegistry.register(constructor, scope, subgraphs);
14
+ graphRegistry.register(constructor, subgraphs);
18
15
  return constructor;
19
16
  };
20
17
  }
@@ -0,0 +1,14 @@
1
+ import { Constructable } from '../types';
2
+ import { ObjectGraph } from '../graph/ObjectGraph';
3
+
4
+ export function Singleton() {
5
+ return function singleton(
6
+ constructorOrGraph: Constructable<ObjectGraph> | ObjectGraph,
7
+ _property?: string,
8
+ descriptor?: PropertyDescriptor,
9
+ ): any {
10
+ const target = descriptor || constructorOrGraph;
11
+ Reflect.defineMetadata('isSingleton', true, target);
12
+ return target;
13
+ };
14
+ }
@@ -0,0 +1,17 @@
1
+ import { isNumber } from 'lodash';
2
+ import InjectionMetadata from '../../injectors/class/InjectionMetadata';
3
+
4
+ export function Inject(name?: string) {
5
+ return (
6
+ target: Object | any,
7
+ propertyKey?: string,
8
+ indexOrPropertyDescriptor?: number | PropertyDescriptor,
9
+ ) => {
10
+ const metadata = new InjectionMetadata();
11
+ if (name && isNumber(indexOrPropertyDescriptor)) {
12
+ metadata.saveConstructorParamMetadata(target, name!, indexOrPropertyDescriptor);
13
+ } else {
14
+ metadata.savePropertyMetadata(target.constructor, propertyKey!);
15
+ }
16
+ };
17
+ }
@@ -0,0 +1,8 @@
1
+ import { Constructable } from '../../types';
2
+ import { Graph } from '../../graph/Graph';
3
+ import graphRegistry from '../../graph/registry/GraphRegistry';
4
+ import ClassInjector from '../../injectors/class/ClassInjector';
5
+
6
+ export function Injectable(Graph: Constructable<Graph>): any {
7
+ return new ClassInjector(graphRegistry).inject(Graph);
8
+ }
@@ -2,12 +2,11 @@
2
2
  export function memoizeDescriptor(propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor {
3
3
  const originalValue = descriptor.value;
4
4
  descriptor.value = function value(...args: any[]) {
5
+ const memoizationTarget = Reflect.getMetadata('isSingleton', descriptor) ? descriptor : this;
5
6
  const key = `memoized${propertyKey}`;
6
- if (Reflect.hasMetadata(key, this)) {
7
- return Reflect.getMetadata(key, this);
8
- }
7
+ if (Reflect.hasMetadata(key, memoizationTarget)) return Reflect.getMetadata(key, memoizationTarget);
9
8
  const result = originalValue.apply(this, args);
10
- Reflect.defineMetadata(key, result, this);
9
+ Reflect.defineMetadata(key, result, memoizationTarget);
11
10
  return result;
12
11
  };
13
12
  return descriptor;
@@ -1,10 +1,8 @@
1
- import { Scope } from '../../types';
2
1
  import { Graph } from '../../graph/Graph';
3
2
  import providedPropertiesStore from '../../ProvidedPropertiesStore';
4
3
  import { memoizeDescriptor } from './MemoizeDescriptor';
5
4
 
6
5
  interface ProvidesParams {
7
- scope?: Scope;
8
6
  name: string;
9
7
  }
10
8
 
@@ -1,13 +1,10 @@
1
1
  import { uniqueId } from 'lodash';
2
2
  import Memoize from '../decorators/Memoize';
3
- import { Scope } from '../types';
4
- import { autobind } from './autobind';
3
+ import { bindProviders } from './ProviderBinder';
5
4
  import { Graph } from './Graph';
6
5
  import PropertyRetriever from './PropertyRetriever';
7
6
 
8
7
  export abstract class ObjectGraph<T = unknown> implements Graph {
9
- // TODO? rename scope to singleInstance
10
- public scope!: Scope;
11
8
  private propertyRetriever = new PropertyRetriever(this);
12
9
 
13
10
  @Memoize()
@@ -16,7 +13,7 @@ export abstract class ObjectGraph<T = unknown> implements Graph {
16
13
  }
17
14
 
18
15
  constructor(protected _props?: T) {
19
- autobind(this);
16
+ bindProviders(this);
20
17
  }
21
18
 
22
19
  retrieve<Dependency>(property: string, receiver?: unknown): Dependency | undefined {
@@ -0,0 +1,12 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import providedPropertiesStore from '../ProvidedPropertiesStore';
3
+ import { Graph } from './Graph';
4
+
5
+ export function bindProviders(graph: Graph & Record<string, any>) {
6
+ providedPropertiesStore.getMangledProperties(graph)
7
+ .forEach((method) => {
8
+ if (graph[method] !== undefined) {
9
+ graph[method] = graph[method].bind(graph);
10
+ }
11
+ });
12
+ }
@@ -1,37 +1,18 @@
1
- import { Constructable, Scope } from '../../types';
1
+ import { Constructable } from '../../types';
2
2
  import { Graph } from '../Graph';
3
3
  import { Middleware } from './Middleware';
4
4
  import GraphMiddlewareChain from './GraphMiddlewareChain';
5
5
 
6
- class GraphRegistry {
7
- private readonly scopedGraphs: Record<Scope, Constructable<Graph>> = {};
8
- private readonly constructorToInstance = new Map<Constructable<Graph>, Graph>();
6
+ export class GraphRegistry {
7
+ private readonly constructorToInstance = new Map<Constructable<Graph>, Set<Graph>>();
9
8
  private readonly instanceToConstructor = new Map<Graph, Constructable<Graph>>();
10
9
  private readonly graphToSubgraphs = new Map<Constructable<Graph>, Set<Constructable<Graph>>>();
11
- private graphMiddlewares = new GraphMiddlewareChain();
10
+ private readonly graphMiddlewares = new GraphMiddlewareChain();
12
11
 
13
- register(
14
- constructor: Constructable<Graph>,
15
- scope: Scope | undefined = undefined,
16
- subgraphs: Constructable<Graph>[] = [],
17
- ) {
18
- if (scope) this.scopedGraphs[scope] = constructor;
12
+ register(constructor: Constructable<Graph>, subgraphs: Constructable<Graph>[] = []) {
19
13
  this.graphToSubgraphs.set(constructor, new Set(subgraphs));
20
14
  }
21
15
 
22
- has(Graph: Constructable<Graph>) {
23
- return this.constructorToInstance.has(Graph);
24
- }
25
-
26
- get<T extends Graph>(Graph: Constructable<T>): T {
27
- return this.constructorToInstance.get(Graph)! as unknown as T;
28
- }
29
-
30
- set(Graph: Constructable<Graph>, graph: Graph) {
31
- this.constructorToInstance.set(Graph, graph);
32
- this.instanceToConstructor.set(graph, Graph);
33
- }
34
-
35
16
  getSubgraphs(graph: Graph): Graph[] {
36
17
  const Graph = this.instanceToConstructor.get(graph)!;
37
18
  const subgraphs = this.graphToSubgraphs.get(Graph) ?? new Set();
@@ -39,23 +20,37 @@ class GraphRegistry {
39
20
  }
40
21
 
41
22
  resolve<T extends Graph>(Graph: Constructable<T>, props?: any): T {
42
- if (this.has(Graph)) {
43
- return this.get(Graph);
44
- // const graph: T = this.get(Graph);
45
- // const scope = Reflect.getMetadata('scope', Graph);
46
- // if (scope) return graph;
47
-
48
- // this.set(Graph, new Graph(props));
23
+ if (this.isSingleton(Graph) && this.has(Graph)) {
24
+ return this.getFirst(Graph);
49
25
  }
50
26
  const graph = this.graphMiddlewares.resolve(Graph, props);
51
27
  this.set(Graph, graph);
52
28
  return graph as T;
53
29
  }
54
30
 
31
+ private has(Graph: Constructable<Graph>) {
32
+ return this.constructorToInstance.has(Graph);
33
+ }
34
+
35
+ private getFirst<T extends Graph>(Graph: Constructable<T>): T {
36
+ return this.constructorToInstance.get(Graph)!.values().next().value;
37
+ }
38
+
39
+ private set(Graph: Constructable<Graph>, graph: Graph) {
40
+ const graphs = this.constructorToInstance.get(Graph) ?? new Set();
41
+ graphs.add(graph);
42
+ this.constructorToInstance.set(Graph, graphs);
43
+ this.instanceToConstructor.set(graph, Graph);
44
+ }
45
+
46
+ private isSingleton(Graph: Constructable<Graph>): boolean {
47
+ return Reflect.getMetadata('isSingleton', Graph) ?? false;
48
+ }
49
+
55
50
  clear(graph: Graph) {
56
51
  const Graph = this.instanceToConstructor.get(graph)!;
57
52
  this.instanceToConstructor.delete(graph);
58
- this.constructorToInstance.delete(Graph);
53
+ this.constructorToInstance.get(Graph)!.delete(graph);
59
54
  }
60
55
 
61
56
  addGraphMiddleware(middleware: Middleware<Graph>) {
package/src/index.ts CHANGED
@@ -8,11 +8,12 @@ import { Constructable } from './types';
8
8
  export * from './types';
9
9
 
10
10
  export { Graph } from './decorators/Graph';
11
+ export { Singleton } from './decorators/Singleton';
11
12
  export { ObjectGraph } from './graph/ObjectGraph';
12
13
  export { Graph as IGraph } from './graph/Graph';
13
14
  export { Provides } from './decorators/provides/Provides';
14
- export { Injectable } from './decorators/injectClass';
15
- export { Inject } from './decorators/injectClass';
15
+ export { Injectable } from './decorators/inject/Injectable';
16
+ export { Inject } from './decorators/inject/Inject';
16
17
  export { GraphMiddleware } from './graph/registry/GraphMiddleware';
17
18
  export { GraphResolveChain as ResolveChain } from './graph/registry/GraphResolveChain';
18
19
  export const Obsidian = new _Obsidian();
@@ -0,0 +1,49 @@
1
+ import { Constructable } from '../../types';
2
+ import { GraphRegistry } from '../../graph/registry/GraphRegistry';
3
+ import { Graph } from '../../graph/Graph';
4
+ import InjectionMetadata from './InjectionMetadata';
5
+
6
+ export default class ClassInjector {
7
+ constructor(
8
+ private graphRegistry: GraphRegistry,
9
+ private injectionMetadata: InjectionMetadata = new InjectionMetadata(),
10
+ ) {}
11
+
12
+ inject(Graph: Constructable<Graph>) {
13
+ return (Target: Constructable<any>) => {
14
+ return new Proxy(Target, this.createProxyHandler(Graph, this.graphRegistry, this.injectionMetadata));
15
+ };
16
+ }
17
+
18
+ private createProxyHandler(
19
+ Graph: Constructable<Graph>,
20
+ graphRegistry: GraphRegistry,
21
+ injectionMetadata: InjectionMetadata,
22
+ ): ProxyHandler<any> {
23
+ return new class Handler implements ProxyHandler<any> {
24
+ construct(target: any, args: any[], newTarget: Function): any {
25
+ const graph = graphRegistry.resolve(Graph);
26
+
27
+ const argsToInject = this.injectConstructorArgs(args, graph, target);
28
+ const createdObject = Reflect.construct(target, argsToInject, newTarget);
29
+ this.injectProperties(target, createdObject, graph);
30
+
31
+ return createdObject;
32
+ }
33
+
34
+ private injectConstructorArgs(args: any[], graph: Graph, target: any): any[] {
35
+ const argsToInject = injectionMetadata.getConstructorArgsToInject(target);
36
+ if (!argsToInject.hasArgs()) return args;
37
+ return [...args, ...new Array(Math.abs(args.length - argsToInject.size()))].map((value, idx): any => {
38
+ return value ?? graph.retrieve(argsToInject.getProperty(idx));
39
+ });
40
+ }
41
+
42
+ private injectProperties(target: any, createdObject: any, graph: Graph) {
43
+ injectionMetadata.getPropertiesToInject(target).forEach((key) => {
44
+ Reflect.set(createdObject, key, graph.retrieve(key));
45
+ });
46
+ }
47
+ }();
48
+ }
49
+ }
@@ -0,0 +1,20 @@
1
+ export class ConstructorArgs {
2
+ private readonly args = new Array<[string, number]>();
3
+
4
+ hasArgs(): boolean {
5
+ return this.args.length > 0;
6
+ }
7
+
8
+ size(): number {
9
+ return this.args.length;
10
+ }
11
+
12
+ add(paramName: string, index: number) {
13
+ this.args.push([paramName, index]);
14
+ }
15
+
16
+ getProperty(index: number): any {
17
+ if (this.args.length <= index) throw new Error('IOOB while trying to get constructor args to inject');
18
+ return this.args[index][0];
19
+ }
20
+ }
@@ -0,0 +1,32 @@
1
+ import { ConstructorArgs } from './ConstructorArgs';
2
+
3
+ export default class InjectionMetadata {
4
+ private readonly injectionMetadataKey = 'injectionMetadata';
5
+ private readonly injectedConstructorArgsKey = 'injectedConstructorArgsKey';
6
+
7
+ getConstructorArgsToInject(target: any): ConstructorArgs {
8
+ return Reflect.getMetadata(this.injectedConstructorArgsKey, target) ?? new ConstructorArgs();
9
+ }
10
+
11
+ getPropertiesToInject(target: any): Set<string> {
12
+ return Reflect.getMetadata(this.injectionMetadataKey, target) ?? new Set();
13
+ }
14
+
15
+ saveConstructorParamMetadata(target: any, paramName: string, index: number) {
16
+ const argsToInject = this.getConstructorArgsToInject(target);
17
+ argsToInject.add(paramName, index);
18
+ Reflect.defineMetadata(
19
+ this.injectedConstructorArgsKey,
20
+ argsToInject,
21
+ target,
22
+ );
23
+ }
24
+
25
+ savePropertyMetadata(target: any, property: string) {
26
+ Reflect.defineMetadata(
27
+ this.injectionMetadataKey,
28
+ this.getPropertiesToInject(target).add(property),
29
+ target,
30
+ );
31
+ }
32
+ }
@@ -1,6 +1,5 @@
1
1
  import React, { useState } from 'react';
2
2
  import hoistNonReactStatics from 'hoist-non-react-statics';
3
- import 'reflect-metadata';
4
3
  import { ObjectGraph } from '../../graph/ObjectGraph';
5
4
  import PropsInjector from './PropsInjector';
6
5
  import useGraph from './useGraph';
@@ -2,8 +2,6 @@ export type Constructable<T> = {
2
2
  new(...args: any): T;
3
3
  };
4
4
 
5
- export type Scope = string | number | symbol;
6
-
7
5
  export type Constructor = { new(...args: any[]): any };
8
6
 
9
7
  export type ServiceLocator<Clazz> = {
package/testkit/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GraphResolveChain } from 'src/graph/registry/GraphResolveChain';
1
+ import { GraphResolveChain } from '../src/graph/registry/GraphResolveChain';
2
2
  import {
3
3
  ObjectGraph,
4
4
  Constructable,
@@ -7,9 +7,12 @@ import {
7
7
  Identifier,
8
8
  ObjectExpression,
9
9
  ObjectPattern,
10
+ TSParameterProperty,
10
11
  } from '@babel/types';
11
12
  import { get } from 'lodash';
12
13
 
14
+ const never = '';
15
+
13
16
  export function providerIsNotNamed(decorator: Decorator): boolean {
14
17
  const argument = getDecoratorArgument(decorator);
15
18
  if (t.isObjectExpression(argument)) {
@@ -44,8 +47,11 @@ export function getMethodName(node: ClassMethod): string {
44
47
  throw new Error(`Tried to get class name but encountered unexpected key of type: ${node.key.type}`);
45
48
  }
46
49
 
47
- export function getProviderDecorator(decorators: Array<Decorator> | undefined | null): Decorator | undefined {
48
- return decorators?.find((decorator) => get(decorator, 'expression.callee.name') === 'Provides');
50
+ export function getDecoratorByName(
51
+ decorators: Array<Decorator> | undefined | null,
52
+ decoratorName: string,
53
+ ): Decorator | undefined {
54
+ return decorators?.find((decorator) => get(decorator, 'expression.callee.name') === decoratorName);
49
55
  }
50
56
 
51
57
  export function getDecoratorName(decorator?: Decorator): string | undefined {
@@ -57,3 +63,21 @@ export function paramsToDestructuringAssignment(params: (Identifier | any)[]): O
57
63
  .filter((p) => t.isIdentifier(p))
58
64
  .map((p) => t.objectProperty(t.identifier(p.name), t.identifier(p.name))));
59
65
  }
66
+
67
+ export function passParamNameAsInjectArgument(node: Identifier | TSParameterProperty, decorator: Decorator) {
68
+ if (t.isCallExpression(decorator.expression)) {
69
+ decorator.expression.arguments = [
70
+ t.stringLiteral(getIdentifierOrParamName(node)),
71
+ ];
72
+ }
73
+ }
74
+
75
+ function getIdentifierOrParamName(node: Identifier | TSParameterProperty): string {
76
+ if (t.isTSParameterProperty(node)) {
77
+ if (t.isIdentifier(node.parameter)) {
78
+ return node.parameter.name;
79
+ }
80
+ return never;
81
+ }
82
+ return node.name;
83
+ }
@@ -1,12 +1,20 @@
1
1
  /* eslint-disable no-param-reassign */
2
- import { ClassMethod, Decorator, Program } from '@babel/types';
2
+ import {
3
+ ClassMethod,
4
+ Identifier,
5
+ Decorator,
6
+ Program,
7
+ TSParameterProperty,
8
+ } from '@babel/types';
3
9
  import { NodePath, PluginObj } from '@babel/core';
4
10
  import {
5
11
  addNameToProviderArguments,
6
12
  getDecoratorName,
7
- getProviderDecorator,
13
+ getDecoratorByName,
8
14
  paramsToDestructuringAssignment,
9
15
  providerIsNotNamed,
16
+ passParamNameAsInjectArgument,
17
+ getDecoratorArgument,
10
18
  } from './helpers';
11
19
 
12
20
  const providerArgumentsTransformer: PluginObj = {
@@ -20,15 +28,41 @@ const providerArgumentsTransformer: PluginObj = {
20
28
  const internalVisitor = {
21
29
  ClassMethod: {
22
30
  enter({ node }: NodePath<ClassMethod>) {
23
- const decorator = getProviderDecorator(node.decorators);
31
+ const decorator = getDecoratorByName(node.decorators, 'Provides');
24
32
  if (getDecoratorName(decorator) === 'Provides') {
25
33
  convertProviderParamsToDestructuringAssignment(node);
26
34
  saveUnmangledMethodNameInProviderArguments(node, decorator!);
27
35
  }
28
36
  },
29
37
  },
38
+ Identifier: {
39
+ enter({ node }: NodePath<Identifier>) {
40
+ const decorator = getDecoratorByName(node.decorators, 'Inject');
41
+ if (getDecoratorName(decorator) === 'Inject') {
42
+ saveUnmangledParamName(node, decorator!);
43
+ }
44
+ },
45
+ },
46
+ TSParameterProperty: {
47
+ enter({ node }: NodePath<TSParameterProperty>) {
48
+ const decorator = getDecoratorByName(node.decorators, 'Inject');
49
+ if (getDecoratorName(decorator) === 'Inject') {
50
+ saveUnmangledParamName(node, decorator!);
51
+ }
52
+ },
53
+ },
30
54
  };
31
55
 
56
+ function saveUnmangledParamName(node: Identifier | TSParameterProperty, decorator: Decorator) {
57
+ if (injectIsNotNamed(decorator)) {
58
+ passParamNameAsInjectArgument(node, decorator);
59
+ }
60
+ }
61
+
62
+ function injectIsNotNamed(decorator: Decorator): boolean {
63
+ return getDecoratorArgument(decorator) === undefined;
64
+ }
65
+
32
66
  function convertProviderParamsToDestructuringAssignment(node: ClassMethod) {
33
67
  if (node.params.length === 0) return;
34
68
  const destructuredParams = paramsToDestructuringAssignment(node.params);
@@ -1,11 +0,0 @@
1
- import { Scope } from './types';
2
- declare class ScopedValuesRegistry {
3
- private readonly values;
4
- has(scope: Scope, property: string): boolean;
5
- get(scope: Scope, property: string): any;
6
- set(scope: Scope, property: string, value: any): void;
7
- clear(scope: Scope, property: string): void;
8
- }
9
- declare const _default: ScopedValuesRegistry;
10
- export default _default;
11
- //# sourceMappingURL=ScopedValuesRegistry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScopedValuesRegistry.d.ts","sourceRoot":"","sources":["../../src/ScopedValuesRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,cAAM,oBAAoB;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IAEtD,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI5C,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG;IAOxC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG;IAI9C,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM;CAGrC;;AAED,wBAA0C"}