@getstrata/core 0.5.89 → 0.5.91
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/core/database/factory.d.ts +3 -0
- package/dist/core/scheduler/osCron.d.ts +3 -1
- package/dist/entries/audit/exportAuditLogs.js +2 -2
- package/dist/entries/audit/siemFormatter.js +2 -2
- package/dist/entries/auth/intendedUrlCookie.js +2 -2
- package/dist/entries/auth/oauth/providers.js +2 -2
- package/dist/entries/auth/oauth/samlProvider.js +2 -2
- package/dist/entries/auth/passwordConfirmCookie.js +2 -2
- package/dist/entries/auth/sessionCookie.js +2 -2
- package/dist/entries/auth/sessionGuard.js +2 -2
- package/dist/entries/auth/tokenHash.js +2 -2
- package/dist/entries/cache/createCacheStore.js +2 -2
- package/dist/entries/database/factory.js +13 -0
- package/dist/entries/facades.js +2 -2
- package/dist/entries/http/csrfMiddleware.js +2 -2
- package/dist/entries/http/csrfToken.js +2 -2
- package/dist/entries/http/flashMiddleware.js +2 -2
- package/dist/entries/http/flashSession.js +2 -2
- package/dist/entries/http/loginThrottleMiddleware.js +2 -2
- package/dist/entries/http/memoryThrottleMiddleware.js +2 -2
- package/dist/entries/http/scimThrottleMiddleware.js +2 -2
- package/dist/entries/http/securityHeadersMiddleware.js +2 -2
- package/dist/entries/http/signedUrl.js +2 -2
- package/dist/entries/http/throttleMiddleware.js +2 -2
- package/dist/entries/jobs/exportAuditLogsJob.js +2 -2
- package/dist/entries/mail/mailer.js +2 -2
- package/dist/entries/openapi/generator.js +5 -5
- package/dist/entries/queue/createAppQueue.js +2 -2
- package/dist/entries/queue/publicQueue.js +2 -2
- package/dist/entries/queue/queueMetrics.js +2 -2
- package/dist/entries/queue/redisQueue.js +2 -2
- package/dist/entries/runtime/appKeyPrefix.js +2 -2
- package/dist/entries/scheduler/osCron.js +26 -0
- package/dist/entries/scheduler/schedule.js +45 -11
- package/dist/entries/security/oauthState.js +2 -2
- package/dist/entries/security/safeFetch.js +2 -2
- package/dist/entries/security/totp.js +2 -2
- package/dist/entries/tracing/tracingMiddleware.js +2 -2
- package/dist/entries/view.js +2 -2
- package/dist/index.js +32 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.91
|
|
4
|
+
|
|
5
|
+
- `Schedule.command()` accepts any expression `Bun.cron.parse` understands. `dueTasks()` uses the next fire time in the current minute instead of a `*/N` whitelist.
|
|
6
|
+
- `Factory.create()` persists `make()` through subclass `persist()` and strips a placeholder `id` of `0`. No states, sequences, or relationships.
|
|
7
|
+
|
|
8
|
+
## 0.5.90
|
|
9
|
+
|
|
10
|
+
- **Breaking identity defaults:** `appKeyPrefix()` is `strata` and `appDisplayName()` is `Strata` when `APP_KEY_PREFIX` / `APP_NAME` are unset (were `workhub` / `WorkHub`). WorkHub pins those env vars.
|
|
11
|
+
- `Schedule.command()` rejects cron strings other than `* * * * *` and `*/N * * * *` instead of silently never running them.
|
|
12
|
+
- OpenAPI marks `GET /users/me/*` as bearer-authenticated.
|
|
13
|
+
- OpenAPI `/users/me/current-organization` summaries no longer say Jetstream.
|
|
14
|
+
|
|
3
15
|
## 0.5.89
|
|
4
16
|
|
|
5
17
|
- **Breaking:** removed `@getstrata/core/jobs/dispatchWebhookJob`. Import `DispatchWebhookJob` from the app webhook module (`src/modules/webhook/dispatchWebhookJob.ts`).
|
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ import type { Migration } from "@getstrata/core/database/migrations/types";
|
|
|
82
82
|
Package name: **`@getstrata/core`** (npm org [`@getstrata`](https://www.npmjs.com/org/getstrata)).
|
|
83
83
|
|
|
84
84
|
1. Add `NPM_TOKEN` to GitHub repository secrets.
|
|
85
|
-
2. Tag a release: `git tag v0.5.
|
|
85
|
+
2. Tag a release: `git tag v0.5.96 && git push origin v0.5.96`
|
|
86
86
|
3. [Release workflow](../../.github/workflows/release.yml) builds and runs `npm publish --access public`.
|
|
87
87
|
|
|
88
88
|
Previously published as `@eyk-workhub/framework@0.1.0`, deprecated in favor of this package.
|
|
@@ -2,5 +2,8 @@ declare class Factory<TRecord extends object> {
|
|
|
2
2
|
constructor();
|
|
3
3
|
protected definition(): TRecord;
|
|
4
4
|
make(overrides?: Partial<TRecord>): TRecord;
|
|
5
|
+
create(overrides?: Partial<TRecord>): Promise<TRecord>;
|
|
6
|
+
protected insertable(record: TRecord): Partial<TRecord>;
|
|
7
|
+
protected persist(_values: Partial<TRecord>): Promise<TRecord>;
|
|
5
8
|
}
|
|
6
9
|
export { Factory };
|
|
@@ -7,8 +7,10 @@ interface InProcessCronJob {
|
|
|
7
7
|
unref(): InProcessCronJob;
|
|
8
8
|
}
|
|
9
9
|
declare function parseScheduleExpression(expression: string, from?: Date): Date | null;
|
|
10
|
+
declare function isScheduleExpressionDue(expression: string, now?: Date): boolean;
|
|
11
|
+
declare function assertScheduleExpression(expression: string): void;
|
|
10
12
|
declare function registerInProcessScheduleRunner(run: () => void | Promise<void>, expression?: string): InProcessCronJob;
|
|
11
13
|
declare function installOsScheduleRunner(workerScriptPath: string, expression?: string, title?: string): Promise<void>;
|
|
12
14
|
declare function uninstallOsScheduleRunner(title?: string): Promise<void>;
|
|
13
15
|
export type { InProcessCronJob };
|
|
14
|
-
export { DEFAULT_SCHEDULE_RUN_EXPRESSION, installOsScheduleRunner, OS_CRON_JOB_TITLE, parseScheduleExpression, registerInProcessScheduleRunner, uninstallOsScheduleRunner, };
|
|
16
|
+
export { assertScheduleExpression, DEFAULT_SCHEDULE_RUN_EXPRESSION, installOsScheduleRunner, isScheduleExpressionDue, OS_CRON_JOB_TITLE, parseScheduleExpression, registerInProcessScheduleRunner, uninstallOsScheduleRunner, };
|
|
@@ -4,7 +4,7 @@ import { repositoryConnection as db2 } from "@getstrata/core/database/repository
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -34,7 +34,7 @@ function loginRedirectLocation(request) {
|
|
|
34
34
|
|
|
35
35
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
36
36
|
function appKeyPrefix() {
|
|
37
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
37
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
38
38
|
}
|
|
39
39
|
function appCookieName(kind) {
|
|
40
40
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -63,7 +63,7 @@ function webhookSignatureHeader() {
|
|
|
63
63
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
64
64
|
}
|
|
65
65
|
function appDisplayName() {
|
|
66
|
-
return process.env.APP_NAME?.trim() || "
|
|
66
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
67
67
|
}
|
|
68
68
|
function appEnv() {
|
|
69
69
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -89,7 +89,7 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|
|
89
89
|
|
|
90
90
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
91
91
|
function appKeyPrefix() {
|
|
92
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
92
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
93
93
|
}
|
|
94
94
|
function appCookieName(kind) {
|
|
95
95
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -118,7 +118,7 @@ function webhookSignatureHeader() {
|
|
|
118
118
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
119
119
|
}
|
|
120
120
|
function appDisplayName() {
|
|
121
|
-
return process.env.APP_NAME?.trim() || "
|
|
121
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
122
122
|
}
|
|
123
123
|
function appEnv() {
|
|
124
124
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { createHash, createHmac } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -11,6 +11,19 @@ class Factory {
|
|
|
11
11
|
...overrides
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
+
async create(overrides = {}) {
|
|
15
|
+
return this.persist(this.insertable(this.make(overrides)));
|
|
16
|
+
}
|
|
17
|
+
insertable(record) {
|
|
18
|
+
const values = { ...record };
|
|
19
|
+
if (values.id === 0 || values.id === undefined || values.id === null) {
|
|
20
|
+
delete values.id;
|
|
21
|
+
}
|
|
22
|
+
return values;
|
|
23
|
+
}
|
|
24
|
+
persist(_values) {
|
|
25
|
+
throw new Error("Factory.persist() must be implemented to use create().");
|
|
26
|
+
}
|
|
14
27
|
}
|
|
15
28
|
export {
|
|
16
29
|
Factory
|
package/dist/entries/facades.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
|
|
14
14
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
15
15
|
function appKeyPrefix() {
|
|
16
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
16
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
17
17
|
}
|
|
18
18
|
function appCookieName(kind) {
|
|
19
19
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -42,7 +42,7 @@ function webhookSignatureHeader() {
|
|
|
42
42
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
43
43
|
}
|
|
44
44
|
function appDisplayName() {
|
|
45
|
-
return process.env.APP_NAME?.trim() || "
|
|
45
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
46
46
|
}
|
|
47
47
|
function appEnv() {
|
|
48
48
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -7,7 +7,7 @@ import { timingSafeEqual } from "crypto";
|
|
|
7
7
|
|
|
8
8
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
9
9
|
function appKeyPrefix() {
|
|
10
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
10
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
11
11
|
}
|
|
12
12
|
function appCookieName(kind) {
|
|
13
13
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -36,7 +36,7 @@ function webhookSignatureHeader() {
|
|
|
36
36
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
37
37
|
}
|
|
38
38
|
function appDisplayName() {
|
|
39
|
-
return process.env.APP_NAME?.trim() || "
|
|
39
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
40
40
|
}
|
|
41
41
|
function appEnv() {
|
|
42
42
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { timingSafeEqual } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -9,7 +9,7 @@ import { currentRequestMeta, runWithRequestMeta } from "@getstrata/core/http/req
|
|
|
9
9
|
|
|
10
10
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
11
11
|
function appKeyPrefix() {
|
|
12
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
12
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
13
13
|
}
|
|
14
14
|
function appCookieName(kind) {
|
|
15
15
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -38,7 +38,7 @@ function webhookSignatureHeader() {
|
|
|
38
38
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
39
39
|
}
|
|
40
40
|
function appDisplayName() {
|
|
41
|
-
return process.env.APP_NAME?.trim() || "
|
|
41
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
42
42
|
}
|
|
43
43
|
function appEnv() {
|
|
44
44
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -6,7 +6,7 @@ import { timingSafeCompareString } from "@getstrata/core/security/timingSafeComp
|
|
|
6
6
|
|
|
7
7
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
8
8
|
function appKeyPrefix() {
|
|
9
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
9
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
10
10
|
}
|
|
11
11
|
function appCookieName(kind) {
|
|
12
12
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -35,7 +35,7 @@ function webhookSignatureHeader() {
|
|
|
35
35
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
36
36
|
}
|
|
37
37
|
function appDisplayName() {
|
|
38
|
-
return process.env.APP_NAME?.trim() || "
|
|
38
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
39
39
|
}
|
|
40
40
|
function appEnv() {
|
|
41
41
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -6,7 +6,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
6
6
|
|
|
7
7
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
8
8
|
function appKeyPrefix() {
|
|
9
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
9
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
10
10
|
}
|
|
11
11
|
function appCookieName(kind) {
|
|
12
12
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -35,7 +35,7 @@ function webhookSignatureHeader() {
|
|
|
35
35
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
36
36
|
}
|
|
37
37
|
function appDisplayName() {
|
|
38
|
-
return process.env.APP_NAME?.trim() || "
|
|
38
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
39
39
|
}
|
|
40
40
|
function appEnv() {
|
|
41
41
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { repositoryConnection as db2 } from "@getstrata/core/database/repository
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -66,8 +66,8 @@ var PUBLIC_ROUTE_DESCRIPTIONS = {
|
|
|
66
66
|
"POST /auth/tokens": "Create API token",
|
|
67
67
|
"DELETE /auth/tokens/:id": "Revoke API token",
|
|
68
68
|
"GET /users/me/export": "GDPR export of user data",
|
|
69
|
-
"GET /users/me/current-organization": "Current
|
|
70
|
-
"PUT /users/me/current-organization": "Switch current
|
|
69
|
+
"GET /users/me/current-organization": "Current organization",
|
|
70
|
+
"PUT /users/me/current-organization": "Switch current organization",
|
|
71
71
|
"GET /users/me/invitations": "List pending team invitations for the signed-in email",
|
|
72
72
|
"POST /users/me/invitations/:id/accept": "Accept a pending team invitation",
|
|
73
73
|
"DELETE /users/me/invitations/:id": "Decline a pending team invitation",
|
|
@@ -126,7 +126,7 @@ function requiresBearerAuth(path, method) {
|
|
|
126
126
|
if (method === "GET" && ["/organizations", "/projects", "/tasks", "/search"].some((prefix) => relative.startsWith(prefix) || path.startsWith(prefix))) {
|
|
127
127
|
return false;
|
|
128
128
|
}
|
|
129
|
-
return relative.startsWith("/auth/") || ["POST", "PATCH", "PUT", "DELETE"].includes(method);
|
|
129
|
+
return relative.startsWith("/auth/") || relative.startsWith("/users/me") || path.startsWith("/users/me") || ["POST", "PATCH", "PUT", "DELETE"].includes(method);
|
|
130
130
|
}
|
|
131
131
|
function generateOpenApiSpec(routes) {
|
|
132
132
|
const paths = {};
|
|
@@ -158,7 +158,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
158
158
|
|
|
159
159
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
160
160
|
function appKeyPrefix() {
|
|
161
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
161
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
162
162
|
}
|
|
163
163
|
function appCookieName(kind) {
|
|
164
164
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -187,7 +187,7 @@ function webhookSignatureHeader() {
|
|
|
187
187
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
188
188
|
}
|
|
189
189
|
function appDisplayName() {
|
|
190
|
-
return process.env.APP_NAME?.trim() || "
|
|
190
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
191
191
|
}
|
|
192
192
|
function appEnv() {
|
|
193
193
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -158,7 +158,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
158
158
|
|
|
159
159
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
160
160
|
function appKeyPrefix() {
|
|
161
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
161
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
162
162
|
}
|
|
163
163
|
function appCookieName(kind) {
|
|
164
164
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -187,7 +187,7 @@ function webhookSignatureHeader() {
|
|
|
187
187
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
188
188
|
}
|
|
189
189
|
function appDisplayName() {
|
|
190
|
-
return process.env.APP_NAME?.trim() || "
|
|
190
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
191
191
|
}
|
|
192
192
|
function appEnv() {
|
|
193
193
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -161,7 +161,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
161
161
|
|
|
162
162
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
163
163
|
function appKeyPrefix() {
|
|
164
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
164
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
165
165
|
}
|
|
166
166
|
function appCookieName(kind) {
|
|
167
167
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -190,7 +190,7 @@ function webhookSignatureHeader() {
|
|
|
190
190
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
191
191
|
}
|
|
192
192
|
function appDisplayName() {
|
|
193
|
-
return process.env.APP_NAME?.trim() || "
|
|
193
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
194
194
|
}
|
|
195
195
|
function appEnv() {
|
|
196
196
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -5,6 +5,30 @@ var OS_CRON_JOB_TITLE = "getstrata-schedule-run";
|
|
|
5
5
|
function parseScheduleExpression(expression, from = new Date) {
|
|
6
6
|
return Bun.cron.parse(expression, from);
|
|
7
7
|
}
|
|
8
|
+
function minuteWindow(now) {
|
|
9
|
+
const start = new Date(now);
|
|
10
|
+
start.setSeconds(0, 0);
|
|
11
|
+
return { start, end: new Date(start.getTime() + 60000) };
|
|
12
|
+
}
|
|
13
|
+
function isScheduleExpressionDue(expression, now = new Date) {
|
|
14
|
+
const { start, end } = minuteWindow(now);
|
|
15
|
+
const next = parseScheduleExpression(expression, new Date(start.getTime() - 1));
|
|
16
|
+
if (!next) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const timestamp = next.getTime();
|
|
20
|
+
return timestamp >= start.getTime() && timestamp < end.getTime();
|
|
21
|
+
}
|
|
22
|
+
function assertScheduleExpression(expression) {
|
|
23
|
+
try {
|
|
24
|
+
const next = parseScheduleExpression(expression);
|
|
25
|
+
if (!(next instanceof Date) || Number.isNaN(next.getTime())) {
|
|
26
|
+
throw new Error("unparsable");
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
throw new Error(`Unsupported schedule expression "${expression}".`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
8
32
|
function registerInProcessScheduleRunner(run, expression = DEFAULT_SCHEDULE_RUN_EXPRESSION) {
|
|
9
33
|
const register = Bun.cron;
|
|
10
34
|
return register(expression, async () => {
|
|
@@ -20,7 +44,9 @@ async function uninstallOsScheduleRunner(title = OS_CRON_JOB_TITLE) {
|
|
|
20
44
|
export {
|
|
21
45
|
DEFAULT_SCHEDULE_RUN_EXPRESSION,
|
|
22
46
|
OS_CRON_JOB_TITLE,
|
|
47
|
+
assertScheduleExpression,
|
|
23
48
|
installOsScheduleRunner,
|
|
49
|
+
isScheduleExpressionDue,
|
|
24
50
|
parseScheduleExpression,
|
|
25
51
|
registerInProcessScheduleRunner,
|
|
26
52
|
uninstallOsScheduleRunner
|
|
@@ -1,23 +1,57 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// ../../src/core/scheduler/osCron.ts
|
|
3
|
+
var DEFAULT_SCHEDULE_RUN_EXPRESSION = "* * * * *";
|
|
4
|
+
var OS_CRON_JOB_TITLE = "getstrata-schedule-run";
|
|
5
|
+
function parseScheduleExpression(expression, from = new Date) {
|
|
6
|
+
return Bun.cron.parse(expression, from);
|
|
7
|
+
}
|
|
8
|
+
function minuteWindow(now) {
|
|
9
|
+
const start = new Date(now);
|
|
10
|
+
start.setSeconds(0, 0);
|
|
11
|
+
return { start, end: new Date(start.getTime() + 60000) };
|
|
12
|
+
}
|
|
13
|
+
function isScheduleExpressionDue(expression, now = new Date) {
|
|
14
|
+
const { start, end } = minuteWindow(now);
|
|
15
|
+
const next = parseScheduleExpression(expression, new Date(start.getTime() - 1));
|
|
16
|
+
if (!next) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const timestamp = next.getTime();
|
|
20
|
+
return timestamp >= start.getTime() && timestamp < end.getTime();
|
|
21
|
+
}
|
|
22
|
+
function assertScheduleExpression(expression) {
|
|
23
|
+
try {
|
|
24
|
+
const next = parseScheduleExpression(expression);
|
|
25
|
+
if (!(next instanceof Date) || Number.isNaN(next.getTime())) {
|
|
26
|
+
throw new Error("unparsable");
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
throw new Error(`Unsupported schedule expression "${expression}".`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function registerInProcessScheduleRunner(run, expression = DEFAULT_SCHEDULE_RUN_EXPRESSION) {
|
|
33
|
+
const register = Bun.cron;
|
|
34
|
+
return register(expression, async () => {
|
|
35
|
+
await run();
|
|
36
|
+
}).unref();
|
|
37
|
+
}
|
|
38
|
+
async function installOsScheduleRunner(workerScriptPath, expression = DEFAULT_SCHEDULE_RUN_EXPRESSION, title = OS_CRON_JOB_TITLE) {
|
|
39
|
+
await Bun.cron(workerScriptPath, expression, title);
|
|
40
|
+
}
|
|
41
|
+
async function uninstallOsScheduleRunner(title = OS_CRON_JOB_TITLE) {
|
|
42
|
+
await Bun.cron.remove(title);
|
|
43
|
+
}
|
|
44
|
+
|
|
2
45
|
// ../../src/core/scheduler/schedule.ts
|
|
3
46
|
class Schedule {
|
|
4
47
|
tasks = [];
|
|
5
48
|
command(expression, name, run) {
|
|
49
|
+
assertScheduleExpression(expression);
|
|
6
50
|
this.tasks.push({ expression, name, run });
|
|
7
51
|
return this;
|
|
8
52
|
}
|
|
9
53
|
dueTasks(now = new Date) {
|
|
10
|
-
|
|
11
|
-
return this.tasks.filter((task) => {
|
|
12
|
-
if (task.expression === "* * * * *") {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
if (task.expression.startsWith("*/")) {
|
|
16
|
-
const interval = Number.parseInt(task.expression.slice(2), 10);
|
|
17
|
-
return Number.isInteger(interval) && interval > 0 && minute % interval === 0;
|
|
18
|
-
}
|
|
19
|
-
return false;
|
|
20
|
-
});
|
|
54
|
+
return this.tasks.filter((task) => isScheduleExpressionDue(task.expression, now));
|
|
21
55
|
}
|
|
22
56
|
tasksList() {
|
|
23
57
|
return [...this.tasks];
|
|
@@ -4,7 +4,7 @@ import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
3
3
|
function appKeyPrefix() {
|
|
4
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
4
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
5
5
|
}
|
|
6
6
|
function appCookieName(kind) {
|
|
7
7
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -30,7 +30,7 @@ function webhookSignatureHeader() {
|
|
|
30
30
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
31
31
|
}
|
|
32
32
|
function appDisplayName() {
|
|
33
|
-
return process.env.APP_NAME?.trim() || "
|
|
33
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
34
34
|
}
|
|
35
35
|
function appEnv() {
|
|
36
36
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { createHmac, randomBytes } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
|
@@ -4,7 +4,7 @@ import { randomBytes } from "crypto";
|
|
|
4
4
|
|
|
5
5
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
6
6
|
function appKeyPrefix() {
|
|
7
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
7
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
8
8
|
}
|
|
9
9
|
function appCookieName(kind) {
|
|
10
10
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -33,7 +33,7 @@ function webhookSignatureHeader() {
|
|
|
33
33
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
34
34
|
}
|
|
35
35
|
function appDisplayName() {
|
|
36
|
-
return process.env.APP_NAME?.trim() || "
|
|
36
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
37
37
|
}
|
|
38
38
|
function appEnv() {
|
|
39
39
|
return process.env.APP_ENV?.trim() || "local";
|
package/dist/entries/view.js
CHANGED
|
@@ -386,7 +386,7 @@ import { timingSafeEqual } from "crypto";
|
|
|
386
386
|
|
|
387
387
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
388
388
|
function appKeyPrefix() {
|
|
389
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
389
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
390
390
|
}
|
|
391
391
|
function appCookieName(kind) {
|
|
392
392
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -415,7 +415,7 @@ function webhookSignatureHeader() {
|
|
|
415
415
|
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
416
416
|
}
|
|
417
417
|
function appDisplayName() {
|
|
418
|
-
return process.env.APP_NAME?.trim() || "
|
|
418
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
419
419
|
}
|
|
420
420
|
function appEnv() {
|
|
421
421
|
return process.env.APP_ENV?.trim() || "local";
|
package/dist/index.js
CHANGED
|
@@ -977,7 +977,7 @@ var {RedisClient } = globalThis.Bun;
|
|
|
977
977
|
|
|
978
978
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
979
979
|
function appKeyPrefix() {
|
|
980
|
-
return process.env.APP_KEY_PREFIX?.trim() || "
|
|
980
|
+
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
981
981
|
}
|
|
982
982
|
function appCookieName(kind) {
|
|
983
983
|
return `${appKeyPrefix()}_${kind}`;
|
|
@@ -6556,25 +6556,45 @@ async function collectQueueMetrics() {
|
|
|
6556
6556
|
failedCount
|
|
6557
6557
|
};
|
|
6558
6558
|
}
|
|
6559
|
+
// ../../src/core/scheduler/osCron.ts
|
|
6560
|
+
function parseScheduleExpression(expression, from = new Date) {
|
|
6561
|
+
return Bun.cron.parse(expression, from);
|
|
6562
|
+
}
|
|
6563
|
+
function minuteWindow(now) {
|
|
6564
|
+
const start = new Date(now);
|
|
6565
|
+
start.setSeconds(0, 0);
|
|
6566
|
+
return { start, end: new Date(start.getTime() + 60000) };
|
|
6567
|
+
}
|
|
6568
|
+
function isScheduleExpressionDue(expression, now = new Date) {
|
|
6569
|
+
const { start, end } = minuteWindow(now);
|
|
6570
|
+
const next = parseScheduleExpression(expression, new Date(start.getTime() - 1));
|
|
6571
|
+
if (!next) {
|
|
6572
|
+
return false;
|
|
6573
|
+
}
|
|
6574
|
+
const timestamp = next.getTime();
|
|
6575
|
+
return timestamp >= start.getTime() && timestamp < end.getTime();
|
|
6576
|
+
}
|
|
6577
|
+
function assertScheduleExpression(expression) {
|
|
6578
|
+
try {
|
|
6579
|
+
const next = parseScheduleExpression(expression);
|
|
6580
|
+
if (!(next instanceof Date) || Number.isNaN(next.getTime())) {
|
|
6581
|
+
throw new Error("unparsable");
|
|
6582
|
+
}
|
|
6583
|
+
} catch {
|
|
6584
|
+
throw new Error(`Unsupported schedule expression "${expression}".`);
|
|
6585
|
+
}
|
|
6586
|
+
}
|
|
6587
|
+
|
|
6559
6588
|
// ../../src/core/scheduler/schedule.ts
|
|
6560
6589
|
class Schedule {
|
|
6561
6590
|
tasks = [];
|
|
6562
6591
|
command(expression, name, run) {
|
|
6592
|
+
assertScheduleExpression(expression);
|
|
6563
6593
|
this.tasks.push({ expression, name, run });
|
|
6564
6594
|
return this;
|
|
6565
6595
|
}
|
|
6566
6596
|
dueTasks(now = new Date) {
|
|
6567
|
-
|
|
6568
|
-
return this.tasks.filter((task) => {
|
|
6569
|
-
if (task.expression === "* * * * *") {
|
|
6570
|
-
return true;
|
|
6571
|
-
}
|
|
6572
|
-
if (task.expression.startsWith("*/")) {
|
|
6573
|
-
const interval = Number.parseInt(task.expression.slice(2), 10);
|
|
6574
|
-
return Number.isInteger(interval) && interval > 0 && minute % interval === 0;
|
|
6575
|
-
}
|
|
6576
|
-
return false;
|
|
6577
|
-
});
|
|
6597
|
+
return this.tasks.filter((task) => isScheduleExpressionDue(task.expression, now));
|
|
6578
6598
|
}
|
|
6579
6599
|
tasksList() {
|
|
6580
6600
|
return [...this.tasks];
|