alepha 0.15.3 → 0.15.5
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 +26 -11
- package/dist/api/audits/index.d.ts +335 -335
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +11 -3
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +3 -3
- package/dist/api/files/index.js +4 -3
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +198 -155
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +103 -5
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +198 -198
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/keys/index.js +3 -3
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js +1 -0
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +3 -3
- package/dist/api/notifications/index.js +4 -3
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +263 -263
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +41 -30
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.d.ts +383 -77
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +284 -72
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +131 -131
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +3 -3
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +3 -3
- package/dist/batch/index.js +3 -3
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +3 -3
- package/dist/bucket/index.js +6 -6
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +3 -3
- package/dist/cache/core/index.js +3 -3
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cli/index.d.ts +5612 -20
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +122 -91
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +11 -4
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +8 -6
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +4 -8
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +3 -3
- package/dist/datetime/index.js +3 -3
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +16 -16
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +10562 -10
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +3 -3
- package/dist/fake/index.js +3 -3
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +9 -4
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +12 -4
- package/dist/lock/core/index.js.map +1 -1
- package/dist/logger/index.d.ts +3 -3
- package/dist/logger/index.js +6 -3
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +3 -3
- package/dist/mcp/index.js +3 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.d.ts +12 -12
- package/dist/orm/index.js +4 -4
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +3 -3
- package/dist/queue/core/index.js +3 -3
- package/dist/queue/core/index.js.map +1 -1
- package/dist/react/auth/index.browser.js +2 -1
- package/dist/react/auth/index.browser.js.map +1 -1
- package/dist/react/auth/index.d.ts +3 -3
- package/dist/react/auth/index.js +5 -4
- package/dist/react/auth/index.js.map +1 -1
- package/dist/react/core/index.d.ts +6 -6
- package/dist/react/core/index.js +3 -3
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +3 -3
- package/dist/react/form/index.js +3 -3
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.d.ts +3 -3
- package/dist/react/head/index.js +3 -3
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +3 -3
- package/dist/react/i18n/index.js +3 -3
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.css +337 -0
- package/dist/react/intro/index.css.map +1 -0
- package/dist/react/intro/index.d.ts +10 -0
- package/dist/react/intro/index.d.ts.map +1 -0
- package/dist/react/intro/index.js +222 -0
- package/dist/react/intro/index.js.map +1 -0
- package/dist/react/router/index.browser.js +2 -2
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +11 -1
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +21 -11
- package/dist/react/router/index.js.map +1 -1
- package/dist/redis/index.d.ts +22 -22
- package/dist/redis/index.js +3 -3
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +3 -3
- package/dist/retry/index.js +3 -3
- package/dist/retry/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +16 -4
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +45 -7
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +3 -3
- package/dist/security/index.js +5 -5
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +3 -3
- package/dist/server/auth/index.js +3 -3
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +3 -3
- package/dist/server/cache/index.js +3 -3
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +3 -3
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +4 -3
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +3 -3
- package/dist/server/cookies/index.js +3 -3
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +14 -25
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +13 -29
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +3 -3
- package/dist/server/cors/index.js +3 -3
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/health/index.d.ts +20 -20
- package/dist/server/health/index.js +3 -3
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/helmet/index.d.ts +3 -3
- package/dist/server/helmet/index.js +3 -3
- package/dist/server/helmet/index.js.map +1 -1
- package/dist/server/links/index.d.ts +42 -42
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +4 -4
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +3 -3
- package/dist/server/metrics/index.js +3 -3
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts +3 -3
- package/dist/server/multipart/index.js +3 -3
- package/dist/server/multipart/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +3 -3
- package/dist/server/proxy/index.js +3 -3
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +3 -3
- package/dist/server/rate-limit/index.js +3 -3
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +3 -3
- package/dist/server/static/index.js +6 -6
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +3 -3
- package/dist/server/swagger/index.js +6 -6
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +3 -3
- package/dist/sms/index.js +6 -6
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.d.ts +3 -3
- package/dist/system/index.js +3 -3
- package/dist/system/index.js.map +1 -1
- package/dist/thread/index.d.ts +3 -3
- package/dist/thread/index.js +3 -3
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts +3 -3
- package/dist/topic/core/index.js +3 -3
- package/dist/topic/core/index.js.map +1 -1
- package/dist/vite/index.d.ts +6286 -4
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +28 -2
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +37 -37
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +3 -3
- package/dist/websocket/index.js.map +1 -1
- package/package.json +12 -4
- package/src/api/audits/controllers/AdminAuditController.ts +8 -0
- package/src/api/audits/index.ts +3 -3
- package/src/api/files/controllers/AdminFileStatsController.ts +1 -0
- package/src/api/files/index.ts +3 -3
- package/src/api/jobs/controllers/AdminJobController.ts +18 -2
- package/src/api/jobs/index.ts +4 -3
- package/src/api/jobs/services/JobAudits.spec.ts +89 -0
- package/src/api/jobs/services/JobAudits.ts +101 -0
- package/src/api/keys/index.ts +3 -3
- package/src/api/notifications/controllers/AdminNotificationController.ts +1 -0
- package/src/api/notifications/index.ts +3 -3
- package/src/api/parameters/controllers/AdminConfigController.ts +10 -0
- package/src/api/parameters/index.ts +5 -3
- package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1 -1
- package/src/api/users/__tests__/ApiKeys.spec.ts +1 -1
- package/src/api/users/__tests__/EmailVerification.spec.ts +16 -1
- package/src/api/users/__tests__/PasswordReset.spec.ts +11 -0
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -0
- package/src/api/users/controllers/AdminIdentityController.ts +3 -0
- package/src/api/users/controllers/AdminSessionController.ts +3 -0
- package/src/api/users/controllers/AdminUserController.ts +5 -0
- package/src/api/users/index.ts +8 -9
- package/src/api/users/primitives/$realm.ts +117 -19
- package/src/api/users/providers/RealmProvider.ts +15 -7
- package/src/api/users/services/CredentialService.spec.ts +11 -0
- package/src/api/users/services/CredentialService.ts +47 -24
- package/src/api/users/services/IdentityService.ts +12 -4
- package/src/api/users/services/RegistrationService.spec.ts +11 -0
- package/src/api/users/services/RegistrationService.ts +33 -12
- package/src/api/users/services/SessionService.ts +83 -12
- package/src/api/users/services/UserAudits.ts +47 -0
- package/src/api/users/services/UserFiles.ts +19 -0
- package/src/api/users/services/UserJobs.spec.ts +107 -0
- package/src/api/users/services/UserJobs.ts +62 -0
- package/src/api/users/services/UserParameters.ts +23 -0
- package/src/api/users/services/UserService.ts +34 -17
- package/src/api/verifications/index.ts +3 -3
- package/src/batch/index.ts +3 -3
- package/src/bucket/index.ts +3 -3
- package/src/cache/core/index.ts +3 -3
- package/src/cli/commands/build.ts +1 -0
- package/src/cli/commands/db.ts +9 -0
- package/src/cli/commands/init.spec.ts +2 -17
- package/src/cli/commands/init.ts +37 -1
- package/src/cli/providers/ViteDevServerProvider.ts +36 -2
- package/src/cli/services/AlephaCliUtils.ts +17 -0
- package/src/cli/services/PackageManagerUtils.ts +15 -1
- package/src/cli/services/ProjectScaffolder.ts +8 -13
- package/src/cli/templates/agentMd.ts +2 -25
- package/src/cli/templates/apiAppSecurityTs.ts +37 -2
- package/src/cli/templates/mainCss.ts +2 -32
- package/src/cli/templates/webAppRouterTs.ts +5 -5
- package/src/cli/templates/webHomeComponentTsx.ts +10 -0
- package/src/command/helpers/Runner.ts +14 -1
- package/src/command/index.ts +3 -3
- package/src/core/helpers/primitive.ts +0 -5
- package/src/core/index.ts +3 -3
- package/src/datetime/index.ts +3 -3
- package/src/email/index.ts +3 -3
- package/src/email/index.workerd.ts +36 -0
- package/src/email/providers/LocalEmailProvider.ts +2 -2
- package/src/email/providers/WorkermailerEmailProvider.ts +221 -0
- package/src/fake/index.ts +3 -3
- package/src/lock/core/index.ts +3 -3
- package/src/lock/core/primitives/$lock.ts +13 -1
- package/src/logger/index.ts +3 -3
- package/src/logger/providers/PrettyFormatterProvider.ts +7 -0
- package/src/mcp/index.ts +3 -3
- package/src/orm/index.ts +3 -3
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
- package/src/queue/core/index.ts +3 -3
- package/src/react/auth/index.ts +3 -3
- package/src/react/auth/services/ReactAuth.ts +3 -1
- package/src/react/core/index.ts +3 -3
- package/src/react/form/index.ts +3 -3
- package/src/react/head/index.ts +3 -3
- package/src/react/i18n/index.ts +3 -3
- package/src/react/intro/components/GettingStarted.css +334 -0
- package/src/react/intro/components/GettingStarted.tsx +276 -0
- package/src/react/intro/index.ts +1 -0
- package/src/react/router/atoms/ssrManifestAtom.ts +7 -0
- package/src/react/router/index.browser.ts +2 -0
- package/src/react/router/index.ts +2 -0
- package/src/react/router/providers/ReactServerProvider.ts +14 -4
- package/src/react/router/providers/SSRManifestProvider.ts +7 -0
- package/src/redis/index.ts +3 -3
- package/src/retry/index.ts +3 -3
- package/src/router/index.ts +3 -3
- package/src/scheduler/index.ts +3 -3
- package/src/scheduler/index.workerd.ts +43 -0
- package/src/scheduler/providers/CronProvider.ts +53 -6
- package/src/scheduler/providers/WorkerdCronProvider.ts +102 -0
- package/src/security/index.ts +3 -3
- package/src/security/providers/JwtProvider.ts +2 -2
- package/src/server/auth/index.ts +3 -3
- package/src/server/cache/index.ts +3 -3
- package/src/server/compress/index.ts +3 -3
- package/src/server/compress/providers/ServerCompressProvider.ts +6 -0
- package/src/server/cookies/index.ts +3 -3
- package/src/server/core/index.ts +3 -3
- package/src/server/core/primitives/$action.spec.ts +3 -2
- package/src/server/core/primitives/$action.ts +6 -2
- package/src/server/core/providers/NodeHttpServerProvider.ts +2 -15
- package/src/server/core/providers/ServerProvider.ts +4 -2
- package/src/server/core/providers/ServerRouterProvider.ts +5 -27
- package/src/server/cors/index.ts +3 -3
- package/src/server/health/index.ts +3 -3
- package/src/server/helmet/index.ts +3 -3
- package/src/server/links/index.ts +3 -3
- package/src/server/links/providers/ServerLinksProvider.spec.ts +332 -0
- package/src/server/links/providers/ServerLinksProvider.ts +1 -1
- package/src/server/metrics/index.ts +3 -3
- package/src/server/multipart/index.ts +3 -3
- package/src/server/proxy/index.ts +3 -3
- package/src/server/rate-limit/index.ts +3 -3
- package/src/server/static/index.ts +3 -3
- package/src/server/swagger/index.ts +3 -3
- package/src/sms/index.ts +3 -3
- package/src/system/index.ts +3 -3
- package/src/thread/index.ts +3 -3
- package/src/topic/core/index.ts +3 -3
- package/src/vite/tasks/generateCloudflare.ts +38 -2
- package/src/websocket/index.ts +3 -3
- package/src/cli/templates/webHelloComponentTsx.ts +0 -30
- /package/src/api/users/{notifications → services}/UserNotifications.ts +0 -0
package/src/redis/index.ts
CHANGED
|
@@ -18,9 +18,9 @@ export * from "./providers/RedisSubscriberProvider.ts";
|
|
|
18
18
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* |
|
|
22
|
-
*
|
|
23
|
-
* |
|
|
21
|
+
* | Stability | Since | Runtime |
|
|
22
|
+
* |-----------|-------|---------|
|
|
23
|
+
* | 3 - stable | 0.1.0 | node, bun|
|
|
24
24
|
*
|
|
25
25
|
* Redis client wrapper.
|
|
26
26
|
*
|
package/src/retry/index.ts
CHANGED
|
@@ -12,9 +12,9 @@ export * from "./providers/RetryProvider.ts";
|
|
|
12
12
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* |
|
|
16
|
-
*
|
|
17
|
-
* |
|
|
15
|
+
* | Stability | Since | Runtime |
|
|
16
|
+
* |-----------|-------|---------|
|
|
17
|
+
* | 3 - stable | 0.12.0 | node, bun, workerd, browser, expo|
|
|
18
18
|
*
|
|
19
19
|
* Automatic retry with backoff.
|
|
20
20
|
*
|
package/src/router/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* |
|
|
3
|
-
*
|
|
4
|
-
* |
|
|
2
|
+
* | Stability | Since | Runtime |
|
|
3
|
+
* |-----------|-------|---------|
|
|
4
|
+
* | 3 - stable | 0.2.0 | node, bun, workerd, browser, expo|
|
|
5
5
|
*
|
|
6
6
|
* Frontend routing infrastructure.
|
|
7
7
|
*
|
package/src/scheduler/index.ts
CHANGED
|
@@ -35,9 +35,9 @@ declare module "alepha" {
|
|
|
35
35
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* |
|
|
39
|
-
*
|
|
40
|
-
* |
|
|
38
|
+
* | Stability | Since | Runtime |
|
|
39
|
+
* |-----------|-------|---------|
|
|
40
|
+
* | 3 - stable | 0.1.0 | node, bun, workerd|
|
|
41
41
|
*
|
|
42
42
|
* Cron and interval-based task execution.
|
|
43
43
|
*
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { $module } from "alepha";
|
|
2
|
+
import { AlephaLock } from "alepha/lock";
|
|
3
|
+
import { $scheduler } from "./primitives/$scheduler.ts";
|
|
4
|
+
import { CronProvider } from "./providers/CronProvider.ts";
|
|
5
|
+
import { WorkerdCronProvider } from "./providers/WorkerdCronProvider.ts";
|
|
6
|
+
|
|
7
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
export * from "./constants/CRON.ts";
|
|
10
|
+
export * from "./primitives/$scheduler.ts";
|
|
11
|
+
export * from "./providers/CronProvider.ts";
|
|
12
|
+
export * from "./providers/WorkerdCronProvider.ts";
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
declare module "alepha" {
|
|
17
|
+
interface Hooks {
|
|
18
|
+
/**
|
|
19
|
+
* Cloudflare Workers scheduled event.
|
|
20
|
+
*
|
|
21
|
+
* Emitted when a cron trigger fires in Cloudflare Workers.
|
|
22
|
+
*/
|
|
23
|
+
"cloudflare:scheduled": {
|
|
24
|
+
cron: string;
|
|
25
|
+
scheduledTime: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
export const AlephaScheduler = $module({
|
|
33
|
+
name: "alepha.scheduler",
|
|
34
|
+
primitives: [$scheduler],
|
|
35
|
+
services: [AlephaLock, CronProvider, WorkerdCronProvider],
|
|
36
|
+
register: (alepha) => {
|
|
37
|
+
// Replace CronProvider with WorkerdCronProvider for Cloudflare Workers
|
|
38
|
+
alepha.with({
|
|
39
|
+
provide: CronProvider,
|
|
40
|
+
use: WorkerdCronProvider,
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -16,6 +16,11 @@ export class CronProvider {
|
|
|
16
16
|
protected readonly start = $hook({
|
|
17
17
|
on: "start",
|
|
18
18
|
handler: () => {
|
|
19
|
+
if (this.alepha.isServerless()) {
|
|
20
|
+
this.log.info("Ignoring cron jobs in serverless environment");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
for (const cron of this.cronJobs) {
|
|
20
25
|
if (!cron.running) {
|
|
21
26
|
cron.running = true;
|
|
@@ -62,12 +67,12 @@ export class CronProvider {
|
|
|
62
67
|
? this.cronJobs.find((c) => c.name === name)
|
|
63
68
|
: name;
|
|
64
69
|
|
|
65
|
-
if (!cron) {
|
|
70
|
+
if (!cron || !cron.running) {
|
|
66
71
|
return;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
cron.running = false;
|
|
70
|
-
cron.abort
|
|
75
|
+
cron.abort?.abort();
|
|
71
76
|
this.log.debug(`Cron task '${cron.name}' stopped`);
|
|
72
77
|
}
|
|
73
78
|
|
|
@@ -109,13 +114,13 @@ export class CronProvider {
|
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
const duration = next.getTime() - now.toDate().getTime();
|
|
112
|
-
|
|
113
|
-
task.abort =
|
|
117
|
+
const abort = new AbortController();
|
|
118
|
+
task.abort = abort;
|
|
114
119
|
|
|
115
120
|
this.dt
|
|
116
121
|
.wait(duration, {
|
|
117
122
|
now: now.valueOf(),
|
|
118
|
-
signal:
|
|
123
|
+
signal: abort.signal,
|
|
119
124
|
})
|
|
120
125
|
.then(() => {
|
|
121
126
|
if (!task.running) {
|
|
@@ -141,6 +146,48 @@ export class CronProvider {
|
|
|
141
146
|
this.log.warn("Issue during cron waiting timer", err as Error);
|
|
142
147
|
});
|
|
143
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Trigger a specific cron job by name.
|
|
152
|
+
*/
|
|
153
|
+
public async trigger(name: string): Promise<void> {
|
|
154
|
+
const job = this.cronJobs.find((j) => j.name === name);
|
|
155
|
+
if (!job) {
|
|
156
|
+
this.log.warn(`Cron job '${name}' not found`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
await this.runJobs([job], this.dt.now());
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Trigger all registered cron jobs.
|
|
164
|
+
*/
|
|
165
|
+
public async triggerAll(): Promise<void> {
|
|
166
|
+
await this.runJobs(this.cronJobs, this.dt.now());
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Run multiple cron jobs in parallel.
|
|
171
|
+
*/
|
|
172
|
+
protected async runJobs(jobs: CronJob[], now: DateTime): Promise<void> {
|
|
173
|
+
const results = await Promise.allSettled(
|
|
174
|
+
jobs.map(async (job) => {
|
|
175
|
+
this.log.debug(`Running cron job '${job.name}'`);
|
|
176
|
+
try {
|
|
177
|
+
await job.handler({ now });
|
|
178
|
+
this.log.debug(`Cron job '${job.name}' completed`);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
this.log.error(`Cron job '${job.name}' failed`, error);
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const failures = results.filter((r) => r.status === "rejected");
|
|
187
|
+
if (failures.length > 0) {
|
|
188
|
+
this.log.error(`${failures.length}/${jobs.length} cron jobs failed`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
144
191
|
}
|
|
145
192
|
|
|
146
193
|
export interface CronJob {
|
|
@@ -151,5 +198,5 @@ export interface CronJob {
|
|
|
151
198
|
loop: boolean;
|
|
152
199
|
running?: boolean;
|
|
153
200
|
onError?: (error: Error) => void;
|
|
154
|
-
abort
|
|
201
|
+
abort?: AbortController;
|
|
155
202
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { $hook } from "alepha";
|
|
2
|
+
import type { DateTime } from "alepha/datetime";
|
|
3
|
+
import { parseCronExpression } from "cron-schedule";
|
|
4
|
+
import { CronProvider } from "./CronProvider.ts";
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
declare module "alepha" {
|
|
9
|
+
interface Hooks {
|
|
10
|
+
/**
|
|
11
|
+
* Cloudflare Workers scheduled event.
|
|
12
|
+
*
|
|
13
|
+
* Emitted when a cron trigger fires in Cloudflare Workers.
|
|
14
|
+
*/
|
|
15
|
+
"cloudflare:scheduled": {
|
|
16
|
+
cron: string;
|
|
17
|
+
scheduledTime: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Cloudflare Workers cron provider.
|
|
26
|
+
*
|
|
27
|
+
* This provider handles scheduled events from Cloudflare Workers Cron Triggers.
|
|
28
|
+
* Unlike the Node.js CronProvider, this doesn't use intervals/timeouts - instead,
|
|
29
|
+
* it reacts to scheduled events triggered by Cloudflare.
|
|
30
|
+
*
|
|
31
|
+
* **Usage:**
|
|
32
|
+
* 1. Define schedulers with `$scheduler({ cron: "0 * * * *", handler: ... })`
|
|
33
|
+
* 2. Build your app with `alepha build` - cron triggers are automatically added to `wrangler.jsonc`
|
|
34
|
+
* 3. Deploy to Cloudflare Workers
|
|
35
|
+
*
|
|
36
|
+
* **How it works:**
|
|
37
|
+
* - During build, all registered `$scheduler` cron expressions are collected
|
|
38
|
+
* - The build generates `wrangler.jsonc` with `triggers.crons` automatically filled
|
|
39
|
+
* - When Cloudflare fires a cron trigger, the `scheduled` handler emits `cloudflare:scheduled`
|
|
40
|
+
* - This provider listens to that event and runs matching schedulers
|
|
41
|
+
*
|
|
42
|
+
* @see https://developers.cloudflare.com/workers/configuration/cron-triggers/
|
|
43
|
+
*/
|
|
44
|
+
export class WorkerdCronProvider extends CronProvider {
|
|
45
|
+
/**
|
|
46
|
+
* Override to avoid creating AbortController in global scope.
|
|
47
|
+
* Cloudflare Workers doesn't allow this during initialization.
|
|
48
|
+
*/
|
|
49
|
+
public override createCronJob(
|
|
50
|
+
name: string,
|
|
51
|
+
expression: string,
|
|
52
|
+
handler: (context: { now: DateTime }) => Promise<void>,
|
|
53
|
+
): void {
|
|
54
|
+
this.cronJobs.push({
|
|
55
|
+
name,
|
|
56
|
+
cron: parseCronExpression(expression),
|
|
57
|
+
expression,
|
|
58
|
+
handler,
|
|
59
|
+
loop: false,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Handle a scheduled event from Cloudflare Workers.
|
|
65
|
+
*/
|
|
66
|
+
protected readonly onScheduledEvent = $hook({
|
|
67
|
+
on: "cloudflare:scheduled",
|
|
68
|
+
handler: async (event) => {
|
|
69
|
+
const now = this.dt.of(event.scheduledTime);
|
|
70
|
+
|
|
71
|
+
this.log.info("Received scheduled event", {
|
|
72
|
+
cron: event.cron,
|
|
73
|
+
scheduledTime: now.format(),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Find jobs that match this cron expression
|
|
77
|
+
const matchingJobs = this.cronJobs.filter(
|
|
78
|
+
(job) => job.expression === event.cron,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (matchingJobs.length === 0) {
|
|
82
|
+
// No exact match - try to find jobs that would fire at this time
|
|
83
|
+
const matchingByTime = this.cronJobs.filter((job) =>
|
|
84
|
+
job.cron.matchDate(now.toDate()),
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
if (matchingByTime.length > 0) {
|
|
88
|
+
this.log.debug(
|
|
89
|
+
`No exact cron match for '${event.cron}', found ${matchingByTime.length} jobs matching by time`,
|
|
90
|
+
);
|
|
91
|
+
await this.runJobs(matchingByTime, now);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.log.warn(`No cron jobs found for expression '${event.cron}'`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await this.runJobs(matchingJobs, now);
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
package/src/security/index.ts
CHANGED
|
@@ -89,9 +89,9 @@ declare module "alepha/server" {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
* |
|
|
93
|
-
*
|
|
94
|
-
* |
|
|
92
|
+
* | Stability | Since | Runtime |
|
|
93
|
+
* |-----------|-------|---------|
|
|
94
|
+
* | 3 - stable | 0.1.0 | node, bun, workerd, browser|
|
|
95
95
|
*
|
|
96
96
|
* Complete authentication and authorization system with JWT, RBAC, and multi-issuer support.
|
|
97
97
|
*
|
|
@@ -47,7 +47,7 @@ export class JwtProvider {
|
|
|
47
47
|
} else if (this.isSecretKey(secretKeyOrJwks)) {
|
|
48
48
|
const secretKey = this.encoder.encode(secretKeyOrJwks);
|
|
49
49
|
this.log.info(
|
|
50
|
-
`will verify JWTs from '${name}' with secret
|
|
50
|
+
`will verify JWTs from issuer '${name}' with secret key (${secretKey.length} bytes)`,
|
|
51
51
|
);
|
|
52
52
|
this.keystore.push({
|
|
53
53
|
name,
|
|
@@ -56,7 +56,7 @@ export class JwtProvider {
|
|
|
56
56
|
});
|
|
57
57
|
} else {
|
|
58
58
|
this.log.info(
|
|
59
|
-
`will verify JWTs from '${name}' with JWKS ${secretKeyOrJwks}`,
|
|
59
|
+
`will verify JWTs from issuer '${name}' with JWKS ${secretKeyOrJwks}`,
|
|
60
60
|
);
|
|
61
61
|
this.keystore.push({
|
|
62
62
|
name,
|
package/src/server/auth/index.ts
CHANGED
|
@@ -29,9 +29,9 @@ declare module "alepha" {
|
|
|
29
29
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* |
|
|
33
|
-
*
|
|
34
|
-
* |
|
|
32
|
+
* | Stability | Since | Runtime |
|
|
33
|
+
* |-----------|-------|---------|
|
|
34
|
+
* | 3 - stable | 0.8.0 | node, bun, workerd|
|
|
35
35
|
*
|
|
36
36
|
* OAuth2/OIDC authentication with social login providers.
|
|
37
37
|
*
|
|
@@ -9,9 +9,9 @@ export * from "./providers/ServerCacheProvider.ts";
|
|
|
9
9
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* |
|
|
13
|
-
*
|
|
14
|
-
* |
|
|
12
|
+
* | Stability | Since | Runtime |
|
|
13
|
+
* |-----------|-------|---------|
|
|
14
|
+
* | 3 - stable | 0.10.0 | node, bun, workerd|
|
|
15
15
|
*
|
|
16
16
|
* ETag-based response caching.
|
|
17
17
|
*
|
|
@@ -9,9 +9,9 @@ export * from "./providers/ServerCompressProvider.ts";
|
|
|
9
9
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* |
|
|
13
|
-
*
|
|
14
|
-
* |
|
|
12
|
+
* | Stability | Since | Runtime |
|
|
13
|
+
* |-----------|-------|---------|
|
|
14
|
+
* | 3 - stable | 0.13.0 | node, bun|
|
|
15
15
|
*
|
|
16
16
|
* Response compression.
|
|
17
17
|
*
|
|
@@ -62,6 +62,12 @@ export class ServerCompressProvider {
|
|
|
62
62
|
public readonly onResponse = $hook({
|
|
63
63
|
on: "server:onResponse",
|
|
64
64
|
handler: async ({ request, response }) => {
|
|
65
|
+
// In serverless (Cloudflare Workers), skip compression entirely:
|
|
66
|
+
// Cloudflare's edge network automatically compresses responses
|
|
67
|
+
if (this.alepha.isServerless()) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
65
71
|
// skip if already compressed
|
|
66
72
|
if (response.headers["content-encoding"]) {
|
|
67
73
|
return;
|
|
@@ -18,9 +18,9 @@ declare module "alepha/server" {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* |
|
|
22
|
-
*
|
|
23
|
-
* |
|
|
21
|
+
* | Stability | Since | Runtime |
|
|
22
|
+
* |-----------|-------|---------|
|
|
23
|
+
* | 3 - stable | 0.3.0 | node, bun, workerd|
|
|
24
24
|
*
|
|
25
25
|
* Server and browser-safe cookie handling.
|
|
26
26
|
*
|
package/src/server/core/index.ts
CHANGED
|
@@ -114,9 +114,9 @@ export * from "./services/UserAgentParser.ts";
|
|
|
114
114
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
* |
|
|
118
|
-
*
|
|
119
|
-
* |
|
|
117
|
+
* | Stability | Since | Runtime |
|
|
118
|
+
* |-----------|-------|---------|
|
|
119
|
+
* | 3 - stable | 0.1.0 | node, bun, workerd|
|
|
120
120
|
*
|
|
121
121
|
* Convention-driven HTTP server with automatic validation and type inference.
|
|
122
122
|
*
|
|
@@ -81,8 +81,9 @@ describe("$action", () => {
|
|
|
81
81
|
|
|
82
82
|
expect(await app.a1.fetch({}).then((it) => it.data)).toBe("ok:a1");
|
|
83
83
|
expect(await app.a2.fetch({}).then((it) => it.data)).toBe("Not Found");
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
await expect(app.a2.run({})).rejects.toThrowError(
|
|
85
|
+
"Action 'a2' is disabled.",
|
|
86
|
+
);
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
test("should return nothing", async ({ expect }) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
$env,
|
|
3
3
|
$inject,
|
|
4
|
+
AlephaError,
|
|
4
5
|
type Async,
|
|
5
6
|
createPrimitive,
|
|
6
7
|
isTypeFile,
|
|
@@ -188,8 +189,8 @@ export interface ActionPrimitiveOptions<TConfig extends RequestConfigSchema>
|
|
|
188
189
|
description?: string;
|
|
189
190
|
|
|
190
191
|
/**
|
|
191
|
-
* Disable the route. Useful with env variables
|
|
192
|
-
* Route won't be available in the API
|
|
192
|
+
* Disable the route. Useful with env variables to disable one specific route.
|
|
193
|
+
* Route won't be available in the API nor locally.
|
|
193
194
|
*/
|
|
194
195
|
disabled?: boolean;
|
|
195
196
|
|
|
@@ -317,6 +318,9 @@ export class ActionPrimitive<
|
|
|
317
318
|
config?: ClientRequestEntry<TConfig>,
|
|
318
319
|
options: ClientRequestOptions = {}, // most of the options are ignored here
|
|
319
320
|
): Promise<ClientRequestResponse<TConfig>> {
|
|
321
|
+
if (this.options.disabled) {
|
|
322
|
+
throw new AlephaError(`Action '${this.name}' is disabled.`);
|
|
323
|
+
}
|
|
320
324
|
const handler = this.options.handler;
|
|
321
325
|
const {
|
|
322
326
|
body,
|
|
@@ -76,22 +76,9 @@ export class NodeHttpServerProvider extends ServerProvider {
|
|
|
76
76
|
res.end("Internal Server Error");
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
// P3: Pre-allocated event object to avoid { req, res } allocation per request
|
|
80
|
-
// Safe because handleNodeRequest completes before the next request reuses this object
|
|
81
|
-
protected readonly nodeRequestEvent = {
|
|
82
|
-
req: null as unknown as IncomingMessage,
|
|
83
|
-
res: null as unknown as ServerResponse,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
79
|
public readonly server = this.createHttpServer((req, res) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
ev.req = req;
|
|
90
|
-
ev.res = res;
|
|
91
|
-
// Note: handleNodeRequest returns a promise that resolves after response is sent
|
|
92
|
-
this.handleNodeRequest(ev).catch((err) =>
|
|
93
|
-
this.handleRequestError(res, err),
|
|
94
|
-
);
|
|
80
|
+
const promise = this.handleNodeRequest({ req, res });
|
|
81
|
+
promise.catch((err) => this.handleRequestError(res, err));
|
|
95
82
|
});
|
|
96
83
|
|
|
97
84
|
public readonly start = $hook({
|
|
@@ -220,13 +220,15 @@ export class ServerProvider {
|
|
|
220
220
|
|
|
221
221
|
// empty body - just send status & headers
|
|
222
222
|
if (!response.body) {
|
|
223
|
-
res.writeHead(response.status, response.headers)
|
|
223
|
+
res.writeHead(response.status, response.headers);
|
|
224
|
+
res.end();
|
|
224
225
|
return;
|
|
225
226
|
}
|
|
226
227
|
|
|
227
228
|
// if response.body is string or buffer
|
|
228
229
|
if (typeof response.body === "string" || Buffer.isBuffer(response.body)) {
|
|
229
|
-
res.writeHead(response.status, response.headers)
|
|
230
|
+
res.writeHead(response.status, response.headers);
|
|
231
|
+
res.end(response.body);
|
|
230
232
|
return;
|
|
231
233
|
}
|
|
232
234
|
|
|
@@ -45,23 +45,6 @@ export class ServerRouterProvider extends RouterProvider<ServerRouteMatcher> {
|
|
|
45
45
|
>;
|
|
46
46
|
protected compiledOnError?: CompiledEventExecutor<Hooks["server:onError"]>;
|
|
47
47
|
|
|
48
|
-
// Reusable context.run options object - mutated per request
|
|
49
|
-
// Includes slots for request data to avoid closure allocation in context.run
|
|
50
|
-
protected readonly contextRunOptions = {
|
|
51
|
-
context: "",
|
|
52
|
-
// Request data slots - populated before context.run, read by processRequestBound
|
|
53
|
-
_request: null as unknown as ServerRequest,
|
|
54
|
-
_route: null as unknown as ServerRoute,
|
|
55
|
-
_responseKind: "any" as ResponseKind,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Pre-bound method reference - created once at instantiation, reused for all requests
|
|
59
|
-
// Reads arguments from contextRunOptions to avoid closure allocation per request
|
|
60
|
-
protected readonly processRequestBound = (): Promise<any> => {
|
|
61
|
-
const opts = this.contextRunOptions;
|
|
62
|
-
return this.processRequest(opts._request, opts._route, opts._responseKind);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
48
|
// Cache query schema keys to avoid property enumeration on every request
|
|
66
49
|
// WeakMap allows GC of schemas that are no longer referenced
|
|
67
50
|
protected readonly queryKeysCache = new WeakMap<object, string[]>();
|
|
@@ -137,16 +120,11 @@ export class ServerRouterProvider extends RouterProvider<ServerRouteMatcher> {
|
|
|
137
120
|
const request =
|
|
138
121
|
this.serverRequestParser.createServerRequest(rawRequest);
|
|
139
122
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
opts._route = route;
|
|
146
|
-
opts._responseKind = responseKind;
|
|
147
|
-
|
|
148
|
-
// Use pre-bound method reference instead of creating closure per request
|
|
149
|
-
return this.alepha.context.run(this.processRequestBound, opts);
|
|
123
|
+
// Create context options per request to avoid race conditions with concurrent requests
|
|
124
|
+
return this.alepha.context.run(
|
|
125
|
+
() => this.processRequest(request, route, responseKind),
|
|
126
|
+
{ context: this.getContextId(rawRequest.headers) },
|
|
127
|
+
);
|
|
150
128
|
},
|
|
151
129
|
});
|
|
152
130
|
}
|
package/src/server/cors/index.ts
CHANGED
|
@@ -25,9 +25,9 @@ declare module "alepha/server" {
|
|
|
25
25
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* |
|
|
29
|
-
*
|
|
30
|
-
* |
|
|
28
|
+
* | Stability | Since | Runtime |
|
|
29
|
+
* |-----------|-------|---------|
|
|
30
|
+
* | 3 - stable | 0.3.0 | node, bun, workerd|
|
|
31
31
|
*
|
|
32
32
|
* Cross-Origin Resource Sharing configuration.
|
|
33
33
|
*
|
|
@@ -10,9 +10,9 @@ export * from "./schemas/healthSchema.ts";
|
|
|
10
10
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* |
|
|
14
|
-
*
|
|
15
|
-
* |
|
|
13
|
+
* | Stability | Since | Runtime |
|
|
14
|
+
* |-----------|-------|---------|
|
|
15
|
+
* | 3 - stable | 0.7.0 | node, bun, workerd|
|
|
16
16
|
*
|
|
17
17
|
* Application health monitoring endpoints.
|
|
18
18
|
*
|
|
@@ -9,9 +9,9 @@ export * from "./providers/ServerHelmetProvider.ts";
|
|
|
9
9
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* |
|
|
13
|
-
*
|
|
14
|
-
* |
|
|
12
|
+
* | Stability | Since | Runtime |
|
|
13
|
+
* |-----------|-------|---------|
|
|
14
|
+
* | 3 - stable | 0.15.0 | node, bun, workerd|
|
|
15
15
|
*
|
|
16
16
|
* HTTP security headers.
|
|
17
17
|
*
|
|
@@ -35,9 +35,9 @@ declare module "alepha" {
|
|
|
35
35
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* |
|
|
39
|
-
*
|
|
40
|
-
* |
|
|
38
|
+
* | Stability | Since | Runtime |
|
|
39
|
+
* |-----------|-------|---------|
|
|
40
|
+
* | 3 - stable | 0.6.0 | node, bun, workerd, expo |
|
|
41
41
|
*
|
|
42
42
|
* Type-safe API client with request deduplication.
|
|
43
43
|
*
|