@getstrata/core 0.5.30 → 0.5.33

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.
@@ -4,7 +4,7 @@ declare const CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
4
4
  declare const CACHE_DRIVER_CONFIG_KEY = "cache.driver";
5
5
  declare const REDIS_URL_CONFIG_KEY = "cache.redisUrl";
6
6
  declare const DATABASE_URL_CONFIG_KEY = "database.url";
7
- export { CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, } from "../core/contracts/serviceTokens.ts";
7
+ export { CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, } from "@getstrata/core/contracts/serviceTokens.ts";
8
8
  declare const AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
9
9
  declare const DEFAULT_APP_PORT = 3000;
10
10
  declare const DEFAULT_CACHE_TTL_MS = 3600000;
@@ -0,0 +1,35 @@
1
+ // @bun
2
+ // ../../src/core/config/envSchema.ts
3
+ function defineEnvSchema(schema) {
4
+ return schema;
5
+ }
6
+ function validateEnv(schema, env = process.env) {
7
+ const resolved = {};
8
+ for (const [name, rule] of Object.entries(schema)) {
9
+ const rawValue = env[name];
10
+ const value = rawValue === undefined || rawValue.trim() === "" ? rule.default : rawValue;
11
+ if (value === undefined || value.trim() === "") {
12
+ if (rule.required) {
13
+ throw new Error(`Missing required environment variable "${name}".`);
14
+ }
15
+ continue;
16
+ }
17
+ if (rule.integer) {
18
+ const parsed = Number.parseInt(value, 10);
19
+ const minimum = rule.minimum ?? Number.NEGATIVE_INFINITY;
20
+ if (!Number.isInteger(parsed) || parsed < minimum) {
21
+ const comparison = minimum === Number.NEGATIVE_INFINITY ? "an integer" : `an integer >= ${minimum}`;
22
+ throw new Error(`Environment variable "${name}" must be ${comparison}.`);
23
+ }
24
+ }
25
+ if (rule.pattern && !rule.pattern.test(value)) {
26
+ throw new Error(`Environment variable "${name}" has an invalid format.`);
27
+ }
28
+ resolved[name] = value;
29
+ }
30
+ return resolved;
31
+ }
32
+ export {
33
+ validateEnv,
34
+ defineEnvSchema
35
+ };
@@ -0,0 +1,97 @@
1
+ // @bun
2
+ // ../../src/core/errors/http.ts
3
+ class HttpError extends Error {
4
+ status;
5
+ details;
6
+ constructor(status, message, details) {
7
+ super(message);
8
+ this.name = new.target.name;
9
+ this.status = status;
10
+ this.details = details;
11
+ }
12
+ }
13
+
14
+ class BadRequestError extends HttpError {
15
+ constructor(message = "Bad Request", details) {
16
+ super(400, message, details);
17
+ }
18
+ }
19
+
20
+ class NotFoundError extends HttpError {
21
+ constructor(message = "Not Found", details) {
22
+ super(404, message, details);
23
+ }
24
+ }
25
+
26
+ class ConflictError extends HttpError {
27
+ constructor(message = "Conflict", details) {
28
+ super(409, message, details);
29
+ }
30
+ }
31
+
32
+ class UnprocessableEntityError extends HttpError {
33
+ constructor(message = "Unprocessable Entity", details) {
34
+ super(422, message, details);
35
+ }
36
+ }
37
+
38
+ class ValidationError extends HttpError {
39
+ constructor(message = "Validation failed", details) {
40
+ super(422, message, details);
41
+ }
42
+ }
43
+
44
+ class ForbiddenError extends HttpError {
45
+ constructor(message = "Forbidden", details) {
46
+ super(403, message, details);
47
+ }
48
+ }
49
+
50
+ class UnauthorizedError extends HttpError {
51
+ constructor(message = "Unauthorized", details) {
52
+ super(401, message, details);
53
+ }
54
+ }
55
+
56
+ class PayloadTooLargeError extends HttpError {
57
+ constructor(message = "Payload Too Large", details) {
58
+ super(413, message, details);
59
+ }
60
+ }
61
+
62
+ class PreconditionFailedError extends HttpError {
63
+ constructor(message = "Precondition Failed", details) {
64
+ super(412, message, details);
65
+ }
66
+ }
67
+
68
+ // ../../src/core/http/bodySizeLimitMiddleware.ts
69
+ var DEFAULT_MAX_BODY_BYTES = 1048576;
70
+ function resolveMaxBodyBytes() {
71
+ const raw = process.env.MAX_REQUEST_BODY_BYTES?.trim();
72
+ if (!raw) {
73
+ return DEFAULT_MAX_BODY_BYTES;
74
+ }
75
+ const parsed = Number.parseInt(raw, 10);
76
+ if (!Number.isInteger(parsed) || parsed <= 0) {
77
+ return DEFAULT_MAX_BODY_BYTES;
78
+ }
79
+ return parsed;
80
+ }
81
+ function createBodySizeLimitMiddleware(maxBytes = resolveMaxBodyBytes()) {
82
+ return async (request, next) => {
83
+ const contentLength = request.headers.get("content-length");
84
+ if (contentLength) {
85
+ const bytes = Number.parseInt(contentLength, 10);
86
+ if (Number.isInteger(bytes) && bytes > maxBytes) {
87
+ const error = new PayloadTooLargeError(`Request body exceeds the ${maxBytes} byte limit.`);
88
+ return Response.json({ error: error.message }, { status: error.status });
89
+ }
90
+ }
91
+ return await next();
92
+ };
93
+ }
94
+ export {
95
+ resolveMaxBodyBytes,
96
+ createBodySizeLimitMiddleware
97
+ };
@@ -0,0 +1 @@
1
+ // @bun
@@ -0,0 +1,38 @@
1
+ // @bun
2
+ // ../../src/core/scheduler/schedule.ts
3
+ class Schedule {
4
+ tasks = [];
5
+ command(expression, name, run) {
6
+ this.tasks.push({ expression, name, run });
7
+ return this;
8
+ }
9
+ dueTasks(now = new Date) {
10
+ const minute = now.getMinutes();
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
+ });
21
+ }
22
+ tasksList() {
23
+ return [...this.tasks];
24
+ }
25
+ }
26
+ var appSchedule = new Schedule;
27
+ async function runDueScheduledTasks(schedule = appSchedule, now = new Date) {
28
+ const due = schedule.dueTasks(now);
29
+ for (const task of due) {
30
+ await task.run();
31
+ }
32
+ return due.length;
33
+ }
34
+ export {
35
+ runDueScheduledTasks,
36
+ appSchedule,
37
+ Schedule
38
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/core",
3
- "version": "0.5.30",
3
+ "version": "0.5.33",
4
4
  "description": "Strata — Laravel-inspired Bun framework public API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -95,6 +95,11 @@
95
95
  "import": "./dist/entries/cache/createCacheStore.js",
96
96
  "default": "./dist/entries/cache/createCacheStore.js"
97
97
  },
