proteum 2.2.6 → 2.2.8

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 (42) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +4 -4
  3. package/agents/project/AGENTS.md +2 -1
  4. package/agents/project/app-root/AGENTS.md +1 -1
  5. package/agents/project/diagnostics.md +1 -1
  6. package/agents/project/root/AGENTS.md +2 -1
  7. package/cli/commands/configure.ts +14 -35
  8. package/cli/commands/dev.ts +105 -52
  9. package/cli/compiler/artifacts/controllers.ts +30 -4
  10. package/cli/compiler/artifacts/manifest.ts +1 -5
  11. package/cli/compiler/artifacts/services.ts +67 -29
  12. package/cli/presentation/commands.ts +9 -9
  13. package/cli/presentation/help.ts +1 -1
  14. package/cli/scaffold/index.ts +2 -5
  15. package/cli/scaffold/templates.ts +3 -10
  16. package/cli/utils/agents.ts +281 -199
  17. package/client/dev/profiler/ApexChart.tsx +4 -3
  18. package/common/dev/serverHotReload.ts +26 -25
  19. package/package.json +1 -1
  20. package/server/app/commands.ts +11 -16
  21. package/server/app/commandsManager.ts +5 -1
  22. package/server/app/controller/index.ts +68 -16
  23. package/server/app/devCommands.ts +3 -3
  24. package/server/app/devDiagnostics.ts +2 -2
  25. package/server/app/index.ts +19 -8
  26. package/server/app/service/container.ts +22 -19
  27. package/server/app/service/index.ts +33 -13
  28. package/server/app.tsconfig.json +0 -1
  29. package/server/services/auth/index.ts +12 -6
  30. package/server/services/auth/router/index.ts +12 -14
  31. package/server/services/auth/router/request.ts +34 -13
  32. package/server/services/disks/driver.ts +1 -1
  33. package/server/services/disks/index.ts +11 -8
  34. package/server/services/email/index.ts +1 -1
  35. package/server/services/prisma/Facet.ts +6 -5
  36. package/server/services/router/index.ts +8 -7
  37. package/server/services/router/request/validation/zod.ts +2 -0
  38. package/server/services/router/response/index.ts +9 -9
  39. package/server/services/router/service.ts +12 -8
  40. package/tests/agents-utils.test.cjs +207 -0
  41. package/tests/dev-transpile-watch.test.cjs +513 -0
  42. package/types/global/vendors.d.ts +70 -0
