alepha 0.6.10 → 0.7.1

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 (100) hide show
  1. package/README.md +14 -3
  2. package/assets/logo.png +0 -0
  3. package/cache.cjs +0 -1
  4. package/cache.d.ts +30 -13
  5. package/cache.js +0 -1
  6. package/core.cjs +0 -1
  7. package/core.d.ts +465 -183
  8. package/core.js +0 -1
  9. package/datetime.cjs +0 -1
  10. package/datetime.d.ts +32 -31
  11. package/datetime.js +0 -1
  12. package/lock.cjs +0 -1
  13. package/lock.d.ts +2 -2
  14. package/lock.js +0 -1
  15. package/package.json +55 -47
  16. package/postgres.cjs +0 -1
  17. package/postgres.d.ts +3276 -124
  18. package/postgres.js +0 -1
  19. package/queue.cjs +0 -1
  20. package/queue.d.ts +2 -2
  21. package/queue.js +0 -1
  22. package/react/auth.cjs +0 -1
  23. package/react/auth.d.ts +40 -32
  24. package/react/auth.js +0 -1
  25. package/react.cjs +0 -1
  26. package/react.d.ts +417 -234
  27. package/react.js +0 -1
  28. package/redis.cjs +0 -1
  29. package/redis.js +0 -1
  30. package/retry.cjs +12 -0
  31. package/retry.d.ts +68 -0
  32. package/retry.js +1 -0
  33. package/scheduler.cjs +0 -1
  34. package/scheduler.js +0 -1
  35. package/security.cjs +0 -1
  36. package/security.d.ts +71 -17
  37. package/security.js +0 -1
  38. package/server/cookies.cjs +0 -1
  39. package/server/cookies.d.ts +1 -1
  40. package/server/cookies.js +0 -1
  41. package/server/metrics.cjs +0 -1
  42. package/server/metrics.d.ts +1 -1
  43. package/server/metrics.js +0 -1
  44. package/server/proxy.cjs +0 -1
  45. package/server/proxy.d.ts +1 -35
  46. package/server/proxy.js +0 -1
  47. package/server/static.cjs +0 -1
  48. package/server/static.d.ts +6 -0
  49. package/server/static.js +0 -1
  50. package/server/swagger.cjs +0 -1
  51. package/server/swagger.d.ts +1 -0
  52. package/server/swagger.js +0 -1
  53. package/server.cjs +0 -1
  54. package/server.d.ts +639 -346
  55. package/server.js +0 -1
  56. package/src/retry.ts +1 -0
  57. package/topic.cjs +0 -1
  58. package/topic.d.ts +3 -3
  59. package/topic.js +0 -1
  60. package/vite.cjs +0 -1
  61. package/vite.d.ts +29 -30
  62. package/vite.js +0 -1
  63. package/cache.cjs.map +0 -1
  64. package/cache.js.map +0 -1
  65. package/core.cjs.map +0 -1
  66. package/core.js.map +0 -1
  67. package/datetime.cjs.map +0 -1
  68. package/datetime.js.map +0 -1
  69. package/lock.cjs.map +0 -1
  70. package/lock.js.map +0 -1
  71. package/postgres.cjs.map +0 -1
  72. package/postgres.js.map +0 -1
  73. package/queue.cjs.map +0 -1
  74. package/queue.js.map +0 -1
  75. package/react/auth.cjs.map +0 -1
  76. package/react/auth.js.map +0 -1
  77. package/react.cjs.map +0 -1
  78. package/react.js.map +0 -1
  79. package/redis.cjs.map +0 -1
  80. package/redis.js.map +0 -1
  81. package/scheduler.cjs.map +0 -1
  82. package/scheduler.js.map +0 -1
  83. package/security.cjs.map +0 -1
  84. package/security.js.map +0 -1
  85. package/server/cookies.cjs.map +0 -1
  86. package/server/cookies.js.map +0 -1
  87. package/server/metrics.cjs.map +0 -1
  88. package/server/metrics.js.map +0 -1
  89. package/server/proxy.cjs.map +0 -1
  90. package/server/proxy.js.map +0 -1
  91. package/server/static.cjs.map +0 -1
  92. package/server/static.js.map +0 -1
  93. package/server/swagger.cjs.map +0 -1
  94. package/server/swagger.js.map +0 -1
  95. package/server.cjs.map +0 -1
  96. package/server.js.map +0 -1
  97. package/topic.cjs.map +0 -1
  98. package/topic.js.map +0 -1
  99. package/vite.cjs.map +0 -1
  100. package/vite.js.map +0 -1
package/server.d.ts CHANGED
@@ -1,41 +1,48 @@
1
1
  import * as _alepha_core from '@alepha/core';
2
- import { Static as Static$1, TObject as TObject$1, TSchema as TSchema$1, Async, StreamLike, Alepha, OPTIONS, KIND, FileLike } from '@alepha/core';
2
+ import { Static as Static$1, TObject as TObject$1, TSchema as TSchema$2, Async, StreamLike, Alepha, FileLike, OPTIONS, KIND, Service } from '@alepha/core';
3
3
  export { KIND } from '@alepha/core';
4
- import { UserAccountToken, Permission, SecurityProvider, JwtProvider } from '@alepha/security';
4
+ import * as _alepha_cache from '@alepha/cache';
5
+ import { CacheDescriptorOptions } from '@alepha/cache';
6
+ import { DurationLike, DateTimeProvider } from '@alepha/datetime';
7
+ import { UserAccountToken, Permission, ServiceAccountDescriptor as ServiceAccountDescriptor$1, SecurityProvider, JwtProvider } from '@alepha/security';
5
8
  import { IncomingMessage, ServerResponse as ServerResponse$1 } from 'node:http';
6
9
  import { Readable } from 'node:stream';
7
10
  import { ReadableStream } from 'node:stream/web';
8
11
  import { Route, RouterProvider } from '@alepha/router';
9
- import * as _alepha_cache from '@alepha/cache';
10
- import { DurationLike } from '@alepha/datetime';
12
+ import * as _alepha_retry from '@alepha/retry';
11
13
  import { BusboyConfig } from '@fastify/busboy';
12
14
  import * as http from 'http';
13
15
 
14
16
  /** Symbol key applied to readonly types */
15
- declare const ReadonlyKind: unique symbol;
17
+ declare const ReadonlyKind$1: unique symbol;
16
18
  /** Symbol key applied to optional types */
17
- declare const OptionalKind: unique symbol;
19
+ declare const OptionalKind$1: unique symbol;
18
20
  /** Symbol key applied to types */
19
- declare const Hint: unique symbol;
21
+ declare const Hint$1: unique symbol;
20
22
  /** Symbol key applied to types */
21
- declare const Kind: unique symbol;
23
+ declare const Kind$1: unique symbol;
24
+
25
+ interface TAny extends TSchema$1 {
26
+ [Kind$1]: 'Any';
27
+ static: any;
28
+ }
22
29
 
