@bool-ts/core 1.9.1 → 1.9.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bool-ts/core",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -21,12 +21,12 @@
21
21
  "@bool-ts/date-time": "^1.0.0",
22
22
  "qs": "^6.14.0",
23
23
  "reflect-metadata": "^0.2.2",
24
- "zod": "^3.24.1"
24
+ "zod": "^3.24.2"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/bun": "latest",
28
28
  "@types/qs": "^6.9.18",
29
- "typescript": "^5.7.3"
29
+ "typescript": "^5.8.2"
30
30
  },
31
31
  "private": "false"
32
32
  }
@@ -2,6 +2,7 @@ import * as Zod from "zod";
2
2
  import {
3
3
  argumentsKey,
4
4
  contextArgsKey,
5
+ httpServerArgsKey,
5
6
  paramArgsKey,
6
7
  paramsArgsKey,
7
8
  queryArgsKey,
@@ -64,6 +65,10 @@ export type TArgumentsMetadata =
64
65
  | {
65
66
  index: number;
66
67
  type: typeof routeModelArgsKey;
68
+ }
69
+ | {
70
+ index: number;
71
+ type: typeof httpServerArgsKey;
67
72
  };
68
73
 
69
74
  export type TArgumentsMetadataCollection = Record<`argumentIndexes.${number}`, TArgumentsMetadata>;
@@ -306,3 +311,25 @@ export const RouteModel =
306
311
 
307
312
  Reflect.defineMetadata(argumentsKey, metadata, target.constructor, methodName);
308
313
  };
314
+
315
+ export const HttpServer =
316
+ () => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => {
317
+ if (!methodName) {
318
+ return;
319
+ }
320
+
321
+ const metadata: TArgumentsMetadataCollection =
322
+ Reflect.getOwnMetadata(argumentsKey, target.constructor, methodName) || {};
323
+
324
+ metadata[`argumentIndexes.${parameterIndex}`] = {
325
+ index: parameterIndex,
326
+ type: httpServerArgsKey
327
+ } satisfies Extract<
328
+ TArgumentsMetadata,
329
+ {
330
+ type: typeof httpServerArgsKey;
331
+ }
332
+ >;
333
+
334
+ Reflect.defineMetadata(argumentsKey, metadata, target.constructor, methodName);
335
+ };
@@ -1,45 +1,60 @@
1
1
  import type { IModule } from "../interfaces";
2
2
 
3
- import { containerKey, dispatcherKey, guardKey, injectableKey, middlewareKey } from "../keys";
3
+ import { containerKey, guardKey, injectableKey, middlewareKey, moduleKey } from "../keys";
4
4
 
5
5
  type TInstances = Array<new (...args: any[]) => any>;
6
6
  type TLoaders<TConfig extends {} = {}> = Record<
7
7
  string | symbol,
8
8
  (args: { config: TConfig }) => [string | symbol, any] | Promise<[string | symbol, any]>
9
9
  >;
10
+ export type TContainerConfig<TConfig> =
11
+ | TConfig
12
+ | (() => TConfig | Promise<TConfig>)
13
+ | Readonly<{
14
+ key: symbol;
15
+ value: TConfig | (() => TConfig | Promise<TConfig>);
16
+ }>;
10
17
 
11
18
  export type TContainerOptions<TConfig extends {} = {}> =
12
- | (Required<{
19
+ | Partial<{
20
+ config: TContainerConfig<TConfig>;
13
21
  modules: TInstances;
14
- }> &
15
- Partial<{
16
- config: TConfig | (() => TConfig | Promise<TConfig>);
17
- dependencies: TInstances;
18
- loaders: TLoaders<TConfig>;
19
- middlewares: TInstances;
20
- guards: TInstances;
21
- dispatchers: TInstances;
22
- }>)
22
+ dependencies: TInstances;
23
+ loaders: TLoaders<TConfig>;
24
+ middlewares: TInstances;
25
+ guards: TInstances;
26
+ }>
23
27
  | undefined;
24
28
 
25
29
  export type TContainerMetadata<TConfig extends {} = {}> =
26
- | (Required<{
30
+ | Partial<{
27
31
  modules: TInstances;
28
- }> &
29
- Partial<{
30
- config: TConfig | ((...args: any[]) => TConfig | Promise<TConfig>);
31
- dependencies: TInstances;
32
- loaders: TLoaders<TConfig>;
33
- middlewares: TInstances;
34
- guards: TInstances;
35
- dispatchers: TInstances;
36
- }>)
32
+ config: TContainerConfig<TConfig>;
33
+ dependencies: TInstances;
34
+ loaders: TLoaders<TConfig>;
35
+ middlewares: TInstances;
36
+ guards: TInstances;
37
+ }>
37
38
  | undefined;
38
39
 
39
40
  export const Container =
40
41
  <TConfig extends {} = {}>(args?: TContainerOptions<TConfig>) =>