@@ -18,7 +18,7 @@ export default function ApexChart({
18
18
  if (!target || !options) return;
19
19
 
20
20
  let disposed = false;
21
- let chart: { destroy: () => void } | undefined;
21
+ let chart: { destroy: () => void; render: () => Promise<unknown> | void } | undefined;
22
22
 
23
23
  target.innerHTML = '';
24
24
  setErrorMessage(undefined);
@@ -29,8 +29,9 @@ export default function ApexChart({
29
29
  if (disposed || !mountRef.current) return;
30
30
 
31
31
  const ApexCharts = module.default;
32
- chart = new ApexCharts(mountRef.current, options);
33
- await chart.render();
32
+ const nextChart = new ApexCharts(mountRef.current, options);
33
+ chart = nextChart;
34
+ await nextChart.render();
34
35
  } catch (error) {
35
36
  if (!disposed) setErrorMessage(readErrorMessage(error));
36
37
  }
@@ -27,33 +27,34 @@ export type TServerReadyMessage = {
27
27
  connectedProjects?: TServerReadyConnectedProject[];
28
28
  };
29
29
 
30
+ const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;
31
+
30
32
  export const isServerHotReloadRequest = (value: unknown): value is TServerHotReloadRequest =>
31
- typeof value === 'object' &&
32
- value !== null &&
33
- (value as TServerHotReloadRequest).type === serverHotReloadMessageType.request &&
34
- Array.isArray((value as TServerHotReloadRequest).changedFiles);
33
+ isRecord(value) &&
34
+ value.type === serverHotReloadMessageType.request &&
35
+ Array.isArray(value.changedFiles);
35
36
 
36
37
  export const isServerHotReloadResult = (value: unknown): value is TServerHotReloadResult =>
37
- typeof value === 'object' &&
38
- value !== null &&
39
- ((value as TServerHotReloadResult).type === serverHotReloadMessageType.succeeded ||
40
- (value as TServerHotReloadResult).type === serverHotReloadMessageType.failed) &&
41
- Array.isArray((value as TServerHotReloadResult).changedFiles);
38
+ isRecord(value) &&
39
+ (value.type === serverHotReloadMessageType.succeeded || value.type === serverHotReloadMessageType.failed) &&
40
+ Array.isArray(value.changedFiles);
42
41
 
43
42
  const isServerReadyConnectedProject = (value: unknown): value is TServerReadyConnectedProject =>
44
- typeof value === 'object' &&
45
- value !== null &&
46
- typeof (value as TServerReadyConnectedProject).namespace === 'string' &&
47
- typeof (value as TServerReadyConnectedProject).identifier === 'string' &&
48
- typeof (value as TServerReadyConnectedProject).name === 'string' &&
49
- typeof (value as TServerReadyConnectedProject).urlInternal === 'string' &&
50
- typeof (value as TServerReadyConnectedProject).healthUrl === 'string';
51
-
52
- export const isServerReadyMessage = (value: unknown): value is TServerReadyMessage =>
53
- typeof value === 'object' &&
54
- value !== null &&
55
- (value as TServerReadyMessage).type === serverHotReloadMessageType.ready &&
56
- typeof (value as TServerReadyMessage).publicUrl === 'string' &&
57
- ((value as TServerReadyMessage).connectedProjects === undefined ||
58
- (Array.isArray((value as TServerReadyMessage).connectedProjects) &&
59
- (value as TServerReadyMessage).connectedProjects.every(isServerReadyConnectedProject)));
43
+ isRecord(value) &&
44
+ typeof value.namespace === 'string' &&
45
+ typeof value.identifier === 'string' &&
46
+ typeof value.name === 'string' &&
47
+ typeof value.urlInternal === 'string' &&
48
+ typeof value.healthUrl === 'string';
49
+
50
+ export const isServerReadyMessage = (value: unknown): value is TServerReadyMessage => {
51
+ if (!isRecord(value)) return false;
52
+
53
+ const connectedProjects = value.connectedProjects;
54
+ return (
55
+ value.type === serverHotReloadMessageType.ready &&
56
+ typeof value.publicUrl === 'string' &&
57
+ (connectedProjects === undefined ||
58
+ (Array.isArray(connectedProjects) && connectedProjects.every(isServerReadyConnectedProject)))
59
+ );
60
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "proteum",
3
3
  "description": "LLM-first Opinionated Typescript Framework for web applications.",
4
- "version": "2.2.6",
4
+ "version": "2.2.8",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/proteum.git",
7
7
  "license": "MIT",
@@ -3,26 +3,25 @@
3
3
  ----------------------------------*/
4
4
 
5
5
  import { Command as ClipanionCommand, Option, UsageError } from 'clipanion';
6
- import type CurrentCommandApplication from '@/server/index';
7
6
 
8
7
  /*----------------------------------
9
8
  - TYPES
10
9
  ----------------------------------*/
11
10
 
12
11
  export type TCommandApplication = {
13
- env: {
12
+ env?: {
14
13
  profile?: string;
15
14
  name?: string;
16
15
  [key: string]: unknown;
17
16
  };
18
- identity: {
17
+ identity?: {
19
18
  identifier?: string;
20
19
  [key: string]: unknown;
21
20
  };
22
- getRootServices: () => Record<string, unknown>;
21
+ getRootServices?: () => Record<string, unknown>;
23
22
  findService?: (serviceId: string) => unknown;
24
- models?: { client?: any };
25
- Models?: { client?: any };
23
+ models?: { client?: object };
24
+ Models?: { client?: object };
26
25
  };
27
26
 
28
27
  export type TCommandService = {
@@ -33,23 +32,19 @@ export type TCommandService = {
33
32
  - COMMAND CLASSES
34
33
  ----------------------------------*/
35
34
 
36
- export abstract class Commands<TApplication extends TCommandApplication = CurrentCommandApplication> {
37
- public app: CurrentCommandApplication;
35
+ export abstract class Commands<TApplication extends TCommandApplication = TCommandApplication> {
36
+ public app: TApplication;
38
37
 
39
- public constructor(app: CurrentCommandApplication) {
38
+ public constructor(app: TApplication) {
40
39
  this.app = app;
41
40
  }
42
41
 
43
- public get services(): CurrentCommandApplication {
42
+ public get services(): TApplication {
44
43
  return this.app;
45
44
  }
46
45
 
47
- public get models(): any {
48
- const app = this.app as {
49
- models?: { client?: any };
50
- Models?: { client?: any };
51
- };
52
- const models = app.models?.client ?? app.Models?.client;
46
+ public get models(): object {
47
+ const models = this.app.models?.client ?? this.app.Models?.client;
53
48
 
54
49
  if (!models)
55
50
  throw new Error(`${this.constructor.name} tried to access models but no Models service is registered.`);
@@ -197,13 +197,17 @@ const parseCommandOptionTokens = (tokens: string[]) => {
197
197
  - SERVICE
198
198
  ----------------------------------*/
199
199
 
200
- export default class CommandsManager extends Service<Config, Hooks, Application> {
200
+ export default class CommandsManager extends Service<Config, Hooks, Application, object> {
201
201
  public priority = 2 as 2;
202
202
 
203
203
  public commandsIndex: CommandsList = {};
204
204
 
205
205
  private runtimeCli?: Cli;
206
206
 
207
+ public constructor(parent: object | 'self', config: Config | null | undefined, app: Application | 'self') {
208
+ super(parent, config, app);
209
+ }
210
+
207
211
  public command<TArgs extends any[]>(
208
212
  ...args:
209
213
  | [name: string, description: string, childrens: RuntimeCommand[]]
@@ -7,39 +7,88 @@ import zod from 'zod';
7
7
 
8
8
  // Core
9
9
  import context from '@server/context';
10
- import type { Application } from '../index';
11
- import type { TServiceModelsClient } from '../service';
12
- import type { TRouterContext, TAnyRouter } from '@server/services/router';
13
10
  import {
14
11
  toValidationSchema,
15
12
  type TValidationSchema,
16
13
  type TValidationShape,
17
14
  } from '@server/services/router/request/validation/zod';
15
+ import type {
16
+ Request as ServerRequest,
17
+ Response as ServerResponse,
18
+ TAnyRouter,
19
+ TRouterContextServices,
20
+ } from '@server/services/router';
18
21
 
19
22
  export { schema } from '@server/services/router/request/validation/zod';
20
- export type { z } from '@server/services/router/request/validation/zod';
23
+ export type {
24
+ z,
25
+ TInferValidationSchema,
26
+ TTypedValidationSchema,
27
+ TValidationSchema,
28
+ TValidationShape,
29
+ } from '@server/services/router/request/validation/zod';
21
30
 
22
31
  /*----------------------------------
23
32
  - TYPES
24
33
  ----------------------------------*/
25
34
 
26
- type TControllerRouter<TApplication extends Application = Application> = TApplication extends { Router: infer TRouter }
27
- ? TRouter extends TAnyRouter
28
- ? TRouter
29
- : TAnyRouter
35
+ type TControllerModelsClient<TApplication extends object = object> = TApplication extends {
36
+ Models: { client: infer TModels };
37
+ }
38
+ ? TModels
39
+ : TApplication extends {
40
+ models: { client: infer TModels };
41
+ }
42
+ ? TModels
43
+ : object;
44
+
45
+ type TControllerRouter<TRouter> = TRouter extends TAnyRouter ? TRouter : TAnyRouter;
46
+ type TControllerApplicationRouter<TApplication extends object> = TApplication extends { Router: infer TRouter }
47
+ ? TControllerRouter<TRouter>
30
48
  : TAnyRouter;
31
49
 
32
- export type TControllerRequestContext<TApplication extends Application = Application> = TRouterContext<
33
- TControllerRouter<TApplication>
34
- >;
50
+ export type TControllerRequestContext<
51
+ TApplication extends object = object,
52
+ TRouter extends object = object,
53
+ TRequestServices extends object = {},
54
+ > = {
55
+ app: TApplication;
56
+ context: object;
57
+ request: ServerRequest<TControllerRouter<TRouter>>;
58
+ api: ServerRequest<TControllerRouter<TRouter>>['api'];
59
+ response: ServerResponse<TControllerRouter<TRouter>>;
60
+ route: object;
61
+ page?: object;
62
+ Router: TControllerRouter<TRouter>;
63
+ } & (TRouter extends TAnyRouter ? TRouterContextServices<TControllerRouter<TRouter>> : {}) &
64
+ TRequestServices;
65
+
66
+ type TControllerBaseContext<TApplication extends object> = {
67
+ app: TApplication;
68
+ request: { data: TObjetDonnees };
69
+ };
70
+
71
+ type TControllerDefaultContext<TApplication extends object, TRequestServices extends object> = {
72
+ app: TApplication;
73
+ context: object;
74
+ request: ServerRequest<TControllerApplicationRouter<TApplication>>;
75
+ api: ServerRequest<TControllerApplicationRouter<TApplication>>['api'];
76
+ response: ServerResponse<TControllerApplicationRouter<TApplication>>;
77
+ route: object;
78
+ page?: object;
79
+ Router: TControllerApplicationRouter<TApplication>;
80
+ } & TRouterContextServices<TControllerApplicationRouter<TApplication>> &
81
+ TRequestServices;
35
82
 
36
83
  /*----------------------------------
37
84
  - CLASS
38
85
  ----------------------------------*/
39
86
 
40
87
  export default abstract class Controller<
41
- TApplication extends Application = Application,
42
- TContext extends TControllerRequestContext<TApplication> = TControllerRequestContext<TApplication>,
88
+ TApplication extends object = object,
89
+ TRouter extends object = object,
90
+ TRequestServices extends object = {},
91
+ TContext extends TControllerBaseContext<TApplication> = TControllerDefaultContext<TApplication, TRequestServices>,
43
92
  > {
44
93
  public constructor(public request: TContext) {}
45
94
 
@@ -51,9 +100,12 @@ export default abstract class Controller<
51
100
  return this.app;
52
101
  }
53
102
 
54
- public get models(): TServiceModelsClient<TApplication> {
55
- const app = this.app as { models?: { client?: unknown }; Models?: { client?: unknown } };
56
- return (app.models?.client ?? app.Models?.client) as TServiceModelsClient<TApplication>;
103
+ public get models(): TControllerModelsClient<TApplication> {
104
+ const app = this.app as {
105
+ models?: { client?: TControllerModelsClient<TApplication> };
106
+ Models?: { client?: TControllerModelsClient<TApplication> };
107
+ };
108
+ return (app.models?.client ?? app.Models?.client) as TControllerModelsClient<TApplication>;
57
109
  }
58
110
 
59
111
  public input<TSchema extends TValidationSchema>(schema: TSchema): zod.output<TSchema>;
@@ -112,10 +112,10 @@ const loadGeneratedCommandDefinitions = () =>
112
112
  (a, b) => a.path.localeCompare(b.path),
113
113
  );
114
114
 
115
- export default class DevCommandsRegistry<TApplication extends Application = Application> {
115
+ export default class DevCommandsRegistry {
116
116
  private definitions = loadGeneratedCommandDefinitions();
117
117
 
118
- public constructor(private app: TApplication) {}
118
+ public constructor(private app: Application) {}
119
119
 
120
120
  public list() {
121
121
  return this.definitions.map((definition) => ({
@@ -150,7 +150,7 @@ export default class DevCommandsRegistry<TApplication extends Application = Appl
150
150
 
151
151
  try {
152
152
  const instance = new definition.Command(this.app);
153
- const method = (instance as Record<string, unknown>)[definition.methodName];
153
+ const method = Reflect.get(instance, definition.methodName);
154
154
 
155
155
  if (typeof method !== 'function') {
156
156
  throw new Error(
@@ -36,8 +36,8 @@ const isExplainSectionName = (value: string): value is TExplainSectionName =>
36
36
  const isConsoleLogLevel = (value: string): value is TDevConsoleLogLevel =>
37
37
  ['silly', 'log', 'info', 'warn', 'error'].includes(value);
38
38
 
39
- export default class DevDiagnosticsRegistry<TApplication extends Application = Application> {
40
- public constructor(private app: TApplication) {}
39
+ export default class DevDiagnosticsRegistry {
40
+ public constructor(private app: Application) {}
41
41
 
42
42
  private getManifestFilepath() {
43
43
  return path.join(this.app.container.path.root, '.proteum', 'manifest.json');
@@ -44,8 +44,13 @@ export const Service = ServicesContainer;
44
44
  type Prettify<T> = { [K in keyof T]: T[K] } & {};
45
45
 
46
46
  export type ApplicationProperties = Prettify<keyof Application>;
47
- export type RootServicesOf<TApplication extends Application = Application> = Prettify<{
48
- [TKey in Exclude<keyof TApplication, ApplicationProperties> as TApplication[TKey] extends AnyService ? TKey : never]: TApplication[TKey];
47
+ type RootServiceCandidate = {
48
+ runHook: object;
49
+ getServiceInstance: object;
50
+ status: string | undefined;
51
+ };
52
+ export type RootServicesOf<TApplication extends object = object> = Prettify<{
53
+ [TKey in Exclude<keyof TApplication, ApplicationProperties> as TApplication[TKey] extends RootServiceCandidate ? TKey : never]: TApplication[TKey];
49
54
  }>;
50
55
 
51
56
  const isServiceInstance = (value: unknown): value is AnyService => {
@@ -56,19 +61,24 @@ const isServiceInstance = (value: unknown): value is AnyService => {
56
61
  return typeof service.runHook === 'function' && typeof service.getServiceInstance === 'function' && service.status !== undefined;
57
62
  };
58
63
 
64
+ const createCommandsManager = (app: Application) => new CommandsManager(app, { debug: true }, app);
65
+ const createDevCommandsRegistry = (app: Application) => new DevCommandsRegistry(app);
66
+ const createDevDiagnosticsRegistry = (app: Application) => new DevDiagnosticsRegistry(app);
67
+
59
68
  /*----------------------------------
60
69
  - FUNCTIONS
61
70
  ----------------------------------*/
62
71
  export abstract class Application<
63
72
  TServicesContainer extends ServicesContainerClass = ServicesContainerClass,
64
73
  TUser extends TBasicUser = TBasicUser,
65
- > extends ApplicationService<Config, Hooks, Application, Application> {
74
+ > extends ApplicationService<Config, Hooks, object, object> {
66
75
  public static identity = ConfigApplication.identity;
67
76
  public static setup = ConfigApplication.setup;
68
77
 
69
78
  public app!: this;
70
79
  public servicesContainer!: TServicesContainer;
71
80
  public userType!: TUser;
81
+ public declare Router: object;
72
82
 
73
83
  /*----------------------------------
74
84
  - PROPERTIES
@@ -122,21 +132,22 @@ export abstract class Application<
122
132
  - COMMANDS
123
133
  ----------------------------------*/
124
134
 
125
- private commandsManager = new CommandsManager(this, { debug: true }, this);
126
- private devCommandsRegistry?: DevCommandsRegistry<this>;
127
- private devDiagnosticsRegistry?: DevDiagnosticsRegistry<this>;
135
+ private commandsManager?: CommandsManager;
136
+ private devCommandsRegistry?: DevCommandsRegistry;
137
+ private devDiagnosticsRegistry?: DevDiagnosticsRegistry;
128
138
 
129
139
  public command(...args: Parameters<CommandsManager['command']>) {
140
+ this.commandsManager ??= createCommandsManager(this as Application);
130
141
  return this.commandsManager.command(...args);
131
142
  }
132
143
 
133
144
  public getDevCommands() {
134
- this.devCommandsRegistry ??= new DevCommandsRegistry(this);
145
+ this.devCommandsRegistry ??= createDevCommandsRegistry(this as Application);
135
146
  return this.devCommandsRegistry;
136
147
  }
137
148
 
138
149
  public getDevDiagnostics() {
139
- this.devDiagnosticsRegistry ??= new DevDiagnosticsRegistry(this);
150
+ this.devDiagnosticsRegistry ??= createDevDiagnosticsRegistry(this as Application);
140
151
  return this.devDiagnosticsRegistry;
141
152
  }
142
153
 
@@ -3,29 +3,32 @@
3
3
  ----------------------------------*/
4
4
 
5
5
  // Specific
6
- import type { AnyService, AnyServiceClass, StartedServicesIndex } from '.';
6
+ import type { AnyServiceClass, StartedServicesIndex } from '.';
7
7
 
8
8
  /*----------------------------------
9
9
  - TYPES
10
10
  ----------------------------------*/
11
11
 
12
- export type ServiceConfig<TServiceClass extends AnyServiceClass> = NonNullable<ConstructorParameters<TServiceClass>[1]>;
12
+ type ConstructorConfig<TServiceClass extends AnyServiceClass> = ConstructorParameters<TServiceClass> extends [
13
+ _parent: object | 'self',
14
+ config: infer TConfig,
15
+ _app: object | 'self',
16
+ ..._rest: []
17
+ ]
18
+ ? NonNullable<TConfig>
19
+ : ConstructorParameters<TServiceClass> extends [config: infer TConfig, _app: object | 'self', ..._rest: []]
20
+ ? NonNullable<TConfig>
21
+ : {};
13
22
 
14
- type ExactConfig<TValue, TShape> = TValue extends TShape
15
- ? TShape extends (...args: never[]) => infer _TReturn
16
- ? TValue
17
- : TValue extends readonly (infer TValueItem)[]
18
- ? TShape extends readonly (infer TShapeItem)[]
19
- ? readonly ExactConfig<TValueItem, TShapeItem>[]
20
- : never
21
- : TValue extends object
22
- ? TShape extends object
23
- ? Exclude<keyof TValue, keyof TShape> extends never
24
- ? { [K in keyof TValue]: K extends keyof TShape ? ExactConfig<TValue[K], TShape[K]> : never }
25
- : never
26
- : TValue
27
- : TValue
28
- : never;
23
+ export type ServiceConfig<TServiceClass extends AnyServiceClass> = ConstructorConfig<TServiceClass>;
24
+
25
+ type ExactConfig<TConfig, TExpected> = TExpected extends object
26
+ ? TConfig extends object
27
+ ? { [TKey in Exclude<keyof TConfig, keyof TExpected>]: never } & {
28
+ [TKey in keyof TConfig & keyof TExpected]?: ExactConfig<TConfig[TKey], NonNullable<TExpected[TKey]>>;
29
+ }
30
+ : {}
31
+ : {};
29
32
 
30
33
  /*----------------------------------
31
34
  - CLASS
@@ -41,7 +44,7 @@ export class ServicesContainer<TServicesIndex extends StartedServicesIndex = Sta
41
44
  public callableInstance = <TInstance extends object, TCallableName extends keyof TInstance>(
42
45
  instance: TInstance,
43
46
  funcName: TCallableName,
44
- ): TInstance[TCallableName] & TInstance => {
47
+ ): TInstance[TCallableName] & { serviceInstance: TInstance } => {
45
48
  const instanceRecord = instance as Record<string, unknown>;
46
49
  const callableFunc = instance[funcName];
47
50
  if (typeof callableFunc !== 'function') throw new Error(`instance[funcName] isn't callable.`);
@@ -66,7 +69,7 @@ export class ServicesContainer<TServicesIndex extends StartedServicesIndex = Sta
66
69
  // Allow us to recognize a callable as a service
67
70
  callable.serviceInstance = instance;
68
71
 
69
- return callable as TInstance[TCallableName] & TInstance;
72
+ return callable as TInstance[TCallableName] & { serviceInstance: TInstance };
70
73
  };
71
74
  }
72
75
 
@@ -5,16 +5,27 @@
5
5
  // Specific
6
6
  import type { Application } from '../index';
7
7
  import type { Command } from '../commands';
8
- import type { TRouterContext, TAnyRouter } from '../../services/router';
8
+ import type {
9
+ Request as ServerRequest,
10
+ Response as ServerResponse,
11
+ TRouterContextServices,
12
+ TAnyRouter,
13
+ } from '../../services/router';
9
14
 
10
15
  export { schema } from '../../services/router/request/validation/zod';
11
- export type { z } from '../../services/router/request/validation/zod';
16
+ export type {
17
+ z,
18
+ TInferValidationSchema,
19
+ TTypedValidationSchema,
20
+ TValidationSchema,
21
+ TValidationShape,
22
+ } from '../../services/router/request/validation/zod';
12
23
 
13
24
  /*----------------------------------
14
25
  - TYPES: OPTIONS
15
26
  ----------------------------------*/
16
27
 
17
- export type AnyService = Service<{}, {}, Application, any>;
28
+ export type AnyService = Service<{}, any, any, any>;
18
29
  export type AnyServiceClass = ClassType<AnyService>;
19
30
 
20
31
  /*----------------------------------
@@ -31,7 +42,7 @@ export type THooksIndex<THooks extends THooksList> = { [name in keyof THooks]?:
31
42
 
32
43
  export type StartedServicesIndex = { [serviceId: string]: AnyService };
33
44
 
34
- type TServiceRouter<TApplication extends Application> = TApplication extends { Router: infer TRouter }
45
+ type TServiceRouter<TApplication extends object> = TApplication extends { Router: infer TRouter }
35
46
  ? TRouter extends TAnyRouter
36
47
  ? TRouter
37
48
  : TAnyRouter
@@ -41,11 +52,18 @@ type TServiceRouter<TApplication extends Application> = TApplication extends { R
41
52
  * @deprecated Services should not depend on request context.
42
53
  * Resolve auth/input/request data in controllers and pass explicit typed values into services instead.
43
54
  */
44
- export type TServiceRequestContext<TApplication extends Application = Application> = TRouterContext<
45
- TServiceRouter<TApplication>
46
- >;
47
-
48
- export type TServiceModelsClient<TApplication extends Application = Application> = TApplication extends {
55
+ export type TServiceRequestContext<TApplication extends object = object> = {
56
+ app: TApplication;
57
+ context: object;
58
+ request: ServerRequest<TServiceRouter<TApplication>>;
59
+ api: ServerRequest<TServiceRouter<TApplication>>['api'];
60
+ response: ServerResponse<TServiceRouter<TApplication>>;
61
+ route: object;
62
+ page?: object;
63
+ Router: TServiceRouter<TApplication>;
64
+ } & TRouterContextServices<TServiceRouter<TApplication>>;
65
+
66
+ export type TServiceModelsClient<TApplication extends object = object> = TApplication extends {
49
67
  Models: { client: infer TModels };
50
68
  }
51
69
  ? TModels
@@ -53,10 +71,12 @@ export type TServiceModelsClient<TApplication extends Application = Application>
53
71
  models: { client: infer TModels };
54
72
  }
55
73
  ? TModels
56
- : never;
74
+ : object;
57
75
 
58
- export type TSetupConfig<TConfig> = TConfig extends (...args: any[]) => any
76
+ export type TSetupConfig<TConfig> = TConfig extends (...args: infer TFunctionArgs) => infer TFunctionResult
59
77
  ? TConfig
78
+ : TConfig extends { getServiceInstance: (...args: infer TServiceArgs) => infer TServiceInstance }
79
+ ? TConfig
60
80
  : TConfig extends Array<infer TItem>
61
81
  ? Array<TSetupConfig<TItem>>
62
82
  : TConfig extends object
@@ -86,8 +106,8 @@ const resolveSelfReference = <TSelf extends object, TValue extends object>(
86
106
  export default abstract class Service<
87
107
  TConfig extends {},
88
108
  THooks extends THooksList,
89
- TApplication extends Application = Application,
90
- TParent extends object = AnyService,
109
+ TApplication extends object = object,
110
+ TParent extends object = object,
91
111
  > {
92
112
  public started?: Promise<void>;
93
113
  public starting?: Promise<void>;
@@ -6,7 +6,6 @@
6
6
  "paths": {
7
7
 
8
8
  "@/server/models": ["./.proteum/server/models.ts"],
9
- "@/client/context": ["./.proteum/client/context.ts"],
10
9
  "@generated/client/*": ["./.proteum/client/*"],
11
10
  "@generated/common/*": ["./.proteum/common/*"],
12
11
  "@generated/server/*": ["./.proteum/server/*"],
@@ -10,7 +10,6 @@ import type http from 'http';
10
10
  // Core
11
11
  import type { Application } from '@server/app/index';
12
12
  import Service from '@server/app/service';
13
- import { type TAnyRouter, Request as ServerRequest } from '@server/services/router';
14
13
  import * as AuthErrors from '@common/errors';
15
14
  import type { TTraceCaptureMode, TTraceEventType } from '@common/dev/requestTrace';
16
15
 
@@ -103,7 +102,13 @@ export type TAuthConfiguredRules = {
103
102
 
104
103
  export type TAuthTrackingContext = ProteumAuthTrackingContext | null;
105
104
 
106
- export type TAuthRulesFactory<TUser extends TBasicUser, TRequest extends ServerRequest<TAnyRouter>> = (
105
+ export type TAuthRequest = {
106
+ id: string;
107
+ res: Pick<express.Response, 'clearCookie' | 'cookie'>;
108
+ user: TBasicUser | null;
109
+ };
110
+
111
+ export type TAuthRulesFactory<TUser extends TBasicUser, TRequest extends TAuthRequest> = (
107
112
  user: TUser,
108
113
  tracking: TAuthTrackingContext,
109
114
  request: TRequest,
@@ -121,7 +126,7 @@ export const UserRoles = ['USER', 'ADMIN', 'TEST', 'DEV'] as const;
121
126
 
122
127
  export type TConfig<
123
128
  TUser extends TBasicUser = TBasicUser,
124
- TRequest extends ServerRequest<TAnyRouter> = ServerRequest<TAnyRouter>,
129
+ TRequest extends TAuthRequest = TAuthRequest,
125
130
  > = {
126
131
  debug: boolean;
127
132
  logoutUrl: string;
@@ -155,7 +160,7 @@ export default abstract class AuthService<
155
160
  TUser extends TBasicUser,
156
161
  TApplication extends Application,
157
162
  TJwtSession extends TBasicJwtSession = TBasicJwtSession,
158
- TRequest extends ServerRequest<TAnyRouter> = ServerRequest<TAnyRouter>,
163
+ TRequest extends TAuthRequest = TAuthRequest,
159
164
  > extends Service<TConfig<TUser, TRequest>, THooks, TApplication, TApplication> {
160
165
  public login?(request: TRequest, email: string): Promise<unknown>;
161
166
  public abstract decodeSession(jwt: TJwtSession, req: THttpRequest): Promise<TUser | null>;
@@ -200,7 +205,8 @@ export default abstract class AuthService<
200
205
  if ('apiKey' in session) {
201
206
  return {
202
207
  payloadKind: 'api-key',
203
- payloadAccountType: session.accountType ?? null,
208
+ payloadAccountType:
209
+ 'accountType' in session && typeof session.accountType === 'string' ? session.accountType : null,
204
210
  };
205
211
  }
206
212
 
@@ -602,7 +608,7 @@ export default abstract class AuthService<
602
608
  ): TUser | null {
603
609
  const user = this.getDecodedUser(request);
604
610
  const conditionRuleNames =
605
- conditions && conditions !== false
611
+ conditions
606
612
  ? (Object.keys(conditions) as Array<Extract<keyof TAuthConfiguredRules, string>>)
607
613
  : [];
608
614