stitchkit 0.18.0 → 0.19.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/browser/client.d.ts.map +1 -1
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/contract/errors-factory.d.ts +18 -0
- package/dist/contract/errors-factory.d.ts.map +1 -0
- package/dist/contract/factory.d.ts +36 -0
- package/dist/contract/factory.d.ts.map +1 -0
- package/dist/contract/index.d.ts +2 -0
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +6 -1
- package/dist/contract/pagination.d.ts.map +1 -1
- package/dist/index-809wc1tt.js +18 -0
- package/dist/{index-tm7dqzxc.js → index-c7nyw0yt.js} +9 -9
- package/dist/{index-dz2k8d5h.js → index-dzx781tm.js} +1 -1
- package/dist/{index-ktn76xz0.js → index-ng2v2ts4.js} +17 -1
- package/dist/index-tje0q6gp.js +44 -0
- package/dist/{index-6qv1fxqy.js → index-wpbn133x.js} +13 -50
- package/dist/{index-yzac2zbh.js → index-x62gnfsk.js} +50 -9
- package/dist/{index-akv8rk4w.js → index-xmncnw8z.js} +2 -2
- package/dist/{index-yv93m4yr.js → index-ynnh9x6h.js} +11 -29
- package/dist/index.js +82 -62
- package/dist/internal/base64url.d.ts +16 -0
- package/dist/internal/base64url.d.ts.map +1 -0
- package/dist/node.js +5 -4
- package/dist/observability/index.js +2 -2
- package/dist/react/entity-cache.d.ts +54 -0
- package/dist/react/entity-cache.d.ts.map +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +74 -0
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +56 -0
- package/dist/server/error-hook.d.ts.map +1 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +32 -7
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/cors.d.ts +13 -0
- package/dist/server/middleware/cors.d.ts.map +1 -1
- package/dist/server/middleware/pkce.d.ts +0 -6
- package/dist/server/middleware/pkce.d.ts.map +1 -1
- package/dist/server/router.d.ts +0 -2
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/types.d.ts +0 -8
- package/dist/server/types.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +2 -2
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli-format.d.ts +2 -2
- package/dist/tools/cli-format.d.ts.map +1 -1
- package/dist/tools/cli.d.ts +2 -2
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/execute.d.ts +7 -0
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/mcp.d.ts +3 -3
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +3 -3
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/oauth-metadata.d.ts.map +1 -1
- package/dist/tools/oauth-provider.d.ts.map +1 -1
- package/dist/tools/tool-logger.d.ts +31 -0
- package/dist/tools/tool-logger.d.ts.map +1 -0
- package/dist/tools/transports.d.ts +28 -0
- package/dist/tools/transports.d.ts.map +1 -0
- package/dist/tools.d.ts +3 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +71 -11
- package/llms-full.txt +235 -4
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/browser/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAGX,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/browser/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAGX,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;AA+EhB,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC1D,OAAO,GACP;KAAG,CAAC,IAAI,CAAC,GAAG,MAAM;CAAE,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK;IAC5D,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IAClE,eAAe,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,EAE9B,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAChC,cAAc,EAAE,YAAY,GAAG,WAAW,EAC1C,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GACvC,gBAAgB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAepC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,EAC1E,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;CAAE,CAKzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/browser/socket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/browser/socket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AA0D9D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC;AAEvC,MAAM,WAAW,oBAAoB,CAAC,aAAa,SAAS,cAAc,GAAG,cAAc;IACzF,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,IAAI,CAAC,EACD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvE,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAClD;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,2EAA2E;IAC3E,UAAU,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC5C,iDAAiD;IACjD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,2BAA2B,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7C;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,cAAc,CAC7B,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc;IAEpC,6DAA6D;IAC7D,OAAO,IAAI,IAAI,CAAC;IAChB,+CAA+C;IAC/C,UAAU,IAAI,IAAI,CAAC;IACnB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,aAAa,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAC5F,8DAA8D;IAC9D,IAAI,CAAC,CAAC,SAAS,MAAM,aAAa,GAAG,MAAM,EACzC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GACpC,IAAI,CAAC;IACR;;;;;;OAMG;IACH,kBAAkB,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACzF;AAED,wBAAgB,oBAAoB,CAClC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc,EACpC,MAAM,EAAE,oBAAoB,CAAC,aAAa,CAAC,GAAG,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC,CA8J3F"}
|
package/dist/cli.js
CHANGED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
emitResult,
|
|
5
5
|
parseCliArgs,
|
|
6
6
|
pollUntilDone
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-xmncnw8z.js";
|
|
8
8
|
import"./index-0ed3bx43.js";
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-
|
|
9
|
+
import"./index-ng2v2ts4.js";
|
|
10
|
+
import"./index-c7nyw0yt.js";
|
|
11
11
|
export {
|
|
12
12
|
pollUntilDone,
|
|
13
13
|
parseCliArgs,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** A typed thrower — throws an `AppError` with the declared code and status. */
|
|
2
|
+
export type ErrorThrower = (message?: string, details?: Record<string, unknown>, hint?: string) => never;
|
|
3
|
+
/** The handle `defineErrors` returns. `TDef` maps `CODE → HTTP status`. */
|
|
4
|
+
export interface DefinedErrors<TDef extends Record<string, number>> {
|
|
5
|
+
/** One thrower per code — `errors.CODE(message?)` throws the matching `AppError`. */
|
|
6
|
+
errors: {
|
|
7
|
+
[K in keyof TDef]: ErrorThrower;
|
|
8
|
+
};
|
|
9
|
+
/** The code literals — `codes.CODE === 'CODE'`, for client-side matching. */
|
|
10
|
+
codes: {
|
|
11
|
+
readonly [K in keyof TDef]: K;
|
|
12
|
+
};
|
|
13
|
+
/** Type guard — is `code` one of this app's declared codes? */
|
|
14
|
+
isCode: (code: string) => code is keyof TDef & string;
|
|
15
|
+
}
|
|
16
|
+
/** Declare a set of domain error codes (`{ CODE: httpStatus }`). */
|
|
17
|
+
export declare function defineErrors<const TDef extends Record<string, number>>(defs: TDef): DefinedErrors<TDef>;
|
|
18
|
+
//# sourceMappingURL=errors-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-factory.d.ts","sourceRoot":"","sources":["../../src/contract/errors-factory.ts"],"names":[],"mappings":"AA8BA,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAAG,CACzB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,CAAC,EAAE,MAAM,KACV,KAAK,CAAC;AAEX,2EAA2E;AAC3E,MAAM,WAAW,aAAa,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAChE,qFAAqF;IACrF,MAAM,EAAE;SAAG,CAAC,IAAI,MAAM,IAAI,GAAG,YAAY;KAAE,CAAC;IAC5C,6EAA6E;IAC7E,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,IAAI,GAAG,CAAC;KAAE,CAAC;IACzC,+DAA+D;IAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,MAAM,CAAC;CACvD;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpE,IAAI,EAAE,IAAI,GACT,aAAa,CAAC,IAAI,CAAC,CAgBrB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `defineContract` bound to an application's scope vocabulary — so every
|
|
3
|
+
* contract MUST declare a `scope`, typed to that union.
|
|
4
|
+
*
|
|
5
|
+
* Plain `defineContract` defaults a missing `scope` to `'public'` (fail-open):
|
|
6
|
+
* forget it and the endpoint is public. A project that gates everything writes
|
|
7
|
+
* a thin wrapper to make `scope` required and typed — the same 30-line wrapper
|
|
8
|
+
* in every repo. `createContractFactory` is that wrapper, once:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // app: one line
|
|
12
|
+
* const { defineContract } = createContractFactory<'public' | 'user' | 'admin'>();
|
|
13
|
+
*
|
|
14
|
+
* // scope is now REQUIRED and checked against the union — a typo or a missing
|
|
15
|
+
* // scope is a compile error, not a silent public endpoint.
|
|
16
|
+
* export const users = defineContract({ prefix: 'users', scope: 'user' }, { … });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* The scope vocabulary comes from the app; the core stays domain-free (ADR 0002).
|
|
20
|
+
* The returned contracts are ordinary `ContractDef`s — `implement`, `createClient`
|
|
21
|
+
* and the tool mounts treat them exactly as before.
|
|
22
|
+
*/
|
|
23
|
+
import type { ContractDef, EndpointDef } from './define';
|
|
24
|
+
/** A `defineContract` whose `scope` is required and typed to `TScope`. */
|
|
25
|
+
export type ScopedDefineContract<TScope extends string> = <const T extends Record<string, EndpointDef>>(meta: {
|
|
26
|
+
prefix: string;
|
|
27
|
+
scope: TScope;
|
|
28
|
+
}, endpoints: T) => ContractDef<T, TScope>;
|
|
29
|
+
/**
|
|
30
|
+
* Build a `defineContract` that requires a `scope` from the application's own
|
|
31
|
+
* union. Call once per app and re-export the returned `defineContract`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createContractFactory<TScope extends string>(): {
|
|
34
|
+
defineContract: ScopedDefineContract<TScope>;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/contract/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGzD,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,CAAC,MAAM,SAAS,MAAM,IAAI,CACxD,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAE3C,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACvC,SAAS,EAAE,CAAC,KACT,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,SAAS,MAAM,KAAK;IAC9D,cAAc,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;CAC9C,CAcA"}
|
package/dist/contract/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { ALL_TRANSPORTS, type ContractDef, type ContractMeta, defineContract, type EndpointDef, type EndpointFn, type EndpointToolAnnotations, type EndpointUiMeta, type FileDescriptor, type HandlerContext, type HttpMethod, type MultipartFile, type RuntimeContext, type ScopedEndpointFn, type ScopedHttpClient, type Transport, type TransportSource, type TypedClient, type TypedHttpClient, } from './define';
|
|
2
2
|
export { AppError, appError, badRequest, conflict, type ErrorEnvelope, forbidden, isStitchErrorCode, notFound, rateLimited, STITCH_ERROR_STATUS, type StitchErrorCode, unauthorized, } from './errors';
|
|
3
|
+
export { type DefinedErrors, defineErrors, type ErrorThrower, } from './errors-factory';
|
|
4
|
+
export { createContractFactory, type ScopedDefineContract } from './factory';
|
|
3
5
|
export { decodeCursor, encodeCursor, type Paginated, paginatedSchema, } from './pagination';
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,KAAK,aAAa,EAClB,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,aAAa,EAClB,YAAY,EACZ,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAE7E,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,KAAK,SAAS,EACd,eAAe,GAChB,MAAM,cAAc,CAAC"}
|
package/dist/contract/index.js
CHANGED
|
@@ -5,8 +5,10 @@ import {
|
|
|
5
5
|
appError,
|
|
6
6
|
badRequest,
|
|
7
7
|
conflict,
|
|
8
|
+
createContractFactory,
|
|
8
9
|
decodeCursor,
|
|
9
10
|
defineContract,
|
|
11
|
+
defineErrors,
|
|
10
12
|
encodeCursor,
|
|
11
13
|
forbidden,
|
|
12
14
|
isStitchErrorCode,
|
|
@@ -14,7 +16,8 @@ import {
|
|
|
14
16
|
paginatedSchema,
|
|
15
17
|
rateLimited,
|
|
16
18
|
unauthorized
|
|
17
|
-
} from "../index-
|
|
19
|
+
} from "../index-x62gnfsk.js";
|
|
20
|
+
import"../index-809wc1tt.js";
|
|
18
21
|
export {
|
|
19
22
|
unauthorized,
|
|
20
23
|
rateLimited,
|
|
@@ -23,8 +26,10 @@ export {
|
|
|
23
26
|
isStitchErrorCode,
|
|
24
27
|
forbidden,
|
|
25
28
|
encodeCursor,
|
|
29
|
+
defineErrors,
|
|
26
30
|
defineContract,
|
|
27
31
|
decodeCursor,
|
|
32
|
+
createContractFactory,
|
|
28
33
|
conflict,
|
|
29
34
|
badRequest,
|
|
30
35
|
appError,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/contract/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/contract/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,UAAU,EAAE,CAAC;;;kBAK/D;AAuBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GACjB,CAAC,GAAG,IAAI,CAQV"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/internal/typed.ts
|
|
2
|
+
function typedEntries(value) {
|
|
3
|
+
return Object.entries(value);
|
|
4
|
+
}
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function mapObject(source, mapper) {
|
|
9
|
+
const result = {};
|
|
10
|
+
for (const [key, value] of typedEntries(source)) {
|
|
11
|
+
const mapped = mapper(key, value);
|
|
12
|
+
if (mapped !== undefined)
|
|
13
|
+
result[key] = mapped;
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { typedEntries, isRecord, mapObject };
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
3
|
|
|
4
|
-
// src/internal/safe-json.ts
|
|
5
|
-
function isUnsafeKey(key) {
|
|
6
|
-
return key === "__proto__";
|
|
7
|
-
}
|
|
8
|
-
function safeJsonParse(text) {
|
|
9
|
-
return JSON.parse(text, (key, value) => isUnsafeKey(key) ? undefined : value);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
4
|
// src/internal/typed.ts
|
|
13
5
|
function typedEntries(value) {
|
|
14
6
|
return Object.entries(value);
|
|
@@ -17,4 +9,12 @@ function isRecord(value) {
|
|
|
17
9
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18
10
|
}
|
|
19
11
|
|
|
20
|
-
|
|
12
|
+
// src/internal/safe-json.ts
|
|
13
|
+
function isUnsafeKey(key) {
|
|
14
|
+
return key === "__proto__";
|
|
15
|
+
}
|
|
16
|
+
function safeJsonParse(text) {
|
|
17
|
+
return JSON.parse(text, (key, value) => isUnsafeKey(key) ? undefined : value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { __require, typedEntries, isRecord, isUnsafeKey, safeJsonParse };
|
|
@@ -66,6 +66,22 @@ function appError(code, message, details) {
|
|
|
66
66
|
}
|
|
67
67
|
// src/contract/pagination.ts
|
|
68
68
|
import { z } from "zod";
|
|
69
|
+
|
|
70
|
+
// src/internal/base64url.ts
|
|
71
|
+
function bytesToBase64Url(bytes) {
|
|
72
|
+
let binary = "";
|
|
73
|
+
for (const byte of bytes)
|
|
74
|
+
binary += String.fromCharCode(byte);
|
|
75
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
76
|
+
}
|
|
77
|
+
function base64UrlToBytes(segment) {
|
|
78
|
+
if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
|
|
79
|
+
throw new Error("invalid base64url segment");
|
|
80
|
+
}
|
|
81
|
+
const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
82
|
+
const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
|
|
83
|
+
return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
|
|
84
|
+
}
|
|
69
85
|
// src/internal/errors.ts
|
|
70
86
|
import { z as z2 } from "zod";
|
|
71
87
|
function formatZodError(error) {
|
|
@@ -112,4 +128,4 @@ function isWithinDir(root, target) {
|
|
|
112
128
|
return target === root || target === base || target.startsWith(base + sep);
|
|
113
129
|
}
|
|
114
130
|
|
|
115
|
-
export { AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, formatZodError, errorCode, normalizeError, validateHandlerOutput, isWithinDir };
|
|
131
|
+
export { AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, bytesToBase64Url, base64UrlToBytes, formatZodError, errorCode, normalizeError, validateHandlerOutput, isWithinDir };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/server/middleware/cors.ts
|
|
2
|
+
var DEFAULT_CORS_ALLOW_HEADERS = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
|
|
3
|
+
function assertCorsConfig(config) {
|
|
4
|
+
if (config.credentials && (config.origin === undefined || config.origin === "*")) {
|
|
5
|
+
throw new Error("[stitchkit] cors: `credentials: true` cannot be combined with a wildcard origin. " + "Set `origin` to an explicit string or list.");
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
function resolveOrigin(config, requestOrigin) {
|
|
9
|
+
if (config.origin === undefined || config.origin === "*") {
|
|
10
|
+
return "*";
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(config.origin)) {
|
|
13
|
+
if (!requestOrigin)
|
|
14
|
+
return;
|
|
15
|
+
const lower = requestOrigin.toLowerCase();
|
|
16
|
+
return config.origin.some((o) => o.toLowerCase() === lower) ? requestOrigin : undefined;
|
|
17
|
+
}
|
|
18
|
+
return config.origin;
|
|
19
|
+
}
|
|
20
|
+
function corsHeaders(config, requestOrigin) {
|
|
21
|
+
const allowOrigin = resolveOrigin(config, requestOrigin);
|
|
22
|
+
const headers = {
|
|
23
|
+
"Access-Control-Allow-Methods": config.methods ?? "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
24
|
+
"Access-Control-Allow-Headers": config.headers ?? DEFAULT_CORS_ALLOW_HEADERS
|
|
25
|
+
};
|
|
26
|
+
if (allowOrigin !== undefined) {
|
|
27
|
+
headers["Access-Control-Allow-Origin"] = allowOrigin;
|
|
28
|
+
if (config.credentials) {
|
|
29
|
+
headers["Access-Control-Allow-Credentials"] = "true";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(config.origin)) {
|
|
33
|
+
headers.Vary = "Origin";
|
|
34
|
+
}
|
|
35
|
+
return headers;
|
|
36
|
+
}
|
|
37
|
+
function corsPreflightResponse(config, req) {
|
|
38
|
+
return new Response(null, {
|
|
39
|
+
status: 204,
|
|
40
|
+
headers: corsHeaders(config, req.headers.get("origin"))
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { DEFAULT_CORS_ALLOW_HEADERS, assertCorsConfig, corsHeaders, corsPreflightResponse };
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertCorsConfig,
|
|
3
|
+
corsHeaders,
|
|
4
|
+
corsPreflightResponse
|
|
5
|
+
} from "./index-tje0q6gp.js";
|
|
1
6
|
import {
|
|
2
7
|
AppError,
|
|
3
8
|
badRequest,
|
|
@@ -5,7 +10,7 @@ import {
|
|
|
5
10
|
isWithinDir,
|
|
6
11
|
normalizeError,
|
|
7
12
|
validateHandlerOutput
|
|
8
|
-
} from "./index-
|
|
13
|
+
} from "./index-ng2v2ts4.js";
|
|
9
14
|
import {
|
|
10
15
|
extractIp,
|
|
11
16
|
getClientInfo,
|
|
@@ -13,13 +18,13 @@ import {
|
|
|
13
18
|
resolveSocketIp,
|
|
14
19
|
resolveTraceId,
|
|
15
20
|
setRequestEndpoint
|
|
16
|
-
} from "./index-
|
|
21
|
+
} from "./index-dzx781tm.js";
|
|
17
22
|
import {
|
|
18
23
|
__require,
|
|
19
24
|
isUnsafeKey,
|
|
20
25
|
safeJsonParse,
|
|
21
26
|
typedEntries
|
|
22
|
-
} from "./index-
|
|
27
|
+
} from "./index-c7nyw0yt.js";
|
|
23
28
|
|
|
24
29
|
// src/server/multipart.ts
|
|
25
30
|
var DEFAULT_MAX_UPLOAD_BYTES = 25 * 1024 * 1024;
|
|
@@ -79,48 +84,6 @@ async function parseMultipart(req, fileField, fieldsSchema, maxBytes = DEFAULT_M
|
|
|
79
84
|
return { file, fields: fieldsSchema ? fieldsSchema.parse(fields) : fields };
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
// src/server/middleware/cors.ts
|
|
83
|
-
function assertCorsConfig(config) {
|
|
84
|
-
if (config.credentials && (config.origin === undefined || config.origin === "*")) {
|
|
85
|
-
throw new Error("[stitchkit] cors: `credentials: true` cannot be combined with a wildcard origin. " + "Set `origin` to an explicit string or list.");
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function resolveOrigin(config, requestOrigin) {
|
|
89
|
-
if (config.origin === undefined || config.origin === "*") {
|
|
90
|
-
return "*";
|
|
91
|
-
}
|
|
92
|
-
if (Array.isArray(config.origin)) {
|
|
93
|
-
if (!requestOrigin)
|
|
94
|
-
return;
|
|
95
|
-
const lower = requestOrigin.toLowerCase();
|
|
96
|
-
return config.origin.some((o) => o.toLowerCase() === lower) ? requestOrigin : undefined;
|
|
97
|
-
}
|
|
98
|
-
return config.origin;
|
|
99
|
-
}
|
|
100
|
-
function corsHeaders(config, requestOrigin) {
|
|
101
|
-
const allowOrigin = resolveOrigin(config, requestOrigin);
|
|
102
|
-
const headers = {
|
|
103
|
-
"Access-Control-Allow-Methods": config.methods ?? "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
104
|
-
"Access-Control-Allow-Headers": config.headers ?? "Content-Type, Authorization, X-Trace-Id"
|
|
105
|
-
};
|
|
106
|
-
if (allowOrigin !== undefined) {
|
|
107
|
-
headers["Access-Control-Allow-Origin"] = allowOrigin;
|
|
108
|
-
if (config.credentials) {
|
|
109
|
-
headers["Access-Control-Allow-Credentials"] = "true";
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (Array.isArray(config.origin)) {
|
|
113
|
-
headers.Vary = "Origin";
|
|
114
|
-
}
|
|
115
|
-
return headers;
|
|
116
|
-
}
|
|
117
|
-
function corsPreflightResponse(config, req) {
|
|
118
|
-
return new Response(null, {
|
|
119
|
-
status: 204,
|
|
120
|
-
headers: corsHeaders(config, req.headers.get("origin"))
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
87
|
// src/server/router.ts
|
|
125
88
|
import { readFile, stat } from "node:fs/promises";
|
|
126
89
|
import { resolve } from "node:path";
|
|
@@ -192,7 +155,7 @@ function buildRouteMap(groups) {
|
|
|
192
155
|
const fullPath = prefix ? joinPath(prefix, servicePath) : servicePath;
|
|
193
156
|
const segments = fullPath.split("/").filter(Boolean);
|
|
194
157
|
const entries = map.get(method.method) ?? [];
|
|
195
|
-
entries.push({ method,
|
|
158
|
+
entries.push({ method, pattern: fullPath, segments, groupHooks: hooks });
|
|
196
159
|
map.set(method.method, entries);
|
|
197
160
|
}
|
|
198
161
|
}
|
|
@@ -220,7 +183,6 @@ function matchRoute(routeMap, httpMethod, pathname) {
|
|
|
220
183
|
if (pathParams) {
|
|
221
184
|
return {
|
|
222
185
|
method: entry.method,
|
|
223
|
-
service: entry.service,
|
|
224
186
|
pathParams,
|
|
225
187
|
groupHooks: entry.groupHooks
|
|
226
188
|
};
|
|
@@ -569,8 +531,9 @@ function createHandler(config) {
|
|
|
569
531
|
if (hooks?.onRequest) {
|
|
570
532
|
const earlyResponse = await hooks.onRequest(req);
|
|
571
533
|
if (earlyResponse instanceof Response) {
|
|
572
|
-
|
|
573
|
-
|
|
534
|
+
const withCors = applyCors(earlyResponse, cors, req);
|
|
535
|
+
logDone(withCors.status);
|
|
536
|
+
return withCors;
|
|
574
537
|
}
|
|
575
538
|
}
|
|
576
539
|
if (config.rawRoutes) {
|
|
@@ -895,4 +858,4 @@ function socketIoLane(websocket) {
|
|
|
895
858
|
});
|
|
896
859
|
}
|
|
897
860
|
|
|
898
|
-
export { parseMultipart,
|
|
861
|
+
export { parseMultipart, mimeForPath, staticRoute, createHandler, createServer, implement, createImplement, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane };
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mapObject
|
|
3
|
+
} from "./index-809wc1tt.js";
|
|
4
|
+
|
|
1
5
|
// src/contract/define.ts
|
|
2
6
|
var ALL_TRANSPORTS = ["HTTP", "MCP", "AGENT", "CLI"];
|
|
3
7
|
function defineContract(meta, endpoints) {
|
|
@@ -92,8 +96,51 @@ function isStitchErrorCode(code) {
|
|
|
92
96
|
function appError(code, message, details) {
|
|
93
97
|
throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
|
|
94
98
|
}
|
|
99
|
+
// src/contract/errors-factory.ts
|
|
100
|
+
function defineErrors(defs) {
|
|
101
|
+
const errors = mapObject(defs, (code, status) => (message, details, hint) => {
|
|
102
|
+
throw new AppError(String(code), message, status, details, hint);
|
|
103
|
+
});
|
|
104
|
+
const codes = mapObject(defs, (code) => code);
|
|
105
|
+
const known = new Set(Object.keys(defs));
|
|
106
|
+
return {
|
|
107
|
+
errors,
|
|
108
|
+
codes,
|
|
109
|
+
isCode: (code) => known.has(code)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// src/contract/factory.ts
|
|
113
|
+
function createContractFactory() {
|
|
114
|
+
return {
|
|
115
|
+
defineContract: (meta, endpoints) => {
|
|
116
|
+
const validated = defineContract({ prefix: meta.prefix }, endpoints);
|
|
117
|
+
return {
|
|
118
|
+
endpoints: validated.endpoints,
|
|
119
|
+
meta: { prefix: meta.prefix, scope: meta.scope }
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
95
124
|
// src/contract/pagination.ts
|
|
96
125
|
import { z } from "zod";
|
|
126
|
+
|
|
127
|
+
// src/internal/base64url.ts
|
|
128
|
+
function bytesToBase64Url(bytes) {
|
|
129
|
+
let binary = "";
|
|
130
|
+
for (const byte of bytes)
|
|
131
|
+
binary += String.fromCharCode(byte);
|
|
132
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
133
|
+
}
|
|
134
|
+
function base64UrlToBytes(segment) {
|
|
135
|
+
if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
|
|
136
|
+
throw new Error("invalid base64url segment");
|
|
137
|
+
}
|
|
138
|
+
const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
139
|
+
const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
|
|
140
|
+
return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/contract/pagination.ts
|
|
97
144
|
function paginatedSchema(itemSchema) {
|
|
98
145
|
return z.object({
|
|
99
146
|
items: z.array(itemSchema),
|
|
@@ -101,16 +148,10 @@ function paginatedSchema(itemSchema) {
|
|
|
101
148
|
});
|
|
102
149
|
}
|
|
103
150
|
function toBase64Url(str) {
|
|
104
|
-
|
|
105
|
-
let binary = "";
|
|
106
|
-
for (const byte of bytes)
|
|
107
|
-
binary += String.fromCharCode(byte);
|
|
108
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
151
|
+
return bytesToBase64Url(new TextEncoder().encode(str));
|
|
109
152
|
}
|
|
110
153
|
function fromBase64Url(value) {
|
|
111
|
-
|
|
112
|
-
const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
|
|
113
|
-
return new TextDecoder().decode(Uint8Array.from(atob(padded), (c) => c.charCodeAt(0)));
|
|
154
|
+
return new TextDecoder().decode(base64UrlToBytes(value));
|
|
114
155
|
}
|
|
115
156
|
function encodeCursor(value) {
|
|
116
157
|
return toBase64Url(JSON.stringify(value));
|
|
@@ -125,4 +166,4 @@ function decodeCursor(cursor, schema) {
|
|
|
125
166
|
return null;
|
|
126
167
|
}
|
|
127
168
|
}
|
|
128
|
-
export { ALL_TRANSPORTS, defineContract, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, paginatedSchema, encodeCursor, decodeCursor };
|
|
169
|
+
export { ALL_TRANSPORTS, defineContract, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, defineErrors, createContractFactory, paginatedSchema, encodeCursor, decodeCursor };
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
isWithinDir,
|
|
8
8
|
normalizeError,
|
|
9
9
|
validateHandlerOutput
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-ng2v2ts4.js";
|
|
11
11
|
import {
|
|
12
12
|
isRecord,
|
|
13
13
|
isUnsafeKey,
|
|
14
14
|
safeJsonParse
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-c7nyw0yt.js";
|
|
16
16
|
|
|
17
17
|
// src/tools/coerce.ts
|
|
18
18
|
import { z } from "zod";
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
base64UrlToBytes,
|
|
3
|
+
bytesToBase64Url,
|
|
2
4
|
forbidden,
|
|
3
5
|
unauthorized
|
|
4
|
-
} from "./index-
|
|
6
|
+
} from "./index-ng2v2ts4.js";
|
|
5
7
|
import {
|
|
6
8
|
isRecord,
|
|
7
9
|
isUnsafeKey,
|
|
8
10
|
safeJsonParse
|
|
9
|
-
} from "./index-
|
|
11
|
+
} from "./index-c7nyw0yt.js";
|
|
10
12
|
|
|
11
13
|
// src/server/middleware/cookies.ts
|
|
12
14
|
function parseCookies(header) {
|
|
@@ -62,14 +64,6 @@ function defineCookie(config) {
|
|
|
62
64
|
|
|
63
65
|
// src/server/middleware/auth.ts
|
|
64
66
|
var MAX_TOKEN_BYTES = 8192;
|
|
65
|
-
function decodeBase64Url(segment) {
|
|
66
|
-
if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
|
|
67
|
-
throw new Error("invalid base64url segment");
|
|
68
|
-
}
|
|
69
|
-
const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
70
|
-
const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
|
|
71
|
-
return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
|
|
72
|
-
}
|
|
73
67
|
async function verifyJwt(token, secret, options = {}) {
|
|
74
68
|
if (!secret)
|
|
75
69
|
throw new Error("verifyJwt: a non-empty secret is required");
|
|
@@ -83,9 +77,9 @@ async function verifyJwt(token, secret, options = {}) {
|
|
|
83
77
|
let signature;
|
|
84
78
|
try {
|
|
85
79
|
const decoder = new TextDecoder;
|
|
86
|
-
header = JSON.parse(decoder.decode(
|
|
87
|
-
payloadRaw = safeJsonParse(decoder.decode(
|
|
88
|
-
signature =
|
|
80
|
+
header = JSON.parse(decoder.decode(base64UrlToBytes(headerB64)));
|
|
81
|
+
payloadRaw = safeJsonParse(decoder.decode(base64UrlToBytes(payloadB64)));
|
|
82
|
+
signature = base64UrlToBytes(signatureB64);
|
|
89
83
|
} catch {
|
|
90
84
|
throw unauthorized("Malformed token");
|
|
91
85
|
}
|
|
@@ -125,12 +119,6 @@ async function verifyJwt(token, secret, options = {}) {
|
|
|
125
119
|
}
|
|
126
120
|
return payload;
|
|
127
121
|
}
|
|
128
|
-
function encodeBase64Url(bytes) {
|
|
129
|
-
let binary = "";
|
|
130
|
-
for (const byte of bytes)
|
|
131
|
-
binary += String.fromCharCode(byte);
|
|
132
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
133
|
-
}
|
|
134
122
|
async function signJwt(payload, secret, options = {}) {
|
|
135
123
|
if (!secret)
|
|
136
124
|
throw new Error("signJwt: a non-empty secret is required");
|
|
@@ -144,12 +132,12 @@ async function signJwt(payload, secret, options = {}) {
|
|
|
144
132
|
...options.subject !== undefined && { sub: options.subject }
|
|
145
133
|
};
|
|
146
134
|
const encoder = new TextEncoder;
|
|
147
|
-
const headerB64 =
|
|
148
|
-
const payloadB64 =
|
|
135
|
+
const headerB64 = bytesToBase64Url(encoder.encode(JSON.stringify({ alg: "HS256", typ: "JWT" })));
|
|
136
|
+
const payloadB64 = bytesToBase64Url(encoder.encode(JSON.stringify(claims)));
|
|
149
137
|
const signingInput = `${headerB64}.${payloadB64}`;
|
|
150
138
|
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
151
139
|
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(signingInput));
|
|
152
|
-
const signatureB64 =
|
|
140
|
+
const signatureB64 = bytesToBase64Url(new Uint8Array(signature));
|
|
153
141
|
return `${signingInput}.${signatureB64}`;
|
|
154
142
|
}
|
|
155
143
|
function extractToken(req, cookieName) {
|
|
@@ -197,15 +185,9 @@ function createBearerResolver(config) {
|
|
|
197
185
|
}
|
|
198
186
|
|
|
199
187
|
// src/server/middleware/pkce.ts
|
|
200
|
-
function base64UrlEncode(bytes) {
|
|
201
|
-
let binary = "";
|
|
202
|
-
for (const byte of bytes)
|
|
203
|
-
binary += String.fromCharCode(byte);
|
|
204
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
205
|
-
}
|
|
206
188
|
async function deriveCodeChallenge(verifier) {
|
|
207
189
|
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
|
|
208
|
-
return
|
|
190
|
+
return bytesToBase64Url(new Uint8Array(digest));
|
|
209
191
|
}
|
|
210
192
|
async function verifyPkce(verifier, challenge) {
|
|
211
193
|
if (!verifier || !challenge)
|