98
+ "./config/envSchema": {
99
+ "types": "./dist/core/config/envSchema.d.ts",
100
+ "import": "./dist/entries/config/envSchema.js",
101
+ "default": "./dist/entries/config/envSchema.js"
102
+ },
98
103
  "./contracts/serviceTokens": {
99
104
  "types": "./dist/core/contracts/serviceTokens.d.ts",
100
105
  "import": "./dist/entries/contracts/serviceTokens.js",
@@ -150,6 +155,11 @@
150
155
  "import": "./dist/entries/http.js",
151
156
  "default": "./dist/entries/http.js"
152
157
  },
158
+ "./http/bodySizeLimitMiddleware": {
159
+ "types": "./dist/core/http/bodySizeLimitMiddleware.d.ts",
160
+ "import": "./dist/entries/http/bodySizeLimitMiddleware.js",
161
+ "default": "./dist/entries/http/bodySizeLimitMiddleware.js"
162
+ },
153
163
  "./http/contentNegotiation": {
154
164
  "types": "./dist/core/http/contentNegotiation.d.ts",
155
165
  "import": "./dist/entries/http/contentNegotiation.js",
@@ -215,6 +225,11 @@
215
225
  "import": "./dist/entries/metrics/prometheus.js",
216
226
  "default": "./dist/entries/metrics/prometheus.js"
217
227
  },
228
+ "./openapi/registeredRoute": {
229
+ "types": "./dist/core/openapi/registeredRoute.d.ts",
230
+ "import": "./dist/entries/openapi/registeredRoute.js",
231
+ "default": "./dist/entries/openapi/registeredRoute.js"
232
+ },
218
233
  "./pagination": {
219
234
  "types": "./dist/core/pagination/index.d.ts",
220
235
  "import": "./dist/entries/pagination.js",
@@ -260,6 +275,11 @@
260
275
  "import": "./dist/entries/runtime/applicationRegistry.js",
261
276
  "default": "./dist/entries/runtime/applicationRegistry.js"
262
277
  },
