two-stroke 6.5.3 → 7.1.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/CLAUDE.md +50 -0
- package/README.md +373 -90
- package/package.json +17 -15
- package/src/fake.ts +3 -0
- package/src/index.ts +32 -32
- package/src/test.ts +19 -43
- package/tsconfig.json +1 -2
- package/worker-configuration.d.ts +813 -34
- package/wrangler.jsonc +10 -2
package/src/index.ts
CHANGED
|
@@ -132,10 +132,10 @@ export function twoStroke<T extends Env>(
|
|
|
132
132
|
const body = route.input
|
|
133
133
|
? route.input.safeParse(rawBody)
|
|
134
134
|
: {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
success: true,
|
|
136
|
+
data: undefined,
|
|
137
|
+
error: undefined,
|
|
138
|
+
};
|
|
139
139
|
if (body.success)
|
|
140
140
|
response = await route.handler({
|
|
141
141
|
req,
|
|
@@ -211,7 +211,7 @@ export function twoStroke<T extends Env>(
|
|
|
211
211
|
return new Response(
|
|
212
212
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
213
213
|
responseWithHeaders.headers.get("Content-Type") ===
|
|
214
|
-
|
|
214
|
+
"application/json"
|
|
215
215
|
? JSON.stringify(response.body)
|
|
216
216
|
: response.body,
|
|
217
217
|
responseWithHeaders,
|
|
@@ -254,7 +254,7 @@ export function twoStroke<T extends Env>(
|
|
|
254
254
|
}
|
|
255
255
|
},
|
|
256
256
|
async scheduled(
|
|
257
|
-
event:
|
|
257
|
+
event: ScheduledController,
|
|
258
258
|
env: T & {
|
|
259
259
|
readonly SENTRY_DSN: string;
|
|
260
260
|
readonly SENTRY_ENVIRONMENT: string;
|
|
@@ -317,36 +317,36 @@ export function twoStroke<T extends Env>(
|
|
|
317
317
|
noAuth,
|
|
318
318
|
pbkdf:
|
|
319
319
|
(k: keyof T, customHeaderName: string = "Authorization") =>
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
320
|
+
async ({ req, env }: { req: Request; env: T }) => {
|
|
321
|
+
const [scheme, token] = (
|
|
322
|
+
req.headers.get(customHeaderName) ?? " "
|
|
323
|
+
).split(" ");
|
|
324
|
+
if (
|
|
325
|
+
(scheme === "token" || scheme === "Bearer") &&
|
|
326
|
+
(await pbkdfVerify(env[k] as string, token ?? ""))
|
|
327
|
+
)
|
|
328
|
+
return;
|
|
329
|
+
throw Error("Invalid");
|
|
330
|
+
},
|
|
331
331
|
jwt:
|
|
332
332
|
<J>(k: keyof T, ak: keyof T) =>
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
);
|
|
337
|
-
if (scheme === "Bearer") {
|
|
338
|
-
const claims = await jwkVerify<J>(
|
|
339
|
-
token ?? "",
|
|
340
|
-
env[k] as string,
|
|
341
|
-
env[ak] as string,
|
|
333
|
+
async ({ req, env }: { req: Request; env: T }) => {
|
|
334
|
+
const [scheme, token] = (req.headers.get("Authorization") ?? " ").split(
|
|
335
|
+
" ",
|
|
342
336
|
);
|
|
343
|
-
if (
|
|
344
|
-
|
|
337
|
+
if (scheme === "Bearer") {
|
|
338
|
+
const claims = await jwkVerify<J>(
|
|
339
|
+
token ?? "",
|
|
340
|
+
env[k] as string,
|
|
341
|
+
env[ak] as string,
|
|
342
|
+
);
|
|
343
|
+
if (!claims) {
|
|
344
|
+
throw Error("Invalid");
|
|
345
|
+
}
|
|
346
|
+
return claims;
|
|
345
347
|
}
|
|
346
|
-
|
|
347
|
-
}
|
|
348
|
-
throw Error("Invalid");
|
|
349
|
-
},
|
|
348
|
+
throw Error("Invalid");
|
|
349
|
+
},
|
|
350
350
|
queueHandler<I extends ZodType>(
|
|
351
351
|
input: I,
|
|
352
352
|
handler: (c: {
|
package/src/test.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
+
import { env, exports } from "cloudflare:workers";
|
|
1
2
|
import { type JWTPayload, SignJWT, exportJWK, generateKeyPair } from "jose";
|
|
2
|
-
import { fetchMock, SELF, env, type Buffer } from "cloudflare:test";
|
|
3
3
|
import createClient from "openapi-fetch";
|
|
4
|
+
import { http, HttpResponse } from 'msw'
|
|
5
|
+
import { setupServer } from 'msw/node'
|
|
6
|
+
|
|
7
|
+
const msw = setupServer();
|
|
8
|
+
msw.listen();
|
|
4
9
|
|
|
5
10
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/require-await
|
|
6
11
|
export const setupTests = async <Paths extends {}>() => {
|
|
7
|
-
beforeAll(() => {
|
|
8
|
-
fetchMock.activate();
|
|
9
|
-
fetchMock.disableNetConnect();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
12
|
const url = new URL("https://example.com/");
|
|
13
13
|
|
|
14
14
|
const client = createClient<Paths>({
|
|
15
15
|
baseUrl: url.toString(),
|
|
16
|
-
fetch: (...r) =>
|
|
16
|
+
fetch: (...r) => exports.default.fetch(...r),
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
return {
|
|
20
20
|
url,
|
|
21
|
-
fetchMock,
|
|
22
21
|
client,
|
|
22
|
+
msw,
|
|
23
23
|
async waitForQueue(trigger: () => Promise<void>) {
|
|
24
24
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
25
|
const log: any[] = [];
|
|
@@ -49,40 +49,16 @@ export const setupTests = async <Paths extends {}>() => {
|
|
|
49
49
|
jwk.kid = "test";
|
|
50
50
|
jwk.alg = "RS256";
|
|
51
51
|
beforeAll(() => {
|
|
52
|
-
|
|
53
|
-
.get(env[issuer]
|
|
54
|
-
|
|
55
|
-
method: "GET",
|
|
56
|
-
path: "/.well-known/openid-configuration",
|
|
57
|
-
})
|
|
58
|
-
.reply(
|
|
59
|
-
200,
|
|
60
|
-
{
|
|
61
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
52
|
+
msw.use(...[
|
|
53
|
+
http.get(`${env[issuer]}/.well-known/openid-configuration`, () =>
|
|
54
|
+
HttpResponse.json({
|
|
62
55
|
jwks_uri: `${env[issuer]}/.well-known/jwks`,
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"Content-Type": "application/json",
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
)
|
|
70
|
-
.persist();
|
|
71
|
-
fetchMock
|
|
72
|
-
.get(env[issuer] as string)
|
|
73
|
-
.intercept({ method: "GET", path: "/.well-known/jwks" })
|
|
74
|
-
.reply(
|
|
75
|
-
200,
|
|
76
|
-
{
|
|
56
|
+
})),
|
|
57
|
+
http.get(`${env[issuer]}/.well-known/jwks`, () =>
|
|
58
|
+
HttpResponse.json({
|
|
77
59
|
keys: [jwk],
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
headers: {
|
|
81
|
-
"Content-Type": "application/json",
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
)
|
|
85
|
-
.persist();
|
|
60
|
+
}))
|
|
61
|
+
])
|
|
86
62
|
});
|
|
87
63
|
return await new SignJWT(claims)
|
|
88
64
|
.setProtectedHeader({ typ: "JWT", alg: "RS256", kid: jwk.kid })
|
|
@@ -110,7 +86,7 @@ export function recordRequest(
|
|
|
110
86
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
87
|
cb: (data: any) => void,
|
|
112
88
|
statusCode: number,
|
|
113
|
-
data: string | object |
|
|
89
|
+
data: string | object | undefined,
|
|
114
90
|
responseOptions?: {
|
|
115
91
|
headers: Record<string, string | string[] | undefined>;
|
|
116
92
|
},
|
|
@@ -125,7 +101,7 @@ export function recordFormRequest(
|
|
|
125
101
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
102
|
cb: (data: any) => void,
|
|
127
103
|
statusCode: number,
|
|
128
|
-
data: string | object |
|
|
104
|
+
data: string | object | undefined,
|
|
129
105
|
responseOptions?: {
|
|
130
106
|
headers: Record<string, string | string[] | undefined>;
|
|
131
107
|
},
|
|
@@ -144,7 +120,7 @@ export function recordFirehoseRequest(
|
|
|
144
120
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
145
121
|
cb: (data: any) => void,
|
|
146
122
|
statusCode: number,
|
|
147
|
-
data: string | object |
|
|
123
|
+
data: string | object | undefined,
|
|
148
124
|
responseOptions?: {
|
|
149
125
|
headers: Record<string, string | string[] | undefined>;
|
|
150
126
|
},
|