Skip to content

Commit

Permalink
feat: Added tools for creating controllers and view controllers which…
Browse files Browse the repository at this point in the history
… are compatible with Ditox.js dependency container.
  • Loading branch information
mnasyrov committed Dec 10, 2022
1 parent 489a12e commit bccac56
Show file tree
Hide file tree
Showing 10 changed files with 646 additions and 123 deletions.
659 changes: 537 additions & 122 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
"@types/shelljs": "0.8.11",
"@typescript-eslint/eslint-plugin": "5.30.3",
"@typescript-eslint/parser": "5.30.3",
"ditox": "2.2.0",
"ditox-react": "2.2.0",
"eslint": "8.19.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-eslint-comments": "3.2.0",
Expand Down
1 change: 1 addition & 0 deletions packages/rx-effects-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"rx-effects": "0.7.2"
},
"peerDependencies": {
"ditox-react": ">=2.2.0",
"react": ">=17.0.0",
"rxjs": ">=7.0.0"
},
Expand Down
1 change: 1 addition & 0 deletions packages/rx-effects-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './useObserver';
export * from './useSelector';
export * from './useQuery';
export * from './useStore';
export * from './mvc';
43 changes: 43 additions & 0 deletions packages/rx-effects-react/src/mvc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { declareModule, Token } from 'ditox';
import { DependencyModule, useDependencyContainer } from 'ditox-react';
import React, { FC, useEffect, useMemo } from 'react';
import { Controller, ControllerFactory } from 'rx-effects';

type AnyObject = Record<string, any>;

export function useInjectableController<Result extends Record<string, unknown>>(
factory: ControllerFactory<Result>,
): Controller<Result> {
const container = useDependencyContainer('strict');
const controller = useMemo(() => factory(container), [container, factory]);

useEffect(() => () => controller.destroy(), [controller]);

return controller;
}

export const useViewController = useInjectableController;

export function useControllerFactory<Args extends unknown[], Result>(
factoryDeclaration: (...args: Args) => ControllerFactory<Controller<Result>>,
...args: Args
): Controller<Result> {
const controllerFactory = useMemo(
() => factoryDeclaration(...args),
// eslint-disable-next-line react-hooks/exhaustive-deps
[factoryDeclaration, ...args],
);

return useInjectableController<Controller<Result>>(controllerFactory);
}

export function createViewControllerContainer<T extends AnyObject>(
token: Token<T>,
factory: ControllerFactory<T>,
): FC {
const module = declareModule({ factory, token });

return ({ children }) => (
<DependencyModule module={module}>{children}</DependencyModule>
);
}
2 changes: 1 addition & 1 deletion packages/rx-effects-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"jsx": "react"
"jsx": "react-jsx"
}
}
1 change: 1 addition & 0 deletions packages/rx-effects/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"build:esm": "tsc -p tsconfig.build.json --outDir dist/esm --module es2015"
},
"peerDependencies": {
"ditox": ">=2.2.0",
"rxjs": ">=7.0.0"
},
"gitHead": "666d5b8672ebe6cb02174366a799d1da27d387a9"
Expand Down
2 changes: 2 additions & 0 deletions packages/rx-effects/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export { createScope } from './scope';

export type { Controller } from './controller';

export * from './mvc';

export type { Query, QueryOptions } from './query';
export { mapQuery, mergeQueries } from './queryMappers';

Expand Down
55 changes: 55 additions & 0 deletions packages/rx-effects/src/mvc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Container, injectable, Token } from 'ditox';
import { Controller } from './controller';
import { createScope, Scope } from './scope';

export function createController<T>(
factory: (scope: Scope) => T & { destroy?: () => void },
): Controller<T> {
const scope = createScope();

const controller = factory(scope);

return {
...controller,

destroy: () => {
controller?.destroy?.();
scope.destroy();
},
};
}

export type ControllerFactory<Result> = (
container: Container,
) => Controller<Result>;

export type InferredService<Factory> = Factory extends ControllerFactory<
infer Service
>
? Service
: never;

declare type ValuesProps = {
[key: string]: unknown;
};
declare type TokenProps<Props extends ValuesProps> = {
[K in keyof Props]: Token<Props[K]>;
};

export function createInjectableController<Props extends ValuesProps, Result>(
tokens: TokenProps<Props>,
factory: (scope: Scope, props: Props) => Result,
): ControllerFactory<Result> {
return injectable(
(props) => createController((scope) => factory(scope, props as Props)),
tokens,
);
}

export const createViewController = createInjectableController;

export function declareControllerFactory<Result, Args extends unknown[]>(
factory: (...args: Args) => ControllerFactory<Result>,
): (...args: Args) => ControllerFactory<Result> {
return factory;
}
3 changes: 3 additions & 0 deletions packages/rx-effects/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
export type AnyObject = Record<string, any>;
export type EmptyObject = Record<string, never>;

export type PartialProp<T, K extends keyof T> = Omit<T, K> &
Partial<Pick<T, K>>;

/**
* Makes shallow comparison of two objects.
*/
Expand Down

0 comments on commit bccac56

Please sign in to comment.