react-obsidian 0.0.32 → 0.0.33

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 (73) hide show
  1. package/.eslintrc.json +3 -0
  2. package/README.md +21 -326
  3. package/dist/src/graph/registry/GraphResolveChain.d.ts +1 -1
  4. package/dist/src/graph/registry/GraphResolveChain.d.ts.map +1 -1
  5. package/dist/src/index.d.ts +2 -0
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +5 -1
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/injectors/hooks/HookInjector.js +1 -1
  10. package/dist/src/injectors/hooks/HookInjector.js.map +1 -1
  11. package/dist/src/observable/Observable.d.ts +12 -0
  12. package/dist/src/observable/Observable.d.ts.map +1 -0
  13. package/dist/src/observable/Observable.js +31 -0
  14. package/dist/src/observable/Observable.js.map +1 -0
  15. package/dist/src/observable/useObserver.d.ts +3 -0
  16. package/dist/src/observable/useObserver.d.ts.map +1 -0
  17. package/dist/src/observable/useObserver.js +18 -0
  18. package/dist/src/observable/useObserver.js.map +1 -0
  19. package/dist/src/types/index.d.ts +8 -8
  20. package/dist/src/types/index.d.ts.map +1 -1
  21. package/dist/src/utils/React.d.ts +1 -1
  22. package/dist/src/utils/React.d.ts.map +1 -1
  23. package/dist/test/fixtures/LifecycleBoundGraph.d.ts +7 -2
  24. package/dist/test/fixtures/LifecycleBoundGraph.d.ts.map +1 -1
  25. package/dist/test/fixtures/LifecycleBoundGraph.js +15 -3
  26. package/dist/test/fixtures/LifecycleBoundGraph.js.map +1 -1
  27. package/dist/test/fixtures/MainGraph.d.ts +1 -1
  28. package/dist/test/fixtures/MainGraph.d.ts.map +1 -1
  29. package/dist/transformers/babel-plugin-obsidian/helpers/index.d.ts +1 -1
  30. package/dist/transformers/babel-plugin-obsidian/helpers/index.d.ts.map +1 -1
  31. package/documentation/README.md +41 -0
  32. package/documentation/babel.config.js +3 -0
  33. package/documentation/blog/2019-05-28-first-blog-post.md +12 -0
  34. package/documentation/blog/2019-05-29-long-blog-post.md +44 -0
  35. package/documentation/blog/2021-08-01-mdx-blog-post.mdx +20 -0
  36. package/documentation/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  37. package/documentation/blog/2021-08-26-welcome/index.md +25 -0
  38. package/documentation/blog/authors.yml +17 -0
  39. package/documentation/docs/documentation/documentation.mdx +191 -0
  40. package/documentation/docs/documentation/installation.mdx +65 -0
  41. package/documentation/docs/documentation/meta/clearingGraphs.mdx +13 -0
  42. package/documentation/docs/documentation/meta/middlewares.mdx +27 -0
  43. package/documentation/docs/documentation/usage/ClassComponents.mdx +18 -0
  44. package/documentation/docs/documentation/usage/Classes.mdx +41 -0
  45. package/documentation/docs/documentation/usage/FunctionalComponents.mdx +57 -0
  46. package/documentation/docs/documentation/usage/Graphs.mdx +146 -0
  47. package/documentation/docs/documentation/usage/Hooks.mdx +85 -0
  48. package/documentation/docs/documentation/usage/ServiceLocator.mdx +38 -0
  49. package/documentation/docs/documentation/usage/_category_.json +9 -0
  50. package/documentation/docs/guides/configurableApplications.mdx +205 -0
  51. package/documentation/docs/guides/mockDependencies.mdx +141 -0
  52. package/documentation/docusaurus.config.js +146 -0
  53. package/documentation/package-lock.json +21290 -0
  54. package/documentation/package.json +46 -0
  55. package/documentation/sidebars.js +34 -0
  56. package/documentation/src/components/HomepageFeatures/index.tsx +71 -0
  57. package/documentation/src/components/HomepageFeatures/styles.module.css +11 -0
  58. package/documentation/src/css/custom.css +30 -0
  59. package/documentation/src/pages/index.module.css +23 -0
  60. package/documentation/src/pages/index.tsx +41 -0
  61. package/documentation/static/.nojekyll +0 -0
  62. package/documentation/static/img/api.svg +101 -0
  63. package/documentation/static/img/favicon.ico +0 -0
  64. package/documentation/static/img/logo.svg +265 -0
  65. package/documentation/static/img/obsidian.png +0 -0
  66. package/documentation/static/img/prototype.svg +1 -0
  67. package/documentation/static/img/stethoscope.svg +37 -0
  68. package/documentation/tsconfig.json +7 -0
  69. package/package.json +4 -4
  70. package/src/index.ts +3 -0
  71. package/src/injectors/hooks/HookInjector.ts +1 -1
  72. package/src/observable/Observable.ts +26 -0
  73. package/src/observable/useObserver.ts +17 -0
