@noxfly/noxus 2.4.0 → 3.0.0-dev.0

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 (48) hide show
  1. package/README.md +403 -341
  2. package/dist/app-injector-Bz3Upc0y.d.mts +125 -0
  3. package/dist/app-injector-Bz3Upc0y.d.ts +125 -0
  4. package/dist/child.d.mts +48 -22
  5. package/dist/child.d.ts +48 -22
  6. package/dist/child.js +1114 -1239
  7. package/dist/child.mjs +1090 -1193
  8. package/dist/main.d.mts +304 -261
  9. package/dist/main.d.ts +304 -261
  10. package/dist/main.js +1473 -1873
  11. package/dist/main.mjs +1423 -1791
  12. package/dist/renderer.d.mts +113 -2
  13. package/dist/renderer.d.ts +113 -2
  14. package/dist/renderer.js +144 -132
  15. package/dist/renderer.mjs +143 -132
  16. package/dist/request-BlTtiHbi.d.ts +112 -0
  17. package/dist/request-qJ9EiDZc.d.mts +112 -0
  18. package/package.json +7 -7
  19. package/src/DI/app-injector.ts +95 -106
  20. package/src/DI/injector-explorer.ts +100 -81
  21. package/src/DI/token.ts +53 -0
  22. package/src/app.ts +141 -131
  23. package/src/bootstrap.ts +79 -40
  24. package/src/decorators/controller.decorator.ts +38 -27
  25. package/src/decorators/guards.decorator.ts +5 -64
  26. package/src/decorators/injectable.decorator.ts +68 -15
  27. package/src/decorators/method.decorator.ts +40 -81
  28. package/src/decorators/middleware.decorator.ts +5 -72
  29. package/src/index.ts +3 -0
  30. package/src/main.ts +4 -11
  31. package/src/non-electron-process.ts +0 -1
  32. package/src/preload-bridge.ts +1 -1
  33. package/src/renderer-client.ts +2 -2
  34. package/src/renderer-events.ts +1 -1
  35. package/src/request.ts +3 -3
  36. package/src/router.ts +221 -369
  37. package/src/routes.ts +78 -0
  38. package/src/socket.ts +4 -4
  39. package/src/window/window-manager.ts +255 -0
  40. package/tsconfig.json +5 -10
  41. package/tsup.config.ts +2 -2
  42. package/dist/app-injector-B3MvgV3k.d.mts +0 -95
  43. package/dist/app-injector-B3MvgV3k.d.ts +0 -95
  44. package/dist/index-BxWQVi6C.d.ts +0 -253
  45. package/dist/index-DQBQQfMw.d.mts +0 -253
  46. package/src/decorators/inject.decorator.ts +0 -24
  47. package/src/decorators/injectable.metadata.ts +0 -15
  48. package/src/decorators/module.decorator.ts +0 -75
@@ -4,25 +4,78 @@
4
4
  * @author NoxFly
5
5
  */
6
6
 
7
- import { Lifetime } from "src/DI/app-injector";
8
- import { InjectorExplorer } from "src/DI/injector-explorer";
9
- import { defineInjectableMetadata } from "src/decorators/injectable.metadata";
10
- import { Type } from "src/main";
11
- export { getInjectableMetadata, hasInjectableMetadata, INJECTABLE_METADATA_KEY } from "src/decorators/injectable.metadata";
7
+ import { Lifetime } from '../DI/app-injector';
8
+ import { InjectorExplorer } from '../DI/injector-explorer';
9
+ import { Token, TokenKey } from '../DI/token';
10
+ import { Type } from '../utils/types';
11
+
12
+ export interface InjectableOptions {
13
+ /**
14
+ * Lifetime of this injectable.
15
+ * @default 'scope'
16
+ */
17
+ lifetime?: Lifetime;
18
+
19
+ /**
20
+ * Explicit list of constructor dependencies, in the same order as the constructor parameters.
21
+ * Each entry is either a class constructor or a Token created with token().
22
+ *
23
+ * This replaces reflect-metadata / emitDecoratorMetadata entirely.
24
+ *
25
+ * @example
26
+ * @Injectable({ lifetime: 'singleton', deps: [MyRepo, DB_URL] })
27
+ * class MyService {
28
+ * constructor(private repo: MyRepo, private dbUrl: string) {}
29
+ * }
30
+ */
31
+ deps?: ReadonlyArray<TokenKey>;
32
+ }
12
33
 