278
+ "./scheduler/schedule": {
279
+ "types": "./dist/core/scheduler/schedule.d.ts",
280
+ "import": "./dist/entries/scheduler/schedule.js",
281
+ "default": "./dist/entries/scheduler/schedule.js"
282
+ },
263
283
  "./security/oauthState": {
264
284
  "types": "./dist/core/security/oauthState.d.ts",
265
285
  "import": "./dist/entries/security/oauthState.js",
@@ -337,7 +357,7 @@
337
357
  "build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta",
338
358
  "build:types": "tsc -p tsconfig.types.json",
339
359
  "prepublishOnly": "bun run build && bun ../../scripts/prepare-core-package-publish.ts",
340
- "build:subpaths": "bun build entries/auth/oauth/oidcProvider.ts entries/auth/oauth/providers.ts entries/auth/oauth/samlProvider.ts entries/auth/oauth/types.ts entries/auth/password.ts entries/auth/sessionCookie.ts entries/auth/tokenHash.ts entries/cache/tags.ts entries/cache/createCacheStore.ts entries/contracts/serviceTokens.ts entries/contracts/container.ts entries/contracts/di.ts entries/crypto/fieldEncryption.ts entries/crypto/mfaSecret.ts entries/database/factory.ts entries/database/seeders.ts entries/database/types.ts entries/errors/http.ts entries/http/contentNegotiation.ts entries/http/csrfToken.ts entries/http/etag.ts entries/http/flashSession.ts entries/http/parseFormBody.ts entries/http/resources.ts entries/http/webErrorResponse.ts entries/http/webFormRequest.ts entries/jobs/dispatchWebhookJob.ts entries/lifecycle/gracefulShutdown.ts entries/metrics/prometheus.ts entries/pagination.ts entries/queue/createAppQueue.ts entries/queue/failedJobService.ts entries/queue/jobRunner.ts entries/queue/queueMetrics.ts entries/queue/publicQueue.ts entries/queue/types.ts entries/security/oauthState.ts entries/security/publicReads.ts entries/security/safeUrl.ts entries/security/stripeWebhook.ts entries/security/tokenExpiry.ts entries/security/totp.ts entries/storage/storage.ts entries/validation/rules.ts entries/view.ts --outdir dist --root . --target bun --external bun --external eta",
360
+ "build:subpaths": "bun build entries/auth/oauth/oidcProvider.ts entries/auth/oauth/providers.ts entries/auth/oauth/samlProvider.ts entries/auth/oauth/types.ts entries/auth/password.ts entries/auth/sessionCookie.ts entries/auth/tokenHash.ts entries/cache/tags.ts entries/cache/createCacheStore.ts entries/config/envSchema.ts entries/contracts/serviceTokens.ts entries/contracts/container.ts entries/contracts/di.ts entries/crypto/fieldEncryption.ts entries/crypto/mfaSecret.ts entries/database/factory.ts entries/database/seeders.ts entries/database/types.ts entries/errors/http.ts entries/http/bodySizeLimitMiddleware.ts entries/http/contentNegotiation.ts entries/http/csrfToken.ts entries/http/etag.ts entries/http/flashSession.ts entries/http/parseFormBody.ts entries/http/resources.ts entries/http/webErrorResponse.ts entries/http/webFormRequest.ts entries/jobs/dispatchWebhookJob.ts entries/lifecycle/gracefulShutdown.ts entries/metrics/prometheus.ts entries/openapi/registeredRoute.ts entries/pagination.ts entries/queue/createAppQueue.ts entries/queue/failedJobService.ts entries/queue/jobRunner.ts entries/queue/queueMetrics.ts entries/queue/publicQueue.ts entries/queue/types.ts entries/scheduler/schedule.ts entries/security/oauthState.ts entries/security/publicReads.ts entries/security/safeUrl.ts entries/security/stripeWebhook.ts entries/security/tokenExpiry.ts entries/security/totp.ts entries/storage/storage.ts entries/validation/rules.ts entries/view.ts --outdir dist --root . --target bun --external bun --external eta",
341
361
  "build:shims": "bun ../../scripts/write-core-shared-shims.ts"
342
362
  },
343
363
  "publishConfig": {