23
- type TReadonly<T extends TSchema> = T & {
24
- [ReadonlyKind]: 'Readonly';
30
+ type TReadonly<T extends TSchema$1> = T & {
31
+ [ReadonlyKind$1]: 'Readonly';
25
32
  };
26
33
 
27
- type UnionStatic<T extends TSchema[], P extends unknown[]> = {
28
- [K in keyof T]: T[K] extends TSchema ? Static<T[K], P> : never;
34
+ type UnionStatic<T extends TSchema$1[], P extends unknown[]> = {
35
+ [K in keyof T]: T[K] extends TSchema$1 ? Static<T[K], P> : never;
29
36
  }[number];
30
- interface TUnion<T extends TSchema[] = TSchema[]> extends TSchema {
31
- [Kind]: 'Union';
37
+ interface TUnion<T extends TSchema$1[] = TSchema$1[]> extends TSchema$1 {
38
+ [Kind$1]: 'Union';
32
39
  static: UnionStatic<T, this['params']>;
33
40
  anyOf: T;
34
41
  }
35
42
 
36
- type StringFormatOption = 'date-time' | 'time' | 'date' | 'email' | 'idn-email' | 'hostname' | 'idn-hostname' | 'ipv4' | 'ipv6' | 'uri' | 'uri-reference' | 'iri' | 'uuid' | 'iri-reference' | 'uri-template' | 'json-pointer' | 'relative-json-pointer' | 'regex' | ({} & string);
37
- type StringContentEncodingOption = '7bit' | '8bit' | 'binary' | 'quoted-printable' | 'base64' | ({} & string);
38
- interface StringOptions extends SchemaOptions {
43
+ type StringFormatOption$1 = 'date-time' | 'time' | 'date' | 'email' | 'idn-email' | 'hostname' | 'idn-hostname' | 'ipv4' | 'ipv6' | 'uri' | 'uri-reference' | 'iri' | 'uuid' | 'iri-reference' | 'uri-template' | 'json-pointer' | 'relative-json-pointer' | 'regex' | ({} & string);
44
+ type StringContentEncodingOption$1 = '7bit' | '8bit' | 'binary' | 'quoted-printable' | 'base64' | ({} & string);
45
+ interface StringOptions$1 extends SchemaOptions$1 {
39
46
  /** The maximum string length */
40
47
  maxLength?: number;
41
48
  /** The minimum string length */
@@ -43,67 +50,80 @@ interface StringOptions extends SchemaOptions {
43
50
  /** A regular expression pattern this string should match */
44
51
  pattern?: string;
45
52
  /** A format this string should match */
46
- format?: StringFormatOption;
53
+ format?: StringFormatOption$1;
47
54
  /** The content encoding for this string */
48
- contentEncoding?: StringContentEncodingOption;
55
+ contentEncoding?: StringContentEncodingOption$1;
49
56
  /** The content media type for this string */
50
57
  contentMediaType?: string;
51
58
  }
52
- interface TString extends TSchema, StringOptions {
53
- [Kind]: 'String';
59
+ interface TString$1 extends TSchema$1, StringOptions$1 {
60
+ [Kind$1]: 'String';
54
61
  static: string;
55
62
  type: 'string';
56
63
  }
57
64
 
58
- interface TBoolean extends TSchema {
59
- [Kind]: 'Boolean';
65
+ interface TBoolean extends TSchema$1 {
66
+ [Kind$1]: 'Boolean';
60
67
  static: boolean;
61
68
  type: 'boolean';
62
69
  }
63
70
 
64
- interface NumberOptions extends SchemaOptions {
71
+ interface NumberOptions extends SchemaOptions$1 {
65
72
  exclusiveMaximum?: number;
66
73
  exclusiveMinimum?: number;
67
74
  maximum?: number;
68
75
  minimum?: number;
69
76
  multipleOf?: number;
70
77
  }
71
- interface TNumber extends TSchema, NumberOptions {
72
- [Kind]: 'Number';
78
+ interface TNumber extends TSchema$1, NumberOptions {
79
+ [Kind$1]: 'Number';
73
80
  static: number;
74
81
  type: 'number';
75
82
  }
76
83
 
77
- interface IntegerOptions extends SchemaOptions {
84
+ interface IntegerOptions extends SchemaOptions$1 {
78
85
  exclusiveMaximum?: number;
79
86
  exclusiveMinimum?: number;
80
87
  maximum?: number;
81
88
  minimum?: number;
82
89
  multipleOf?: number;
83
90
  }
84
- interface TInteger extends TSchema, IntegerOptions {
85
- [Kind]: 'Integer';
91
+ interface TInteger extends TSchema$1, IntegerOptions {
92
+ [Kind$1]: 'Integer';
86
93
  static: number;
87
94
  type: 'integer';
88
95
  }
89
96
 
90
- type TOptional<T extends TSchema> = T & {
91
- [OptionalKind]: 'Optional';
97
+ type TOptional<T extends TSchema$1> = T & {
98
+ [OptionalKind$1]: 'Optional';
92
99
  };
93
100
 
101
+ type RecordStatic<Key extends TSchema$1, Type extends TSchema$1, P extends unknown[]> = (Evaluate<{
102
+ [_ in Assert<Static<Key>, PropertyKey>]: Static<Type, P>;
103
+ }>);
104
+ interface TRecord<Key extends TSchema$1 = TSchema$1, Type extends TSchema$1 = TSchema$1> extends TSchema$1 {
105
+ [Kind$1]: 'Record';
106
+ static: RecordStatic<Key, Type, this['params']>;
107
+ type: 'object';
108
+ patternProperties: {
109
+ [pattern: string]: Type;
110
+ };
111
+ additionalProperties: TAdditionalProperties;
112
+ }
113
+
94
114
  /** Creates a static type from a TypeBox type */
95
- type Static<Type extends TSchema, Params extends unknown[] = [], Result = (Type & {
115
+ type Static<Type extends TSchema$1, Params extends unknown[] = [], Result = (Type & {
96
116
  params: Params;
97
117
  })['static']> = Result;
98
118
 
99
119
  type ReadonlyOptionalPropertyKeys<T extends TProperties> = {
100
- [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? K : never) : never;
120
+ [K in keyof T]: T[K] extends TReadonly<TSchema$1> ? (T[K] extends TOptional<T[K]> ? K : never) : never;
101
121
  }[keyof T];
102
122
  type ReadonlyPropertyKeys<T extends TProperties> = {
103
- [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? never : K) : never;
123
+ [K in keyof T]: T[K] extends TReadonly<TSchema$1> ? (T[K] extends TOptional<T[K]> ? never : K) : never;
104
124
  }[keyof T];
105
125
  type OptionalPropertyKeys<T extends TProperties> = {
106
- [K in keyof T]: T[K] extends TOptional<TSchema> ? (T[K] extends TReadonly<T[K]> ? never : K) : never;
126
+ [K in keyof T]: T[K] extends TOptional<TSchema$1> ? (T[K] extends TReadonly<T[K]> ? never : K) : never;
107
127
  }[keyof T];
108
128
  type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>;
109
129
  type ObjectStaticProperties<T extends TProperties, R extends Record<keyof any, unknown>> = Evaluate<(Readonly<Partial<Pick<R, ReadonlyOptionalPropertyKeys<T>>>> & Readonly<Pick<R, ReadonlyPropertyKeys<T>>> & Partial<Pick<R, OptionalPropertyKeys<T>>> & Required<Pick<R, RequiredPropertyKeys<T>>>)>;
@@ -111,9 +131,9 @@ type ObjectStatic<T extends TProperties, P extends unknown[]> = ObjectStaticProp
111
131
  [K in keyof T]: Static<T[K], P>;
112
132
  }>;
113
133
  type TPropertyKey = string | number;
114
- type TProperties = Record<TPropertyKey, TSchema>;
115
- type TAdditionalProperties = undefined | TSchema | boolean;
116
- interface ObjectOptions extends SchemaOptions {
134
+ type TProperties = Record<TPropertyKey, TSchema$1>;
135
+ type TAdditionalProperties = undefined | TSchema$1 | boolean;
136
+ interface ObjectOptions extends SchemaOptions$1 {
117
137
  /** Additional property constraints for this object */
118
138
  additionalProperties?: TAdditionalProperties;
119
139
  /** The minimum number of properties allowed on this object */
@@ -121,8 +141,8 @@ interface ObjectOptions extends SchemaOptions {
121
141
  /** The maximum number of properties allowed on this object */
122
142
  maxProperties?: number;
123
143
  }
124
- interface TObject<T extends TProperties = TProperties> extends TSchema, ObjectOptions {
125
- [Kind]: 'Object';
144
+ interface TObject<T extends TProperties = TProperties> extends TSchema$1, ObjectOptions {
145
+ [Kind$1]: 'Object';
126
146
  static: ObjectStatic<T, this['params']>;
127
147
  additionalProperties?: TAdditionalProperties;
128
148
  type: 'object';
@@ -130,12 +150,13 @@ interface TObject<T extends TProperties = TProperties> extends TSchema, ObjectOp
130
150
  required?: string[];
131
151
  }
132
152
 
153
+ type Assert<T, E> = T extends E ? T : never;
133
154
  type Evaluate<T> = T extends infer O ? {
134
155
  [K in keyof O]: O[K];
135
156
  } : never;
136
157
  type Ensure<T> = T extends infer U ? U : never;
137
158
 
138
- interface ArrayOptions extends SchemaOptions {
159
+ interface ArrayOptions extends SchemaOptions$1 {
139
160
  /** The minimum number of items in this array */
140
161
  minItems?: number;
141
162
  /** The maximum number of items in this array */
@@ -143,21 +164,21 @@ interface ArrayOptions extends SchemaOptions {
143
164
  /** Should this schema contain unique items */
144
165
  uniqueItems?: boolean;
145
166
  /** A schema for which some elements should match */
146
- contains?: TSchema;
167
+ contains?: TSchema$1;
147
168
  /** A minimum number of contains schema matches */
148
169
  minContains?: number;
149
170
  /** A maximum number of contains schema matches */
150
171
  maxContains?: number;
151
172
  }
152
- type ArrayStatic<T extends TSchema, P extends unknown[]> = Ensure<Static<T, P>[]>;
153
- interface TArray<T extends TSchema = TSchema> extends TSchema, ArrayOptions {
154
- [Kind]: 'Array';
173
+ type ArrayStatic<T extends TSchema$1, P extends unknown[]> = Ensure<Static<T, P>[]>;
174
+ interface TArray<T extends TSchema$1 = TSchema$1> extends TSchema$1, ArrayOptions {
175
+ [Kind$1]: 'Array';
155
176
  static: ArrayStatic<T, this['params']>;
156
177
  type: 'array';
157
178
  items: T;
158
179
  }
159
180
 
160
- interface SchemaOptions {
181
+ interface SchemaOptions$1 {
161
182
  $schema?: string;
162
183
  /** Id for this schema */
163
184
  $id?: string;
@@ -175,13 +196,13 @@ interface SchemaOptions {
175
196
  writeOnly?: boolean;
176
197
  [prop: string]: any;
177
198
  }
178
- interface TKind {
179
- [Kind]: string;
199
+ interface TKind$1 {
200
+ [Kind$1]: string;
180
201
  }
181
- interface TSchema extends TKind, SchemaOptions {
182
- [ReadonlyKind]?: string;
183
- [OptionalKind]?: string;
184
- [Hint]?: string;
202
+ interface TSchema$1 extends TKind$1, SchemaOptions$1 {
203
+ [ReadonlyKind$1]?: string;
204
+ [OptionalKind$1]?: string;
205
+ [Hint$1]?: string;
185
206
  params: unknown[];
186
207
  static: unknown;
187
208
  }
@@ -189,6 +210,8 @@ interface TSchema extends TKind, SchemaOptions {
189
210
  declare const routeMethods: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "CONNECT", "TRACE"];
190
211
  type RouteMethod = (typeof routeMethods)[number];
191
212
 
213
+ type ServiceRouteCache = boolean | DurationLike | Omit<CacheDescriptorOptions<any>, "handler" | "key">;
214
+
192
215
  declare const envSchema$4: TObject$1<{
193
216
  SERVER_ALS_ENABLED: TBoolean;
194
217
  }>;
@@ -196,6 +219,14 @@ declare module "alepha" {
196
219
  interface Env extends Partial<Static$1<typeof envSchema$4>> {
197
220
  }
198
221
  }
222
+ /**
223
+ * Main router for all routes on the server side.
224
+ *
225
+ * Remember:
226
+ * - $route => generic route
227
+ * - $action => action route (for API calls)
228
+ * - $page => React route (for SSR)
229
+ */
199
230
  declare class ServerRouterProvider extends RouterProvider<ServerRouteWithHandler> {
200
231
  protected readonly alepha: Alepha;
201
232
  protected readonly env: {
@@ -203,7 +234,7 @@ declare class ServerRouterProvider extends RouterProvider<ServerRouteWithHandler
203
234
  };
204
235
  createRequestId(): string;
205
236
  route<TConfig extends RequestConfigSchema = RequestConfigSchema>(route: ServerRoute<TConfig>): Promise<void>;
206
- handle(route: ServerRoute, rawRequest: ServerRawRequest, responseType: ResponseType, withAls: boolean): Promise<ServerResponse>;
237
+ onRequest(route: ServerRoute, rawRequest: ServerRawRequest, responseType: ResponseType, withAls: boolean): Promise<ServerResponse>;
207
238
  protected processRequest(request: ServerRequest, route: ServerRoute, responseType: ResponseType, withAls: boolean): Promise<{
208
239
  status: number;
209
240
  headers: Record<string, string> & {
@@ -211,7 +242,7 @@ declare class ServerRouterProvider extends RouterProvider<ServerRouteWithHandler
211
242
  };
212
243
  body: any;
213
244
  }>;
214
- protected tryRequestProcessing(route: ServerRoute, request: ServerRequest, responseType: ResponseType, withAls: boolean): Promise<void>;
245
+ protected runRouteHandler(route: ServerRoute, request: ServerRequest, responseType: ResponseType, withAls: boolean): Promise<void>;
215
246
  protected getResponseType(schema?: RequestConfigSchema): ResponseType;
216
247
  protected errorHandler(route: ServerRoute, request: ServerRequest, error: Error): Promise<void>;
217
248
  validateRequest(route: {
@@ -220,14 +251,14 @@ declare class ServerRouterProvider extends RouterProvider<ServerRouteWithHandler
220
251
  serializeResponse(route: ServerRoute, reply: ServerReply, responseType: ResponseType): void;
221
252
  }
222
253
  interface RequestConfigSchema {
223
- body?: TSchema$1;
254
+ body?: TSchema$2;
224
255
  params?: TObject$1;
225
256
  query?: TObject$1;
226
257
  headers?: TObject$1;
227
- response?: TSchema$1;
258
+ response?: TSchema$2;
228
259
  }
229
260
  interface ServerRequestConfig<TConfig extends RequestConfigSchema = RequestConfigSchema> {
230
- body: TConfig["body"] extends TSchema$1 ? Static$1<TConfig["body"]> : any;
261
+ body: TConfig["body"] extends TSchema$2 ? Static$1<TConfig["body"]> : any;
231
262
  headers: TConfig["headers"] extends TObject$1 ? Static$1<TConfig["headers"]> : Record<string, string>;
232
263
  params: TConfig["params"] extends TObject$1 ? Static$1<TConfig["params"]> : Record<string, string>;
233
264
  query: TConfig["query"] extends TObject$1 ? Static$1<TConfig["query"]> : Record<string, string>;
@@ -248,14 +279,26 @@ interface ServerRequest<TConfig extends RequestConfigSchema = RequestConfigSchem
248
279
  }
249
280
  interface ServerRoute<TConfig extends RequestConfigSchema = RequestConfigSchema> extends Route {
250
281
  method?: RouteMethod;
251
- silent?: boolean;
252
282
  handler: ServerHandler<TConfig>;
253
283
  schema?: TConfig;
284
+ /**
285
+ * @see ServerLoggerProvider
286
+ */
287
+ silent?: boolean;
288
+ /**
289
+ * @see ServerSecurityProvider
290
+ */
291
+ secure?: ServerRouteSecure;
292
+ /**
293
+ * @see ServerCacheProvider
294
+ */
295
+ cache?: ServiceRouteCache;
254
296
  }
255
- type ServerResponseBody<TConfig extends RequestConfigSchema = RequestConfigSchema> = TConfig["response"] extends TSchema$1 ? Static$1<TConfig["response"]> : ResponseBodyType;
297
+ type ServerResponseBody<TConfig extends RequestConfigSchema = RequestConfigSchema> = TConfig["response"] extends TSchema$2 ? Static$1<TConfig["response"]> : ResponseBodyType;
256
298
  type ResponseType = "json" | "text" | "void" | "file" | "any";
257
299
  type ResponseBodyType = string | Buffer | StreamLike | undefined | null | void;
258
300
  type ServerHandler<TConfig extends RequestConfigSchema = RequestConfigSchema> = (request: ServerRequest<TConfig>) => Async<ServerResponseBody<TConfig>>;
301
+ type ServerMiddlewareHandler<TConfig extends RequestConfigSchema = RequestConfigSchema> = (request: ServerRequest<TConfig>) => Async<ServerResponseBody<TConfig> | undefined>;
259
302
  interface ServerReply {
260
303
  headers: Record<string, string> & {
261
304
  "set-cookie"?: string[];
@@ -265,7 +308,7 @@ interface ServerReply {
265
308
  redirect(url: string): void;
266
309
  }
267
310
  interface ServerResponse {
268
- body: string | ArrayBuffer | Readable | ReadableStream;
311
+ body: string | Buffer | ArrayBuffer | Readable | ReadableStream;
269
312
  headers: Record<string, string>;
270
313
  status: number;
271
314
  }
@@ -285,11 +328,152 @@ interface ServerRawRequest {
285
328
  };
286
329
  };
287
330
  }
331
+ type ServerRouteSecure = boolean | {
332
+ permissions?: string[];
333
+ roles?: string[];
334
+ realms?: string[];
335
+ organizations?: string[];
336
+ };
288
337
 
289
- /**
290
- * Route descriptor options.
291
- */
292
- interface RouteDescriptorOptions<TConfig extends RequestConfigSchema = RequestConfigSchema> extends Omit<ServerRoute, "handler" | "path" | "schema"> {
338
+ declare class ActionDescriptorHelper {
339
+ name(options: ActionDescriptorOptions, _instance: any, key: string): string;
340
+ path(options: ActionDescriptorOptions, _instance: any, key: string): string;
341
+ link(options: ActionDescriptorOptions, instance: any, key: string, prefix?: string): HttpClientLink;
342
+ method(options: {
343
+ method?: string;
344
+ schema?: any;
345
+ }): RouteMethod;
346
+ permission(options: ActionDescriptorOptions, instance: any, key: string): Permission;
347
+ group(options: ActionDescriptorOptions, instance: any): string;
348
+ isMultipart(options: {
349
+ schema?: RequestConfigSchema;
350
+ }): boolean;
351
+ bodyContentType(options: ActionDescriptorOptions): string | undefined;
352
+ protected short(name: string): string;
353
+ fetchLinks(_url: string): void;
354
+ }
355
+
356
+ declare const apiLinkSchema: TObject<{
357
+ name: TString$1;
358
+ path: TString$1;
359
+ method: TOptional<TString$1>;
360
+ group: TOptional<TString$1>;
361
+ requestBodyType: TOptional<TString$1>;
362
+ service: TOptional<TString$1>;
363
+ }>;
364
+ declare const apiLinksResponseSchema: TObject<{
365
+ prefix: TOptional<TString$1>;
366
+ links: TArray<TObject<{
367
+ name: TString$1;
368
+ path: TString$1;
369
+ method: TOptional<TString$1>;
370
+ group: TOptional<TString$1>;
371
+ requestBodyType: TOptional<TString$1>;
372
+ service: TOptional<TString$1>;
373
+ }>>;
374
+ }>;
375
+ type ApiLinksResponse = Static$1<typeof apiLinksResponseSchema>;
376
+ type ApiLink = Static$1<typeof apiLinkSchema>;
377
+
378
+ declare class HttpClient {
379
+ protected readonly log: _alepha_core.Logger;
380
+ protected readonly alepha: Alepha;
381
+ protected readonly helper: ActionDescriptorHelper;
382
+ readonly cache: _alepha_cache.CacheDescriptor<HttpClientCache, any[]>;
383
+ protected readonly pendingRequests: HttpClientPendingRequests;
384
+ readonly URL_LINKS = "/api/_links";
385
+ links?: Array<HttpClientLink>;
386
+ pushLink(link: HttpClientLink): void;
387
+ clear(): Promise<void>;
388
+ fetch<T>(url: string, request?: RequestInit, options?: FetchRunOptions): Promise<FetchResponse<T>>;
389
+ json<T = any>(url: string, options?: RequestInit): Promise<T>;
390
+ protected url(host: string, link: HttpClientLink, args: ServerRequestConfigEntry): string;
391
+ protected body(init: RequestInit, headers: Record<string, string>, link: HttpClientLink, args?: ServerRequestConfigEntry): Promise<void>;
392
+ protected responseData(response: Response, options: FetchRunOptions): Promise<any>;
393
+ protected isMaybeFile(response: Response): boolean;
394
+ protected createFileLike(response: Response, defaultFileName?: string): FileLike;
395
+ protected pathVariables(url: string, action: HttpClientLink, args?: ServerRequestConfigEntry): string;
396
+ protected queryParams(url: string, action: {
397
+ schema?: {
398
+ query?: TObject$1;
399
+ };
400
+ }, args?: ServerRequestConfigEntry): string;
401
+ /**
402
+ * Transform a link into a fetch-request then call fetch().
403
+ */
404
+ fetchLink(args: FetchLinkArgs): Promise<FetchResponse>;
405
+ /**
406
+ * Create a proxy client.
407
+ * This allows to call actions as methods, e.g. `client.actionName()`.
408
+ */
409
+ of<T extends object>(scope?: ClientScope): HttpVirtualClient<T>;
410
+ protected getLinkByName(name: string, options?: ClientScope): Promise<HttpClientLink>;
411
+ /**
412
+ * Resolve a link by its name and call it.
413
+ * - If link is local, it will call the local handler.
414
+ * - If link is remote, it will make a fetch request to the remote server.
415
+ */
416
+ follow(name: string, config?: Partial<ServerRequestConfigEntry>, options?: ClientRequestOptions & ClientScope): Promise<any>;
417
+ protected followRemote(link: HttpClientLink, config?: Partial<ServerRequestConfigEntry>, options?: ClientRequestOptions): Promise<FetchResponse>;
418
+ can(name: string): boolean;
419
+ getLinks(force?: boolean): Promise<HttpClientLink[]>;
420
+ }
421
+ type HttpClientPendingRequests = Record<string, Promise<any> | undefined>;
422
+ interface FetchFactoryAdditionalOptions {
423
+ host?: string | (() => string);
424
+ }
425
+ interface FetchRunOptions {
426
+ /**
427
+ * Key to identify the request in the pending requests.
428
+ */
429
+ key?: string;
430
+ /**
431
+ * The schema to validate the response against.
432
+ */
433
+ schema?: TSchema$2;
434
+ /**
435
+ * Built-in cache options.
436
+ */
437
+ cache?: boolean | number | DurationLike;
438
+ }
439
+ interface HttpClientLink extends ApiLink {
440
+ secured?: boolean;
441
+ prefix?: string;
442
+ host?: string;
443
+ service?: string;
444
+ schema?: RequestConfigSchema;
445
+ handler?: ServerHandler;
446
+ }
447
+ interface ClientScope {
448
+ group?: string;
449
+ service?: string;
450
+ }
451
+ type HttpVirtualClient<T> = {
452
+ [K in keyof T as T[K] extends ActionDescriptor ? K : never]: T[K] extends ActionDescriptor<infer Schema> ? T[K] & {
453
+ can: () => boolean;
454
+ schema: Schema;
455
+ } : never;
456
+ };
457
+ interface HttpClientCache {
458
+ data: any;
459
+ etag?: string;
460
+ }
461
+ interface FetchResponse<T = any> {
462
+ data: T;
463
+ status: number;
464
+ statusText: string;
465
+ headers: Headers;
466
+ raw?: Response;
467
+ }
468
+ interface FetchLinkArgs {
469
+ link: HttpClientLink;
470
+ host?: string;
471
+ config?: ServerRequestConfigEntry;
472
+ options?: ClientRequestOptions;
473
+ }
474
+
475
+ declare const KEY$2 = "ACTION";
476
+ interface ActionDescriptorOptions<TConfig extends RequestConfigSchema = RequestConfigSchema> extends Omit<ServerRoute, "handler" | "path" | "schema"> {
293
477
  /**
294
478
  * Name the route.
295
479
  */
@@ -304,6 +488,7 @@ interface RouteDescriptorOptions<TConfig extends RequestConfigSchema = RequestCo
304
488
  * If false, disabled the security check for this route.
305
489
  *
306
490
  * @default true when SecurityModule is enabled, false otherwise.
491
+ * @deprecated
307
492
  */
308
493
  security?: boolean;
309
494
  /**
@@ -314,7 +499,7 @@ interface RouteDescriptorOptions<TConfig extends RequestConfigSchema = RequestCo
314
499
  * Inherit options from another route.
315
500
  */
316
501
  use?: {
317
- [OPTIONS]: RouteDescriptorOptions<TConfig>;
502
+ [OPTIONS]: ActionDescriptorOptions<TConfig>;
318
503
  };
319
504
  /**
320
505
  * The route method.
@@ -343,80 +528,70 @@ interface RouteDescriptorOptions<TConfig extends RequestConfigSchema = RequestCo
343
528
  */
344
529
  disabled?: boolean;
345
530
  /**
346
- * Mark the route as private. It will not be exposed in the API documentation.
531
+ * Mark the route as private.
532
+ * - It won't be exposed in the API documentation.
533
+ * - It won't be exposed in _links.
347
534
  */
348
535
  internal?: boolean;
349
536
  /**
350
537
  * Main route handler. This is where the route logic is implemented.
351
538
  */
352
539
  handler?: ServerHandler<TConfig>;
540
+ /**
541
+ * If true, the route will be cached.
542
+ * - Number as seconds or boolean to enable cache.
543
+ */
544
+ cache?: boolean | DurationLike | Omit<CacheDescriptorOptions<any>, "handler" | "key">;
353
545
  }
354
- interface RouteDescriptor<TConfig extends RequestConfigSchema = RequestConfigSchema> {
355
- [KIND]: "ROUTE";
356
- [OPTIONS]: RouteDescriptorOptions<TConfig>;
546
+ interface ActionDescriptor<TConfig extends RequestConfigSchema = RequestConfigSchema> {
547
+ [KIND]: typeof KEY$2;
548
+ [OPTIONS]: ActionDescriptorOptions<TConfig>;
357
549
  /**
358
550
  * Fetch or just call local route when available.
359
551
  */
360
- (config?: ClientRequestEntry<TConfig>, opts?: ClientRequestOptions): ClientRequestResponse<TConfig>;
552
+ (config?: ClientRequestEntry<TConfig>, opts?: ClientRequestOptions): Promise<ClientRequestResponse<TConfig>>;
361
553
  /**
362
554
  * Just fetch the route. Skip any local route.
363
555
  */
364
- fetch: (config?: ClientRequestEntry<TConfig>, opts?: ClientRequestOptions) => ClientRequestResponse<TConfig>;
556
+ fetch: (config?: ClientRequestEntry<TConfig>, opts?: ClientRequestOptions) => Promise<FetchResponse<ClientRequestResponse<TConfig>>>;
365
557
  /**
366
558
  * Name of the permission required to access this route.
367
559
  */
368
560
  permission: () => string;
561
+ /**
562
+ * Invalidate the cache for this action.
563
+ * This is only available if the action has cache enabled.
564
+ */
565
+ invalidate: () => Promise<void>;
369
566
  }
370
- /**
371
- * Declare a new route.
372
- *
373
- * ```ts
374
- * class A {
375
- * hello = $route({
376
- * url: "/hello",
377
- * handler: () => "Hello, World!",
378
- * });
379
- * }
380
- * ```
381
- *
382
- * @param options The route options.
383
- * @returns The route.
384
- */
385
- declare const $route: {
386
- <TConfig extends RequestConfigSchema>(options: RouteDescriptorOptions<TConfig>): RouteDescriptor<TConfig>;
387
- [KIND]: string;
388
- };
389
567
  declare const $action: {
390
- <TConfig extends RequestConfigSchema>(options: RouteDescriptorOptions<TConfig>): RouteDescriptor<TConfig>;
568
+ <TConfig extends RequestConfigSchema>(options: ActionDescriptorOptions<TConfig>): ActionDescriptor<TConfig>;
391
569
  [KIND]: string;
392
570
  };
393
571
  type ClientRequestEntry<TConfig extends RequestConfigSchema = RequestConfigSchema, T = ClientRequestEntryContainer<TConfig>> = {
394
572
  [K in keyof T as T[K] extends undefined ? never : K]: T[K];
395
573
  };
396
574
  type ClientRequestEntryContainer<TConfig extends RequestConfigSchema = RequestConfigSchema> = {
397
- body: TConfig["body"] extends TSchema$1 ? Static$1<TConfig["body"]> : undefined;
398
- params: TConfig["params"] extends TSchema$1 ? Static$1<TConfig["params"]> : undefined;
399
- headers?: TConfig["headers"] extends TSchema$1 ? Static$1<TConfig["headers"]> : undefined;
400
- query?: TConfig["query"] extends TSchema$1 ? Partial<Static$1<TConfig["query"]>> : undefined;
575
+ body: TConfig["body"] extends TSchema$2 ? Static$1<TConfig["body"]> : undefined;
576
+ params: TConfig["params"] extends TSchema$2 ? Static$1<TConfig["params"]> : undefined;
577
+ headers?: TConfig["headers"] extends TSchema$2 ? Static$1<TConfig["headers"]> : undefined;
578
+ query?: TConfig["query"] extends TSchema$2 ? Partial<Static$1<TConfig["query"]>> : undefined;
401
579
  };
402
- interface ClientRequestOptions {
403
- /**
404
- * Built-in cache options.
405
- * Number as seconds or boolean to enable cache.
406
- */
407
- cache?: number | boolean;
580
+ interface ClientRequestOptions extends FetchRunOptions {
408
581
  /**
409
582
  * Forward user from the previous request.
583
+ * If "system", use system user. @see {ServerSecurityProvider.localSystemUser}
584
+ * If "context", use the user from the current context (e.g. request).
410
585
  *
411
- * In testing environments, you can pass a partial user token.
586
+ * @default "system" is provided, else "context" is used.
412
587
  */
413
- user?: Partial<UserAccountToken>;
588
+ user?: UserAccountToken | "system" | "context";
414
589
  /**
415
590
  * Standard request fetch options.
416
591
  */
417
592
  request?: RequestInit;
418
593
  }
419
- type ClientRequestResponse<TConfig extends RequestConfigSchema> = Promise<TConfig["response"] extends TSchema$1 ? Static$1<TConfig["response"]> : Response>;
594
+ type ClientRequestResponse<TConfig extends RequestConfigSchema> = TConfig["response"] extends TSchema$2 ? Static$1<TConfig["response"]> : any;
420
595
 
421
596
  declare class HttpError extends Error {
422
597
  static toJSON(error: HttpError): {
@@ -450,155 +625,286 @@ declare class HttpError extends Error {
450
625
  }, cause?: unknown);
451
626
  }
452
627
  declare const errorNameByStatus: Record<number, string>;
628
+ declare const isHttpError: (error: unknown) => error is HttpErrorLike;
629
+ interface HttpErrorLike extends Error {
630
+ status: number;
631
+ }
453
632
 
454
- declare class RouteDescriptorHelper {
455
- name(options: RouteDescriptorOptions, instance: any, key: string): string;
456
- path(options: RouteDescriptorOptions, instance: any, key: string, prefix?: string): string;
457
- link(options: RouteDescriptorOptions, instance: any, key: string, prefix?: string): HttpClientLink;
458
- method(options: {
459
- method?: string;
460
- schema?: any;
461
- }): RouteMethod;
462
- permission(options: RouteDescriptorOptions, instance: any, key: string, prefix?: string): Permission;
463
- group(options: RouteDescriptorOptions, instance: any): string;
464
- isMultipart(options: {
465
- schema?: RequestConfigSchema;
466
- }): boolean;
467
- bodyContentType(options: RouteDescriptorOptions): string | undefined;
468
- protected short(name: string): string;
633
+ declare const $client: <T extends object>(scope?: ClientScope) => HttpVirtualClient<T>;
634
+
635
+ type ProxyDescriptorOptions = {
636
+ path: string;
637
+ target: string;
638
+ disabled?: boolean;
639
+ beforeRequest?: (request: ServerRequest, proxyRequest: RequestInit) => Async<void>;
640
+ afterResponse?: (request: ServerRequest, proxyResponse: Response) => Async<void>;
641
+ rewrite?: (url: URL) => void;
642
+ };
643
+ interface ProxyDescriptor {
644
+ [KIND]: "PROXY";
645
+ [OPTIONS]: ProxyDescriptorOptions;
469
646
  }
647
+ declare const $proxy: {
648
+ (options: ProxyDescriptorOptions): ProxyDescriptor;
649
+ [KIND]: string;
650
+ };
470
651
 
471
- declare class HttpClient {
472
- protected readonly alepha: Alepha;
473
- protected readonly env: {
474
- SERVER_API_URL: string;
475
- CLIENT_API_PREFIX: string;
476
- };
477
- protected readonly helper: RouteDescriptorHelper;
478
- readonly URL_LINKS = "/_links";
479
- readonly cache: _alepha_cache.CacheDescriptor<any, any[]>;
480
- links?: Array<HttpClientLink>;
481
- protected readonly pendingRequests: HttpClientPendingRequests;
482
- json<T = any>(url: string, options?: RequestInit): Promise<T>;
483
- clear(): Promise<void>;
484
- createFetchFunction(link: HttpClientLink, options?: FetchFactoryAdditionalOptions): (config?: Partial<ClientRequestEntry>, request?: ClientRequestOptions) => Promise<any>;
485
- request(args: {
486
- config?: ServerRequestConfigEntry;
487
- link: HttpClientLink;
488
- request?: ClientRequestOptions;
489
- host?: string;
490
- }): Promise<any>;
491
- protected url(host: string, link: HttpClientLink, args: ServerRequestConfigEntry): string;
492
- protected body(init: RequestInit, headers: Record<string, string>, link: HttpClientLink, args?: ServerRequestConfigEntry): Promise<void>;
493
- fetch<T>(url: string, request: RequestInit, options?: FetchRunOptions): Promise<T>;
652
+ /**
653
+ * Represents a User Account extracted from JWT.
654
+ */
655
+ interface UserAccountInfo {
494
656
  /**
495
- * Parse the response.
496
- *
497
- * @param response
498
- * @param options
499
- * @protected
657
+ * ID of user account. Based on JWT.sub.
500
658
  */
501
- protected response(response: Response, options: FetchRunOptions): Promise<Response | any>;
502
- protected isMaybeFile(response: Response): boolean;
503
- protected getFileLike(response: Response, defaultFileName?: string): FileLike;
504
- protected pathVariables(url: string, action: HttpClientLink, args?: ServerRequestConfigEntry): string;
505
- queryParams(url: string, action: {
506
- schema?: {
507
- query?: TObject$1;
508
- };
509
- }, args?: ServerRequestConfigEntry): string;
510
- of<T extends object>(options?: {
511
- group?: string;
512
- host?: string | (() => string);
513
- }): HttpVirtualClient<T>;
514
- follow(name: string, config?: any, options?: {
515
- request?: ClientRequestOptions;
516
- group?: string;
517
- host?: string | (() => string);
518
- }): Promise<any>;
519
- can(name: string): boolean;
520
- getLinks(opts?: {
521
- force?: boolean;
522
- host?: string;
523
- }): Promise<HttpClientLink[]>;
659
+ id: string;
660
+ /**
661
+ * Represents the roles assigned to a user.
662
+ */
663
+ roles?: string[];
664
+ /**
665
+ * User full name, if available.
666
+ */
667
+ name?: string;
668
+ /**
669
+ * User email, if available.
670
+ */
671
+ email?: string;
672
+ /**
673
+ * User profile picture URL, if available.
674
+ */
675
+ picture?: string;
676
+ /**
677
+ * Organization ID, if available.
678
+ */
679
+ organization?: string;
524
680
  }
525
- type HttpClientPendingRequests = Record<string, Promise<any> | undefined>;
526
- interface FetchFactoryAdditionalOptions {
527
- host?: string | (() => string);
681
+
682
+ /** Symbol key applied to readonly types */
683
+ declare const ReadonlyKind: unique symbol;
684
+ /** Symbol key applied to optional types */
685
+ declare const OptionalKind: unique symbol;
686
+ /** Symbol key applied to types */
687
+ declare const Hint: unique symbol;
688
+ /** Symbol key applied to types */
689
+ declare const Kind: unique symbol;
690
+
691
+ type StringFormatOption = 'date-time' | 'time' | 'date' | 'email' | 'idn-email' | 'hostname' | 'idn-hostname' | 'ipv4' | 'ipv6' | 'uri' | 'uri-reference' | 'iri' | 'uuid' | 'iri-reference' | 'uri-template' | 'json-pointer' | 'relative-json-pointer' | 'regex' | ({} & string);
692
+ type StringContentEncodingOption = '7bit' | '8bit' | 'binary' | 'quoted-printable' | 'base64' | ({} & string);
693
+ interface StringOptions extends SchemaOptions {
694
+ /** The maximum string length */
695
+ maxLength?: number;
696
+ /** The minimum string length */
697
+ minLength?: number;
698
+ /** A regular expression pattern this string should match */
699
+ pattern?: string;
700
+ /** A format this string should match */
701
+ format?: StringFormatOption;
702
+ /** The content encoding for this string */
703
+ contentEncoding?: StringContentEncodingOption;
704
+ /** The content media type for this string */
705
+ contentMediaType?: string;
528
706
  }
529
- interface FetchRunOptions {
530
- schema?: TSchema$1;
531
- raw?: boolean;
532
- cache?: boolean | DurationLike;
707
+ interface TString extends TSchema, StringOptions {
708
+ [Kind]: 'String';
709
+ static: string;
710
+ type: 'string';
533
711
  }
534
- interface HttpClientLink {
535
- method: RouteMethod;
536
- path: string;
537
- name: string;
538
- group?: string;
539
- contentType?: string;
540
- protected?: boolean;
541
- schema?: RequestConfigSchema;
542
- handler?: ServerHandler;
543
- host?: string;
544
- proxy?: boolean;
712
+
713
+ interface SchemaOptions {
714
+ $schema?: string;
715
+ /** Id for this schema */
716
+ $id?: string;
717
+ /** Title of this schema */
718
+ title?: string;
719
+ /** Description of this schema */
720
+ description?: string;
721
+ /** Default value for this schema */
722
+ default?: any;
723
+ /** Example values matching this schema */
724
+ examples?: any;
725
+ /** Optional annotation for readOnly */
726
+ readOnly?: boolean;
727
+ /** Optional annotation for writeOnly */
728
+ writeOnly?: boolean;
729
+ [prop: string]: any;
730
+ }
731
+ interface TKind {
732
+ [Kind]: string;
733
+ }
734
+ interface TSchema extends TKind, SchemaOptions {
735
+ [ReadonlyKind]?: string;
736
+ [OptionalKind]?: string;
737
+ [Hint]?: string;
738
+ params: unknown[];
739
+ static: unknown;
740
+ }
741
+
742
+ declare const envSchema$3: _alepha_core.TObject<{
743
+ SECURITY_SECRET_KEY: TString;
744
+ }>;
745
+ interface ServiceAccountDescriptor {
746
+ token: () => Promise<string>;
747
+ }
748
+ declare module "alepha/core" {
749
+ interface Env extends Partial<Static$1<typeof envSchema$3>> {
750
+ }
751
+ }
752
+
753
+ declare module "@alepha/core" {
754
+ interface Hooks {
755
+ "security:user:created": {
756
+ realm: string;
757
+ user: UserAccountInfo;
758
+ };
759
+ }
545
760
  }
546
- type HttpVirtualClient<T> = {
547
- [K in keyof T as T[K] extends RouteDescriptor ? K : never]: T[K] & {
548
- can: () => boolean;
549
- };
550
- };
551
761
 
552
- declare const REMOTE_DESCRIPTOR_KEY = "REMOTE";
762
+ declare const KEY$1 = "REMOTE";
553
763
  interface RemoteDescriptorOptions {
554
764
  /**
555
765
  * The URL of the remote service.
766
+ * You can use a function to generate the URL dynamically.
767
+ * You probably should use $inject(env) to get the URL from the environment.
768
+ *
769
+ * @example
770
+ * ```ts
771
+ * import { $remote } from "@alepha/server";
772
+ * import { $inject, t } from "@alepha/core";
773
+ *
774
+ * class App {
775
+ * env = $inject(t.object({
776
+ * REMOTE_URL: t.string({default: "http://localhost:3000"}),
777
+ * }));
778
+ * remote = $remote({
779
+ * url: this.env.REMOTE_URL,
780
+ * });
781
+ * }
782
+ * ```
556
783
  */
557
784
  url: string | (() => string);
558
- /**
559
- * @default "/api/_links"
560
- */
561
- linkPath?: string;
562
- /**
563
- * If true, all methods of the remote service will be exposed as actions.
564
- */
565
- proxy?: boolean | {
566
- beforeRequest?: (request: ServerRequest, proxyRequest: RequestInit) => Async<void>;
567
- afterResponse?: (request: ServerRequest, proxyResponse: Response) => Async<void>;
568
- rewrite?: (url: URL) => void;
569
- };
570
- /**
571
- * One or many instance of classes to be registered as remote services.
572
- * Services must contain some $action() descriptors.
573
- */
574
- services?: object | Array<object>;
575
785
  /**
576
786
  * The name of the remote service.
577
787
  *
578
788
  * @default Member of the class containing the remote service.
579
789
  */
580
790
  name?: string;
791
+ /**
792
+ * If true, all methods of the remote service will be exposed as actions in this context.
793
+ * > Note: Proxy will never use the service account, it just... proxies the request.
794
+ */
795
+ proxy?: boolean | Partial<ProxyDescriptorOptions & {
796
+ /**
797
+ * If true, the remote service won't be available internally, only through the proxy.
798
+ */
799
+ noInternal: boolean;
800
+ }>;
801
+ /**
802
+ * For communication between the server and the remote service with a security layer.
803
+ * This will be used for internal communication and will not be exposed to the client.
804
+ */
805
+ serviceAccount?: ServiceAccountDescriptor;
581
806
  }
582
807
  interface RemoteDescriptor {
583
- [KIND]: typeof REMOTE_DESCRIPTOR_KEY;
808
+ [KIND]: typeof KEY$1;
584
809
  [OPTIONS]: RemoteDescriptorOptions;
585
810
  }
811
+ /**
812
+ * $remote is a descriptor that allows you to define a remote service access.
813
+ *
814
+ * Use it only when you have 2 or more services that need to communicate with each other.
815
+ *
816
+ * All remote services can be exposed as actions, ... or not.
817
+ *
818
+ * You can add a service account if you want to use a security layer.
819
+ */
586
820
  declare const $remote: {
587
821
  (options: RemoteDescriptorOptions): RemoteDescriptor;
588
822
  [KIND]: string;
589
823
  };
590
824
 
825
+ declare const KEY = "ROUTE";
826
+ interface RouteDescriptorOptions<TConfig extends RequestConfigSchema = RequestConfigSchema> extends ServerRoute<TConfig> {
827
+ }
828
+ type RouteDescriptor<TConfig extends RequestConfigSchema = RequestConfigSchema> = {
829
+ [KIND]: typeof KEY;
830
+ [OPTIONS]: RouteDescriptorOptions<TConfig>;
831
+ };
832
+ declare const $route: {
833
+ <TConfig extends RequestConfigSchema = RequestConfigSchema>(options: RouteDescriptorOptions<TConfig>): RouteDescriptor<TConfig>;
834
+ [KIND]: string;
835
+ };
836
+
837
+ declare class BadRequestError extends HttpError {
838
+ constructor(message?: string, cause?: unknown);
839
+ }
840
+
841
+ declare class ConflictError extends HttpError {
842
+ constructor(message?: string, cause?: unknown);
843
+ }
844
+
845
+ declare class ForbiddenError extends HttpError {
846
+ constructor(message?: string, cause?: unknown);
847
+ }
848
+
849
+ declare class NotFoundError extends HttpError {
850
+ constructor(message?: string, cause?: unknown);
851
+ }
852
+
853
+ declare class UnauthorizedError extends HttpError {
854
+ constructor(message?: string, cause?: unknown);
855
+ }
856
+
857
+ declare class ValidationError extends HttpError {
858
+ constructor(message?: string, cause?: unknown);
859
+ }
860
+
861
+ /**
862
+ * Register `/health` endpoint.
863
+ *
864
+ * - Provides basic health information about the server.
865
+ */
866
+ declare class ServerHealthProvider {
867
+ protected readonly dateTimeProvider: DateTimeProvider;
868
+ protected readonly alepha: Alepha;
869
+ readonly health: RouteDescriptor<{
870
+ response: TObject<{
871
+ message: TString$1;
872
+ uptime: TNumber;
873
+ date: TString$1;
874
+ ready: TBoolean;
875
+ }>;
876
+ }>;
877
+ }
878
+
879
+ declare class ProxyDescriptorProvider {
880
+ protected readonly log: _alepha_core.Logger;
881
+ protected readonly routerProvider: ServerRouterProvider;
882
+ protected readonly alepha: Alepha;
883
+ readonly configure: _alepha_core.HookDescriptor<"configure">;
884
+ createProxyHandler(options: Omit<ProxyDescriptorOptions, "path">): ServerHandler;
885
+ proxy(options: ProxyDescriptorOptions): Promise<void>;
886
+ private getRawRequestBody;
887
+ }
888
+
591
889
  declare class ServerProvider {
592
890
  constructor();
593
891
  get hostname(): string;
594
892
  }
595
893
 
596
- declare const envSchema$3: _alepha_core.TObject<{
597
- SERVER_API_PREFIX: TString;
894
+ declare const envSchema$2: _alepha_core.TObject<{
895
+ SERVER_API_PREFIX: TString$1;
598
896
  SERVER_SECURITY_ENABLED: TBoolean;
599
897
  }>;
600
- declare module "alepha/core" {
601
- interface Env extends Partial<Static$1<typeof envSchema$3>> {
898
+ declare module "@alepha/core" {
899
+ interface Env extends Partial<Static$1<typeof envSchema$2>> {
900
+ }
901
+ interface State {
902
+ /**
903
+ * Real (or fake) user account, used for internal actions.
904
+ * If you define this, you assume that all actions are executed by this user by default.
905
+ * And to force a different user, you need to pass it explicitly in the options.
906
+ */
907
+ "ServerSecurityProvider.localSystemUser"?: UserAccountToken;
602
908
  }
603
909
  }
604
910
  declare class ServerActionDescriptorProvider {
@@ -610,130 +916,110 @@ declare class ServerActionDescriptorProvider {
610
916
  };
611
917
  protected readonly client: HttpClient;
612
918
  protected readonly serverProvider: ServerProvider;
613
- protected readonly helper: RouteDescriptorHelper;
919
+ protected readonly helper: ActionDescriptorHelper;
614
920
  protected readonly routerProvider: ServerRouterProvider;
615
- protected readonly remotes: Array<ServerRemote>;
616
921
  protected readonly actions: ServerRouteAction[];
617
922
  getActions(): ServerRouteAction<RequestConfigSchema>[];
923
+ getPrefix(): string;
618
924
  readonly configure: _alepha_core.HookDescriptor<"configure">;
619
- registerRemote(value: RemoteDescriptor, key: string): Promise<void>;
620
- loadRemoteLinks: (options: RemoteDescriptorOptions) => Promise<Promise<void>>;
621
- proxy(url: string, link: HttpClientLink, options: {
622
- beforeRequest?: (request: ServerRequest, proxyRequest: RequestInit) => Async<void>;
623
- afterResponse?: (request: ServerRequest, proxyResponse: Response) => Async<void>;
624
- rewrite?: (url: URL) => void;
625
- }): Promise<void>;
626
- private getRawRequestBody;
627
- registerAction(value: RouteDescriptor, key: string, instance: any, prefix?: string): Promise<void>;
628
- /**
629
- * When your action has no handler, it's considered as an 'API'.
630
- * Instead of creating an http route, create a bridge to a local or remote function.
631
- *
632
- * ```ts
633
- * class Api {
634
- * hello = $action(); // <- route 'Api'
635
- * }
636
- *
637
- * class Controller {
638
- * api = $inject(Api);
639
- * hello = $action({ // <-- route
640
- * use: this.api.hello,
641
- * handler: () => new Response("Hello world"),
642
- * })
643
- * }
644
- *
645
- * const api = alepha.get(Api);
646
- *
647
- * api.hello(); // <-- call the local controller function if available
648
- *
649
- * // or with $remote
650
- * class Remotes {
651
- * api = $remote({ url: "http://localhost:8080", services: [Api] });
652
- * }
653
- *
654
- * // or with future auto-discovery
655
- * ```
656
- */
657
- registerActionApi(routeDescriptor: RouteDescriptor, instance: any, key: string): void;
925
+ registerAction(value: ActionDescriptor, key: string, instance: any, prefix?: string): Promise<void>;
658
926
  /**
659
927
  * Check a mock function for the specified route.
660
928
  *
661
929
  * This is mostly used for testing purposes.
662
- *
663
- * @param value
664
- * @param permission
665
- * @protected
666
930
  */
667
- protected createLocalFunction(value: RouteDescriptor, permission: Permission): (config?: ServerRequestConfigEntry, options?: ClientRequestOptions) => Promise<any>;
931
+ protected createLocalFunction(action: ActionDescriptorOptions, permission: Permission): (config?: ServerRequestConfigEntry, options?: ClientRequestOptions) => Promise<any>;
668
932
  /**
669
- * Security adapted for local function.
933
+ * Get the user account token for a local action call.
934
+ * It will check the options, context, and system user.
670
935
  */
671
936
  protected getUserFromLocalFunctionContext(options: {
672
- user?: Partial<UserAccountToken>;
673
- }, permission: Permission, security: boolean): UserAccountToken | undefined;
674
- /**
675
- * TODO: remove it, this is a hack for testing purposes
676
- */
677
- protected createSystemUser(): UserAccountToken;
937
+ user?: UserAccountToken | "system" | "context";
938
+ }, permission: Permission, isRouteSecure: boolean): UserAccountToken | undefined;
678
939
  }
679
940
  declare const isServerAction: (value: any) => value is ServerRouteAction;
680
941
  interface ServerRemote {
681
942
  url: string;
682
- services: object[];
683
943
  name: string;
684
944
  proxy: boolean;
945
+ internal: boolean;
946
+ links: (args: {
947
+ authorization?: string;
948
+ }) => Promise<ApiLinksResponse>;
949
+ schema: (args: {
950
+ name: string;
951
+ authorization?: string;
952
+ }) => Promise<any>;
953
+ serviceAccount?: ServiceAccountDescriptor$1;
954
+ prefix: string;
685
955
  }
686
956
  interface ServerRouteAction<TConfig extends RequestConfigSchema = RequestConfigSchema> extends ServerRoute<TConfig> {
957
+ prefix: string;
687
958
  method: RouteMethod;
688
959
  name: string;
689
960
  group: string;
690
961
  permission: Permission;
691
- options: RouteDescriptorOptions;
962
+ options: ActionDescriptorOptions;
692
963
  }
693
964
 
694
- declare const envSchema$2: _alepha_core.TObject<{
695
- SERVER_API_URL: TString;
696
- }>;
697
- declare module "@alepha/core" {
698
- interface Env extends Partial<Static$1<typeof envSchema$2>> {
699
- }
700
- }
701
- declare class BrowserActionDescriptorProvider {
702
- protected readonly log: _alepha_core.Logger;
965
+ declare class RemoteDescriptorProvider {
966
+ static path: {
967
+ apiLinks: string;
968
+ };
703
969
  protected readonly alepha: Alepha;
704
970
  protected readonly client: HttpClient;
705
- protected readonly env: {
706
- SERVER_API_URL: string;
707
- };
708
- protected readonly helper: RouteDescriptorHelper;
709
- readonly configure: _alepha_core.HookDescriptor<"configure">;
710
- configureActions(): void;
711
- registerAction(value: RouteDescriptor, instance: any, key: string): void;
712
- }
713
-
714
- declare class ServerSecurityProvider {
971
+ protected readonly proxyProvider: ProxyDescriptorProvider;
972
+ protected readonly remotes: Array<ServerRemote>;
715
973
  protected readonly log: _alepha_core.Logger;
716
- protected readonly securityProvider: SecurityProvider;
717
- protected readonly jwtProvider: JwtProvider;
718
- protected readonly alepha: Alepha;
719
- readonly onClientRequest: _alepha_core.HookDescriptor<"client:onRequest">;
720
- protected readonly onRequest: _alepha_core.HookDescriptor<"server:onRequest">;
721
- protected readonly onRoute: _alepha_core.HookDescriptor<"server:onRoute">;
974
+ getRemotes(): ServerRemote[];
975
+ readonly configure: _alepha_core.HookDescriptor<"configure">;
976
+ readonly start: _alepha_core.HookDescriptor<"start">;
977
+ registerRemote(value: RemoteDescriptor, key: string): Promise<void>;
978
+ protected readonly fetchLinks: _alepha_retry.RetryDescriptor<(opts: {
979
+ service: string;
980
+ url: string;
981
+ authorization?: string;
982
+ }) => Promise<{
983
+ prefix?: string | undefined;
984
+ links: {
985
+ group?: string | undefined;
986
+ method?: string | undefined;
987
+ requestBodyType?: string | undefined;
988
+ service?: string | undefined;
989
+ path: string;
990
+ name: string;
991
+ }[];
992
+ }>>;
722
993
  }
723
994
 
724
995
  declare class ServerLinksProvider {
725
996
  protected readonly alepha: Alepha;
726
997
  protected readonly client: HttpClient;
998
+ protected readonly remoteProvider: RemoteDescriptorProvider;
999
+ protected readonly serverActionDescriptorProvider: ServerActionDescriptorProvider;
727
1000
  readonly links: RouteDescriptor<{
728
- response: TArray<TObject<{
729
- name: TString;
730
- method: TOptional<TString>;
731
- path: TOptional<TString>;
732
- group: TOptional<TString>;
733
- protected: TOptional<TBoolean>;
734
- contentType: TOptional<TString>;
735
- }>>;
1001
+ response: TObject<{
1002
+ prefix: TOptional<TString$1>;
1003
+ links: TArray<TObject<{
1004
+ name: TString$1;
1005
+ path: TString$1;
1006
+ method: TOptional<TString$1>;
1007
+ group: TOptional<TString$1>;
1008
+ requestBodyType: TOptional<TString$1>;
1009
+ service: TOptional<TString$1>;
1010
+ }>>;
1011
+ }>;
736
1012
  }>;
1013
+ readonly schema: RouteDescriptor<{
1014
+ params: TObject<{
1015
+ name: TString$1;
1016
+ }>;
1017
+ response: TRecord<TString$1, TAny>;
1018
+ }>;
1019
+ getLinks(options: {
1020
+ user?: UserAccountToken;
1021
+ authorization?: string;
1022
+ }): Promise<ApiLinksResponse>;
737
1023
  }
738
1024
 
739
1025
  declare class ServerLoggerProvider {
@@ -745,7 +1031,7 @@ declare class ServerLoggerProvider {
745
1031
  }
746
1032
 
747
1033
  declare class ServerMultipartProvider {
748
- protected readonly helper: RouteDescriptorHelper;
1034
+ protected readonly helper: ActionDescriptorHelper;
749
1035
  protected readonly alepha: Alepha;
750
1036
  readonly onRequest: _alepha_core.HookDescriptor<"server:onRequest">;
751
1037
  readonly onSend: _alepha_core.HookDescriptor<"server:onResponse">;
@@ -767,21 +1053,44 @@ interface HybridFile extends FileLike {
767
1053
  tmpPath: string;
768
1054
  };
769
1055
  }
1056
+
770
1057
  /**
771
- * Create a file-like object from various sources.
1058
+ * On every request, this provider checks if the server is ready.
1059
+ *
1060
+ * If the server is not ready, it responds with a 503 status code and a message indicating that the server is not ready yet.
1061
+ *
1062
+ * The response also includes a `Retry-After` header indicating that the client should retry after 5 seconds.
772
1063
  */
773
- declare const file: (source: string | Buffer | ArrayBuffer | StreamLike, options?: {
774
- type?: string;
775
- name?: string;
776
- }) => FileLike;
777
- declare const bufferToStream: (buffer: Buffer) => Readable;
778
- declare const streamToBuffer: (stream: Readable) => Promise<Buffer>;
779
- declare const bufferToArrayBuffer: (buffer: Buffer) => ArrayBuffer;
780
- declare const getContentType: (filename: string) => string;
1064
+ declare class ServerNotReadyProvider {
1065
+ protected readonly alepha: Alepha;
1066
+ readonly onRequest: _alepha_core.HookDescriptor<"server:onRequest">;
1067
+ }
1068
+
1069
+ declare class ServerSecurityProvider {
1070
+ protected readonly log: _alepha_core.Logger;
1071
+ protected readonly securityProvider: SecurityProvider;
1072
+ protected readonly jwtProvider: JwtProvider;
1073
+ protected readonly alepha: Alepha;
1074
+ readonly onClientRequest: _alepha_core.HookDescriptor<"client:onRequest">;
1075
+ protected readonly onRequest: _alepha_core.HookDescriptor<"server:onRequest">;
1076
+ protected readonly onRoute: _alepha_core.HookDescriptor<"server:onRoute">;
1077
+ }
1078
+
1079
+ type TimingMap = Record<string, [number, number]>;
1080
+ declare class ServerTimingProvider {
1081
+ protected readonly log: _alepha_core.Logger;
1082
+ protected readonly alepha: Alepha;
1083
+ readonly onRequest: _alepha_core.HookDescriptor<"server:onRequest">;
1084
+ readonly onResponse: _alepha_core.HookDescriptor<"server:onResponse">;
1085
+ protected get handlerName(): string;
1086
+ beginTiming(name: string): void;
1087
+ endTiming(name: string): void;
1088
+ protected setDuration(name: string, timing: TimingMap): void;
1089
+ }
781
1090
 
782
1091
  declare const envSchema$1: _alepha_core.TObject<{
783
1092
  SERVER_PORT: TNumber;
784
- SERVER_HOST: TString;
1093
+ SERVER_HOST: TString$1;
785
1094
  }>;
786
1095
  declare module "@alepha/core" {
787
1096
  interface Env extends Partial<Static$1<typeof envSchema$1>> {
@@ -798,6 +1107,7 @@ declare class NodeHttpServerProvider implements ServerProvider {
798
1107
  protected readonly server: http.Server<typeof IncomingMessage, typeof ServerResponse$1>;
799
1108
  handle(req: IncomingMessage, res: ServerResponse$1): Promise<number | void>;
800
1109
  createRouterRequest(req: IncomingMessage, res: ServerResponse$1, params?: Record<string, string>): ServerRawRequest;
1110
+ getProtocol(req: IncomingMessage): "http" | "https";
801
1111
  shouldHaveBody(method: string): boolean;
802
1112
  get hostname(): string;
803
1113
  readonly start: _alepha_core.HookDescriptor<"start">;
@@ -807,49 +1117,28 @@ declare class NodeHttpServerProvider implements ServerProvider {
807
1117
  }
808
1118
 
809
1119
  declare const errorSchema: TObject<{
810
- error: TString;
1120
+ error: TString$1;
811
1121
  status: TNumber;
812
- message: TString;
813
- details: TOptional<TString>;
1122
+ message: TString$1;
1123
+ details: TOptional<TString$1>;
814
1124
  cause: TOptional<TObject<{
815
- name: TString;
816
- message: TString;
1125
+ name: TString$1;
1126
+ message: TString$1;
817
1127
  }>>;
818
1128
  }>;
819
1129
 
820
1130
  declare const okSchema: TObject<{
821
1131
  ok: TBoolean;
822
- id: TOptional<TUnion<[TString, TInteger]>>;
1132
+ id: TOptional<TUnion<[TString$1, TInteger]>>;
823
1133
  count: TOptional<TNumber>;
824
1134
  }>;
825
1135
  type Ok = Static$1<typeof okSchema>;
826
1136
 
827
- declare class BadRequestError extends HttpError {
828
- constructor(message?: string, cause?: unknown);
829
- }
830
-
831
- declare class ConflictError extends HttpError {
832
- constructor(message?: string, cause?: unknown);
833
- }
834
-
835
- declare class ForbiddenError extends HttpError {
836
- constructor(message?: string, cause?: unknown);
837
- }
838
-
839
- declare class NotFoundError extends HttpError {
840
- constructor(message?: string, cause?: unknown);
841
- }
842
-
843
- declare class UnauthorizedError extends HttpError {
844
- constructor(message?: string, cause?: unknown);
845
- }
846
-
847
- declare class ValidationError extends HttpError {
848
- constructor(message?: string, cause?: unknown);
849
- }
850
-
851
1137
  declare const envSchema: _alepha_core.TObject<{
852
1138
  SERVER_LINKS_ENABLED: TBoolean;
1139
+ SERVER_HEALTH_ENABLED: TBoolean;
1140
+ SERVER_NOT_READY_ENABLED: TBoolean;
1141
+ SERVER_TIMING_ENABLED: TOptional<TBoolean>;
853
1142
  }>;
854
1143
  declare module "@alepha/core" {
855
1144
  interface Hooks {
@@ -897,11 +1186,15 @@ declare module "@alepha/core" {
897
1186
  }
898
1187
  }
899
1188
  declare class ServerModule {
1189
+ static plugins: Array<Service>;
900
1190
  protected readonly env: {
1191
+ SERVER_TIMING_ENABLED?: boolean | undefined;
901
1192
  SERVER_LINKS_ENABLED: boolean;
1193
+ SERVER_HEALTH_ENABLED: boolean;
1194
+ SERVER_NOT_READY_ENABLED: boolean;
902
1195
  };
903
1196
  protected readonly alepha: Alepha;
904
1197
  constructor();
905
1198
  }
906
1199
 
907
- export { $action, $remote, $route, BadRequestError, BrowserActionDescriptorProvider, type ClientRequestEntry, type ClientRequestEntryContainer, type ClientRequestOptions, type ClientRequestResponse, ConflictError, type FetchFactoryAdditionalOptions, type FetchRunOptions, ForbiddenError, HttpClient, type HttpClientLink, type HttpClientPendingRequests, HttpError, type HttpVirtualClient, NodeHttpServerProvider, NotFoundError, type Ok, REMOTE_DESCRIPTOR_KEY, type RemoteDescriptor, type RemoteDescriptorOptions, type RequestConfigSchema, type ResponseBodyType, type ResponseType, type RouteDescriptor, type RouteDescriptorOptions, type RouteMethod, ServerActionDescriptorProvider, type ServerHandler, ServerLinksProvider, ServerLoggerProvider, ServerModule, ServerMultipartProvider, ServerProvider, type ServerRawRequest, type ServerRemote, type ServerReply, type ServerRequest, type ServerRequestConfig, type ServerRequestConfigEntry, type ServerResponse, type ServerResponseBody, type ServerRoute, type ServerRouteAction, type ServerRouteWithHandler, ServerRouterProvider, ServerSecurityProvider, UnauthorizedError, ValidationError, bufferToArrayBuffer, bufferToStream, errorNameByStatus, errorSchema, file, getContentType, isServerAction, okSchema, routeMethods, streamToBuffer };
1200
+ export { $action, $client, $proxy, $remote, $route, type ActionDescriptor, type ActionDescriptorOptions, type ApiLink, type ApiLinksResponse, BadRequestError, type ClientRequestEntry, type ClientRequestEntryContainer, type ClientRequestOptions, type ClientRequestResponse, type ClientScope, ConflictError, type FetchFactoryAdditionalOptions, type FetchLinkArgs, type FetchResponse, type FetchRunOptions, ForbiddenError, HttpClient, type HttpClientLink, type HttpClientPendingRequests, HttpError, type HttpErrorLike, type HttpVirtualClient, NodeHttpServerProvider, NotFoundError, type Ok, type ProxyDescriptor, type ProxyDescriptorOptions, ProxyDescriptorProvider, type RemoteDescriptor, type RemoteDescriptorOptions, RemoteDescriptorProvider, type RequestConfigSchema, type ResponseBodyType, type ResponseType, type RouteDescriptor, type RouteDescriptorOptions, type RouteMethod, ServerActionDescriptorProvider, type ServerHandler, ServerHealthProvider, ServerLinksProvider, ServerLoggerProvider, type ServerMiddlewareHandler, ServerModule, ServerMultipartProvider, ServerNotReadyProvider, ServerProvider, type ServerRawRequest, type ServerRemote, type ServerReply, type ServerRequest, type ServerRequestConfig, type ServerRequestConfigEntry, type ServerResponse, type ServerResponseBody, type ServerRoute, type ServerRouteAction, type ServerRouteSecure, type ServerRouteWithHandler, ServerRouterProvider, ServerSecurityProvider, ServerTimingProvider, UnauthorizedError, ValidationError, apiLinkSchema, apiLinksResponseSchema, errorNameByStatus, errorSchema, isHttpError, isServerAction, okSchema, routeMethods };