alepha 0.13.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/api-files/index.d.ts +28 -91
- package/dist/api-files/index.js +10 -755
- package/dist/api-files/index.js.map +1 -1
- package/dist/api-jobs/index.d.ts +46 -46
- package/dist/api-jobs/index.js +13 -13
- package/dist/api-jobs/index.js.map +1 -1
- package/dist/api-notifications/index.d.ts +129 -146
- package/dist/api-notifications/index.js +17 -39
- package/dist/api-notifications/index.js.map +1 -1
- package/dist/api-parameters/index.d.ts +21 -22
- package/dist/api-parameters/index.js +22 -22
- package/dist/api-parameters/index.js.map +1 -1
- package/dist/api-users/index.d.ts +223 -2000
- package/dist/api-users/index.js +914 -4787
- package/dist/api-users/index.js.map +1 -1
- package/dist/api-verifications/index.d.ts +96 -96
- package/dist/batch/index.d.ts +13 -13
- package/dist/batch/index.js +8 -8
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +14 -14
- package/dist/bucket/index.js +12 -12
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/index.d.ts +11 -11
- package/dist/cache/index.js +9 -9
- package/dist/cache/index.js.map +1 -1
- package/dist/cli/index.d.ts +28 -26
- package/dist/cli/index.js +50 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +19 -19
- package/dist/command/index.js +25 -25
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +218 -218
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +232 -232
- package/dist/core/index.js +218 -218
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +2113 -0
- package/dist/core/index.native.js.map +1 -0
- package/dist/datetime/index.d.ts +9 -9
- package/dist/datetime/index.js +7 -7
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +16 -16
- package/dist/email/index.js +9 -9
- package/dist/email/index.js.map +1 -1
- package/dist/file/index.js +1 -1
- package/dist/file/index.js.map +1 -1
- package/dist/lock/index.d.ts +9 -9
- package/dist/lock/index.js +8 -8
- package/dist/lock/index.js.map +1 -1
- package/dist/lock-redis/index.js +3 -66
- package/dist/lock-redis/index.js.map +1 -1
- package/dist/logger/index.d.ts +5 -5
- package/dist/logger/index.js +8 -8
- package/dist/logger/index.js.map +1 -1
- package/dist/orm/index.browser.js +114 -114
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.d.ts +218 -218
- package/dist/orm/index.js +46 -46
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/index.d.ts +29 -29
- package/dist/queue/index.js +20 -20
- package/dist/queue/index.js.map +1 -1
- package/dist/queue-redis/index.d.ts +2 -2
- package/dist/redis/index.d.ts +10 -10
- package/dist/retry/index.d.ts +19 -19
- package/dist/retry/index.js +7 -7
- package/dist/retry/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +16 -16
- package/dist/scheduler/index.js +9 -9
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +80 -80
- package/dist/security/index.js +32 -32
- package/dist/security/index.js.map +1 -1
- package/dist/server/index.browser.js +1 -1
- package/dist/server/index.browser.js.map +1 -1
- package/dist/server/index.d.ts +101 -101
- package/dist/server/index.js +16 -16
- package/dist/server/index.js.map +1 -1
- package/dist/server-auth/index.browser.js +4 -982
- package/dist/server-auth/index.browser.js.map +1 -1
- package/dist/server-auth/index.d.ts +204 -785
- package/dist/server-auth/index.js +47 -1239
- package/dist/server-auth/index.js.map +1 -1
- package/dist/server-cache/index.d.ts +10 -10
- package/dist/server-cache/index.js +2 -2
- package/dist/server-cache/index.js.map +1 -1
- package/dist/server-compress/index.d.ts +4 -4
- package/dist/server-compress/index.js +1 -1
- package/dist/server-compress/index.js.map +1 -1
- package/dist/server-cookies/index.browser.js +8 -8
- package/dist/server-cookies/index.browser.js.map +1 -1
- package/dist/server-cookies/index.d.ts +17 -17
- package/dist/server-cookies/index.js +10 -10
- package/dist/server-cookies/index.js.map +1 -1
- package/dist/server-cors/index.d.ts +17 -17
- package/dist/server-cors/index.js +9 -9
- package/dist/server-cors/index.js.map +1 -1
- package/dist/server-health/index.d.ts +19 -19
- package/dist/server-helmet/index.d.ts +1 -1
- package/dist/server-links/index.browser.js +12 -12
- package/dist/server-links/index.browser.js.map +1 -1
- package/dist/server-links/index.d.ts +59 -251
- package/dist/server-links/index.js +23 -502
- package/dist/server-links/index.js.map +1 -1
- package/dist/server-metrics/index.d.ts +4 -4
- package/dist/server-multipart/index.d.ts +2 -2
- package/dist/server-proxy/index.d.ts +12 -12
- package/dist/server-proxy/index.js +10 -10
- package/dist/server-proxy/index.js.map +1 -1
- package/dist/server-rate-limit/index.d.ts +22 -22
- package/dist/server-rate-limit/index.js +12 -12
- package/dist/server-rate-limit/index.js.map +1 -1
- package/dist/server-security/index.d.ts +22 -22
- package/dist/server-security/index.js +15 -15
- package/dist/server-security/index.js.map +1 -1
- package/dist/server-static/index.d.ts +14 -14
- package/dist/server-static/index.js +8 -8
- package/dist/server-static/index.js.map +1 -1
- package/dist/server-swagger/index.d.ts +25 -184
- package/dist/server-swagger/index.js +21 -724
- package/dist/server-swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +14 -14
- package/dist/sms/index.js +9 -9
- package/dist/sms/index.js.map +1 -1
- package/dist/thread/index.d.ts +11 -11
- package/dist/thread/index.js +17 -17
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/index.d.ts +26 -26
- package/dist/topic/index.js +16 -16
- package/dist/topic/index.js.map +1 -1
- package/dist/topic-redis/index.d.ts +1 -1
- package/dist/vite/index.d.ts +3 -3
- package/dist/vite/index.js +8 -8
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js +11 -11
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +58 -58
- package/dist/websocket/index.js +13 -13
- package/dist/websocket/index.js.map +1 -1
- package/package.json +113 -52
- package/src/api-files/services/FileService.ts +5 -7
- package/src/api-jobs/index.ts +1 -1
- package/src/api-jobs/{descriptors → primitives}/$job.ts +8 -8
- package/src/api-jobs/providers/JobProvider.ts +9 -9
- package/src/api-jobs/services/JobService.ts +5 -5
- package/src/api-notifications/index.ts +5 -15
- package/src/api-notifications/{descriptors → primitives}/$notification.ts +10 -10
- package/src/api-notifications/services/NotificationSenderService.ts +3 -3
- package/src/api-parameters/index.ts +1 -1
- package/src/api-parameters/{descriptors → primitives}/$config.ts +7 -12
- package/src/api-users/index.ts +1 -1
- package/src/api-users/{descriptors → primitives}/$userRealm.ts +8 -8
- package/src/api-users/providers/UserRealmProvider.ts +1 -1
- package/src/batch/index.ts +3 -3
- package/src/batch/{descriptors → primitives}/$batch.ts +13 -16
- package/src/bucket/index.ts +8 -8
- package/src/bucket/{descriptors → primitives}/$bucket.ts +8 -8
- package/src/bucket/providers/LocalFileStorageProvider.ts +3 -3
- package/src/cache/index.ts +4 -4
- package/src/cache/{descriptors → primitives}/$cache.ts +15 -15
- package/src/cli/apps/AlephaPackageBuilderCli.ts +24 -2
- package/src/cli/commands/DrizzleCommands.ts +6 -6
- package/src/cli/commands/VerifyCommands.ts +1 -1
- package/src/cli/commands/ViteCommands.ts +6 -1
- package/src/cli/services/ProjectUtils.ts +34 -3
- package/src/command/index.ts +5 -5
- package/src/command/{descriptors → primitives}/$command.ts +9 -12
- package/src/command/providers/CliProvider.ts +10 -10
- package/src/core/Alepha.ts +30 -33
- package/src/core/constants/KIND.ts +1 -1
- package/src/core/constants/OPTIONS.ts +1 -1
- package/src/core/helpers/{descriptor.ts → primitive.ts} +18 -18
- package/src/core/helpers/ref.ts +1 -1
- package/src/core/index.shared.ts +8 -8
- package/src/core/{descriptors → primitives}/$context.ts +5 -5
- package/src/core/{descriptors → primitives}/$hook.ts +4 -4
- package/src/core/{descriptors → primitives}/$inject.ts +2 -2
- package/src/core/{descriptors → primitives}/$module.ts +9 -9
- package/src/core/{descriptors → primitives}/$use.ts +2 -2
- package/src/core/providers/CodecManager.ts +1 -1
- package/src/core/providers/JsonSchemaCodec.ts +1 -1
- package/src/core/providers/StateManager.ts +2 -2
- package/src/datetime/index.ts +3 -3
- package/src/datetime/{descriptors → primitives}/$interval.ts +6 -6
- package/src/email/index.ts +4 -4
- package/src/email/{descriptors → primitives}/$email.ts +8 -8
- package/src/file/index.ts +1 -1
- package/src/lock/index.ts +3 -3
- package/src/lock/{descriptors → primitives}/$lock.ts +10 -10
- package/src/logger/index.ts +8 -8
- package/src/logger/{descriptors → primitives}/$logger.ts +2 -2
- package/src/logger/services/Logger.ts +1 -1
- package/src/orm/constants/PG_SYMBOLS.ts +2 -2
- package/src/orm/index.browser.ts +2 -2
- package/src/orm/index.ts +8 -8
- package/src/orm/{descriptors → primitives}/$entity.ts +11 -11
- package/src/orm/{descriptors → primitives}/$repository.ts +2 -2
- package/src/orm/{descriptors → primitives}/$sequence.ts +8 -8
- package/src/orm/{descriptors → primitives}/$transaction.ts +4 -4
- package/src/orm/providers/PostgresTypeProvider.ts +3 -3
- package/src/orm/providers/RepositoryProvider.ts +4 -4
- package/src/orm/providers/drivers/DatabaseProvider.ts +7 -7
- package/src/orm/services/ModelBuilder.ts +9 -9
- package/src/orm/services/PgRelationManager.ts +2 -2
- package/src/orm/services/PostgresModelBuilder.ts +5 -5
- package/src/orm/services/Repository.ts +7 -7
- package/src/orm/services/SqliteModelBuilder.ts +5 -5
- package/src/queue/index.ts +7 -7
- package/src/queue/{descriptors → primitives}/$consumer.ts +15 -15
- package/src/queue/{descriptors → primitives}/$queue.ts +12 -12
- package/src/queue/providers/WorkerProvider.ts +7 -7
- package/src/retry/index.ts +3 -3
- package/src/retry/{descriptors → primitives}/$retry.ts +14 -14
- package/src/scheduler/index.ts +3 -3
- package/src/scheduler/{descriptors → primitives}/$scheduler.ts +9 -9
- package/src/scheduler/providers/CronProvider.ts +1 -1
- package/src/security/index.ts +9 -9
- package/src/security/{descriptors → primitives}/$permission.ts +7 -7
- package/src/security/{descriptors → primitives}/$realm.ts +6 -12
- package/src/security/{descriptors → primitives}/$role.ts +12 -12
- package/src/security/{descriptors → primitives}/$serviceAccount.ts +8 -8
- package/src/server/index.browser.ts +1 -1
- package/src/server/index.ts +14 -14
- package/src/server/{descriptors → primitives}/$action.ts +13 -13
- package/src/server/{descriptors → primitives}/$route.ts +9 -9
- package/src/server/providers/NodeHttpServerProvider.ts +1 -1
- package/src/server/services/HttpClient.ts +1 -1
- package/src/server-auth/index.browser.ts +1 -1
- package/src/server-auth/index.ts +6 -6
- package/src/server-auth/{descriptors → primitives}/$auth.ts +10 -10
- package/src/server-auth/{descriptors → primitives}/$authCredentials.ts +4 -4
- package/src/server-auth/{descriptors → primitives}/$authGithub.ts +4 -4
- package/src/server-auth/{descriptors → primitives}/$authGoogle.ts +4 -4
- package/src/server-auth/providers/ServerAuthProvider.ts +4 -4
- package/src/server-cache/providers/ServerCacheProvider.ts +7 -7
- package/src/server-compress/providers/ServerCompressProvider.ts +3 -3
- package/src/server-cookies/index.browser.ts +2 -2
- package/src/server-cookies/index.ts +5 -5
- package/src/server-cookies/{descriptors → primitives}/$cookie.browser.ts +12 -12
- package/src/server-cookies/{descriptors → primitives}/$cookie.ts +13 -13
- package/src/server-cookies/providers/ServerCookiesProvider.ts +4 -4
- package/src/server-cookies/services/CookieParser.ts +1 -1
- package/src/server-cors/index.ts +3 -3
- package/src/server-cors/{descriptors → primitives}/$cors.ts +11 -13
- package/src/server-cors/providers/ServerCorsProvider.ts +5 -5
- package/src/server-links/index.browser.ts +5 -5
- package/src/server-links/index.ts +9 -9
- package/src/server-links/{descriptors → primitives}/$remote.ts +11 -11
- package/src/server-links/providers/LinkProvider.ts +7 -7
- package/src/server-links/providers/{RemoteDescriptorProvider.ts → RemotePrimitiveProvider.ts} +6 -6
- package/src/server-links/providers/ServerLinksProvider.ts +3 -3
- package/src/server-proxy/index.ts +3 -3
- package/src/server-proxy/{descriptors → primitives}/$proxy.ts +8 -8
- package/src/server-proxy/providers/ServerProxyProvider.ts +4 -4
- package/src/server-rate-limit/index.ts +6 -6
- package/src/server-rate-limit/{descriptors → primitives}/$rateLimit.ts +13 -13
- package/src/server-rate-limit/providers/ServerRateLimitProvider.ts +5 -5
- package/src/server-security/index.ts +3 -3
- package/src/server-security/{descriptors → primitives}/$basicAuth.ts +13 -13
- package/src/server-security/providers/ServerBasicAuthProvider.ts +5 -5
- package/src/server-security/providers/ServerSecurityProvider.ts +4 -4
- package/src/server-static/index.ts +3 -3
- package/src/server-static/{descriptors → primitives}/$serve.ts +8 -10
- package/src/server-static/providers/ServerStaticProvider.ts +6 -6
- package/src/server-swagger/index.ts +5 -5
- package/src/server-swagger/{descriptors → primitives}/$swagger.ts +9 -9
- package/src/server-swagger/providers/ServerSwaggerProvider.ts +11 -10
- package/src/sms/index.ts +4 -4
- package/src/sms/{descriptors → primitives}/$sms.ts +8 -8
- package/src/thread/index.ts +3 -3
- package/src/thread/{descriptors → primitives}/$thread.ts +13 -13
- package/src/thread/providers/ThreadProvider.ts +7 -9
- package/src/topic/index.ts +5 -5
- package/src/topic/{descriptors → primitives}/$subscriber.ts +14 -14
- package/src/topic/{descriptors → primitives}/$topic.ts +10 -10
- package/src/topic/providers/TopicProvider.ts +4 -4
- package/src/vite/tasks/copyAssets.ts +1 -1
- package/src/vite/tasks/generateSitemap.ts +3 -3
- package/src/vite/tasks/prerenderPages.ts +2 -2
- package/src/vite/tasks/runAlepha.ts +2 -2
- package/src/websocket/index.browser.ts +3 -3
- package/src/websocket/index.shared.ts +2 -2
- package/src/websocket/index.ts +4 -4
- package/src/websocket/interfaces/WebSocketInterfaces.ts +3 -3
- package/src/websocket/{descriptors → primitives}/$channel.ts +10 -10
- package/src/websocket/{descriptors → primitives}/$websocket.ts +8 -8
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +7 -7
- package/src/websocket/providers/WebSocketServerProvider.ts +3 -3
- package/src/websocket/services/WebSocketClient.ts +5 -5
- package/src/api-notifications/providers/MemorySmsProvider.ts +0 -20
- package/src/api-notifications/providers/SmsProvider.ts +0 -8
- /package/src/core/{descriptors → primitives}/$atom.ts +0 -0
- /package/src/core/{descriptors → primitives}/$env.ts +0 -0
- /package/src/server-auth/{descriptors → primitives}/$authApple.ts +0 -0
- /package/src/server-links/{descriptors → primitives}/$client.ts +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as alepha1 from "alepha";
|
|
2
|
-
import {
|
|
2
|
+
import { KIND, Primitive, Static } from "alepha";
|
|
3
3
|
import * as alepha_logger0 from "alepha/logger";
|
|
4
4
|
import { ServerRouterProvider } from "alepha/server";
|
|
5
5
|
|
|
6
|
-
//#region src/server-cors/
|
|
6
|
+
//#region src/server-cors/primitives/$cors.d.ts
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Declares CORS configuration for specific server routes.
|
|
10
|
-
* This
|
|
10
|
+
* This primitive provides path-based CORS configuration.
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```ts
|
|
@@ -22,20 +22,20 @@ import { ServerRouterProvider } from "alepha/server";
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
declare const $cors: {
|
|
25
|
-
(options:
|
|
26
|
-
[KIND]: typeof
|
|
25
|
+
(options: CorsPrimitiveConfig): AbstractCorsPrimitive;
|
|
26
|
+
[KIND]: typeof CorsPrimitive;
|
|
27
27
|
};
|
|
28
|
-
interface
|
|
28
|
+
interface CorsPrimitiveConfig extends Partial<CorsOptions> {
|
|
29
29
|
/** Name identifier for this CORS config (default: property key) */
|
|
30
30
|
name?: string;
|
|
31
31
|
/** Path patterns to match (supports wildcards like /api/*) */
|
|
32
32
|
paths?: string[];
|
|
33
33
|
}
|
|
34
|
-
interface
|
|
34
|
+
interface AbstractCorsPrimitive {
|
|
35
35
|
readonly name: string;
|
|
36
|
-
readonly options:
|
|
36
|
+
readonly options: CorsPrimitiveConfig;
|
|
37
37
|
}
|
|
38
|
-
declare class
|
|
38
|
+
declare class CorsPrimitive extends Primitive<CorsPrimitiveConfig> implements AbstractCorsPrimitive {
|
|
39
39
|
protected readonly serverCorsProvider: ServerCorsProvider;
|
|
40
40
|
get name(): string;
|
|
41
41
|
protected onInit(): void;
|
|
@@ -71,18 +71,18 @@ declare class ServerCorsProvider {
|
|
|
71
71
|
/**
|
|
72
72
|
* Registered CORS configurations with their path patterns
|
|
73
73
|
*/
|
|
74
|
-
readonly registeredConfigs:
|
|
74
|
+
readonly registeredConfigs: CorsPrimitiveConfig[];
|
|
75
75
|
/**
|
|
76
|
-
* Register a CORS configuration (called by
|
|
76
|
+
* Register a CORS configuration (called by primitives)
|
|
77
77
|
*/
|
|
78
|
-
registerCors(config:
|
|
79
|
-
protected readonly onStart: alepha1.
|
|
80
|
-
protected readonly configure: alepha1.
|
|
81
|
-
protected readonly onRequest: alepha1.
|
|
78
|
+
registerCors(config: CorsPrimitiveConfig): void;
|
|
79
|
+
protected readonly onStart: alepha1.HookPrimitive<"start">;
|
|
80
|
+
protected readonly configure: alepha1.HookPrimitive<"configure">;
|
|
81
|
+
protected readonly onRequest: alepha1.HookPrimitive<"server:onRequest">;
|
|
82
82
|
/**
|
|
83
83
|
* Build complete CORS options by merging with global defaults
|
|
84
84
|
*/
|
|
85
|
-
protected buildCorsOptions(config:
|
|
85
|
+
protected buildCorsOptions(config: CorsPrimitiveConfig): CorsOptions;
|
|
86
86
|
/**
|
|
87
87
|
* Apply CORS headers to the response
|
|
88
88
|
*/
|
|
@@ -136,5 +136,5 @@ declare module "alepha/server" {
|
|
|
136
136
|
*/
|
|
137
137
|
declare const AlephaServerCors: alepha1.Service<alepha1.Module>;
|
|
138
138
|
//#endregion
|
|
139
|
-
export { $cors,
|
|
139
|
+
export { $cors, AbstractCorsPrimitive, AlephaServerCors, CorsOptions, CorsPrimitive, CorsPrimitiveConfig, ServerCorsProvider, ServerCorsProviderOptions, corsOptions };
|
|
140
140
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $atom, $hook, $inject, $module, $use,
|
|
1
|
+
import { $atom, $hook, $inject, $module, $use, KIND, Primitive, createPrimitive, t } from "alepha";
|
|
2
2
|
import { $logger } from "alepha/logger";
|
|
3
3
|
import { ServerRouterProvider } from "alepha/server";
|
|
4
4
|
|
|
@@ -57,7 +57,7 @@ var ServerCorsProvider = class {
|
|
|
57
57
|
*/
|
|
58
58
|
registeredConfigs = [];
|
|
59
59
|
/**
|
|
60
|
-
* Register a CORS configuration (called by
|
|
60
|
+
* Register a CORS configuration (called by primitives)
|
|
61
61
|
*/
|
|
62
62
|
registerCors(config) {
|
|
63
63
|
this.registeredConfigs.push(config);
|
|
@@ -127,10 +127,10 @@ var ServerCorsProvider = class {
|
|
|
127
127
|
};
|
|
128
128
|
|
|
129
129
|
//#endregion
|
|
130
|
-
//#region src/server-cors/
|
|
130
|
+
//#region src/server-cors/primitives/$cors.ts
|
|
131
131
|
/**
|
|
132
132
|
* Declares CORS configuration for specific server routes.
|
|
133
|
-
* This
|
|
133
|
+
* This primitive provides path-based CORS configuration.
|
|
134
134
|
*
|
|
135
135
|
* @example
|
|
136
136
|
* ```ts
|
|
@@ -145,9 +145,9 @@ var ServerCorsProvider = class {
|
|
|
145
145
|
* ```
|
|
146
146
|
*/
|
|
147
147
|
const $cors = (options) => {
|
|
148
|
-
return
|
|
148
|
+
return createPrimitive(CorsPrimitive, options);
|
|
149
149
|
};
|
|
150
|
-
var
|
|
150
|
+
var CorsPrimitive = class extends Primitive {
|
|
151
151
|
serverCorsProvider = $inject(ServerCorsProvider);
|
|
152
152
|
get name() {
|
|
153
153
|
return this.options.name ?? `${this.config.propertyKey}`;
|
|
@@ -156,7 +156,7 @@ var CorsDescriptor = class extends Descriptor {
|
|
|
156
156
|
this.serverCorsProvider.registerCors(this.options);
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
|
-
$cors[KIND] =
|
|
159
|
+
$cors[KIND] = CorsPrimitive;
|
|
160
160
|
|
|
161
161
|
//#endregion
|
|
162
162
|
//#region src/server-cors/index.ts
|
|
@@ -188,10 +188,10 @@ $cors[KIND] = CorsDescriptor;
|
|
|
188
188
|
*/
|
|
189
189
|
const AlephaServerCors = $module({
|
|
190
190
|
name: "alepha.server.cors",
|
|
191
|
-
|
|
191
|
+
primitives: [$cors],
|
|
192
192
|
services: [ServerCorsProvider]
|
|
193
193
|
});
|
|
194
194
|
|
|
195
195
|
//#endregion
|
|
196
|
-
export { $cors, AlephaServerCors,
|
|
196
|
+
export { $cors, AlephaServerCors, CorsPrimitive, ServerCorsProvider, corsOptions };
|
|
197
197
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/server-cors/providers/ServerCorsProvider.ts","../../src/server-cors/descriptors/$cors.ts","../../src/server-cors/index.ts"],"sourcesContent":["import { $atom, $hook, $inject, $use, type Static, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerRouterProvider } from \"alepha/server\";\nimport type { CorsDescriptorConfig } from \"../descriptors/$cors.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * CORS configuration atom (global defaults)\n */\nexport const corsOptions = $atom({\n name: \"alepha.server.cors.options\",\n schema: t.object({\n origin: t.optional(\n t.string({\n description:\n \"Allowed origins (* for all, string for single, comma-separated for multiple)\",\n default: \"*\",\n }),\n ),\n methods: t.array(t.string(), {\n description: \"Allowed HTTP methods\",\n default: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n }),\n headers: t.array(t.string(), {\n description: \"Allowed headers\",\n default: [\"Content-Type\", \"Authorization\"],\n }),\n credentials: t.optional(\n t.boolean({\n description: \"Allow credentials\",\n default: true,\n }),\n ),\n maxAge: t.optional(\n t.number({\n description: \"Preflight cache duration in seconds\",\n }),\n ),\n }),\n default: {\n origin: \"*\",\n methods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n headers: [\"Content-Type\", \"Authorization\"],\n credentials: true,\n },\n});\n\nexport type CorsOptions = Static<typeof corsOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [corsOptions.key]: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ServerCorsProvider {\n protected readonly log = $logger();\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly globalOptions = $use(corsOptions);\n\n /**\n * Registered CORS configurations with their path patterns\n */\n public readonly registeredConfigs: CorsDescriptorConfig[] = [];\n\n /**\n * Register a CORS configuration (called by descriptors)\n */\n public registerCors(config: CorsDescriptorConfig): void {\n this.registeredConfigs.push(config);\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // Apply path-specific CORS configs to routes\n for (const config of this.registeredConfigs) {\n if (config.paths) {\n for (const pattern of config.paths) {\n const matchedRoutes = this.serverRouterProvider.getRoutes(pattern);\n for (const route of matchedRoutes) {\n route.cors = this.buildCorsOptions(config);\n }\n }\n }\n }\n\n if (this.registeredConfigs.length > 0) {\n this.log.info(\n `Initialized with ${this.registeredConfigs.length} registered CORS configurations.`,\n );\n }\n },\n });\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: () => {\n const routes = this.serverRouterProvider.getRoutes();\n for (const route of routes) {\n if (\n !route.method ||\n route.method === \"GET\" ||\n route.method === \"OPTIONS\"\n ) {\n continue;\n }\n\n this.serverRouterProvider.createRoute({\n path: route.path,\n method: \"OPTIONS\",\n handler: ({ reply }) => {\n reply.setStatus(204);\n },\n });\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: ({ route, request }) => {\n // Use route-specific CORS if defined, otherwise use global options\n const corsConfig = route.cors ?? this.globalOptions;\n this.applyCorsHeaders(request, corsConfig);\n },\n });\n\n /**\n * Build complete CORS options by merging with global defaults\n */\n protected buildCorsOptions(config: CorsDescriptorConfig): CorsOptions {\n return {\n origin: config.origin ?? this.globalOptions.origin,\n methods: config.methods ?? this.globalOptions.methods,\n headers: config.headers ?? this.globalOptions.headers,\n credentials: config.credentials ?? this.globalOptions.credentials,\n maxAge: config.maxAge ?? this.globalOptions.maxAge,\n };\n }\n\n /**\n * Apply CORS headers to the response\n */\n protected applyCorsHeaders(\n request: {\n headers: { origin?: string };\n reply: { setHeader: (name: string, value: string) => void };\n },\n options: CorsOptions,\n ): void {\n const reqOrigin = request.headers.origin;\n const { origin, methods, headers, credentials, maxAge } = options;\n\n if (reqOrigin && this.isOriginAllowed(reqOrigin, origin)) {\n request.reply.setHeader(\"Access-Control-Allow-Origin\", reqOrigin);\n }\n\n if (credentials) {\n request.reply.setHeader(\"Access-Control-Allow-Credentials\", \"true\");\n }\n\n request.reply.setHeader(\"Access-Control-Allow-Methods\", methods.join(\", \"));\n request.reply.setHeader(\"Access-Control-Allow-Headers\", headers.join(\", \"));\n\n if (maxAge != null) {\n request.reply.setHeader(\"Access-Control-Max-Age\", String(maxAge));\n }\n }\n\n public isOriginAllowed(\n origin: string | undefined,\n allowed: CorsOptions[\"origin\"],\n ): boolean {\n if (!allowed) return false;\n if (allowed === \"*\") return true;\n return allowed\n .split(\",\")\n .map((o) => o.trim())\n .includes(origin ?? \"\");\n }\n}\n\nexport type ServerCorsProviderOptions = CorsOptions;\n","import { $inject, createDescriptor, Descriptor, KIND } from \"alepha\";\nimport type { CorsOptions } from \"../providers/ServerCorsProvider.ts\";\nimport { ServerCorsProvider } from \"../providers/ServerCorsProvider.ts\";\n\n/**\n * Declares CORS configuration for specific server routes.\n * This descriptor provides path-based CORS configuration.\n *\n * @example\n * ```ts\n * class ApiService {\n * // Apply specific CORS to API routes\n * cors = $cors({\n * paths: [\"/api/*\"],\n * origin: \"https://app.example.com\",\n * credentials: true,\n * });\n * }\n * ```\n */\nexport const $cors = (\n options: CorsDescriptorConfig,\n): AbstractCorsDescriptor => {\n return createDescriptor(CorsDescriptor, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CorsDescriptorConfig extends Partial<CorsOptions> {\n /** Name identifier for this CORS config (default: property key) */\n name?: string;\n /** Path patterns to match (supports wildcards like /api/*) */\n paths?: string[];\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface AbstractCorsDescriptor {\n readonly name: string;\n readonly options: CorsDescriptorConfig;\n}\n\nexport class CorsDescriptor\n extends Descriptor<CorsDescriptorConfig>\n implements AbstractCorsDescriptor\n{\n protected readonly serverCorsProvider = $inject(ServerCorsProvider);\n\n public get name(): string {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n protected onInit() {\n // Register this CORS configuration with the provider\n this.serverCorsProvider.registerCors(this.options);\n }\n}\n\n$cors[KIND] = CorsDescriptor;\n","import { $module } from \"alepha\";\nimport { $cors } from \"./descriptors/$cors.ts\";\nimport {\n type CorsOptions,\n ServerCorsProvider,\n} from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$cors.ts\";\nexport * from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRoute {\n /**\n * Route-specific CORS configuration.\n * If set, overrides the global CORS options for this route.\n */\n cors?: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Plugin for configuring CORS on the Alepha server.\n *\n * @example\n * ```ts\n * import { Alepha, $route } from \"alepha\";\n * import { AlephaServerCors, $cors } from \"alepha/server-cors\";\n *\n * class ApiService {\n * // Global CORS is applied via corsOptions atom\n *\n * // Path-specific CORS for API routes\n * apiCors = $cors({\n * paths: [\"/api/*\"],\n * origin: \"https://app.example.com\",\n * credentials: true,\n * });\n *\n * route = $route({\n * path: \"/api/data\",\n * method: \"POST\",\n * handler: () => ({ data: \"hello\" }),\n * });\n * }\n * ```\n */\nexport const AlephaServerCors = $module({\n name: \"alepha.server.cors\",\n descriptors: [$cors],\n services: [ServerCorsProvider],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/server-cors/providers/ServerCorsProvider.ts","../../src/server-cors/primitives/$cors.ts","../../src/server-cors/index.ts"],"sourcesContent":["import { $atom, $hook, $inject, $use, type Static, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerRouterProvider } from \"alepha/server\";\nimport type { CorsPrimitiveConfig } from \"../primitives/$cors.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * CORS configuration atom (global defaults)\n */\nexport const corsOptions = $atom({\n name: \"alepha.server.cors.options\",\n schema: t.object({\n origin: t.optional(\n t.string({\n description:\n \"Allowed origins (* for all, string for single, comma-separated for multiple)\",\n default: \"*\",\n }),\n ),\n methods: t.array(t.string(), {\n description: \"Allowed HTTP methods\",\n default: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n }),\n headers: t.array(t.string(), {\n description: \"Allowed headers\",\n default: [\"Content-Type\", \"Authorization\"],\n }),\n credentials: t.optional(\n t.boolean({\n description: \"Allow credentials\",\n default: true,\n }),\n ),\n maxAge: t.optional(\n t.number({\n description: \"Preflight cache duration in seconds\",\n }),\n ),\n }),\n default: {\n origin: \"*\",\n methods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n headers: [\"Content-Type\", \"Authorization\"],\n credentials: true,\n },\n});\n\nexport type CorsOptions = Static<typeof corsOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [corsOptions.key]: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ServerCorsProvider {\n protected readonly log = $logger();\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly globalOptions = $use(corsOptions);\n\n /**\n * Registered CORS configurations with their path patterns\n */\n public readonly registeredConfigs: CorsPrimitiveConfig[] = [];\n\n /**\n * Register a CORS configuration (called by primitives)\n */\n public registerCors(config: CorsPrimitiveConfig): void {\n this.registeredConfigs.push(config);\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // Apply path-specific CORS configs to routes\n for (const config of this.registeredConfigs) {\n if (config.paths) {\n for (const pattern of config.paths) {\n const matchedRoutes = this.serverRouterProvider.getRoutes(pattern);\n for (const route of matchedRoutes) {\n route.cors = this.buildCorsOptions(config);\n }\n }\n }\n }\n\n if (this.registeredConfigs.length > 0) {\n this.log.info(\n `Initialized with ${this.registeredConfigs.length} registered CORS configurations.`,\n );\n }\n },\n });\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: () => {\n const routes = this.serverRouterProvider.getRoutes();\n for (const route of routes) {\n if (\n !route.method ||\n route.method === \"GET\" ||\n route.method === \"OPTIONS\"\n ) {\n continue;\n }\n\n this.serverRouterProvider.createRoute({\n path: route.path,\n method: \"OPTIONS\",\n handler: ({ reply }) => {\n reply.setStatus(204);\n },\n });\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: ({ route, request }) => {\n // Use route-specific CORS if defined, otherwise use global options\n const corsConfig = route.cors ?? this.globalOptions;\n this.applyCorsHeaders(request, corsConfig);\n },\n });\n\n /**\n * Build complete CORS options by merging with global defaults\n */\n protected buildCorsOptions(config: CorsPrimitiveConfig): CorsOptions {\n return {\n origin: config.origin ?? this.globalOptions.origin,\n methods: config.methods ?? this.globalOptions.methods,\n headers: config.headers ?? this.globalOptions.headers,\n credentials: config.credentials ?? this.globalOptions.credentials,\n maxAge: config.maxAge ?? this.globalOptions.maxAge,\n };\n }\n\n /**\n * Apply CORS headers to the response\n */\n protected applyCorsHeaders(\n request: {\n headers: { origin?: string };\n reply: { setHeader: (name: string, value: string) => void };\n },\n options: CorsOptions,\n ): void {\n const reqOrigin = request.headers.origin;\n const { origin, methods, headers, credentials, maxAge } = options;\n\n if (reqOrigin && this.isOriginAllowed(reqOrigin, origin)) {\n request.reply.setHeader(\"Access-Control-Allow-Origin\", reqOrigin);\n }\n\n if (credentials) {\n request.reply.setHeader(\"Access-Control-Allow-Credentials\", \"true\");\n }\n\n request.reply.setHeader(\"Access-Control-Allow-Methods\", methods.join(\", \"));\n request.reply.setHeader(\"Access-Control-Allow-Headers\", headers.join(\", \"));\n\n if (maxAge != null) {\n request.reply.setHeader(\"Access-Control-Max-Age\", String(maxAge));\n }\n }\n\n public isOriginAllowed(\n origin: string | undefined,\n allowed: CorsOptions[\"origin\"],\n ): boolean {\n if (!allowed) return false;\n if (allowed === \"*\") return true;\n return allowed\n .split(\",\")\n .map((o) => o.trim())\n .includes(origin ?? \"\");\n }\n}\n\nexport type ServerCorsProviderOptions = CorsOptions;\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { CorsOptions } from \"../providers/ServerCorsProvider.ts\";\nimport { ServerCorsProvider } from \"../providers/ServerCorsProvider.ts\";\n\n/**\n * Declares CORS configuration for specific server routes.\n * This primitive provides path-based CORS configuration.\n *\n * @example\n * ```ts\n * class ApiService {\n * // Apply specific CORS to API routes\n * cors = $cors({\n * paths: [\"/api/*\"],\n * origin: \"https://app.example.com\",\n * credentials: true,\n * });\n * }\n * ```\n */\nexport const $cors = (options: CorsPrimitiveConfig): AbstractCorsPrimitive => {\n return createPrimitive(CorsPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CorsPrimitiveConfig extends Partial<CorsOptions> {\n /** Name identifier for this CORS config (default: property key) */\n name?: string;\n /** Path patterns to match (supports wildcards like /api/*) */\n paths?: string[];\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface AbstractCorsPrimitive {\n readonly name: string;\n readonly options: CorsPrimitiveConfig;\n}\n\nexport class CorsPrimitive\n extends Primitive<CorsPrimitiveConfig>\n implements AbstractCorsPrimitive\n{\n protected readonly serverCorsProvider = $inject(ServerCorsProvider);\n\n public get name(): string {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n protected onInit() {\n // Register this CORS configuration with the provider\n this.serverCorsProvider.registerCors(this.options);\n }\n}\n\n$cors[KIND] = CorsPrimitive;\n","import { $module } from \"alepha\";\nimport { $cors } from \"./primitives/$cors.ts\";\nimport {\n type CorsOptions,\n ServerCorsProvider,\n} from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$cors.ts\";\nexport * from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRoute {\n /**\n * Route-specific CORS configuration.\n * If set, overrides the global CORS options for this route.\n */\n cors?: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Plugin for configuring CORS on the Alepha server.\n *\n * @example\n * ```ts\n * import { Alepha, $route } from \"alepha\";\n * import { AlephaServerCors, $cors } from \"alepha/server-cors\";\n *\n * class ApiService {\n * // Global CORS is applied via corsOptions atom\n *\n * // Path-specific CORS for API routes\n * apiCors = $cors({\n * paths: [\"/api/*\"],\n * origin: \"https://app.example.com\",\n * credentials: true,\n * });\n *\n * route = $route({\n * path: \"/api/data\",\n * method: \"POST\",\n * handler: () => ({ data: \"hello\" }),\n * });\n * }\n * ```\n */\nexport const AlephaServerCors = $module({\n name: \"alepha.server.cors\",\n primitives: [$cors],\n services: [ServerCorsProvider],\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as alepha6 from "alepha";
|
|
2
2
|
import { Alepha } from "alepha";
|
|
3
3
|
import * as alepha_server0 from "alepha/server";
|
|
4
4
|
import { DateTimeProvider } from "alepha/datetime";
|
|
@@ -13,20 +13,20 @@ import { DateTimeProvider } from "alepha/datetime";
|
|
|
13
13
|
declare class ServerHealthProvider {
|
|
14
14
|
protected readonly time: DateTimeProvider;
|
|
15
15
|
protected readonly alepha: Alepha;
|
|
16
|
-
readonly health: alepha_server0.
|
|
17
|
-
response:
|
|
18
|
-
message:
|
|
19
|
-
uptime:
|
|
20
|
-
date:
|
|
21
|
-
ready:
|
|
16
|
+
readonly health: alepha_server0.RoutePrimitive<{
|
|
17
|
+
response: alepha6.TObject<{
|
|
18
|
+
message: alepha6.TString;
|
|
19
|
+
uptime: alepha6.TNumber;
|
|
20
|
+
date: alepha6.TString;
|
|
21
|
+
ready: alepha6.TBoolean;
|
|
22
22
|
}>;
|
|
23
23
|
}>;
|
|
24
|
-
readonly healthz: alepha_server0.
|
|
25
|
-
response:
|
|
26
|
-
message:
|
|
27
|
-
uptime:
|
|
28
|
-
date:
|
|
29
|
-
ready:
|
|
24
|
+
readonly healthz: alepha_server0.RoutePrimitive<{
|
|
25
|
+
response: alepha6.TObject<{
|
|
26
|
+
message: alepha6.TString;
|
|
27
|
+
uptime: alepha6.TNumber;
|
|
28
|
+
date: alepha6.TString;
|
|
29
|
+
ready: alepha6.TBoolean;
|
|
30
30
|
}>;
|
|
31
31
|
}>;
|
|
32
32
|
protected healthCheck(): {
|
|
@@ -38,11 +38,11 @@ declare class ServerHealthProvider {
|
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/server-health/schemas/healthSchema.d.ts
|
|
41
|
-
declare const healthSchema:
|
|
42
|
-
message:
|
|
43
|
-
uptime:
|
|
44
|
-
date:
|
|
45
|
-
ready:
|
|
41
|
+
declare const healthSchema: alepha6.TObject<{
|
|
42
|
+
message: alepha6.TString;
|
|
43
|
+
uptime: alepha6.TNumber;
|
|
44
|
+
date: alepha6.TString;
|
|
45
|
+
ready: alepha6.TBoolean;
|
|
46
46
|
}>;
|
|
47
47
|
//#endregion
|
|
48
48
|
//#region src/server-health/index.d.ts
|
|
@@ -52,7 +52,7 @@ declare const healthSchema: alepha1.TObject<{
|
|
|
52
52
|
* @see {@link ServerHealthProvider}
|
|
53
53
|
* @module alepha.server.health
|
|
54
54
|
*/
|
|
55
|
-
declare const AlephaServerHealth:
|
|
55
|
+
declare const AlephaServerHealth: alepha6.Service<alepha6.Module>;
|
|
56
56
|
//#endregion
|
|
57
57
|
export { AlephaServerHealth, ServerHealthProvider, healthSchema };
|
|
58
58
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -80,7 +80,7 @@ declare class ServerHelmetProvider {
|
|
|
80
80
|
}>;
|
|
81
81
|
protected defaultCspDirectives(): CspDirectives;
|
|
82
82
|
protected buildHeaders(): Record<string, string>;
|
|
83
|
-
protected readonly onResponse: alepha1.
|
|
83
|
+
protected readonly onResponse: alepha1.HookPrimitive<"server:onResponse">;
|
|
84
84
|
}
|
|
85
85
|
//#endregion
|
|
86
86
|
//#region src/server-helmet/index.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $inject, $module, Alepha, AlephaError,
|
|
1
|
+
import { $inject, $module, Alepha, AlephaError, KIND, Primitive, createPrimitive, t } from "alepha";
|
|
2
2
|
import { $logger } from "alepha/logger";
|
|
3
3
|
import { HttpClient, ServerReply, UnauthorizedError } from "alepha/server";
|
|
4
4
|
|
|
@@ -54,7 +54,7 @@ var LinkProvider = class LinkProvider {
|
|
|
54
54
|
this.serverLinks.push(link);
|
|
55
55
|
}
|
|
56
56
|
get links() {
|
|
57
|
-
const apiLinks = this.alepha.
|
|
57
|
+
const apiLinks = this.alepha.store.get("alepha.server.request.apiLinks")?.links;
|
|
58
58
|
if (apiLinks) {
|
|
59
59
|
if (this.alepha.isBrowser()) return apiLinks;
|
|
60
60
|
const links = [];
|
|
@@ -74,7 +74,7 @@ var LinkProvider = class LinkProvider {
|
|
|
74
74
|
method: "GET",
|
|
75
75
|
schema: { response: apiLinksResponseSchema }
|
|
76
76
|
});
|
|
77
|
-
this.alepha.
|
|
77
|
+
this.alepha.store.set("alepha.server.request.apiLinks", data);
|
|
78
78
|
return data.links;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
@@ -178,7 +178,7 @@ var LinkProvider = class LinkProvider {
|
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
async getLinkByName(name, options = {}) {
|
|
181
|
-
if (this.alepha.isBrowser() && !this.alepha.
|
|
181
|
+
if (this.alepha.isBrowser() && !this.alepha.store.get("alepha.server.request.apiLinks")) await this.fetchLinks();
|
|
182
182
|
const link = this.links.find((a) => a.name === name && (!options.group || a.group === options.group) && (!options.service || options.service === a.service));
|
|
183
183
|
if (!link) {
|
|
184
184
|
const error = new UnauthorizedError(`Action ${name} not found.`);
|
|
@@ -197,7 +197,7 @@ var LinkProvider = class LinkProvider {
|
|
|
197
197
|
};
|
|
198
198
|
|
|
199
199
|
//#endregion
|
|
200
|
-
//#region src/server-links/
|
|
200
|
+
//#region src/server-links/primitives/$client.ts
|
|
201
201
|
/**
|
|
202
202
|
* Create a new client.
|
|
203
203
|
*/
|
|
@@ -207,9 +207,9 @@ const $client = (scope) => {
|
|
|
207
207
|
$client[KIND] = "$client";
|
|
208
208
|
|
|
209
209
|
//#endregion
|
|
210
|
-
//#region src/server-links/
|
|
210
|
+
//#region src/server-links/primitives/$remote.ts
|
|
211
211
|
/**
|
|
212
|
-
* $remote is a
|
|
212
|
+
* $remote is a primitive that allows you to define remote service access.
|
|
213
213
|
*
|
|
214
214
|
* Use it only when you have 2 or more services that need to communicate with each other.
|
|
215
215
|
*
|
|
@@ -218,23 +218,23 @@ $client[KIND] = "$client";
|
|
|
218
218
|
* You can add a service account if you want to use a security layer.
|
|
219
219
|
*/
|
|
220
220
|
const $remote = (options) => {
|
|
221
|
-
return
|
|
221
|
+
return createPrimitive(RemotePrimitive, options);
|
|
222
222
|
};
|
|
223
|
-
var
|
|
223
|
+
var RemotePrimitive = class extends Primitive {
|
|
224
224
|
get name() {
|
|
225
225
|
return this.options.name ?? this.config.propertyKey;
|
|
226
226
|
}
|
|
227
227
|
};
|
|
228
|
-
$remote[KIND] =
|
|
228
|
+
$remote[KIND] = RemotePrimitive;
|
|
229
229
|
|
|
230
230
|
//#endregion
|
|
231
231
|
//#region src/server-links/index.browser.ts
|
|
232
232
|
const AlephaServerLinks = $module({
|
|
233
233
|
name: "alepha.server.links",
|
|
234
|
-
|
|
234
|
+
primitives: [$remote, $client],
|
|
235
235
|
services: [LinkProvider]
|
|
236
236
|
});
|
|
237
237
|
|
|
238
238
|
//#endregion
|
|
239
|
-
export { $client, $remote, AlephaServerLinks, LinkProvider,
|
|
239
|
+
export { $client, $remote, AlephaServerLinks, LinkProvider, RemotePrimitive, apiLinkSchema, apiLinksResponseSchema };
|
|
240
240
|
//# sourceMappingURL=index.browser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.js","names":["$: VirtualAction<T>"],"sources":["../../src/server-links/schemas/apiLinksResponseSchema.ts","../../src/server-links/providers/LinkProvider.ts","../../src/server-links/descriptors/$client.ts","../../src/server-links/descriptors/$remote.ts","../../src/server-links/index.browser.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const apiLinkSchema = t.object({\n name: t.text({\n description: \"Name of the API link, used for identification.\",\n }),\n\n group: t.optional(\n t.text({\n description:\n \"Group to which the API link belongs, used for categorization.\",\n }),\n ),\n\n path: t.text({\n description: \"Pathname used to access the API link.\",\n }),\n\n method: t.optional(\n t.text({\n description:\n \"HTTP method used for the API link, e.g., GET, POST, etc. If not specified, defaults to GET.\",\n }),\n ),\n\n requestBodyType: t.optional(\n t.text({\n description:\n \"Type of the request body for the API link. Default is application/json for POST/PUT/PATCH, null for others.\",\n }),\n ),\n\n service: t.optional(\n t.text({\n description:\n \"Service name associated with the API link, used for service discovery.\",\n }),\n ),\n});\n\nexport const apiLinksResponseSchema = t.object({\n prefix: t.optional(t.text()),\n links: t.array(apiLinkSchema),\n});\n\nexport type ApiLinksResponse = Static<typeof apiLinksResponseSchema>;\nexport type ApiLink = Static<typeof apiLinkSchema>;\n","import { $inject, Alepha, AlephaError, type Async, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n type ActionDescriptor,\n type ClientRequestEntry,\n type ClientRequestOptions,\n type ClientRequestResponse,\n type FetchResponse,\n HttpClient,\n type RequestConfigSchema,\n ServerReply,\n type ServerRequest,\n type ServerRequestConfigEntry,\n type ServerResponseBody,\n UnauthorizedError,\n} from \"alepha/server\";\nimport type { ServerRouteSecure } from \"alepha/server/security\";\nimport {\n type ApiLink,\n apiLinksResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\n\n/**\n * Browser, SSR friendly, service to handle links.\n */\nexport class LinkProvider {\n static path = {\n apiLinks: \"/api/_links\",\n apiSchema: \"/api/_links/:name/schema\",\n };\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n\n // all server links (local + remote)\n // THIS IS NOT USER LINKS! (which are filtered by permissions)\n protected serverLinks: Array<HttpClientLink> = [];\n\n /**\n * Get applicative links registered on the server.\n * This does not include lazy-loaded remote links.\n */\n public getServerLinks(): HttpClientLink[] {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Getting server links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return [];\n }\n\n return this.serverLinks;\n }\n\n /**\n * Register a new link for the application.\n */\n public registerLink(link: HttpClientLink): void {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Registering links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return;\n }\n\n if (!link.handler && !link.host) {\n throw new AlephaError(\n \"Can't create link - 'handler' or 'host' is required\",\n );\n }\n\n if (this.serverLinks.some((l) => l.name === link.name)) {\n // remove existing link with the same name\n this.serverLinks = this.serverLinks.filter((l) => l.name !== link.name);\n }\n\n this.serverLinks.push(link);\n }\n\n public get links(): HttpClientLink[] {\n // TODO: not performant at all, use a map instead for ServerLinks\n const apiLinks = this.alepha.state.get(\n \"alepha.server.request.apiLinks\",\n )?.links;\n if (apiLinks) {\n if (this.alepha.isBrowser()) {\n return apiLinks;\n }\n\n const links = [];\n for (const link of apiLinks) {\n const originalLink = this.serverLinks.find((l) => l.name === link.name);\n if (originalLink) {\n links.push(originalLink);\n }\n }\n return links;\n }\n\n return this.serverLinks ?? [];\n }\n\n /**\n * Force browser to refresh links from the server.\n */\n public async fetchLinks(): Promise<HttpClientLink[]> {\n const { data } = await this.httpClient.fetch(\n `${LinkProvider.path.apiLinks}`,\n {\n method: \"GET\",\n schema: {\n response: apiLinksResponseSchema,\n },\n },\n );\n\n this.alepha.state.set(\"alepha.server.request.apiLinks\", data);\n\n return data.links;\n }\n\n /**\n * Create a virtual client that can be used to call actions.\n *\n * Use js Proxy under the hood.\n */\n public client<T extends object>(\n scope: ClientScope = {},\n ): HttpVirtualClient<T> {\n return new Proxy<HttpVirtualClient<T>>({} as HttpVirtualClient<T>, {\n get: (_, prop) => {\n if (typeof prop !== \"string\") {\n return;\n }\n\n return this.createVirtualAction<RequestConfigSchema>(prop, scope);\n },\n });\n }\n\n /**\n * Check if a link with the given name exists.\n * @param name\n */\n public can(name: string): boolean {\n return this.links.some((link) => link.name === name);\n }\n\n /**\n * Resolve a link by its name and call it.\n * - If link is local, it will call the local handler.\n * - If link is remote, it will make a fetch request to the remote server.\n */\n public async follow(\n name: string,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions & ClientScope = {},\n ): Promise<any> {\n this.log.trace(\"Following link\", { name, config, options });\n const link = await this.getLinkByName(name, options);\n\n // if a handler is defined, use it (ssr)\n if (link.handler && !options.request) {\n this.log.trace(\"Local link found\", { name });\n return link.handler(\n {\n method: link.method,\n url: new URL(`http://localhost${link.path}`),\n query: config.query ?? {},\n body: config.body ?? {},\n params: config.params ?? {},\n headers: config.headers ?? {},\n metadata: {},\n reply: new ServerReply(),\n } as Partial<ServerRequest> as ServerRequest,\n options,\n );\n }\n\n this.log.trace(\"Remote link found\", {\n name,\n host: link.host,\n service: link.service,\n });\n\n return this.followRemote(link, config, options).then(\n (response) => response.data,\n );\n }\n\n protected createVirtualAction<T extends RequestConfigSchema>(\n name: string,\n scope: ClientScope = {},\n ): VirtualAction<T> {\n const $: VirtualAction<T> = async (\n config: any = {},\n options: ClientRequestOptions = {},\n ) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n Object.defineProperty($, \"name\", {\n value: name,\n writable: false,\n });\n\n $.run = async (config: any = {}, options: ClientRequestOptions = {}) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n $.fetch = async (config: any = {}, options: ClientRequestOptions = {}) => {\n const link = await this.getLinkByName(name, scope);\n return this.followRemote(link, config, options);\n };\n\n $.can = () => {\n return this.can(name);\n };\n\n return $;\n }\n\n protected async followRemote(\n link: HttpClientLink,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions = {},\n ): Promise<FetchResponse> {\n options.request ??= {};\n options.request.headers = new Headers(options.request.headers);\n\n const als = this.alepha.context.get<ServerRequest>(\"request\");\n if (als?.headers.authorization) {\n options.request.headers.set(\"authorization\", als.headers.authorization);\n }\n\n const context = this.alepha.context.get(\"context\");\n if (typeof context === \"string\") {\n options.request.headers.set(\"x-request-id\", context);\n }\n\n const action = {\n ...link,\n // schema is not used in the client,\n // we assume that typescript will check\n schema: {\n body: t.any(),\n response: t.any(),\n },\n };\n\n // prefix with service when host is not defined (e.g. browser)\n if (!link.host && link.service) {\n action.path = `/${link.service}${action.path}`;\n }\n\n action.path = `${action.prefix ?? \"/api\"}${action.path}`;\n action.prefix = undefined; // prefix is not used in the client\n\n // else, make a request\n return this.httpClient.fetchAction({\n host: link.host,\n config,\n options,\n action: action as any, // schema.body TAny is not accepted\n });\n }\n\n protected async getLinkByName(\n name: string,\n options: ClientScope = {},\n ): Promise<HttpClientLink> {\n if (\n this.alepha.isBrowser() &&\n !this.alepha.state.get(\"alepha.server.request.apiLinks\")\n ) {\n await this.fetchLinks();\n }\n\n const link = this.links.find(\n (a) =>\n a.name === name &&\n (!options.group || a.group === options.group) &&\n (!options.service || options.service === a.service),\n );\n\n if (!link) {\n const error = new UnauthorizedError(`Action ${name} not found.`);\n // mimic http error handling\n await this.alepha.events.emit(\"client:onError\", {\n route: link,\n error,\n });\n throw error;\n }\n\n if (options.hostname) {\n return {\n ...link,\n host: options.hostname,\n };\n }\n\n return link;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface HttpClientLink extends ApiLink {\n secured?: boolean | ServerRouteSecure;\n prefix?: string;\n // -- server only --\n // only for remote actions\n host?: string;\n service?: string;\n // used only for local actions, not for remote actions\n schema?: RequestConfigSchema;\n handler?: (\n request: ServerRequest,\n options: ClientRequestOptions,\n ) => Async<ServerResponseBody>;\n}\n\nexport interface ClientScope {\n group?: string;\n service?: string;\n hostname?: string;\n}\n\nexport type HttpVirtualClient<T> = {\n [K in keyof T as T[K] extends ActionDescriptor<RequestConfigSchema>\n ? K\n : never]: T[K] extends ActionDescriptor<infer Schema>\n ? VirtualAction<Schema>\n : never;\n};\n\nexport interface VirtualAction<T extends RequestConfigSchema>\n extends Pick<ActionDescriptor<T>, \"name\" | \"run\" | \"fetch\"> {\n (\n config?: ClientRequestEntry<T>,\n opts?: ClientRequestOptions,\n ): Promise<ClientRequestResponse<T>>;\n can: () => boolean;\n}\n","import { $inject, KIND } from \"alepha\";\nimport {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"../providers/LinkProvider.ts\";\n\n/**\n * Create a new client.\n */\nexport const $client = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n return $inject(LinkProvider).client<T>(scope);\n};\n\n$client[KIND] = \"$client\";\n","import { createDescriptor, Descriptor, KIND } from \"alepha\";\nimport type { ServiceAccountDescriptor } from \"alepha/security\";\nimport type { ProxyDescriptorOptions } from \"alepha/server/proxy\";\n\n/**\n * $remote is a descriptor that allows you to define remote service access.\n *\n * Use it only when you have 2 or more services that need to communicate with each other.\n *\n * All remote services can be exposed as actions, ... or not.\n *\n * You can add a service account if you want to use a security layer.\n */\nexport const $remote = (options: RemoteDescriptorOptions) => {\n return createDescriptor(RemoteDescriptor, options);\n};\n\nexport interface RemoteDescriptorOptions {\n /**\n * The URL of the remote service.\n * You can use a function to generate the URL dynamically.\n * You probably should use $env(env) to get the URL from the environment.\n *\n * @example\n * ```ts\n * import { $remote } from \"alepha/server\";\n * import { $inject, t } from \"alepha\";\n *\n * class App {\n * env = $env(t.object({\n * REMOTE_URL: t.text({default: \"http://localhost:3000\"}),\n * }));\n * remote = $remote({\n * url: this.env.REMOTE_URL,\n * });\n * }\n * ```\n */\n url: string | (() => string);\n\n /**\n * The name of the remote service.\n *\n * @default Member of the class containing the remote service.\n */\n name?: string;\n\n /**\n * If true, all methods of the remote service will be exposed as actions in this context.\n * > Note: Proxy will never use the service account, it just... proxies the request.\n */\n proxy?:\n | boolean\n | Partial<\n ProxyDescriptorOptions & {\n /**\n * If true, the remote service won't be available internally, only through the proxy.\n */\n noInternal: boolean;\n }\n >;\n\n /**\n * For communication between the server and the remote service with a security layer.\n * This will be used for internal communication and will not be exposed to the client.\n */\n serviceAccount?: ServiceAccountDescriptor;\n}\n\nexport class RemoteDescriptor extends Descriptor<RemoteDescriptorOptions> {\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n}\n\n$remote[KIND] = RemoteDescriptor;\n","import { $module } from \"alepha\";\nimport { $client } from \"./descriptors/$client.ts\";\nimport { $remote } from \"./descriptors/$remote.ts\";\nimport { LinkProvider } from \"./providers/LinkProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$client.ts\";\nexport * from \"./descriptors/$remote.ts\";\nexport * from \"./providers/LinkProvider.ts\";\nexport * from \"./schemas/apiLinksResponseSchema.ts\";\n\n// ---------------------------------------------------------------- -----------------------------------------------------\n\nexport const AlephaServerLinks = $module({\n name: \"alepha.server.links\",\n descriptors: [$remote, $client],\n services: [LinkProvider],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.browser.js","names":["$: VirtualAction<T>"],"sources":["../../src/server-links/schemas/apiLinksResponseSchema.ts","../../src/server-links/providers/LinkProvider.ts","../../src/server-links/primitives/$client.ts","../../src/server-links/primitives/$remote.ts","../../src/server-links/index.browser.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const apiLinkSchema = t.object({\n name: t.text({\n description: \"Name of the API link, used for identification.\",\n }),\n\n group: t.optional(\n t.text({\n description:\n \"Group to which the API link belongs, used for categorization.\",\n }),\n ),\n\n path: t.text({\n description: \"Pathname used to access the API link.\",\n }),\n\n method: t.optional(\n t.text({\n description:\n \"HTTP method used for the API link, e.g., GET, POST, etc. If not specified, defaults to GET.\",\n }),\n ),\n\n requestBodyType: t.optional(\n t.text({\n description:\n \"Type of the request body for the API link. Default is application/json for POST/PUT/PATCH, null for others.\",\n }),\n ),\n\n service: t.optional(\n t.text({\n description:\n \"Service name associated with the API link, used for service discovery.\",\n }),\n ),\n});\n\nexport const apiLinksResponseSchema = t.object({\n prefix: t.optional(t.text()),\n links: t.array(apiLinkSchema),\n});\n\nexport type ApiLinksResponse = Static<typeof apiLinksResponseSchema>;\nexport type ApiLink = Static<typeof apiLinkSchema>;\n","import { $inject, Alepha, AlephaError, type Async, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n type ActionPrimitive,\n type ClientRequestEntry,\n type ClientRequestOptions,\n type ClientRequestResponse,\n type FetchResponse,\n HttpClient,\n type RequestConfigSchema,\n ServerReply,\n type ServerRequest,\n type ServerRequestConfigEntry,\n type ServerResponseBody,\n UnauthorizedError,\n} from \"alepha/server\";\nimport type { ServerRouteSecure } from \"alepha/server/security\";\nimport {\n type ApiLink,\n apiLinksResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\n\n/**\n * Browser, SSR friendly, service to handle links.\n */\nexport class LinkProvider {\n static path = {\n apiLinks: \"/api/_links\",\n apiSchema: \"/api/_links/:name/schema\",\n };\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n\n // all server links (local + remote)\n // THIS IS NOT USER LINKS! (which are filtered by permissions)\n protected serverLinks: Array<HttpClientLink> = [];\n\n /**\n * Get applicative links registered on the server.\n * This does not include lazy-loaded remote links.\n */\n public getServerLinks(): HttpClientLink[] {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Getting server links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return [];\n }\n\n return this.serverLinks;\n }\n\n /**\n * Register a new link for the application.\n */\n public registerLink(link: HttpClientLink): void {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Registering links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return;\n }\n\n if (!link.handler && !link.host) {\n throw new AlephaError(\n \"Can't create link - 'handler' or 'host' is required\",\n );\n }\n\n if (this.serverLinks.some((l) => l.name === link.name)) {\n // remove existing link with the same name\n this.serverLinks = this.serverLinks.filter((l) => l.name !== link.name);\n }\n\n this.serverLinks.push(link);\n }\n\n public get links(): HttpClientLink[] {\n // TODO: not performant at all, use a map instead for ServerLinks\n const apiLinks = this.alepha.store.get(\n \"alepha.server.request.apiLinks\",\n )?.links;\n if (apiLinks) {\n if (this.alepha.isBrowser()) {\n return apiLinks;\n }\n\n const links = [];\n for (const link of apiLinks) {\n const originalLink = this.serverLinks.find((l) => l.name === link.name);\n if (originalLink) {\n links.push(originalLink);\n }\n }\n return links;\n }\n\n return this.serverLinks ?? [];\n }\n\n /**\n * Force browser to refresh links from the server.\n */\n public async fetchLinks(): Promise<HttpClientLink[]> {\n const { data } = await this.httpClient.fetch(\n `${LinkProvider.path.apiLinks}`,\n {\n method: \"GET\",\n schema: {\n response: apiLinksResponseSchema,\n },\n },\n );\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data);\n\n return data.links;\n }\n\n /**\n * Create a virtual client that can be used to call actions.\n *\n * Use js Proxy under the hood.\n */\n public client<T extends object>(\n scope: ClientScope = {},\n ): HttpVirtualClient<T> {\n return new Proxy<HttpVirtualClient<T>>({} as HttpVirtualClient<T>, {\n get: (_, prop) => {\n if (typeof prop !== \"string\") {\n return;\n }\n\n return this.createVirtualAction<RequestConfigSchema>(prop, scope);\n },\n });\n }\n\n /**\n * Check if a link with the given name exists.\n * @param name\n */\n public can(name: string): boolean {\n return this.links.some((link) => link.name === name);\n }\n\n /**\n * Resolve a link by its name and call it.\n * - If link is local, it will call the local handler.\n * - If link is remote, it will make a fetch request to the remote server.\n */\n public async follow(\n name: string,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions & ClientScope = {},\n ): Promise<any> {\n this.log.trace(\"Following link\", { name, config, options });\n const link = await this.getLinkByName(name, options);\n\n // if a handler is defined, use it (ssr)\n if (link.handler && !options.request) {\n this.log.trace(\"Local link found\", { name });\n return link.handler(\n {\n method: link.method,\n url: new URL(`http://localhost${link.path}`),\n query: config.query ?? {},\n body: config.body ?? {},\n params: config.params ?? {},\n headers: config.headers ?? {},\n metadata: {},\n reply: new ServerReply(),\n } as Partial<ServerRequest> as ServerRequest,\n options,\n );\n }\n\n this.log.trace(\"Remote link found\", {\n name,\n host: link.host,\n service: link.service,\n });\n\n return this.followRemote(link, config, options).then(\n (response) => response.data,\n );\n }\n\n protected createVirtualAction<T extends RequestConfigSchema>(\n name: string,\n scope: ClientScope = {},\n ): VirtualAction<T> {\n const $: VirtualAction<T> = async (\n config: any = {},\n options: ClientRequestOptions = {},\n ) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n Object.defineProperty($, \"name\", {\n value: name,\n writable: false,\n });\n\n $.run = async (config: any = {}, options: ClientRequestOptions = {}) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n $.fetch = async (config: any = {}, options: ClientRequestOptions = {}) => {\n const link = await this.getLinkByName(name, scope);\n return this.followRemote(link, config, options);\n };\n\n $.can = () => {\n return this.can(name);\n };\n\n return $;\n }\n\n protected async followRemote(\n link: HttpClientLink,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions = {},\n ): Promise<FetchResponse> {\n options.request ??= {};\n options.request.headers = new Headers(options.request.headers);\n\n const als = this.alepha.context.get<ServerRequest>(\"request\");\n if (als?.headers.authorization) {\n options.request.headers.set(\"authorization\", als.headers.authorization);\n }\n\n const context = this.alepha.context.get(\"context\");\n if (typeof context === \"string\") {\n options.request.headers.set(\"x-request-id\", context);\n }\n\n const action = {\n ...link,\n // schema is not used in the client,\n // we assume that typescript will check\n schema: {\n body: t.any(),\n response: t.any(),\n },\n };\n\n // prefix with service when host is not defined (e.g. browser)\n if (!link.host && link.service) {\n action.path = `/${link.service}${action.path}`;\n }\n\n action.path = `${action.prefix ?? \"/api\"}${action.path}`;\n action.prefix = undefined; // prefix is not used in the client\n\n // else, make a request\n return this.httpClient.fetchAction({\n host: link.host,\n config,\n options,\n action: action as any, // schema.body TAny is not accepted\n });\n }\n\n protected async getLinkByName(\n name: string,\n options: ClientScope = {},\n ): Promise<HttpClientLink> {\n if (\n this.alepha.isBrowser() &&\n !this.alepha.store.get(\"alepha.server.request.apiLinks\")\n ) {\n await this.fetchLinks();\n }\n\n const link = this.links.find(\n (a) =>\n a.name === name &&\n (!options.group || a.group === options.group) &&\n (!options.service || options.service === a.service),\n );\n\n if (!link) {\n const error = new UnauthorizedError(`Action ${name} not found.`);\n // mimic http error handling\n await this.alepha.events.emit(\"client:onError\", {\n route: link,\n error,\n });\n throw error;\n }\n\n if (options.hostname) {\n return {\n ...link,\n host: options.hostname,\n };\n }\n\n return link;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface HttpClientLink extends ApiLink {\n secured?: boolean | ServerRouteSecure;\n prefix?: string;\n // -- server only --\n // only for remote actions\n host?: string;\n service?: string;\n // used only for local actions, not for remote actions\n schema?: RequestConfigSchema;\n handler?: (\n request: ServerRequest,\n options: ClientRequestOptions,\n ) => Async<ServerResponseBody>;\n}\n\nexport interface ClientScope {\n group?: string;\n service?: string;\n hostname?: string;\n}\n\nexport type HttpVirtualClient<T> = {\n [K in keyof T as T[K] extends ActionPrimitive<RequestConfigSchema>\n ? K\n : never]: T[K] extends ActionPrimitive<infer Schema>\n ? VirtualAction<Schema>\n : never;\n};\n\nexport interface VirtualAction<T extends RequestConfigSchema>\n extends Pick<ActionPrimitive<T>, \"name\" | \"run\" | \"fetch\"> {\n (\n config?: ClientRequestEntry<T>,\n opts?: ClientRequestOptions,\n ): Promise<ClientRequestResponse<T>>;\n can: () => boolean;\n}\n","import { $inject, KIND } from \"alepha\";\nimport {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"../providers/LinkProvider.ts\";\n\n/**\n * Create a new client.\n */\nexport const $client = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n return $inject(LinkProvider).client<T>(scope);\n};\n\n$client[KIND] = \"$client\";\n","import { createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { ServiceAccountPrimitive } from \"alepha/security\";\nimport type { ProxyPrimitiveOptions } from \"alepha/server/proxy\";\n\n/**\n * $remote is a primitive that allows you to define remote service access.\n *\n * Use it only when you have 2 or more services that need to communicate with each other.\n *\n * All remote services can be exposed as actions, ... or not.\n *\n * You can add a service account if you want to use a security layer.\n */\nexport const $remote = (options: RemotePrimitiveOptions) => {\n return createPrimitive(RemotePrimitive, options);\n};\n\nexport interface RemotePrimitiveOptions {\n /**\n * The URL of the remote service.\n * You can use a function to generate the URL dynamically.\n * You probably should use $env(env) to get the URL from the environment.\n *\n * @example\n * ```ts\n * import { $remote } from \"alepha/server\";\n * import { $inject, t } from \"alepha\";\n *\n * class App {\n * env = $env(t.object({\n * REMOTE_URL: t.text({default: \"http://localhost:3000\"}),\n * }));\n * remote = $remote({\n * url: this.env.REMOTE_URL,\n * });\n * }\n * ```\n */\n url: string | (() => string);\n\n /**\n * The name of the remote service.\n *\n * @default Member of the class containing the remote service.\n */\n name?: string;\n\n /**\n * If true, all methods of the remote service will be exposed as actions in this context.\n * > Note: Proxy will never use the service account, it just... proxies the request.\n */\n proxy?:\n | boolean\n | Partial<\n ProxyPrimitiveOptions & {\n /**\n * If true, the remote service won't be available internally, only through the proxy.\n */\n noInternal: boolean;\n }\n >;\n\n /**\n * For communication between the server and the remote service with a security layer.\n * This will be used for internal communication and will not be exposed to the client.\n */\n serviceAccount?: ServiceAccountPrimitive;\n}\n\nexport class RemotePrimitive extends Primitive<RemotePrimitiveOptions> {\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n}\n\n$remote[KIND] = RemotePrimitive;\n","import { $module } from \"alepha\";\nimport { $client } from \"./primitives/$client.ts\";\nimport { $remote } from \"./primitives/$remote.ts\";\nimport { LinkProvider } from \"./providers/LinkProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$client.ts\";\nexport * from \"./primitives/$remote.ts\";\nexport * from \"./providers/LinkProvider.ts\";\nexport * from \"./schemas/apiLinksResponseSchema.ts\";\n\n// ---------------------------------------------------------------- -----------------------------------------------------\n\nexport const AlephaServerLinks = $module({\n name: \"alepha.server.links\",\n primitives: [$remote, $client],\n services: [LinkProvider],\n});\n"],"mappings":"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"}
|