mirror of
https://github.com/sern-handler/handler
synced 2026-06-28 02:32:15 +00:00
refactor: move things to core, imports not fixed yet
This commit is contained in:
2
src/core/dependencies/index.ts
Normal file
2
src/core/dependencies/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { single, transient, many } from './lifetimeFunctions';
|
||||
export { useContainerRaw } from './provider';
|
||||
63
src/core/dependencies/lifetimeFunctions.ts
Normal file
63
src/core/dependencies/lifetimeFunctions.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { _const } from '../utilities/functions';
|
||||
|
||||
type NotFunction =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| undefined
|
||||
| bigint
|
||||
| readonly any[]
|
||||
| { apply?: never; [k: string]: any }
|
||||
| { call?: never; [k: string]: any };
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @param cb
|
||||
*/
|
||||
export function single<T extends NotFunction>(cb: T): () => T;
|
||||
/**
|
||||
* New signature
|
||||
* @since 2.0.0
|
||||
* @param cb
|
||||
*/
|
||||
export function single<T extends () => unknown>(cb: T): T;
|
||||
/**
|
||||
* @__PURE__
|
||||
* @since 2.0.0.
|
||||
* Please note that on intellij, the deprecation is for all signatures, which is unintended behavior (and
|
||||
* very annoying).
|
||||
* For future versions, ensure that single is being passed as a **callback!!**
|
||||
* @param cb
|
||||
*/
|
||||
export function single<T>(cb: T) {
|
||||
if (typeof cb === 'function') return cb;
|
||||
return () => cb;
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
* @param cb
|
||||
* Deprecated signature
|
||||
*/
|
||||
export function transient<T extends NotFunction>(cb: T): () => () => T;
|
||||
export function transient<T extends () => () => unknown>(cb: T): T;
|
||||
/**
|
||||
* @__PURE__
|
||||
* @since 2.0.0
|
||||
* Following iti's singleton and transient implementation,
|
||||
* use transient if you want a new dependency every time your container getter is called
|
||||
* @param cb
|
||||
*/
|
||||
export function transient<T>(cb: (() => () => T) | T) {
|
||||
if (typeof cb !== 'function') return () => () => cb;
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @__PURE__
|
||||
* @deprecated
|
||||
* @param value
|
||||
* Please use the transient function instead
|
||||
*/
|
||||
// prettier-ignore
|
||||
export const many = <T>(value: T) => () => _const(value);
|
||||
86
src/core/dependencies/provider.ts
Normal file
86
src/core/dependencies/provider.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { Container } from 'iti';
|
||||
import type { Dependencies, DependencyConfiguration, MapDeps } from '../../types/handler';
|
||||
import SernEmitter from '../sernEmitter';
|
||||
import { DefaultErrorHandling, DefaultLogging, DefaultModuleManager } from '../contracts';
|
||||
import { Result } from 'ts-results-es';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { createContainer } from 'iti';
|
||||
import { type Wrapper, ModuleStore, SernError } from '../structures';
|
||||
|
||||
export const containerSubject = new BehaviorSubject(defaultContainer());
|
||||
|
||||
/**
|
||||
* Given the user's conf, check for any excluded dependency keys.
|
||||
* Then, call conf.build to get the rest of the users' dependencies.
|
||||
* Finally, update the containerSubject with the new container state
|
||||
* @param conf
|
||||
*/
|
||||
export function composeRoot<T extends Dependencies>(conf: DependencyConfiguration<T>) {
|
||||
//Get the current container. This should have no client or possible logger yet.
|
||||
const currentContainer = containerSubject.getValue();
|
||||
const excludeLogger = conf.exclude?.has('@sern/logger');
|
||||
if (!excludeLogger) {
|
||||
currentContainer.add({
|
||||
'@sern/logger': () => new DefaultLogging(),
|
||||
});
|
||||
}
|
||||
//Build the container based on the callback provided by the user
|
||||
const container = conf.build(currentContainer);
|
||||
//Check if the built container contains @sern/client or throw
|
||||
// a runtime exception
|
||||
Result.wrap(() => container.get('@sern/client')).expect(SernError.MissingRequired);
|
||||
|
||||
if (!excludeLogger) {
|
||||
container.get('@sern/logger')?.info({ message: 'All dependencies loaded successfully.' });
|
||||
}
|
||||
//I'm sorry little one
|
||||
containerSubject.next(container as any);
|
||||
}
|
||||
|
||||
export function useContainer<T extends Dependencies>() {
|
||||
const container = containerSubject.getValue() as Container<T, {}>;
|
||||
return <V extends (keyof T)[]>(...keys: [...V]) =>
|
||||
keys.map(key => Result.wrap(() => container.get(key)).unwrapOr(undefined)) as MapDeps<T, V>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying data structure holding all dependencies.
|
||||
* Please be careful as this only gets the client's current state.
|
||||
* Exposes some methods from iti
|
||||
*/
|
||||
export function useContainerRaw<T extends Dependencies>() {
|
||||
return containerSubject.getValue() as Container<T, {}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides all the defaults for sern to function properly.
|
||||
* The only user provided dependency needs to be @sern/client
|
||||
*/
|
||||
function defaultContainer() {
|
||||
return createContainer()
|
||||
.add({ '@sern/errors': () => new DefaultErrorHandling() })
|
||||
.add({ '@sern/store': () => new ModuleStore() })
|
||||
.add(ctx => {
|
||||
return {
|
||||
'@sern/modules': () => new DefaultModuleManager(ctx['@sern/store']),
|
||||
};
|
||||
})
|
||||
.add({ '@sern/emitter': () => new SernEmitter() }) as Container<
|
||||
Omit<Dependencies, '@sern/client' | '@sern/logger'>,
|
||||
{}
|
||||
>;
|
||||
}
|
||||
|
||||
export function makeFetcher(wrapper: Wrapper) {
|
||||
const requiredDependencyKeys = [
|
||||
'@sern/emitter',
|
||||
'@sern/client',
|
||||
'@sern/errors',
|
||||
'@sern/logger',
|
||||
] as ['@sern/emitter', '@sern/client', '@sern/errors', '@sern/logger'];
|
||||
return <Keys extends (keyof Dependencies)[]>(otherKeys: [...Keys]) =>
|
||||
wrapper.containerConfig.get(...requiredDependencyKeys, ...otherKeys) as MapDeps<
|
||||
Dependencies,
|
||||
[...typeof requiredDependencyKeys, ...Keys]
|
||||
>;
|
||||
}
|
||||
Reference in New Issue
Block a user