13
34
  /**
14
- * The Injectable decorator marks a class as injectable.
15
- * It allows the class to be registered in the dependency injection system.
16
- * A class decorated with @Injectable can be injected into other classes
17
- * either from the constructor of the class that needs it of from the `inject` function.
18
- * @param lifetime - The lifetime of the injectable. Can be 'singleton', 'scope', or 'transient'.
35
+ * Marks a class as injectable into the Noxus DI container.
36
+ *
37
+ * Unlike the v2 @Injectable, this decorator:
38
+ * - Does NOT require reflect-metadata or emitDecoratorMetadata.
39
+ * - Requires you to declare deps explicitly when the class has constructor parameters.
40
+ * - Supports standalone usage — no module declaration needed.
41
+ *
42
+ * @example
43
+ * // No dependencies
44
+ * @Injectable()
45
+ * class Logger {}
46
+ *
47
+ * // With dependencies
48
+ * @Injectable({ lifetime: 'singleton', deps: [Logger, MyRepo] })
49
+ * class MyService {
50
+ * constructor(private logger: Logger, private repo: MyRepo) {}
51
+ * }
52
+ *
53
+ * // With a named token
54
+ * const DB_URL = token<string>('DB_URL');
55
+ *
56
+ * @Injectable({ deps: [DB_URL] })
57
+ * class DbService {
58
+ * constructor(private url: string) {}
59
+ * }
19
60
  */