41
42
  <T extends { new (...args: any[]): IModule }>(target: T) => {
42
- const { middlewares, guards, dispatchers, dependencies } = args || {};
43
+ const { modules, middlewares, guards, dependencies } = args || {};
44
+
45
+ if (Reflect.hasOwnMetadata(moduleKey, target)) {
46
+ throw new Error(
47
+ `Conflict detected! ${target.name} class cannot be both a Module and a Container.`
48
+ );
49
+ }
50
+
51
+ if (modules) {
52
+ for (let i = 0; i < modules.length; i++) {
53
+ if (!Reflect.getOwnMetadataKeys(modules[i]).includes(moduleKey)) {
54
+ throw Error(`${modules[i].name} is not a module.`);
55
+ }
56
+ }
57
+ }
43
58
 
44
59
  if (middlewares) {
45
60
  for (let i = 0; i < middlewares.length; i++) {
@@ -49,18 +64,18 @@ export const Container =
49
64
  }
50
65
  }
51
66
 
52
- if (guards) {
53
- for (let i = 0; i < guards.length; i++) {
54
- if (!Reflect.getOwnMetadataKeys(guards[i]).includes(guardKey)) {
55
- throw Error(`${guards[i].name} is not a guard.`);
67
+ if (middlewares) {
68
+ for (let i = 0; i < middlewares.length; i++) {
69
+ if (!Reflect.getOwnMetadataKeys(middlewares[i]).includes(middlewareKey)) {
70
+ throw Error(`${middlewares[i].name} is not a middleware.`);
56
71
  }
57
72
  }
58
73
  }
59
74
 
60
- if (dispatchers) {
61
- for (let i = 0; i < dispatchers.length; i++) {
62
- if (!Reflect.getOwnMetadataKeys(dispatchers[i]).includes(dispatcherKey)) {
63
- throw Error(`${dispatchers[i].name} is not a dispatcher.`);
75
+ if (guards) {
76
+ for (let i = 0; i < guards.length; i++) {
77
+ if (!Reflect.getOwnMetadataKeys(guards[i]).includes(guardKey)) {
78
+ throw Error(`${guards[i].name} is not a guard.`);
64
79
  }
65
80
  }
66
81
  }
@@ -1,5 +1,6 @@
1
1
  export {
2
2
  Context,
3
+ HttpServer,
3
4
  Param,
4
5
  Params,
5
6
  Query,
@@ -10,6 +11,7 @@ export {
10
11
  ResponseHeaders,
11
12
  RouteModel
12
13
  } from "./arguments";
14
+ export { Container } from "./container";
13
15
  export { Controller } from "./controller";
14
16
  export { Dispatcher } from "./dispatcher";
15
17
  export { Guard } from "./guard";
@@ -29,11 +31,12 @@ export { WebSocketEvent } from "./webSocketEvent";
29
31
  export { ZodSchema } from "./zodSchema";
30
32
 
31
33
  export type { TArgumentsMetadata } from "./arguments";
34
+ export type { TContainerConfig, TContainerMetadata, TContainerOptions } from "./container";
32
35
  export type { TControllerMetadata } from "./controller";
33
36
  export type { TDispatcherMetadata } from "./dispatcher";
34
37
  export type { TGuardMetadata } from "./guard";
35
38
  export type { THttpMetadata } from "./http";
36
39
  export type { TMiddlewareMetadata } from "./middleware";
37
- export type { TModuleMetadata, TModuleOptions } from "./module";
40
+ export type { TModuleConfig, TModuleMetadata, TModuleOptions } from "./module";
38
41
  export type { TWebSocketMetadata } from "./webSocket";
39
42
  export type { TWebSocketEventHandlerMetadata, TWebSocketEventMetadata } from "./webSocketEvent";
@@ -1,6 +1,7 @@
1
1
  import type { IModule } from "../interfaces";
2
2
 
3
3
  import {
4
+ containerKey,
4
5
  controllerKey,
5
6
  dispatcherKey,
6
7
  guardKey,
@@ -15,10 +16,17 @@ type TLoaders<TConfig extends {} = {}> = Record<
15
16
  string | symbol,
16
17
  (args: { config: TConfig }) => [string | symbol, any] | Promise<[string | symbol, any]>
17
18
  >;
19
+ export type TModuleConfig<TConfig> =
20
+ | TConfig
21
+ | (() => TConfig | Promise<TConfig>)
22
+ | Readonly<{
23
+ key: symbol;
24
+ value: TConfig | (() => TConfig | Promise<TConfig>);
25
+ }>;
18
26
 
19
27
  export type TModuleOptions<TConfig extends {} = {}> =
20
28
  | Partial<{
21
- config: TConfig | (() => TConfig | Promise<TConfig>);
29
+ config: TModuleConfig<TConfig>;
22
30
  prefix: string;
23
31
  dependencies: TInstances;
24
32
  loaders: TLoaders<TConfig>;
@@ -32,7 +40,7 @@ export type TModuleOptions<TConfig extends {} = {}> =
32
40
 
33
41
  export type TModuleMetadata<TConfig extends {} = {}> =
34
42
  | Partial<{
35
- config: TConfig | ((...args: any[]) => TConfig | Promise<TConfig>);
43
+ config: TModuleConfig<TConfig>;
36
44
  prefix: string;
37
45
  dependencies: TInstances;
38
46
  loaders: TLoaders<TConfig>;
@@ -47,6 +55,12 @@ export type TModuleMetadata<TConfig extends {} = {}> =
47
55
  export const Module =
48
56
  <TConfig extends {} = {}>(args?: TModuleOptions<TConfig>) =>
49
57
  <T extends { new (...args: any[]): IModule }>(target: T) => {
58
+ if (Reflect.hasOwnMetadata(containerKey, target)) {
59
+ throw new Error(
60
+ `Conflict detected! ${target.name} class cannot be both a Module and a Container.`
61
+ );
62
+ }
63
+
50
64
  const { middlewares, guards, dispatchers, controllers, dependencies, webSockets } =
51
65
  args || {};
52
66
 
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@ import "reflect-metadata";
3
3
  export type { THttpRouteModel } from "./entities";
4
4
 
5
5
  export * from "./decorators";
6
- export * from "./hooks";
7
6
  export * from "./http";
8
7
  export * from "./interfaces";
9
8
  export * as Keys from "./keys";
9
+ export * from "./producers";
@@ -1,4 +1,11 @@
1
+ export type TContextOptions = Partial<{
2
+ isStatic: boolean;
3
+ isPassthrough: boolean;
4
+ }>;
5
+
1
6
  export interface IContext {
2
- get: (key: symbol) => any;
3
- set: (key: symbol, value: any) => void;
7
+ get: <T = unknown>(key: symbol, options?: TContextOptions) => T;
8
+ has: (key: symbol, options?: TContextOptions) => boolean;
9
+ set: <T = unknown>(key: symbol, value: T, options?: TContextOptions) => ThisType<IContext>;
10
+ setOptions: (options: TContextOptions) => ThisType<IContext>;
4
11
  }
@@ -1,4 +1,4 @@
1
- export type { IContext } from "./context";
1
+ export type { IContext, TContextOptions } from "./context";
2
2
  export type { IController } from "./controller";
3
3
  export type { IDispatcher } from "./dispatcher";
4
4
  export type { IGuard } from "./guard";
package/src/keys/index.ts CHANGED
@@ -32,3 +32,5 @@ export const responseHeadersArgsKey = Symbol("__bool:httpArguments:responseHeade
32
32
  export const contextArgsKey = Symbol("__bool:httpArguments:context__");
33
33
  export const routeModelArgsKey = Symbol("__bool:httpArguments:routeModel__");
34
34
  export const responseBodyArgsKey = Symbol("__bool:httpArguments:responseBody__");
35
+ export const responseStatusArgsKey = Symbol("__bool:httpArguments:responseStatus__");
36
+ export const responseStatusTextArgsKey = Symbol("__bool:httpArguments:responseStatusText__");
@@ -0,0 +1,63 @@
1
+ import type { IContext, TContextOptions } from "../interfaces";
2
+
3
+ export class Context implements IContext {
4
+ private readonly _staticMap = new Map<symbol, any>();
5
+ private readonly _dynamicMap = new Map<symbol, any>();
6
+
7
+ private _options?: TContextOptions = undefined;
8
+
9
+ constructor(...contexts: Array<Context>) {
10
+ contexts.forEach((context) => {
11
+ context.staticEntries.forEach(([key, value]) =>
12
+ this.set(key, value, { isStatic: true, isPassthrough: true })
13
+ );
14
+ context.dynamicEntries.forEach(([key, value]) =>
15
+ this.set(key, value, { isStatic: false })
16
+ );
17
+ });
18
+ }
19
+
20
+ get<T = unknown>(key: symbol, options?: TContextOptions) {
21
+ const temporaryOptions = options || this._options;
22
+
23
+ return !temporaryOptions?.isStatic
24
+ ? (this._dynamicMap.get(key) as T)
25
+ : (this._staticMap.get(key) as T);
26
+ }
27
+
28
+ has(key: symbol, options?: TContextOptions) {
29
+ const temporaryOptions = options || this._options;
30
+
31
+ return !temporaryOptions?.isStatic ? this._dynamicMap.has(key) : this._staticMap.has(key);
32
+ }
33
+
34
+ set(key: symbol, value: any, options?: TContextOptions) {
35
+ const temporaryOptions = options || this._options;
36
+
37
+ if (!temporaryOptions?.isStatic) {
38
+ this._dynamicMap.set(key, value);
39
+ } else {
40
+ if (!this._staticMap.has(key)) {
41
+ this._staticMap.set(key, value);
42
+ } else if (!temporaryOptions.isPassthrough) {
43
+ throw Error(`${String(key)} already exists in context static collection.`);
44
+ }
45
+ }
46
+
47
+ return this;
48
+ }
49
+
50
+ setOptions(options: TContextOptions) {
51
+ this._options = options;
52
+
53
+ return this;
54
+ }
55
+
56
+ get staticEntries() {
57
+ return [...this._staticMap.entries()];
58
+ }
59
+
60
+ get dynamicEntries() {
61
+ return [...this._dynamicMap.entries()];
62
+ }
63
+ }