@@ -29,18 +29,30 @@ var src_1 = require("../../src");
29
29
  var LifecycleBound_1 = require("../../src/decorators/LifecycleBound");
30
30
  var LifecycleBoundGraph = /** @class */ (function (_super) {
31
31
  __extends(LifecycleBoundGraph, _super);
32
- function LifecycleBoundGraph() {
33
- var _this = _super.call(this) || this;
32
+ function LifecycleBoundGraph(props) {
33
+ var _this = _super.call(this, props) || this;
34
+ _this.props = props;
34
35
  LifecycleBoundGraph_1.timesCreated++;
35
36
  return _this;
36
37
  }
37
38
  LifecycleBoundGraph_1 = LifecycleBoundGraph;
39
+ LifecycleBoundGraph.prototype.computedFromProps = function () {
40
+ return this.props.stringFromProps
41
+ ? "A string passed via props: ".concat(this.props.stringFromProps)
42
+ : 'stringFromProps does not exist';
43
+ };
38
44
  var LifecycleBoundGraph_1;
39
45
  LifecycleBoundGraph.timesCreated = 0;
46
+ __decorate([
47
+ (0, src_1.Provides)(),
48
+ __metadata("design:type", Function),
49
+ __metadata("design:paramtypes", []),
50
+ __metadata("design:returntype", String)
51
+ ], LifecycleBoundGraph.prototype, "computedFromProps", null);
40
52
  LifecycleBoundGraph = LifecycleBoundGraph_1 = __decorate([
41
53
  (0, LifecycleBound_1.LifecycleBound)(),
42
54
  (0, src_1.Graph)(),
43
- __metadata("design:paramtypes", [])
55
+ __metadata("design:paramtypes", [Object])
44
56
  ], LifecycleBoundGraph);
45
57
  return LifecycleBoundGraph;
46
58
  }(src_1.ObjectGraph));
@@ -1 +1 @@
1
- {"version":3,"file":"LifecycleBoundGraph.js","sourceRoot":"","sources":["../../../test/fixtures/LifecycleBoundGraph.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iCAA+C;AAC/C,sEAAqE;AAGrE;IAAyC,uCAAW;IAGlD;QAAA,YACE,iBAAO,SAER;QADC,qBAAmB,CAAC,YAAY,EAAE,CAAC;;IACrC,CAAC;4BANU,mBAAmB;;IACvB,gCAAY,GAAG,CAAC,CAAC;IADb,mBAAmB;QAD/B,IAAA,+BAAc,GAAE;QAAE,IAAA,WAAK,GAAE;;OACb,mBAAmB,CAO/B;IAAD,0BAAC;CAAA,AARD,CACyC,iBAAW,GAOnD;AAPY,kDAAmB"}
1
+ {"version":3,"file":"LifecycleBoundGraph.js","sourceRoot":"","sources":["../../../test/fixtures/LifecycleBoundGraph.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iCAAyD;AACzD,sEAAqE;AAKrE;IAAiD,uCAAsB;IAIrE,6BAAY,KAAgB;QAA5B,YACE,kBAAM,KAAK,CAAC,SAGb;QAFC,KAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,qBAAmB,CAAC,YAAY,EAAE,CAAC;;IACrC,CAAC;4BARU,mBAAmB;IAW9B,+CAAiB,GADjB;QAEE,OAAO,IAAI,CAAC,KAAK,CAAC,eAAe;YAC/B,CAAC,CAAC,qCAA8B,IAAI,CAAC,KAAK,CAAC,eAAe,CAAE;YAC5D,CAAC,CAAC,gCAAgC,CAAC;IACvC,CAAC;;IAdM,gCAAY,GAAG,CAAC,CAAC;IASxB;QAAC,IAAA,cAAQ,GAAE;;;;gEAKV;IAfU,mBAAmB;QAD/B,IAAA,+BAAc,GAAE;QAAE,IAAA,WAAK,GAAE;;OACb,mBAAmB,CAgB/B;IAAD,0BAAC;CAAA,AAjBD,CACiD,iBAAW,GAgB3D;AAhBY,kDAAmB"}
@@ -1,7 +1,7 @@
1
1
  import { ObjectGraph, DependenciesOf } from '../../src';
2
2
  import StringProvider from './StringProvider';
3
3
  import Subgraph from './Subgraph';
4
- export declare type Dependencies = DependenciesOf<[MainGraph, Subgraph]>;
4
+ export type Dependencies = DependenciesOf<[MainGraph, Subgraph]>;
5
5
  export default class MainGraph extends ObjectGraph {
6
6
  someString(stringProvider: StringProvider): string;
7
7
  anotherString(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"MainGraph.d.ts","sourceRoot":"","sources":["../../../test/fixtures/MainGraph.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAEX,cAAc,EACf,MAAM,WAAW,CAAC;AAEnB,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,oBAAY,YAAY,GAAG,cAAc,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGjE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAEhD,UAAU,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM;IAKlD,aAAa,IAAI,MAAM;CAGxB"}
1
+ {"version":3,"file":"MainGraph.d.ts","sourceRoot":"","sources":["../../../test/fixtures/MainGraph.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAEX,cAAc,EACf,MAAM,WAAW,CAAC;AAEnB,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGjE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAEhD,UAAU,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM;IAKlD,aAAa,IAAI,MAAM;CAGxB"}
@@ -1,5 +1,5 @@
1
1
  import { ClassMethod, ClassProperty, Decorator, Identifier, ObjectExpression, ObjectPattern, TSParameterProperty } from '@babel/types';
2
- export declare type AcceptedNodeType = Identifier | TSParameterProperty | ClassProperty;
2
+ export type AcceptedNodeType = Identifier | TSParameterProperty | ClassProperty;
3
3
  export declare function providerIsNotNamed(decorator: Decorator): boolean;
4
4
  export declare function addNameToProviderArguments(node: ClassMethod, decorator: Decorator): void;
5
5
  export declare function getDecoratorArgument(decorator: Decorator): ObjectExpression | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../transformers/babel-plugin-obsidian/helpers/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,WAAW,EACX,aAAa,EACb,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAKtB,oBAAY,gBAAgB,GAAG,UAAU,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAEhF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAWhE;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,QAOjF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAKvF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAGvD;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI,EAC/C,aAAa,EAAE,MAAM,GACpB,SAAS,GAAG,SAAS,CAEvB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,EAAE,GAAG,aAAa,CAI3F;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,SAAS,QAOrB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../transformers/babel-plugin-obsidian/helpers/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,WAAW,EACX,aAAa,EACb,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAKtB,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAEhF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAWhE;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,QAOjF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAKvF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAGvD;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI,EAC/C,aAAa,EAAE,MAAM,GACpB,SAAS,GAAG,SAAS,CAEvB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,EAAE,GAAG,aAAa,CAI3F;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,SAAS,QAOrB"}
@@ -0,0 +1,41 @@
1
+ # Website
2
+
3
+ This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4
+
5
+ ### Installation
6
+
7
+ ```
8
+ $ yarn
9
+ ```
10
+
11
+ ### Local Development
12
+
13
+ ```
14
+ $ yarn start
15
+ ```
16
+
17
+ This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18
+
19
+ ### Build
20
+
21
+ ```
22
+ $ yarn build
23
+ ```
24
+
25
+ This command generates static content into the `build` directory and can be served using any static contents hosting service.
26
+
27
+ ### Deployment
28
+
29
+ Using SSH:
30
+
31
+ ```
32
+ $ USE_SSH=true yarn deploy
33
+ ```
34
+
35
+ Not using SSH:
36
+
37
+ ```
38
+ $ GIT_USER=<Your GitHub username> yarn deploy
39
+ ```
40
+
41
+ If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3
+ };
@@ -0,0 +1,12 @@
1
+ ---
2
+ slug: first-blog-post
3
+ title: First Blog Post
4
+ authors:
5
+ name: Gao Wei
6
+ title: Docusaurus Core Team
7
+ url: https://github.com/wgao19
8
+ image_url: https://github.com/wgao19.png
9
+ tags: [hola, docusaurus]
10
+ ---
11
+
12
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
@@ -0,0 +1,44 @@
1
+ ---
2
+ slug: long-blog-post
3
+ title: Long Blog Post
4
+ authors: endi
5
+ tags: [hello, docusaurus]
6
+ ---
7
+
8
+ This is the summary of a very long blog post,
9
+
10
+ Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
11
+
12
+ <!--truncate-->
13
+
14
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
15
+
16
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
17
+
18
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
19
+
20
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
21
+
22
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
23
+
24
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
25
+
26
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
27
+
28
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
29
+
30
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
31
+
32
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
33
+
34
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
35
+
36
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
37
+
38
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
39
+
40
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
41
+
42
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
43
+
44
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
@@ -0,0 +1,20 @@
1
+ ---
2
+ slug: mdx-blog-post
3
+ title: MDX Blog Post
4
+ authors: [slorber]
5
+ tags: [docusaurus]
6
+ ---
7
+
8
+ Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
9
+
10
+ :::tip
11
+
12
+ Use the power of React to create interactive blog posts.
13
+
14
+ ```js
15
+ <button onClick={() => alert('button clicked!')}>Click me!</button>
16
+ ```
17
+
18
+ <button onClick={() => alert('button clicked!')}>Click me!</button>
19
+
20
+ :::
@@ -0,0 +1,25 @@
1
+ ---
2
+ slug: welcome
3
+ title: Welcome
4
+ authors: [slorber, yangshun]
5
+ tags: [facebook, hello, docusaurus]
6
+ ---
7
+
8
+ [Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
9
+
10
+ Simply add Markdown files (or folders) to the `blog` directory.
11
+
12
+ Regular blog authors can be added to `authors.yml`.
13
+
14
+ The blog post date can be extracted from filenames, such as:
15
+
16
+ - `2019-05-30-welcome.md`
17
+ - `2019-05-30-welcome/index.md`
18
+
19
+ A blog post folder can be convenient to co-locate blog post images:
20
+
21
+ ![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)
22
+
23
+ The blog supports tags as well!
24
+
25
+ **And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
@@ -0,0 +1,17 @@
1
+ endi:
2
+ name: Endilie Yacop Sucipto
3
+ title: Maintainer of Docusaurus
4
+ url: https://github.com/endiliey
5
+ image_url: https://github.com/endiliey.png
6
+
7
+ yangshun:
8
+ name: Yangshun Tay
9
+ title: Front End Engineer @ Facebook
10
+ url: https://github.com/yangshun
11
+ image_url: https://github.com/yangshun.png
12
+
13
+ slorber:
14
+ name: Sébastien Lorber
15
+ title: Docusaurus maintainer
16
+ url: https://sebastienlorber.com
17
+ image_url: https://github.com/slorber.png
@@ -0,0 +1,191 @@
1
+ ---
2
+ sidebar_position: 1
3
+ ---
4
+
5
+ import Tabs from '@theme/Tabs';
6
+ import TabItem from '@theme/TabItem';
7
+
8
+
9
+ # Introduction
10
+
11
+ Obsidian is a dependency injection container with first-class support for React and React Native applications.
12
+
13
+ Get started by **following the installation guide** bellow.
14
+ <!-- Or **try Obsidian immediately** in the **[Online Playground](https://docusaurus.new)**. -->
15
+
16
+ ## The 2 steps tutorial for injecting dependencies with Obsidian
17
+
18
+ ### Step 1: Declare how dependencies should be created
19
+
20
+ Define a singleton graph that is instantiated once and is retained throughout the lifespan of the application. All dependencies it provides are also singletons. The graph bellow provides two dependencies that can be injected: `fooService` and `barManager`.
21
+ ```ts title="A singleton graph that provides two dependencies"
22
+ import {Singleton, Graph, ObjectGraph, Provides} from 'react-obsidian';
23
+
24
+
25
+ @Singleton() @Graph()
26
+ export class ApplicationGraph extends ObjectGraph {
27
+
28
+ // fooService requires a barManager so it receives one as a parameter.
29
+ @Provides()
30
+ fooService(barManager: BarManager): FooService {
31
+ return new FooService(barManager);
32
+ }
33
+
34
+
35
+ @Provides()
36
+ barManager(): BarManager {
37
+ return new BarManager();
38
+ }
39
+ }
40
+ ```
41
+
42
+ ### Step 2: Inject the dependencies
43
+ Obsidian can inject dependencies into components, hooks, and classes.
44
+
45
+
46
+
47
+ <Tabs>
48
+ <TabItem value="functionalComponent" label="Functional component injection" default>
49
+
50
+ Injecting React functional components essentially revolves around two things: declaring the required dependencies in the hook's prototype and exporting an injected hook using the `injectComponent` function.
51
+
52
+ ```ts title="MyComponent.tsx"
53
+ import {DependenciesOf, injectComponent} from 'react-obsidian';
54
+ import {ApplicationGraph} from './ApplicationGraph';
55
+
56
+ // 1. Declare which dependencies should be injected.
57
+ type Props = DependenciesOf<ApplicationGraph, 'fooService'>; // {fooService: FooService}
58
+
59
+ // 2. Implement the component.
60
+ const myComponent = ({fooService}: Props) => {
61
+ // Do something useful with fooService
62
+ }
63
+
64
+ // 3. Export the injected component.
65
+ export default injectComponent(myComponent, ApplicationGraph);
66
+ ```
67
+
68
+ Now we can use the injected component without providing its dependencies manually:
69
+ ```tsx title="SomeComponent.tsx"
70
+ import MyComponent from './MyComponent';
71
+
72
+ const SomeComponent = () => {
73
+ // 4. Render the component - its dependencies are resolved automatically by Obsidian.
74
+ return <MyComponent />;
75
+ }
76
+ ```
77
+ </TabItem>
78
+ <TabItem value="hook" label="Hook injection">
79
+
80
+ Hooks are injected in a similar way to functional components. The only difference is that the `injectHook` function is used instead of `injectComponent`.
81
+
82
+ ```ts title="MyHook.ts"
83
+ import {DependenciesOf, injectHook} from 'react-obsidian';
84
+ import {ApplicationGraph} from './ApplicationGraph';
85
+
86
+ // 1. Declare which dependencies should be injected.
87
+ type Props = DependenciesOf<ApplicationGraph, 'fooService'>; // {fooService: FooService}
88
+
89
+ // 2. Implement the hook.
90
+ const myHook = ({fooService}: Props) => {
91
+ // Do something useful with fooService
92
+ }
93
+
94
+ // 3. Export the injected hook.
95
+ export default injectHook(myHook, ApplicationGraph);
96
+ ```
97
+
98
+ The injected hook can be used without providing its dependencies manually:
99
+ ```tsx title="SomeComponent.tsx"
100
+ import myHook from './MyHook';
101
+
102
+ const SomeComponent = () => {
103
+ // 4. Use the hook without providing any dependencies manually - they are injected automatically.
104
+ myHook();
105
+
106
+ return <>Obsidian is awesome!</>;
107
+ }
108
+ ```
109
+ </TabItem>
110
+ <TabItem value="classComponent" label="Class component injection">
111
+
112
+ To inject a class, annotate it with the `@Injectable` decorator. The `@Injectable` decorator takes a single parameter - the graph that should be used to resolve the dependencies. Declare the dependencies as class members and annotate them with the `@Inject` decorator.
113
+
114
+ ```ts title="MyComponent.tsx"
115
+ import {Injectable, Inject} from 'react-obsidian';
116
+ import {ApplicationGraph} from './ApplicationGraph';
117
+
118
+ @Injectable(ApplicationGraph)
119
+ export MyClassComponent extends React.Component {
120
+ @Inject() private fooService!: FooService;
121
+
122
+ }
123
+ ```
124
+
125
+ Render the injected component. Obsidian resolves the required dependencies automatically.
126
+ ```tsx title="SomeComponent.tsx"
127
+ import MyComponent from './MyComponent';
128
+
129
+ const SomeComponent = () => {
130
+ // 4. Render the component - its dependencies are resolved automatically by Obsidian.
131
+ return <MyComponent />;
132
+ }
133
+ ```
134
+
135
+ </TabItem>
136
+ <TabItem value="class" label="Class constructor injection">
137
+
138
+ To inject a class, annotate it with the `@Injectable` decorator. The `@Injectable` decorator takes a single parameter - the graph that should be used to resolve the dependencies.
139
+ Declare the dependencies as constructor parameters and annotate them with the `@Inject` decorator.
140
+
141
+ ```ts title="MyClass.tsx"
142
+ import {Injectable, Inject} from 'react-obsidian';
143
+ import {ApplicationGraph} from './ApplicationGraph';
144
+
145
+ @Injectable(ApplicationGraph)
146
+ export MyClass {
147
+ constructor (fooService?: FooService);
148
+ constructor(@Inject() private fooService: FooService) { }
149
+ }
150
+ ```
151
+
152
+ Now we can use the injected class without providing its dependencies manually:
153
+ ```ts
154
+ const myClass = new MyClass();
155
+ ```
156
+
157
+ Of course, passing dependencies explicitly is still possible:
158
+ ```ts
159
+ const myClass = new MyClass(new FooService());
160
+ ```
161
+
162
+ </TabItem>
163
+ </Tabs>
164
+
165
+ ___
166
+
167
+ ## Features
168
+
169
+ * ⚛️ Inject all React constructs
170
+ * Functional components
171
+ * Hooks
172
+ * Class components
173
+ * 🛠 Improve code structure
174
+ * Easily write object-oriented code with Single Responsibility in mind
175
+ * Eliminate circular dependencies
176
+ * Avoid implicit dependencies to make your code easier to reason about
177
+ * ❤️ Developer experience
178
+ * Seamlessly integrates into existing projects
179
+ * Easy to adopt gradually
180
+ * Scales well
181
+ * Idiomatic API that's easy to understand
182
+
183
+ ## Design principles
184
+
185
+ React Obsidian is guided by the principles of the Dependency Injection pattern, but does not strictly follow them. We allowed ourselves a degree of freedom when designing the library in order to reduce boilerplate code and library footprint.
186
+
187
+ * **Easy to start** - Obsidian requires very little code to get you started. Once you declare a graph, using it to inject dependencies requires as little as two lines of code.
188
+ * **Intuitive API** - The API should be verbose and understandable even to new users without prior experience with Dependency Injection.
189
+ * **Minimal boilerplate** - Require the bare minimum in order to construct dependencies and resolve them.
190
+
191
+ <!-- ## Comparison with other libraries -->
@@ -0,0 +1,65 @@
1
+ ---
2
+ sidebar_position: 2
3
+ ---
4
+
5
+ # Installation
6
+
7
+ Like most Dependency Injection frameworks, Obsidian uses automatic code generation to create the bindings necessary for resolving dependencies. This approach helps reduce the amount of boilerplate code required by developers. Obsidian relies on Babel for code generation, so you'll need to have Babel configured in your project.
8
+
9
+ ## 1. Install Obsidian
10
+
11
+ ```bash
12
+ npm install react-obsidian
13
+ ```
14
+
15
+ ## 2. Install Reflect-metadata
16
+ First, install and enable the reflect-metadata polyfill.
17
+ ```bash
18
+ npm install reflect-metadata
19
+ ```
20
+
21
+ Then, add the following line to the top of your application's entry point (usually index.js or index.ts):
22
+ ```js
23
+ import 'reflect-metadata';
24
+ ```
25
+
26
+ ## 3. Enable experimental decorators
27
+ Obsidian uses the Decorators feature whose proposal is at stage 3.
28
+
29
+ Add the following options to your tsconfig.json file.
30
+
31
+ ```js
32
+ {
33
+ "compilerOptions": {
34
+ "experimentalDecorators": true,
35
+ "emitDecoratorMetadata": true
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## 4. Add the required Babel plugins
41
+ Add the transformer to the list of plugins in your `.babel` file.
42
+
43
+ ```diff
44
+ module.exports = {
45
+ presets: [
46
+ 'module:metro-react-native-babel-preset',
47
+ + ['@babel/preset-typescript', {'onlyRemoveTypeImports': true}]
48
+ ],
49
+ plugins: [
50
+ + react-obsidian/dist/transformers/babel-plugin-obsidian,
51
+ + ['@babel/plugin-proposal-decorators', {legacy: true}],
52
+ + ['@babel/plugin-proposal-class-properties', { legacy: true }],
53
+ + 'babel-plugin-parameter-decorator'
54
+ ]
55
+ };
56
+ ```
57
+
58
+ ## 5. Jest
59
+ If you're using Jest, you'll need to add react-obsidian to [transformIgnorePatterns](https://jestjs.io/docs/configuration#transformignorepatterns-arraystring) so it's transpiled before tests are executed.
60
+
61
+ ## 6. Peer Dependencies
62
+ Obsidian has a peer dependency on `lodash`.
63
+
64
+
65
+
@@ -0,0 +1,13 @@
1
+ ---
2
+ sidebar_position: 2
3
+ title: "Clearing graphs"
4
+ ---
5
+
6
+ Graphs can be cleared by invoking the `Obsidian.clearGraphs()` function. This is useful in tests or when you need to reset the system to it's original state, for example after a user logs out.
7
+
8
+ #### Clearing graphs automatically during execution of Jest tests
9
+ Create a `jest.setup.js` file and add it to [setupFilesAfterEnv](https://jestjs.io/docs/configuration#setupfilesafterenv-array). Then, import the following file when ensures graphs are cleared before each test.
10
+
11
+ ```js
12
+ import 'react-obsidian/clearGraphs';
13
+ ```
@@ -0,0 +1,27 @@
1
+ ---
2
+ sidebar_position: 1
3
+ title: "Graph middlewares"
4
+ ---
5
+
6
+ Graph middlewares let you plug into the graph creation process and modify the graph in any way you want. This is useful when working on large scale applications where "observability" is a key concern. For example, you can use a middleware to swizzle providers, add logging, or even add a new provider to the graph.
7
+
8
+ Middleware follow the Chain of Responsibility pattern and therefore must always return a graph, either by creating one explicitly or by returning the instance created by another member in the resolve chain.
9
+
10
+ ## Example: adding a logging middleware
11
+ The following example demonstrates how to add a middleware that's used for logging purposes.
12
+
13
+ ```ts
14
+ import { GraphMiddleware } from 'react-obsidian';
15
+
16
+ const loggingMiddleware = new class extends GraphMiddleware {
17
+ resolve<Props>(resolveChain: GraphResolveChain, Graph: Constructable<T>, props?: Props) {
18
+ const t1 = Date.now();
19
+ const graph = resolveChain.proceed(Graph, props);
20
+ const t2 = Date.now();
21
+ console.log(`Graph created in ${t2 - t1} milliseconds`);
22
+ return graph;
23
+ }
24
+ }();
25
+
26
+ Obsidian.addGraphMiddleware(loggingMiddleware);
27
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ sidebar_position: 4
3
+ title: "Class components"
4
+ ---
5
+
6
+ ## Injecting class components
7
+ Injecting class components is a two step process. First, annotate the class with the `@Injectable` annotation and pass the graph from which dependencies should be resolve. Then, declare the dependencies as class members and annotate them with the `@Inject` annotation.
8
+
9
+ ```ts
10
+ import {Injectable, Inject} from 'react-obsidian';
11
+ import {ApplicationGraph} from './ApplicationGraph';
12
+
13
+ @Injectable(ApplicationGraph)
14
+ export class ClassComponent extends React.Component {
15
+ @Inject() private httpClient!: HttpClient;
16
+
17
+ }
18
+ ```
@@ -0,0 +1,41 @@
1
+ ---
2
+ sidebar_position: 5
3
+ title: "Classes"
4
+ ---
5
+
6
+ ## Injecting classes
7
+ Injecting classes is a two step process. First, annotate the class with the `@Injectable` annotation and pass the graph from which dependencies should be resolve. Then, declare the dependencies as class members and annotate them with the `@Inject` annotation.
8
+
9
+ ```ts
10
+ import {Injectable, Inject} from 'react-obsidian';
11
+ import {ApplicationGraph} from './ApplicationGraph';
12
+
13
+ @Injectable(ApplicationGraph)
14
+ export class MyClass {
15
+ @Inject() private httpClient!: HttpClient;
16
+
17
+ }
18
+ ```
19
+
20
+ :::important Always prefer constructor injection over field injection
21
+ Constructor injection is the preferred way to inject dependencies. It is more explicit and easier to test. **Field injection should only be used when a class is not instantiated by a graph.**
22
+ :::
23
+
24
+ ## Lazy injection
25
+ Dependencies annotated with the `@Inject` annotation are resolved immediately **after** the constructor is called. If you want to inject a class at a later point in time, you can use the `@LazyInject` annotation instead, and inject the dependencies by manually with the `Obsidian.inject()` function.
26
+
27
+ ```ts
28
+ import {Injectable, LazyInject} from 'react-obsidian';
29
+ import {ApplicationGraph} from './ApplicationGraph';
30
+
31
+ @Injectable(ApplicationGraph)
32
+ export class MyClass {
33
+ @LazyInject() private httpClient!: HttpClient;
34
+
35
+ public init() {
36
+ console.log(this.httpClient === undefined); // true
37
+ Obsidian.inject(this);
38
+ console.log(this.httpClient === undefined); // false
39
+ }
40
+ }
41
+ ```
@@ -0,0 +1,57 @@
1
+ ---
2
+ sidebar_position: 3
3
+ title: "Functional components"
4
+ ---
5
+
6
+ ## Injecting functional components
7
+ Component injection is identical in principle to how hooks are injected. The only difference is that instead of using the `injectHook` function, you use the `injectComponent` function. The `injectComponent` function takes the same arguments as the `injectHook` function, except that it takes a component as the second argument instead of a hook.
8
+
9
+ ```tsx title="Injecting a functional component"
10
+ import { injectComponent, DependenciesOf } from 'react-obsidian';
11
+ import { ApplicationGraph } from './ApplicationGraph';
12
+
13
+ const MyComponent = ({httpService}: DependenciesOf<ApplicationGraph, 'httpClient'>) => {
14
+ return <div>My component</div>
15
+ }
16
+
17
+ export default injectComponent(MyComponent, ApplicationGraph);
18
+ ```
19
+
20
+ :::tip Prefer injecting hooks over components
21
+ Every entity (class, functional component etc.) in your application should have a single responsibility, and as such, there should be only one reason to change it. Components are responsible for rendering the UI, and therefor should change only when UI requirements change.
22
+
23
+ Prefer injecting hooks that will bridge between components and application logic. This allows components to emphasize "what" they need instead of "how", thus, preventing implementation details from leaking into them.
24
+ :::
25
+
26
+ ## Strongly typed components
27
+ The `injectComponent` function leverages *generics* to correctly type injected components.
28
+
29
+ ### Typing components that require props and injected dependencies
30
+ In cases where a component requires both props and injected dependencies, we recommend typing them separately and declaring the component's props as the intersection of the two types. This way the component returned by the `injectComponent` function will require its `Own` props while all `Injected` dependencies will be marked as optional. `Injected` dependencies are marked as optional because they can either be injected manually or automatically by Obsidian.
31
+
32
+ ```tsx title="Separate declaration for passed (own) props and injected dependencies"
33
+ import { injectComponent, DependenciesOf } from 'react-obsidian';
34
+ import {ApplicationGraph} from './ApplicationGraph';
35
+
36
+ type Injected = DependenciesOf<ApplicationGraph, 'httpClient'>;
37
+ type Own = {name: string};
38
+
39
+ const MyComponent = ({name, httpService}: Own & Injected) => {
40
+ return <div>Hey, my name is: {name} 👋</div>
41
+ }
42
+
43
+ // The result type is React.FunctionComponent<{name: string , httpClient?: HttpClient}>
44
+ export default injectComponent<Own, Injected>(MyComponent, ApplicationGraph);
45
+ ```
46
+
47
+ ### Typing components that don't require Props
48
+ If a component doesn't require any props from its parent component, simply use the `DependenciesOf` utility type provided by Obsidian to type the component's props. There's no need to use generics in this case as all props will are marked as optional.
49
+
50
+ ```tsx title="Typing components that don't require props"
51
+ const MyComponent = ({httpService}: DependenciesOf<ApplicationGraph, 'httpClient'>) => {
52
+ return <div>Hello world 👋</div>
53
+ }
54
+
55
+ // The result type is React.FunctionComponent<{httpClient?: HttpClient}>
56
+ export default injectComponent(MyComponent, ApplicationGraph);
57
+ ```