20
- export function Injectable(lifetime: Lifetime = "scope"): ClassDecorator {
61
+ export function Injectable(options: InjectableOptions = {}): ClassDecorator {
62
+ const { lifetime = 'scope', deps = [] } = options;
63
+
21
64
  return (target) => {
22
- if (typeof target !== "function" || !target.prototype) {
23
- throw new Error(`@Injectable can only be used on classes, not on ${typeof target}`);
65
+ if (typeof target !== 'function' || !target.prototype) {
66
+ throw new Error(`@Injectable can only be applied to classes, not ${typeof target}`);
24
67
  }
25
- defineInjectableMetadata(target, lifetime);
26
- InjectorExplorer.enqueue(target as unknown as Type<any>, lifetime);
68
+
69
+ const key = target as unknown as Type<unknown>;
70
+
71
+ InjectorExplorer.enqueue({
72
+ key,
73
+ implementation: key,
74
+ lifetime,
75
+ deps,
76
+ isController: false,
77
+ });
27
78
  };
28
79
  }
80
+
81
+ export { Token, TokenKey };
@@ -4,104 +4,63 @@
4
4
  * @author NoxFly
5
5
  */
6
6
 
7
- import { getGuardForControllerAction, IGuard } from "src/decorators/guards.decorator";
8
- import { Type } from "src/utils/types";
7
+ import { Guard } from './guards.decorator';
8
+ import { Middleware } from './middleware.decorator';
9
+
10
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'BATCH';
11
+ export type AtomicHttpMethod = Exclude<HttpMethod, 'BATCH'>;
12
+
13
+ const ATOMIC_METHODS = new Set<AtomicHttpMethod>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
14
+ export function isAtomicHttpMethod(m: unknown): m is AtomicHttpMethod {
15
+ return typeof m === 'string' && ATOMIC_METHODS.has(m as AtomicHttpMethod);
16
+ }
17
+
18
+ export interface IRouteOptions {
19
+ /**
20
+ * Guards specific to this route (merged with controller guards).
21
+ */
22
+ guards?: Guard[];
23
+ /**
24
+ * Middlewares specific to this route (merged with controller middlewares).
25
+ */
26
+ middlewares?: Middleware[];
27
+ }
9
28
 
10
- /**
11
- * IRouteMetadata interface defines the metadata for a route.
12
- * It includes the HTTP method, path, handler name, and guards associated with the route.
13
- * This metadata is used to register the route in the application.
14
- * This is the configuration that waits a route's decorator.
15
- */
16
29
  export interface IRouteMetadata {
17
30
  method: HttpMethod;
18
31
  path: string;
19
32
  handler: string;
20
- guards: Type<IGuard>[];
33
+ guards: Guard[];
34
+ middlewares: Middleware[];
21
35
  }
22
36
 
23
- /**
24
- * The different HTTP methods that can be used in the application.
25
- */
26
- export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'BATCH';
37
+ const routeMetaMap = new WeakMap<object, IRouteMetadata[]>();
27
38
 
28
- /**
29
- * Atomic HTTP verbs supported by controllers. BATCH is handled at the router level only.
30
- */
31
- export type AtomicHttpMethod = Exclude<HttpMethod, 'BATCH'>;
32
-
33
- /**
34
- * The configuration that waits a route's decorator.
35
- * It contains the HTTP method, path, handler, and guards for the route.
36
- * @param verb The HTTP method for the route.
37
- * @returns A method decorator that registers the route with the specified HTTP method.
38
- */
39
- function createRouteDecorator(verb: HttpMethod): (path: string) => MethodDecorator {
40
- return (path: string): MethodDecorator => {
39
+ function createRouteDecorator(verb: HttpMethod) {
40
+ return (path: string, options: IRouteOptions = {}): MethodDecorator => {
41
41
  return (target, propertyKey) => {
42
- const existingRoutes: IRouteMetadata[] = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) || [];
42
+ const ctor = target.constructor;
43
+ const existing: IRouteMetadata[] = routeMetaMap.get(ctor) ?? [];
43
44
 
44
- const metadata: IRouteMetadata = {
45
+ existing.push({
45
46
  method: verb,
46
- path: path.trim().replace(/^\/|\/$/g, ''),
47
+ path: (path ?? '').trim().replace(/^\/|\/$/g, ''),
47
48
  handler: propertyKey as string,
48
- guards: getGuardForControllerAction((target.constructor as any).__controllerName, propertyKey as string),
49
- };
49
+ guards: options.guards ?? [],
50
+ middlewares: options.middlewares ?? [],
51
+ });
50
52
 
51
- existingRoutes.push(metadata);
52
-
53
- Reflect.defineMetadata(ROUTE_METADATA_KEY, existingRoutes, target.constructor);
53
+ routeMetaMap.set(ctor, existing);
54
54
  };
55
55
  };
56
56
  }
57
57
 
58
- /**
59
- * Gets the route metadata for a given target class.
60
- * This metadata includes the HTTP method, path, handler, and guards defined by the route decorators.
61
- * @see Get
62
- * @see Post
63
- * @see Put
64
- * @see Patch
65
- * @see Delete
66
- * @param target The target class to get the route metadata from.
67
- * @returns An array of route metadata if it exists, otherwise an empty array.
68
- */
69
- export function getRouteMetadata(target: Type<unknown>): IRouteMetadata[] {
70
- return Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
58
+ export function getRouteMetadata(target: object): IRouteMetadata[] {
59
+ return routeMetaMap.get(target) ?? [];
71
60
  }
72
61
 
73
- /**
74
- * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
75
- * that will be called when the route is matched.
76
- * This route will have to be called with the GET method.
77
- */
78
- export const Get = createRouteDecorator('GET');
79
-
80
- /**
81
- * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
82
- * that will be called when the route is matched.
83
- * This route will have to be called with the POST method.
84
- */
85
- export const Post = createRouteDecorator('POST');
86
-
87
- /**
88
- * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
89
- * that will be called when the route is matched.
90
- * This route will have to be called with the PUT method.
91
- */
92
- export const Put = createRouteDecorator('PUT');
93
- /**
94
- * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
95
- * that will be called when the route is matched.
96
- * This route will have to be called with the PATCH method.
97
- */
98
- export const Patch = createRouteDecorator('PATCH');
99
-
100
- /**
101
- * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
102
- * that will be called when the route is matched.
103
- * This route will have to be called with the DELETE method.
104
- */
62
+ export const Get = createRouteDecorator('GET');
63
+ export const Post = createRouteDecorator('POST');
64
+ export const Put = createRouteDecorator('PUT');
65
+ export const Patch = createRouteDecorator('PATCH');
105
66
  export const Delete = createRouteDecorator('DELETE');
106
-
107
- export const ROUTE_METADATA_KEY = Symbol('ROUTE_METADATA_KEY');
@@ -4,79 +4,12 @@
4
4
  * @author NoxFly
5
5
  */
6
6
 
7
- import { IResponse, Request } from "src/request";
8
- import { Logger } from "src/utils/logger";
9
- import { MaybeAsync, Type } from "src/utils/types";
7
+ import { IResponse, Request } from '../request';
8
+ import { MaybeAsync } from '../utils/types';
10
9
 
11
10
  /**
12
- * NextFunction is a function that is called to continue the middleware chain.
13
- * It returns an Promise that emits when the next middleware is done.
11
+ * A middleware intercepts requests before they reach guards and the handler.
12
+ * Implement this interface and pass the class to @Controller({ middlewares }) or per-route options.
14
13
  */
14
+ export type Middleware = (request: Request, response: IResponse, next: NextFunction) => MaybeAsync<void>;
15
15
  export type NextFunction = () => Promise<void>;
16
-
17
- /**
18
- * IMiddleware interface defines a middleware that can be used in the application.
19
- * It has an `invoke` method that takes a request, a response, and a next function.
20
- * The `invoke` method can return a MaybeAsync, which means it can return either a value or a Promise.
21
- *
22
- * Use it on a class that should be registered as a middleware in the application.
23
- */
24
- export interface IMiddleware {
25
- invoke(request: Request, response: IResponse, next: NextFunction): MaybeAsync<void>;
26
- }
27
-
28
- /**
29
- * UseMiddlewares decorator can be used to register middlewares for a controller or a controller action.
30
- *
31
- * @param mdlw - The middlewares list to register for the controller or the controller action.
32
- */
33
- export function UseMiddlewares(mdlw: Type<IMiddleware>[]): ClassDecorator & MethodDecorator {
34
- return (target: Function | object, propertyKey?: string | symbol) => {
35
- let key: string;
36
-
37
- // Method decorator
38
- if(propertyKey) {
39
- const ctrlName = target.constructor.name;
40
- const actionName = propertyKey as string;
41
- key = `${ctrlName}.${actionName}`;
42
- }
43
- // Class decorator
44
- else {
45
- const ctrlName = (target as Type<unknown>).name;
46
- key = `${ctrlName}`;
47
- }
48
-
49
- if(middlewares.has(key)) {
50
- throw new Error(`Middlewares(s) already registered for ${key}`);
51
- }
52
-
53
- middlewares.set(key, mdlw);
54
- };
55
- }
56
-
57
- /**
58
- * Gets the middlewares for a controller or a controller action.
59
- * This function retrieves the middlewares registered with the UseMiddlewares decorator.
60
- * It returns an array of middleware classes that can be used to process requests for the specified controller.
61
- * @param controllerName The name of the controller to get the middlewares for.
62
- * @returns An array of middlewares for the controller.
63
- */
64
- export function getMiddlewaresForController(controllerName: string): Type<IMiddleware>[] {
65
- const key = `${controllerName}`;
66
- return middlewares.get(key) ?? [];
67
- }
68
-
69
- /**
70
- * Gets the middlewares for a controller action.
71
- * This function retrieves the middlewares registered with the UseMiddlewares decorator for a specific action in a controller.
72
- * It returns an array of middleware classes that can be used to process requests for the specified controller action.
73
- * @param controllerName The name of the controller to get the middlewares for.
74
- * @param actionName The name of the action to get the middlewares for.
75
- * @returns An array of middlewares for the controller action.
76
- */
77
- export function getMiddlewaresForControllerAction(controllerName: string, actionName: string): Type<IMiddleware>[] {
78
- const key = `${controllerName}.${actionName}`;
79
- return middlewares.get(key) ?? [];
80
- }
81
-
82
- const middlewares = new Map<string, Type<IMiddleware>[]>();
package/src/index.ts CHANGED
@@ -2,9 +2,12 @@
2
2
  * @copyright 2025 NoxFly
3
3
  * @license MIT
4
4
  * @author NoxFly
5
+ *
6
+ * Entry point for renderer process and preload consumers.
5
7
  */
6
8
 
7
9
  export * from './request';
10
+ export * from './preload-bridge';
8
11
  export * from './renderer-events';
9
12
  export * from './renderer-client';
10
13
  export type { HttpMethod, AtomicHttpMethod } from './decorators/method.decorator';
package/src/main.ts CHANGED
@@ -2,15 +2,12 @@
2
2
  * @copyright 2025 NoxFly
3
3
  * @license MIT
4
4
  * @author NoxFly
5
- */
6
-
7
- /**
5
+ *
8
6
  * Entry point for Electron main-process consumers.
9
- * order of exports here matters and can affect module resolution.
10
- * Please be cautious when modifying.
11
7
  */
12
8
 
13
9
  export * from './DI/app-injector';
10
+ export * from './DI/token';
14
11
  export * from './router';
15
12
  export * from './app';
16
13
  export * from './bootstrap';
@@ -19,15 +16,11 @@ export * from './decorators/middleware.decorator';
19
16
  export * from './decorators/guards.decorator';
20
17
  export * from './decorators/controller.decorator';
21
18
  export * from './decorators/injectable.decorator';
22
- export * from './decorators/inject.decorator';
23
19
  export * from './decorators/method.decorator';
24
- export * from './decorators/module.decorator';
25
- export * from './preload-bridge';
26
20
  export * from './utils/logger';
27
21
  export * from './utils/types';
28
22
  export * from './utils/forward-ref';
29
23
  export * from './request';
30
- export * from './renderer-events';
31
- export * from './renderer-client';
32
24
  export * from './socket';
33
-
25
+ export * from './window/window-manager';
26
+ export * from './routes';
@@ -17,7 +17,6 @@
17
17
  export * from './DI/app-injector';
18
18
  export * from './exceptions';
19
19
  export * from './decorators/injectable.decorator';
20
- export * from './decorators/inject.decorator';
21
20
  export * from './utils/logger';
22
21
  export * from './utils/types';
23
22
  export * from './utils/forward-ref';
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { contextBridge, ipcRenderer } from 'electron/renderer';
8
- import type { IPortRequester } from 'src/renderer-client';
8
+ import type { IPortRequester } from './renderer-client';
9
9
 
10
10
  export interface NoxusPreloadAPI extends IPortRequester {}
11
11
 
@@ -4,8 +4,8 @@
4
4
  * @author NoxFly
5
5
  */
6
6
 
7
- import { IBatchRequestItem, IBatchResponsePayload, IRequest, IResponse } from 'src/request';
8
- import { RendererEventRegistry } from 'src/renderer-events';
7
+ import { IBatchRequestItem, IBatchResponsePayload, IRequest, IResponse } from './request';
8
+ import { RendererEventRegistry } from './renderer-events';
9
9
 
10
10
  export interface IPortRequester {
11
11
  requestPort(): void;
@@ -8,7 +8,7 @@
8
8
  * Lightweight event registry to help renderer processes subscribe to
9
9
  * push messages sent by the main process through Noxus.
10
10
  */
11
- import { IRendererEventMessage, isRendererEventMessage } from 'src/request';
11
+ import { IRendererEventMessage, isRendererEventMessage } from './request';
12
12
 
13
13
  export type RendererEventHandler<TPayload = unknown> = (payload: TPayload) => void;
14
14
 
package/src/request.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  * @author NoxFly
5
5
  */
6
6
 
7
- import 'reflect-metadata';
8
- import { AtomicHttpMethod, HttpMethod } from 'src/decorators/method.decorator';
9
- import { AppInjector, RootInjector } from 'src/DI/app-injector';
7
+
8
+ import { AtomicHttpMethod, HttpMethod } from './decorators/method.decorator';
9
+ import { AppInjector, RootInjector } from './DI/app-injector';
10
10
 
11
11
  /**
12
12
  * The Request class represents an HTTP request in the Noxus framework.