@cequrebackends/cequre-ts 0.14.0 → 0.15.0
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/dist/adapters/bun/index.js +2 -2
- package/dist/adapters/node/index.js +2 -2
- package/dist/adapters/vercel/index.js +51 -15
- package/dist/adapters/vercel/vercel-cron.d.ts +6 -1
- package/dist/adapters/vercel/vercel-queue.d.ts +6 -1
- package/dist/adapters/vercel/vercel-storage.d.ts +1 -1
- package/dist/{index-8bhn0nb4.js → index-6vf0r9nh.js} +18 -7
- package/dist/{index-7xxm1add.js → index-z2xccrdm.js} +1 -1
- package/dist/index.js +2 -2
- package/package.json +11 -11
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "../../index-mfqj7cwr.js";
|
|
16
16
|
import {
|
|
17
17
|
CequreQueueManager
|
|
18
|
-
} from "../../index-
|
|
18
|
+
} from "../../index-z2xccrdm.js";
|
|
19
19
|
import {
|
|
20
20
|
CequreError
|
|
21
21
|
} from "../../index-qzzg2p5r.js";
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
init_bun_redis_cache,
|
|
25
25
|
init_logger,
|
|
26
26
|
logger
|
|
27
|
-
} from "../../index-
|
|
27
|
+
} from "../../index-6vf0r9nh.js";
|
|
28
28
|
import {
|
|
29
29
|
ulid
|
|
30
30
|
} from "../../index-cpw1bjf1.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
CequreQueueManager
|
|
4
|
-
} from "../../index-
|
|
4
|
+
} from "../../index-z2xccrdm.js";
|
|
5
5
|
import {
|
|
6
6
|
CequreError
|
|
7
7
|
} from "../../index-qzzg2p5r.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
exports_logger,
|
|
10
10
|
init_logger,
|
|
11
11
|
logger
|
|
12
|
-
} from "../../index-
|
|
12
|
+
} from "../../index-6vf0r9nh.js";
|
|
13
13
|
import {
|
|
14
14
|
__toCommonJS,
|
|
15
15
|
ulid
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
init_logger,
|
|
5
5
|
init_upstash_kv,
|
|
6
6
|
logger
|
|
7
|
-
} from "../../index-
|
|
7
|
+
} from "../../index-6vf0r9nh.js";
|
|
8
8
|
import {
|
|
9
9
|
ulid
|
|
10
10
|
} from "../../index-cpw1bjf1.js";
|
|
@@ -41,7 +41,20 @@ class VercelCronProvider {
|
|
|
41
41
|
this.jobs.set(name, { name, schedule, handler });
|
|
42
42
|
logger.info(`[Cequre Cron (Vercel)] Registered "${name}" with schedule "${schedule}". ` + `Add to vercel.json crons: { "path": "/_cron/${name}", "schedule": "${schedule}" }`);
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
verifyCronSecret(request) {
|
|
45
|
+
const cronSecret = process.env.CRON_SECRET;
|
|
46
|
+
if (!cronSecret) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
const authHeader = request.headers.get("authorization");
|
|
50
|
+
const customHeader = request.headers.get("x-cron-secret");
|
|
51
|
+
const bearerSecret = authHeader?.startsWith("Bearer ") ? authHeader.substring(7) : null;
|
|
52
|
+
return bearerSecret === cronSecret || customHeader === cronSecret;
|
|
53
|
+
}
|
|
54
|
+
async execute(name, request) {
|
|
55
|
+
if (request && !this.verifyCronSecret(request)) {
|
|
56
|
+
throw new Error(`[Cequre Cron (Vercel)] Unauthorized cron invocation for "${name}".`);
|
|
57
|
+
}
|
|
45
58
|
const job = this.jobs.get(name);
|
|
46
59
|
if (!job) {
|
|
47
60
|
throw new Error(`[Cequre Cron (Vercel)] Job "${name}" not found.`);
|
|
@@ -136,19 +149,21 @@ class VercelStorageProvider {
|
|
|
136
149
|
}
|
|
137
150
|
}
|
|
138
151
|
async saveFile(file, options) {
|
|
152
|
+
if (!this.token) {
|
|
153
|
+
throw new Error("[Cequre Storage (Vercel)] BLOB_READ_WRITE_TOKEN is not configured.");
|
|
154
|
+
}
|
|
139
155
|
const ext = file.name ? file.name.substring(file.name.lastIndexOf(".")) : "";
|
|
140
156
|
const safeName = options?.filename ? options.filename : `${ulid()}${ext}`;
|
|
141
157
|
const buffer = await file.arrayBuffer();
|
|
142
|
-
const res = await fetch(
|
|
143
|
-
method: "
|
|
158
|
+
const res = await fetch(`https://blob.vercel.com/${encodeURIComponent(safeName)}`, {
|
|
159
|
+
method: "PUT",
|
|
144
160
|
headers: {
|
|
145
161
|
Authorization: `Bearer ${this.token}`,
|
|
146
|
-
"
|
|
162
|
+
"x-api-version": "7",
|
|
163
|
+
"x-add-random-suffix": "0",
|
|
164
|
+
"content-type": file.type || "application/octet-stream"
|
|
147
165
|
},
|
|
148
|
-
body:
|
|
149
|
-
pathname: safeName,
|
|
150
|
-
payload: Array.from(new Uint8Array(buffer))
|
|
151
|
-
})
|
|
166
|
+
body: buffer
|
|
152
167
|
});
|
|
153
168
|
if (!res.ok) {
|
|
154
169
|
throw new Error(`Vercel Blob upload failed: ${res.status} ${await res.text()}`);
|
|
@@ -162,17 +177,23 @@ class VercelStorageProvider {
|
|
|
162
177
|
url: blob.url
|
|
163
178
|
};
|
|
164
179
|
}
|
|
165
|
-
async deleteFile(
|
|
166
|
-
|
|
167
|
-
|
|
180
|
+
async deleteFile(filenameOrUrl) {
|
|
181
|
+
if (!this.token) {
|
|
182
|
+
console.warn("[Cequre Storage (Vercel)] BLOB_READ_WRITE_TOKEN not configured.");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const url = filenameOrUrl.startsWith("http") ? filenameOrUrl : `https://blob.vercel.com/${filenameOrUrl}`;
|
|
186
|
+
const res = await fetch("https://blob.vercel.com/delete", {
|
|
187
|
+
method: "POST",
|
|
168
188
|
headers: {
|
|
169
189
|
Authorization: `Bearer ${this.token}`,
|
|
190
|
+
"x-api-version": "7",
|
|
170
191
|
"Content-Type": "application/json"
|
|
171
192
|
},
|
|
172
|
-
body: JSON.stringify({
|
|
193
|
+
body: JSON.stringify({ urls: [url] })
|
|
173
194
|
});
|
|
174
195
|
if (!res.ok && res.status !== 404) {
|
|
175
|
-
console.error(`[Cequre Storage (Vercel)] Failed to delete ${
|
|
196
|
+
console.error(`[Cequre Storage (Vercel)] Failed to delete ${filenameOrUrl}:`, await res.text());
|
|
176
197
|
}
|
|
177
198
|
}
|
|
178
199
|
}
|
|
@@ -221,7 +242,22 @@ class VercelQueueProvider {
|
|
|
221
242
|
this.workers.set(queueName, handler);
|
|
222
243
|
logger.info(`[Cequre Queue (Vercel)] Worker registered for queue "${queueName}". Route: /_queue/${queueName}`);
|
|
223
244
|
}
|
|
224
|
-
async
|
|
245
|
+
async verifySignature(request) {
|
|
246
|
+
const signature = request.headers.get("upstash-signature");
|
|
247
|
+
const currentKey = process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
248
|
+
const nextKey = process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
249
|
+
if (!currentKey && !nextKey) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
if (!signature) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
async processDelivery(queueName, body, request) {
|
|
258
|
+
if (request && !await this.verifySignature(request)) {
|
|
259
|
+
throw new Error(`[Cequre Queue (Vercel)] Invalid QStash signature for queue "${queueName}".`);
|
|
260
|
+
}
|
|
225
261
|
const handler = this.workers.get(queueName);
|
|
226
262
|
if (!handler) {
|
|
227
263
|
throw new Error(`[Cequre Queue (Vercel)] No worker for queue "${queueName}".`);
|
|
@@ -16,10 +16,15 @@ import type { CronProvider } from "../../shared/core/types";
|
|
|
16
16
|
export declare class VercelCronProvider implements CronProvider {
|
|
17
17
|
private jobs;
|
|
18
18
|
registerJob(name: string, schedule: string, handler: () => void | Promise<void>): void;
|
|
19
|
+
/**
|
|
20
|
+
* Verifies the Vercel Cron request secret if CRON_SECRET environment variable is set.
|
|
21
|
+
* Vercel sends `Authorization: Bearer <CRON_SECRET>` or `x-cron-secret` header.
|
|
22
|
+
*/
|
|
23
|
+
verifyCronSecret(request: Request): boolean;
|
|
19
24
|
/**
|
|
20
25
|
* Execute a cron job by name. Called by the /_cron/:name route handler.
|
|
21
26
|
*/
|
|
22
|
-
execute(name: string): Promise<void>;
|
|
27
|
+
execute(name: string, request?: Request): Promise<void>;
|
|
23
28
|
/**
|
|
24
29
|
* Returns all registered cron jobs for vercel.json generation.
|
|
25
30
|
*/
|
|
@@ -22,10 +22,15 @@ export declare class VercelQueueProvider {
|
|
|
22
22
|
constructor();
|
|
23
23
|
enqueue<T = any>(queueName: string, jobName: string, data: T, options?: any): Promise<string>;
|
|
24
24
|
registerWorker<T = any>(queueName: string, handler: (job: QueueJob) => Promise<void>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies QStash signature for incoming webhook deliveries.
|
|
27
|
+
* QStash passes `upstash-signature` header.
|
|
28
|
+
*/
|
|
29
|
+
verifySignature(request: Request): Promise<boolean>;
|
|
25
30
|
/**
|
|
26
31
|
* Process a QStash webhook delivery. Called by the /_queue/:name route.
|
|
27
32
|
*/
|
|
28
|
-
processDelivery(queueName: string, body: any): Promise<void>;
|
|
33
|
+
processDelivery(queueName: string, body: any, request?: Request): Promise<void>;
|
|
29
34
|
startWorkers(): void;
|
|
30
35
|
}
|
|
31
36
|
export {};
|
|
@@ -122,7 +122,16 @@ var log = null;
|
|
|
122
122
|
var init_memory = () => {};
|
|
123
123
|
|
|
124
124
|
// shared/utils/kv/adapters/sqlite.ts
|
|
125
|
-
|
|
125
|
+
function getBunDatabase() {
|
|
126
|
+
if (!BunDatabase) {
|
|
127
|
+
try {
|
|
128
|
+
BunDatabase = __require("bun:sqlite").Database;
|
|
129
|
+
} catch {
|
|
130
|
+
throw new Error("[Cequre KV (SQLite)] SQLite adapter requires Bun runtime (bun:sqlite).");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return BunDatabase;
|
|
134
|
+
}
|
|
126
135
|
function getLog2() {
|
|
127
136
|
if (!log2) {
|
|
128
137
|
const { createLogger } = (init_logger(), __toCommonJS(exports_logger));
|
|
@@ -144,6 +153,7 @@ class SQLiteAdapter {
|
|
|
144
153
|
stmtCount;
|
|
145
154
|
constructor(options) {
|
|
146
155
|
const dbPath = options?.path ?? "./data/cequre-kv.sqlite";
|
|
156
|
+
const DB = getBunDatabase();
|
|
147
157
|
if (dbPath !== ":memory:") {
|
|
148
158
|
const dir = dbPath.substring(0, dbPath.lastIndexOf("/"));
|
|
149
159
|
if (dir) {
|
|
@@ -153,7 +163,7 @@ class SQLiteAdapter {
|
|
|
153
163
|
} catch {}
|
|
154
164
|
}
|
|
155
165
|
}
|
|
156
|
-
this.db = new
|
|
166
|
+
this.db = new DB(dbPath);
|
|
157
167
|
this.db.run("PRAGMA journal_mode = WAL");
|
|
158
168
|
this.db.run("PRAGMA synchronous = NORMAL");
|
|
159
169
|
this.db.run(`
|
|
@@ -255,7 +265,7 @@ class SQLiteAdapter {
|
|
|
255
265
|
getLog2().debug("SQLite KV adapter closed");
|
|
256
266
|
}
|
|
257
267
|
}
|
|
258
|
-
var log2 = null;
|
|
268
|
+
var BunDatabase = null, log2 = null;
|
|
259
269
|
var init_sqlite = () => {};
|
|
260
270
|
|
|
261
271
|
// adapters/bun/bun-redis-cache.ts
|
|
@@ -552,7 +562,7 @@ function getErrorKV() {
|
|
|
552
562
|
return kvStore;
|
|
553
563
|
}
|
|
554
564
|
function createStream() {
|
|
555
|
-
if (
|
|
565
|
+
if (env.NODE_ENV !== "production" && env.NODE_ENV !== "test") {
|
|
556
566
|
return pretty({
|
|
557
567
|
colorize: true,
|
|
558
568
|
translateTime: "yyyy-mm-dd HH:MM:ss.l",
|
|
@@ -638,11 +648,12 @@ function createLogger(component) {
|
|
|
638
648
|
}
|
|
639
649
|
return logger.child({ component });
|
|
640
650
|
}
|
|
641
|
-
var LOG_LEVEL, ERROR_LOG_KV, kvStore = null, consoleStream, logger;
|
|
651
|
+
var env, LOG_LEVEL, ERROR_LOG_KV, kvStore = null, consoleStream, logger;
|
|
642
652
|
var init_logger = __esm(() => {
|
|
643
653
|
init_kv();
|
|
644
|
-
|
|
645
|
-
|
|
654
|
+
env = typeof process !== "undefined" ? process.env : typeof Bun !== "undefined" ? Bun.env : {};
|
|
655
|
+
LOG_LEVEL = env.CEQURE_LOG_LEVEL || env.LOG_LEVEL || (env.NODE_ENV === "test" ? "silent" : "info");
|
|
656
|
+
ERROR_LOG_KV = env.CEQURE_ERROR_LOG_KV === "true";
|
|
646
657
|
consoleStream = createStream();
|
|
647
658
|
logger = consoleStream ? pino({ name: "cequre", level: LOG_LEVEL }, consoleStream) : pino({ name: "cequre", level: LOG_LEVEL });
|
|
648
659
|
if (ERROR_LOG_KV) {
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
} from "./index-mfqj7cwr.js";
|
|
32
32
|
import {
|
|
33
33
|
CequreQueueManager
|
|
34
|
-
} from "./index-
|
|
34
|
+
} from "./index-z2xccrdm.js";
|
|
35
35
|
import {
|
|
36
36
|
CequreError,
|
|
37
37
|
buildErrorResponse,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
init_kv,
|
|
49
49
|
init_logger,
|
|
50
50
|
logger
|
|
51
|
-
} from "./index-
|
|
51
|
+
} from "./index-6vf0r9nh.js";
|
|
52
52
|
import {
|
|
53
53
|
__require,
|
|
54
54
|
__toCommonJS,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cequrebackends/cequre-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "The Cequre Universal Runtime Engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -48,21 +48,21 @@
|
|
|
48
48
|
"build": "rm -rf dist && bun build ./index.ts ./shared/core/index.ts ./adapters/bun/index.ts ./adapters/node/index.ts ./adapters/vercel/index.ts --outdir ./dist --target bun --packages external --splitting --format esm && tsc --emitDeclarationOnly"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@sinclair/typebox": "^0.34.
|
|
52
|
-
"bullmq": "^5.
|
|
53
|
-
"effect": "^3.
|
|
54
|
-
"ioredis": "^5.
|
|
55
|
-
"jose": "^6.2.
|
|
56
|
-
"node-cron": "^
|
|
51
|
+
"@sinclair/typebox": "^0.34.52",
|
|
52
|
+
"bullmq": "^5.81.2",
|
|
53
|
+
"effect": "^3.22.0",
|
|
54
|
+
"ioredis": "^5.11.1",
|
|
55
|
+
"jose": "^6.2.4",
|
|
56
|
+
"node-cron": "^4.6.0",
|
|
57
57
|
"pino": "^10.3.1",
|
|
58
58
|
"pino-pretty": "^13.1.3",
|
|
59
|
-
"ws": "^8.
|
|
59
|
+
"ws": "^8.21.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@types/node": "^
|
|
62
|
+
"@types/node": "^26.1.1",
|
|
63
63
|
"@types/node-cron": "^3.0.11",
|
|
64
|
-
"@types/ws": "^8.
|
|
64
|
+
"@types/ws": "^8.18.1",
|
|
65
65
|
"openapi-typescript": "^7.13.0",
|
|
66
|
-
"typescript": "^
|
|
66
|
+
"typescript": "^7.0.2"
|
|
67
67
|
}
|
|
68
68
|
}
|