@upstash/qstash 0.0.9 → 0.0.12
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 +2 -2
- package/esm/_dnt.shims.js +0 -3
- package/esm/deps/deno.land/std@0.147.0/_wasm_crypto/lib/deno_std_wasm_crypto.generated.mjs +3159 -0
- package/esm/deps/deno.land/std@0.147.0/_wasm_crypto/mod.js +38 -0
- package/esm/deps/deno.land/std@0.147.0/crypto/_fnv/fnv32.js +24 -0
- package/esm/deps/deno.land/std@0.147.0/crypto/_fnv/fnv64.js +27 -0
- package/esm/deps/deno.land/std@0.147.0/crypto/_fnv/index.js +21 -0
- package/esm/deps/deno.land/std@0.147.0/crypto/_fnv/util.js +48 -0
- package/esm/deps/deno.land/std@0.147.0/crypto/mod.js +149 -0
- package/esm/deps/deno.land/{std@0.144.0 → std@0.147.0}/encoding/base64.js +0 -0
- package/esm/deps/deno.land/{std@0.144.0 → std@0.147.0}/encoding/base64url.js +1 -1
- package/esm/deps.js +1 -0
- package/esm/entrypoints/cloudflare.js +12 -0
- package/esm/entrypoints/nextjs.js +8 -3
- package/esm/pkg/client/client.js +130 -0
- package/esm/pkg/client/endpoints.js +63 -0
- package/esm/pkg/client/error.js +9 -0
- package/esm/pkg/client/http.js +81 -0
- package/esm/pkg/client/messages.js +64 -0
- package/esm/pkg/client/schedules.js +41 -0
- package/esm/pkg/client/topics.js +71 -0
- package/esm/pkg/client/types.js +1 -0
- package/esm/{consumer.js → pkg/consumer.js} +18 -8
- package/package.json +11 -7
- package/script/_dnt.shims.js +1 -5
- package/script/deps/deno.land/std@0.147.0/_wasm_crypto/lib/deno_std_wasm_crypto.generated.mjs +3167 -0
- package/script/deps/deno.land/std@0.147.0/_wasm_crypto/mod.js +43 -0
- package/script/deps/deno.land/std@0.147.0/crypto/_fnv/fnv32.js +29 -0
- package/script/deps/deno.land/std@0.147.0/crypto/_fnv/fnv64.js +32 -0
- package/script/deps/deno.land/std@0.147.0/crypto/_fnv/index.js +25 -0
- package/script/deps/deno.land/std@0.147.0/crypto/_fnv/util.js +54 -0
- package/script/deps/deno.land/std@0.147.0/crypto/mod.js +175 -0
- package/script/deps/deno.land/{std@0.144.0 → std@0.147.0}/encoding/base64.js +0 -0
- package/script/deps/deno.land/{std@0.144.0 → std@0.147.0}/encoding/base64url.js +1 -2
- package/script/deps.js +27 -0
- package/script/entrypoints/cloudflare.js +42 -0
- package/script/entrypoints/nextjs.js +31 -3
- package/script/pkg/client/client.js +134 -0
- package/script/pkg/client/endpoints.js +67 -0
- package/script/pkg/client/error.js +13 -0
- package/script/pkg/client/http.js +85 -0
- package/script/pkg/client/messages.js +68 -0
- package/script/pkg/client/schedules.js +45 -0
- package/script/pkg/client/topics.js +75 -0
- package/script/pkg/client/types.js +2 -0
- package/script/{consumer.js → pkg/consumer.js} +18 -31
- package/types/_dnt.shims.d.ts +1 -4
- package/types/deps/deno.land/std@0.147.0/_wasm_crypto/lib/deno_std_wasm_crypto.generated.d.mts +125 -0
- package/types/deps/deno.land/std@0.147.0/_wasm_crypto/mod.d.ts +12 -0
- package/types/deps/deno.land/std@0.147.0/crypto/_fnv/fnv32.d.ts +2 -0
- package/types/deps/deno.land/std@0.147.0/crypto/_fnv/fnv64.d.ts +2 -0
- package/types/deps/deno.land/std@0.147.0/crypto/_fnv/index.d.ts +1 -0
- package/types/deps/deno.land/std@0.147.0/crypto/_fnv/util.d.ts +13 -0
- package/types/deps/deno.land/std@0.147.0/crypto/mod.d.ts +53 -0
- package/types/deps/deno.land/{std@0.144.0 → std@0.147.0}/encoding/base64.d.ts +0 -0
- package/types/deps/deno.land/{std@0.144.0 → std@0.147.0}/encoding/base64url.d.ts +0 -1
- package/types/deps.d.ts +1 -0
- package/types/entrypoints/cloudflare.d.ts +5 -0
- package/types/entrypoints/nextjs.d.ts +6 -0
- package/types/pkg/client/client.d.ts +193 -0
- package/types/pkg/client/endpoints.d.ts +59 -0
- package/types/pkg/client/error.d.ts +6 -0
- package/types/pkg/client/http.d.ts +66 -0
- package/types/pkg/client/messages.d.ts +66 -0
- package/types/pkg/client/schedules.d.ts +63 -0
- package/types/pkg/client/topics.d.ts +64 -0
- package/types/pkg/client/types.d.ts +20 -0
- package/types/{consumer.d.ts → pkg/consumer.d.ts} +14 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Endpoints = void 0;
|
|
4
|
+
class Endpoints {
|
|
5
|
+
constructor(http) {
|
|
6
|
+
Object.defineProperty(this, "http", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
this.http = http;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a new endpoint with the given name.
|
|
16
|
+
*/
|
|
17
|
+
async create(req) {
|
|
18
|
+
return await this.http.request({
|
|
19
|
+
method: "POST",
|
|
20
|
+
path: ["v1", "endpoints"],
|
|
21
|
+
body: JSON.stringify(req),
|
|
22
|
+
headers: { "Content-Type": "application/json" },
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a list of all endpoints.
|
|
27
|
+
*/
|
|
28
|
+
async list() {
|
|
29
|
+
return await this.http.request({
|
|
30
|
+
method: "GET",
|
|
31
|
+
path: ["v1", "endpoints"],
|
|
32
|
+
headers: { "Content-Type": "application/json" },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get a single endpoint.
|
|
37
|
+
*/
|
|
38
|
+
async get(req) {
|
|
39
|
+
return await this.http.request({
|
|
40
|
+
method: "GET",
|
|
41
|
+
path: ["v1", "endpoints", req.id],
|
|
42
|
+
headers: { "Content-Type": "application/json" },
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Update a endpoint
|
|
47
|
+
*/
|
|
48
|
+
async update(req) {
|
|
49
|
+
return await this.http.request({
|
|
50
|
+
method: "PUT",
|
|
51
|
+
path: ["v1", "endpoints", req.id],
|
|
52
|
+
body: JSON.stringify({ url: req.url }),
|
|
53
|
+
headers: { "Content-Type": "application/json" },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Delete a endpoint.
|
|
58
|
+
*/
|
|
59
|
+
async delete(req) {
|
|
60
|
+
return await this.http.request({
|
|
61
|
+
method: "DELETE",
|
|
62
|
+
path: ["v1", "endpoints", req.id],
|
|
63
|
+
headers: { "Content-Type": "application/json" },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.Endpoints = Endpoints;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QstashError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Result of 500 Internal Server Error
|
|
6
|
+
*/
|
|
7
|
+
class QstashError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "QstashError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.QstashError = QstashError;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpClient = void 0;
|
|
4
|
+
const error_js_1 = require("./error.js");
|
|
5
|
+
class HttpClient {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
Object.defineProperty(this, "baseUrl", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: void 0
|
|
12
|
+
});
|
|
13
|
+
Object.defineProperty(this, "authorization", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: void 0
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(this, "options", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: void 0
|
|
24
|
+
});
|
|
25
|
+
Object.defineProperty(this, "retry", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
configurable: true,
|
|
28
|
+
writable: true,
|
|
29
|
+
value: void 0
|
|
30
|
+
});
|
|
31
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
32
|
+
this.authorization = config.authorization;
|
|
33
|
+
if (typeof config?.retry === "boolean" && config?.retry === false) {
|
|
34
|
+
this.retry = {
|
|
35
|
+
attempts: 1,
|
|
36
|
+
backoff: () => 0,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.retry = {
|
|
41
|
+
attempts: config?.retry?.retries ?? 5,
|
|
42
|
+
backoff: config?.retry?.backoff ??
|
|
43
|
+
((retryCount) => Math.exp(retryCount) * 50),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async request(req) {
|
|
48
|
+
const headers = new Headers(req.headers);
|
|
49
|
+
headers.set("Upstash-Authorization", `Bearer ${this.authorization}`);
|
|
50
|
+
const requestOptions = {
|
|
51
|
+
method: req.method,
|
|
52
|
+
headers,
|
|
53
|
+
body: req.body,
|
|
54
|
+
keepalive: req.keepalive,
|
|
55
|
+
};
|
|
56
|
+
const url = new URL([this.baseUrl, ...(req.path ?? [])].join("/"));
|
|
57
|
+
if (req.query) {
|
|
58
|
+
for (const [key, value] of Object.entries(req.query)) {
|
|
59
|
+
if (typeof value !== "undefined") {
|
|
60
|
+
url.searchParams.set(key, value.toString());
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let res = null;
|
|
65
|
+
let error = null;
|
|
66
|
+
for (let i = 0; i <= this.retry.attempts; i++) {
|
|
67
|
+
try {
|
|
68
|
+
res = await fetch(url.toString(), requestOptions);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
error = err;
|
|
73
|
+
await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (!res) {
|
|
77
|
+
throw error ?? new Error("Exhausted all retries");
|
|
78
|
+
}
|
|
79
|
+
if (res.status < 200 || res.status >= 300) {
|
|
80
|
+
throw new error_js_1.QstashError(await res.text() ?? res.statusText);
|
|
81
|
+
}
|
|
82
|
+
return (await res.json());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.HttpClient = HttpClient;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Messages = void 0;
|
|
4
|
+
class Messages {
|
|
5
|
+
constructor(http) {
|
|
6
|
+
Object.defineProperty(this, "http", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
this.http = http;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get a message
|
|
16
|
+
*/
|
|
17
|
+
async get(req) {
|
|
18
|
+
return await this.http.request({
|
|
19
|
+
method: "GET",
|
|
20
|
+
path: ["v1", "messages", req.id],
|
|
21
|
+
headers: { "Content-Type": "application/json" },
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* List your messages
|
|
26
|
+
*/
|
|
27
|
+
async list(req) {
|
|
28
|
+
return await this.http.request({
|
|
29
|
+
method: "GET",
|
|
30
|
+
path: ["v1", "messages"],
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
query: { cursor: req?.cursor },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* List logs from a message
|
|
37
|
+
*/
|
|
38
|
+
async logs(req) {
|
|
39
|
+
return await this.http.request({
|
|
40
|
+
method: "GET",
|
|
41
|
+
path: ["v1", "messages", req.id, "logs"],
|
|
42
|
+
headers: { "Content-Type": "application/json" },
|
|
43
|
+
query: { cursor: req.cursor },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* List tasks for a message
|
|
48
|
+
*/
|
|
49
|
+
async tasks(req) {
|
|
50
|
+
return await this.http.request({
|
|
51
|
+
method: "GET",
|
|
52
|
+
path: ["v1", "messages", req.id, "tasks"],
|
|
53
|
+
headers: { "Content-Type": "application/json" },
|
|
54
|
+
query: { cursor: req.cursor },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Cancel a topic by name or id.
|
|
59
|
+
*/
|
|
60
|
+
async delete(req) {
|
|
61
|
+
return await this.http.request({
|
|
62
|
+
method: "DELETE",
|
|
63
|
+
path: ["v1", "messages", req.id],
|
|
64
|
+
headers: { "Content-Type": "application/json" },
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.Messages = Messages;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Schedules = void 0;
|
|
4
|
+
class Schedules {
|
|
5
|
+
constructor(http) {
|
|
6
|
+
Object.defineProperty(this, "http", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
this.http = http;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get a schedule
|
|
16
|
+
*/
|
|
17
|
+
async get(req) {
|
|
18
|
+
return await this.http.request({
|
|
19
|
+
method: "GET",
|
|
20
|
+
path: ["v1", "schedules", req.id],
|
|
21
|
+
headers: { "Content-Type": "application/json" },
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* List your schedules
|
|
26
|
+
*/
|
|
27
|
+
async list() {
|
|
28
|
+
return await this.http.request({
|
|
29
|
+
method: "GET",
|
|
30
|
+
path: ["v1", "schedules"],
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Delete a schedule
|
|
36
|
+
*/
|
|
37
|
+
async delete(req) {
|
|
38
|
+
return await this.http.request({
|
|
39
|
+
method: "DELETE",
|
|
40
|
+
path: ["v1", "schedules", req.id],
|
|
41
|
+
headers: { "Content-Type": "application/json" },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.Schedules = Schedules;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Topics = void 0;
|
|
4
|
+
class Topics {
|
|
5
|
+
constructor(http) {
|
|
6
|
+
Object.defineProperty(this, "http", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
this.http = http;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a new topic with the given name.
|
|
16
|
+
*/
|
|
17
|
+
async create(req) {
|
|
18
|
+
return await this.http.request({
|
|
19
|
+
method: "POST",
|
|
20
|
+
path: ["v1", "topics"],
|
|
21
|
+
headers: { "Content-Type": "application/json" },
|
|
22
|
+
body: JSON.stringify({ name: req.name }),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a list of all topics.
|
|
27
|
+
*/
|
|
28
|
+
async list() {
|
|
29
|
+
return await this.http.request({
|
|
30
|
+
method: "GET",
|
|
31
|
+
path: ["v1", "topics"],
|
|
32
|
+
headers: { "Content-Type": "application/json" },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get a single topic by name or id.
|
|
37
|
+
*/
|
|
38
|
+
async get(req) {
|
|
39
|
+
const idOrName = req.id ?? req.name;
|
|
40
|
+
if (!idOrName) {
|
|
41
|
+
throw new Error("Either id or name must be provided");
|
|
42
|
+
}
|
|
43
|
+
return await this.http.request({
|
|
44
|
+
method: "GET",
|
|
45
|
+
path: ["v1", "topics", idOrName],
|
|
46
|
+
headers: { "Content-Type": "application/json" },
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Update a topic
|
|
51
|
+
*/
|
|
52
|
+
async update(req) {
|
|
53
|
+
return await this.http.request({
|
|
54
|
+
method: "PUT",
|
|
55
|
+
path: ["v1", "topics", req.id],
|
|
56
|
+
body: JSON.stringify({ name: req.name }),
|
|
57
|
+
headers: { "Content-Type": "application/json" },
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Delete a topic by name or id.
|
|
62
|
+
*/
|
|
63
|
+
async delete(req) {
|
|
64
|
+
const idOrName = req.id ?? req.name;
|
|
65
|
+
if (!idOrName) {
|
|
66
|
+
throw new Error("Either id or name must be provided");
|
|
67
|
+
}
|
|
68
|
+
return await this.http.request({
|
|
69
|
+
method: "DELETE",
|
|
70
|
+
path: ["v1", "topics", idOrName],
|
|
71
|
+
headers: { "Content-Type": "application/json" },
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.Topics = Topics;
|
|
@@ -1,31 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
3
|
exports.Consumer = exports.SignatureError = void 0;
|
|
27
|
-
const
|
|
28
|
-
const base64url = __importStar(require("./deps/deno.land/std@0.144.0/encoding/base64url.js"));
|
|
4
|
+
const deps_js_1 = require("../deps.js");
|
|
29
5
|
class SignatureError extends Error {
|
|
30
6
|
constructor(message) {
|
|
31
7
|
super(message);
|
|
@@ -50,8 +26,15 @@ class Consumer {
|
|
|
50
26
|
writable: true,
|
|
51
27
|
value: void 0
|
|
52
28
|
});
|
|
29
|
+
Object.defineProperty(this, "subtleCrypto", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
configurable: true,
|
|
32
|
+
writable: true,
|
|
33
|
+
value: void 0
|
|
34
|
+
});
|
|
53
35
|
this.currentSigningKey = config.currentSigningKey;
|
|
54
36
|
this.nextSigningKey = config.nextSigningKey;
|
|
37
|
+
this.subtleCrypto = config.subtleCrypto;
|
|
55
38
|
}
|
|
56
39
|
/**
|
|
57
40
|
* Verify the signature of a request.
|
|
@@ -78,12 +61,12 @@ class Consumer {
|
|
|
78
61
|
throw new SignatureError("`Upstash-Signature` header is not a valid signature");
|
|
79
62
|
}
|
|
80
63
|
const [header, payload, signature] = parts;
|
|
81
|
-
const k = await
|
|
82
|
-
const isValid = await
|
|
64
|
+
const k = await this.subtleCrypto.importKey("raw", new TextEncoder().encode(key), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
|
|
65
|
+
const isValid = await this.subtleCrypto.verify({ name: "HMAC" }, k, deps_js_1.base64Url.decode(signature), new TextEncoder().encode(`${header}.${payload}`));
|
|
83
66
|
if (!isValid) {
|
|
84
67
|
throw new SignatureError("signature does not match");
|
|
85
68
|
}
|
|
86
|
-
const p = JSON.parse(new TextDecoder().decode(
|
|
69
|
+
const p = JSON.parse(new TextDecoder().decode(deps_js_1.base64Url.decode(payload)));
|
|
87
70
|
console.log(JSON.stringify(p, null, 2));
|
|
88
71
|
if (p.iss !== "Upstash") {
|
|
89
72
|
throw new SignatureError(`invalid issuer: ${p.iss}`);
|
|
@@ -99,9 +82,13 @@ class Consumer {
|
|
|
99
82
|
if (now < p.nbf) {
|
|
100
83
|
throw new SignatureError("token is not yet valid");
|
|
101
84
|
}
|
|
102
|
-
const bodyHash = await
|
|
103
|
-
|
|
104
|
-
|
|
85
|
+
const bodyHash = await this.subtleCrypto.digest("SHA-256", typeof req.body === "string"
|
|
86
|
+
? new TextEncoder().encode(req.body)
|
|
87
|
+
: req.body);
|
|
88
|
+
const padding = new RegExp(/=+$/);
|
|
89
|
+
if (p.body.replace(padding, "") !=
|
|
90
|
+
deps_js_1.base64Url.encode(bodyHash).replace(padding, "")) {
|
|
91
|
+
throw new SignatureError(`body hash does not match, want: ${p.body}, got: ${deps_js_1.base64Url.encode(bodyHash)}`);
|
|
105
92
|
}
|
|
106
93
|
return true;
|
|
107
94
|
}
|
package/types/_dnt.shims.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { Deno } from "@deno/shim-deno";
|
|
2
|
-
export { Deno } from "@deno/shim-deno";
|
|
3
1
|
export { crypto, type Crypto, type SubtleCrypto, type AlgorithmIdentifier, type Algorithm, type RsaOaepParams, type BufferSource, type AesCtrParams, type AesCbcParams, type AesGcmParams, type CryptoKey, type KeyAlgorithm, type KeyType, type KeyUsage, type EcdhKeyDeriveParams, type HkdfParams, type HashAlgorithmIdentifier, type Pbkdf2Params, type AesDerivedKeyParams, type HmacImportParams, type JsonWebKey, type RsaOtherPrimesInfo, type KeyFormat, type RsaHashedKeyGenParams, type RsaKeyGenParams, type BigInteger, type EcKeyGenParams, type NamedCurve, type CryptoKeyPair, type AesKeyGenParams, type HmacKeyGenParams, type RsaHashedImportParams, type EcKeyImportParams, type AesKeyAlgorithm, type RsaPssParams, type EcdsaParams } from "@deno/shim-crypto";
|
|
4
|
-
export declare const dntGlobalThis: Omit<typeof globalThis, "crypto"
|
|
5
|
-
Deno: typeof Deno;
|
|
2
|
+
export declare const dntGlobalThis: Omit<typeof globalThis, "crypto"> & {
|
|
6
3
|
crypto: import("@deno/shim-crypto").Crypto;
|
|
7
4
|
};
|
package/types/deps/deno.land/std@0.147.0/_wasm_crypto/lib/deno_std_wasm_crypto.generated.d.mts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the digest of the given `data` using the given hash `algorithm`.
|
|
3
|
+
*
|
|
4
|
+
* `length` will usually be left `undefined` to use the default length for
|
|
5
|
+
* the algorithm. For algorithms with variable-length output, it can be used
|
|
6
|
+
* to specify a non-negative integer number of bytes.
|
|
7
|
+
*
|
|
8
|
+
* An error will be thrown if `algorithm` is not a supported hash algorithm or
|
|
9
|
+
* `length` is not a supported length for the algorithm.
|
|
10
|
+
* @param {string} algorithm
|
|
11
|
+
* @param {Uint8Array} data
|
|
12
|
+
* @param {number | undefined} length
|
|
13
|
+
* @returns {Uint8Array}
|
|
14
|
+
*/
|
|
15
|
+
export function digest(algorithm: string, data: Uint8Array, length: number | undefined): Uint8Array;
|
|
16
|
+
/** Instantiates an instance of the Wasm module returning its functions.
|
|
17
|
+
* @remarks It is safe to call this multiple times and once successfully
|
|
18
|
+
* loaded it will always return a reference to the same object.
|
|
19
|
+
*/
|
|
20
|
+
export function instantiate(): {
|
|
21
|
+
digest: typeof digest;
|
|
22
|
+
DigestContext: typeof DigestContext;
|
|
23
|
+
};
|
|
24
|
+
/** Instantiates an instance of the Wasm module along with its exports.
|
|
25
|
+
* @remarks It is safe to call this multiple times and once successfully
|
|
26
|
+
* loaded it will always return a reference to the same object.
|
|
27
|
+
* @returns {{
|
|
28
|
+
* instance: WebAssembly.Instance;
|
|
29
|
+
* exports: { digest: typeof digest; DigestContext : typeof DigestContext }
|
|
30
|
+
* }}
|
|
31
|
+
*/
|
|
32
|
+
export function instantiateWithInstance(): {
|
|
33
|
+
instance: WebAssembly.Instance;
|
|
34
|
+
exports: {
|
|
35
|
+
digest: typeof digest;
|
|
36
|
+
DigestContext: typeof DigestContext;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
/** Gets if the Wasm module has been instantiated. */
|
|
40
|
+
export function isInstantiated(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* A context for incrementally computing a digest using a given hash algorithm.
|
|
43
|
+
*/
|
|
44
|
+
export class DigestContext {
|
|
45
|
+
static __wrap(ptr: any): any;
|
|
46
|
+
/**
|
|
47
|
+
* Creates a new context incrementally computing a digest using the given
|
|
48
|
+
* hash algorithm.
|
|
49
|
+
*
|
|
50
|
+
* An error will be thrown if `algorithm` is not a supported hash algorithm.
|
|
51
|
+
* @param {string} algorithm
|
|
52
|
+
*/
|
|
53
|
+
constructor(algorithm: string);
|
|
54
|
+
__destroy_into_raw(): number | undefined;
|
|
55
|
+
ptr: number | undefined;
|
|
56
|
+
free(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Update the digest's internal state with the additional input `data`.
|
|
59
|
+
*
|
|
60
|
+
* If the `data` array view is large, it will be split into subarrays (via
|
|
61
|
+
* JavaScript bindings) which will be processed sequentially in order to
|
|
62
|
+
* limit the amount of memory that needs to be allocated in the Wasm heap.
|
|
63
|
+
* @param {Uint8Array} data
|
|
64
|
+
*/
|
|
65
|
+
update(data: Uint8Array): void;
|
|
66
|
+
/**
|
|
67
|
+
* Returns the digest of the input data so far. This may be called repeatedly
|
|
68
|
+
* without side effects.
|
|
69
|
+
*
|
|
70
|
+
* `length` will usually be left `undefined` to use the default length for
|
|
71
|
+
* the algorithm. For algorithms with variable-length output, it can be used
|
|
72
|
+
* to specify a non-negative integer number of bytes.
|
|
73
|
+
*
|
|
74
|
+
* An error will be thrown if `algorithm` is not a supported hash algorithm or
|
|
75
|
+
* `length` is not a supported length for the algorithm.
|
|
76
|
+
* @param {number | undefined} length
|
|
77
|
+
* @returns {Uint8Array}
|
|
78
|
+
*/
|
|
79
|
+
digest(length: number | undefined): Uint8Array;
|
|
80
|
+
/**
|
|
81
|
+
* Returns the digest of the input data so far, and resets this context to
|
|
82
|
+
* its initial state, as though it has not yet been provided with any input
|
|
83
|
+
* data. (It will still use the same algorithm.)
|
|
84
|
+
*
|
|
85
|
+
* `length` will usually be left `undefined` to use the default length for
|
|
86
|
+
* the algorithm. For algorithms with variable-length output, it can be used
|
|
87
|
+
* to specify a non-negative integer number of bytes.
|
|
88
|
+
*
|
|
89
|
+
* An error will be thrown if `algorithm` is not a supported hash algorithm or
|
|
90
|
+
* `length` is not a supported length for the algorithm.
|
|
91
|
+
* @param {number | undefined} length
|
|
92
|
+
* @returns {Uint8Array}
|
|
93
|
+
*/
|
|
94
|
+
digestAndReset(length: number | undefined): Uint8Array;
|
|
95
|
+
/**
|
|
96
|
+
* Returns the digest of the input data so far, and then drops the context
|
|
97
|
+
* from memory on the Wasm side. This context must no longer be used, and any
|
|
98
|
+
* further method calls will result in null pointer errors being thrown.
|
|
99
|
+
* https://github.com/rustwasm/wasm-bindgen/blob/bf39cfd8/crates/backend/src/codegen.rs#L186
|
|
100
|
+
*
|
|
101
|
+
* `length` will usually be left `undefined` to use the default length for
|
|
102
|
+
* the algorithm. For algorithms with variable-length output, it can be used
|
|
103
|
+
* to specify a non-negative integer number of bytes.
|
|
104
|
+
*
|
|
105
|
+
* An error will be thrown if `algorithm` is not a supported hash algorithm or
|
|
106
|
+
* `length` is not a supported length for the algorithm.
|
|
107
|
+
* @param {number | undefined} length
|
|
108
|
+
* @returns {Uint8Array}
|
|
109
|
+
*/
|
|
110
|
+
digestAndDrop(length: number | undefined): Uint8Array;
|
|
111
|
+
/**
|
|
112
|
+
* Resets this context to its initial state, as though it has not yet been
|
|
113
|
+
* provided with any input data. (It will still use the same algorithm.)
|
|
114
|
+
*/
|
|
115
|
+
reset(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Returns a new `DigestContext` that is a copy of this one, i.e., using the
|
|
118
|
+
* same algorithm and with a copy of the same internal state.
|
|
119
|
+
*
|
|
120
|
+
* This may be a more efficient option for computing multiple digests that
|
|
121
|
+
* start with a common prefix.
|
|
122
|
+
* @returns {DigestContext}
|
|
123
|
+
*/
|
|
124
|
+
clone(): DigestContext;
|
|
125
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { DigestContext, instantiate as instantiateWasm, } from "./lib/deno_std_wasm_crypto.generated.js";
|
|
2
|
+
/**
|
|
3
|
+
* All cryptographic hash/digest algorithms supported by std/_wasm_crypto.
|
|
4
|
+
*
|
|
5
|
+
* For algorithms that are supported by WebCrypto, the name here must match the
|
|
6
|
+
* one used by WebCrypto. Otherwise we should prefer the formatting used in the
|
|
7
|
+
* official specification. All names are uppercase to facilitate case-insensitive
|
|
8
|
+
* comparisons required by the WebCrypto spec.
|
|
9
|
+
*/
|
|
10
|
+
export declare const digestAlgorithms: readonly ["BLAKE2B-256", "BLAKE2B-384", "BLAKE2B", "BLAKE2S", "BLAKE3", "KECCAK-224", "KECCAK-256", "KECCAK-384", "KECCAK-512", "SHA-384", "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512", "SHAKE128", "SHAKE256", "TIGER", "RIPEMD-160", "SHA-224", "SHA-256", "SHA-512", "MD4", "MD5", "SHA-1"];
|
|
11
|
+
/** An algorithm name supported by std/_wasm_crypto. */
|
|
12
|
+
export declare type DigestAlgorithm = typeof digestAlgorithms[number];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fnv: (name: string, buf: Uint8Array | undefined) => ArrayBuffer;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function swap32(val: number): number;
|
|
2
|
+
/**
|
|
3
|
+
* mul32 performs 32-bit multiplication, a * b
|
|
4
|
+
* @param a
|
|
5
|
+
* @param b
|
|
6
|
+
*/
|
|
7
|
+
export declare function mul32(a: number, b: number): number;
|
|
8
|
+
/**
|
|
9
|
+
* mul64 performs 64-bit multiplication with two 32-bit words
|
|
10
|
+
* @param [ah, al]
|
|
11
|
+
* @param [bh, bl]
|
|
12
|
+
*/
|
|
13
|
+
export declare function mul64([ah, al]: [number, number], [bh, bl]: [number, number]): [number, number];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as dntShim from "../../../../_dnt.shims.js";
|
|
2
|
+
import { DigestAlgorithm as WasmDigestAlgorithm } from "../_wasm_crypto/mod.js";
|
|
3
|
+
/**
|
|
4
|
+
* An wrapper for WebCrypto adding support for additional non-standard
|
|
5
|
+
* algorithms, but delegating to the runtime WebCrypto implementation whenever
|
|
6
|
+
* possible.
|
|
7
|
+
*/
|
|
8
|
+
declare const stdCrypto: {
|
|
9
|
+
subtle: {
|
|
10
|
+
/**
|
|
11
|
+
* Returns a new `Promise` object that will digest `data` using the specified
|
|
12
|
+
* `AlgorithmIdentifier`.
|
|
13
|
+
*/
|
|
14
|
+
digest(algorithm: DigestAlgorithm, data: dntShim.BufferSource | AsyncIterable<dntShim.BufferSource> | Iterable<dntShim.BufferSource>): Promise<ArrayBuffer>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a ArrayBuffer with the result of digesting `data` using the
|
|
17
|
+
* specified `AlgorithmIdentifier`.
|
|
18
|
+
*/
|
|
19
|
+
digestSync(algorithm: DigestAlgorithm, data: dntShim.BufferSource | Iterable<dntShim.BufferSource>): ArrayBuffer;
|
|
20
|
+
decrypt: (algorithm: dntShim.AlgorithmIdentifier | dntShim.RsaOaepParams | dntShim.AesCtrParams | dntShim.AesCbcParams | dntShim.AesGcmParams, key: dntShim.CryptoKey, data: dntShim.BufferSource) => Promise<any>;
|
|
21
|
+
deriveBits: (algorithm: dntShim.AlgorithmIdentifier | dntShim.EcdhKeyDeriveParams | dntShim.HkdfParams | dntShim.Pbkdf2Params, baseKey: dntShim.CryptoKey, length: number) => Promise<ArrayBuffer>;
|
|
22
|
+
deriveKey: (algorithm: dntShim.AlgorithmIdentifier | dntShim.EcdhKeyDeriveParams | dntShim.HkdfParams | dntShim.Pbkdf2Params, baseKey: dntShim.CryptoKey, derivedKeyType: dntShim.AlgorithmIdentifier | dntShim.HkdfParams | dntShim.Pbkdf2Params | dntShim.AesDerivedKeyParams | dntShim.HmacImportParams, extractable: boolean, keyUsages: dntShim.KeyUsage[]) => Promise<dntShim.CryptoKey>;
|
|
23
|
+
encrypt: (algorithm: dntShim.AlgorithmIdentifier | dntShim.RsaOaepParams | dntShim.AesCtrParams | dntShim.AesCbcParams | dntShim.AesGcmParams, key: dntShim.CryptoKey, data: dntShim.BufferSource) => Promise<any>;
|
|
24
|
+
exportKey: {
|
|
25
|
+
(format: "jwk", key: dntShim.CryptoKey): Promise<dntShim.JsonWebKey>;
|
|
26
|
+
(format: "pkcs8" | "raw" | "spki", key: dntShim.CryptoKey): Promise<ArrayBuffer>;
|
|
27
|
+
};
|
|
28
|
+
generateKey: {
|
|
29
|
+
(algorithm: dntShim.RsaHashedKeyGenParams | dntShim.EcKeyGenParams, extractable: boolean, keyUsages: readonly dntShim.KeyUsage[]): Promise<dntShim.CryptoKeyPair>;
|
|
30
|
+
(algorithm: dntShim.Pbkdf2Params | dntShim.AesKeyGenParams | dntShim.HmacKeyGenParams, extractable: boolean, keyUsages: readonly dntShim.KeyUsage[]): Promise<dntShim.CryptoKey>;
|
|
31
|
+
(algorithm: dntShim.AlgorithmIdentifier, extractable: boolean, keyUsages: dntShim.KeyUsage[]): Promise<dntShim.CryptoKey | dntShim.CryptoKeyPair>;
|
|
32
|
+
};
|
|
33
|
+
importKey: {
|
|
34
|
+
(format: "jwk", keyData: dntShim.JsonWebKey, algorithm: dntShim.AlgorithmIdentifier | dntShim.HmacImportParams | dntShim.RsaHashedImportParams | dntShim.EcKeyImportParams | dntShim.AesKeyAlgorithm, extractable: boolean, keyUsages: readonly dntShim.KeyUsage[]): Promise<dntShim.CryptoKey>;
|
|
35
|
+
(format: "pkcs8" | "raw" | "spki", keyData: dntShim.BufferSource, algorithm: dntShim.AlgorithmIdentifier | dntShim.HmacImportParams | dntShim.RsaHashedImportParams | dntShim.EcKeyImportParams | dntShim.AesKeyAlgorithm, extractable: boolean, keyUsages: dntShim.KeyUsage[]): Promise<dntShim.CryptoKey>;
|
|
36
|
+
};
|
|
37
|
+
sign: (algorithm: dntShim.AlgorithmIdentifier | dntShim.RsaPssParams | dntShim.EcdsaParams, key: dntShim.CryptoKey, data: dntShim.BufferSource) => Promise<ArrayBuffer>;
|
|
38
|
+
unwrapKey: (format: dntShim.KeyFormat, wrappedKey: dntShim.BufferSource, unwrappingKey: dntShim.CryptoKey, unwrapAlgorithm: dntShim.AlgorithmIdentifier | dntShim.RsaOaepParams | dntShim.AesCtrParams | dntShim.AesCbcParams | dntShim.AesGcmParams, unwrappedKeyAlgorithm: dntShim.AlgorithmIdentifier | dntShim.HmacImportParams | dntShim.RsaHashedImportParams | dntShim.EcKeyImportParams | dntShim.AesKeyAlgorithm, extractable: boolean, keyUsages: dntShim.KeyUsage[]) => Promise<dntShim.CryptoKey>;
|
|
39
|
+
verify: (algorithm: dntShim.AlgorithmIdentifier | dntShim.RsaPssParams | dntShim.EcdsaParams, key: dntShim.CryptoKey, signature: dntShim.BufferSource, data: dntShim.BufferSource) => Promise<boolean>;
|
|
40
|
+
wrapKey: (format: dntShim.KeyFormat, key: dntShim.CryptoKey, wrappingKey: dntShim.CryptoKey, wrapAlgorithm: dntShim.AlgorithmIdentifier | dntShim.RsaOaepParams | dntShim.AesCtrParams | dntShim.AesCbcParams | dntShim.AesGcmParams) => Promise<ArrayBuffer>;
|
|
41
|
+
};
|
|
42
|
+
getRandomValues: <T extends ArrayBufferView | null>(array: T) => T;
|
|
43
|
+
randomUUID: () => string;
|
|
44
|
+
};
|
|
45
|
+
declare const FNVAlgorithms: string[];
|
|
46
|
+
declare type FNVAlgorithms = "FNV32" | "FNV32A" | "FNV64" | "FNV64A";
|
|
47
|
+
declare type DigestAlgorithmName = WasmDigestAlgorithm | FNVAlgorithms;
|
|
48
|
+
declare type DigestAlgorithmObject = {
|
|
49
|
+
name: DigestAlgorithmName;
|
|
50
|
+
length?: number;
|
|
51
|
+
};
|
|
52
|
+
declare type DigestAlgorithm = DigestAlgorithmName | DigestAlgorithmObject;
|
|
53
|
+
export { stdCrypto as crypto };
|