@toapi/common 0.12.1

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.
@@ -0,0 +1,8 @@
1
+ export declare const TAGS_HEADER = "X-TAPI-Tags";
2
+ export declare const EXPIRES_AT_HEADER = "X-TAPI-Expires-At";
3
+ export declare const TAGS_CONTENT_TYPE = "text/tapi-tags";
4
+ export declare const SESSION_COOKIE_NAME = "__tapi-session";
5
+ export declare const INVALIDATION_POST_EVENT = "TAPI_INVALIDATE_TAGS";
6
+ export declare const INVALIDATIONS_ROUTE = "/__tapi/invalidations";
7
+ export declare const OPENAPI_ROUTE = "/__tapi/openapi.json";
8
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAClD,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,eAAO,MAAM,uBAAuB,yBAAyB,CAAC;AAC9D,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAC3D,eAAO,MAAM,aAAa,yBAAyB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export const TAGS_HEADER = "X-TAPI-Tags";
2
+ export const EXPIRES_AT_HEADER = "X-TAPI-Expires-At";
3
+ export const TAGS_CONTENT_TYPE = "text/tapi-tags";
4
+ export const SESSION_COOKIE_NAME = "__tapi-session";
5
+ export const INVALIDATION_POST_EVENT = "TAPI_INVALIDATE_TAGS";
6
+ export const INVALIDATIONS_ROUTE = "/__tapi/invalidations";
7
+ export const OPENAPI_ROUTE = "/__tapi/openapi.json";
@@ -0,0 +1,39 @@
1
+ interface CookieListItem {
2
+ name: string;
3
+ value: string;
4
+ domain: string | null;
5
+ path: string;
6
+ expires: number | null;
7
+ secure: boolean;
8
+ sameSite: "strict" | "lax" | "none";
9
+ partitioned: boolean;
10
+ }
11
+ interface CookieStoreGetOptions {
12
+ name: string;
13
+ }
14
+ interface CookieInit {
15
+ name: string;
16
+ value: string;
17
+ domain?: string | null;
18
+ path?: string;
19
+ expires?: number | null;
20
+ sameSite?: "strict" | "lax" | "none";
21
+ partitioned?: boolean;
22
+ }
23
+ interface CookieStoreDeleteOptions {
24
+ name: string;
25
+ domain?: string | null;
26
+ path?: string;
27
+ partitioned?: boolean;
28
+ }
29
+ export declare class CookieStore {
30
+ #private;
31
+ constructor(request: Request);
32
+ get(nameOrOptions?: string | CookieStoreGetOptions): Promise<CookieListItem | undefined>;
33
+ getAll(nameOrOptions?: string | CookieStoreGetOptions): Promise<CookieListItem[]>;
34
+ set(nameOrOptions: string | CookieInit, value?: string): Promise<void>;
35
+ delete(nameOrOptions: string | CookieStoreDeleteOptions): Promise<void>;
36
+ write(headers: Headers): void;
37
+ }
38
+ export {};
39
+ //# sourceMappingURL=cookie-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie-store.d.ts","sourceRoot":"","sources":["../src/cookie-store.ts"],"names":[],"mappings":"AAAA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACpC,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,wBAAwB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAyCD,qBAAa,WAAW;;gBAKV,OAAO,EAAE,OAAO;IAItB,GAAG,CACP,aAAa,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAC7C,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAOhC,MAAM,CACV,aAAa,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAC7C,OAAO,CAAC,cAAc,EAAE,CAAC;IAOtB,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BtE,MAAM,CACV,aAAa,EAAE,MAAM,GAAG,wBAAwB,GAC/C,OAAO,CAAC,IAAI,CAAC;IAehB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAe9B"}
@@ -0,0 +1,109 @@
1
+ function parseCookieString(cookieString) {
2
+ if (!cookieString)
3
+ return [];
4
+ return cookieString.split(";").reduce((cookies, part) => {
5
+ const eqIndex = part.indexOf("=");
6
+ if (eqIndex === -1)
7
+ return cookies;
8
+ const name = part.slice(0, eqIndex).trim();
9
+ const value = part.slice(eqIndex + 1).trim();
10
+ if (!name)
11
+ return cookies;
12
+ cookies.push({
13
+ name,
14
+ value: decodeURIComponent(value),
15
+ domain: null,
16
+ path: "/",
17
+ expires: null,
18
+ secure: false,
19
+ sameSite: "lax",
20
+ partitioned: false,
21
+ });
22
+ return cookies;
23
+ }, []);
24
+ }
25
+ function serializeSetCookie(cookie) {
26
+ let str = `${cookie.name}=${encodeURIComponent(cookie.value)}`;
27
+ if (cookie.domain)
28
+ str += `; Domain=${cookie.domain}`;
29
+ if (cookie.path)
30
+ str += `; Path=${cookie.path}`;
31
+ if (cookie.expires !== null) {
32
+ str += `; Expires=${new Date(cookie.expires).toUTCString()}`;
33
+ }
34
+ if (cookie.secure)
35
+ str += "; Secure";
36
+ if (cookie.sameSite) {
37
+ str += `; SameSite=${cookie.sameSite.charAt(0).toUpperCase() + cookie.sameSite.slice(1)}`;
38
+ }
39
+ if (cookie.partitioned)
40
+ str += "; Partitioned";
41
+ return str;
42
+ }
43
+ export class CookieStore {
44
+ #cookies;
45
+ #changed = new Set();
46
+ #deleted = new Set();
47
+ constructor(request) {
48
+ this.#cookies = parseCookieString(request.headers.get("cookie") ?? "");
49
+ }
50
+ async get(nameOrOptions) {
51
+ const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions?.name;
52
+ if (name === undefined)
53
+ return this.#cookies[0];
54
+ return this.#cookies.find((c) => c.name === name);
55
+ }
56
+ async getAll(nameOrOptions) {
57
+ const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions?.name;
58
+ if (name === undefined)
59
+ return [...this.#cookies];
60
+ return this.#cookies.filter((c) => c.name === name);
61
+ }
62
+ async set(nameOrOptions, value) {
63
+ const init = typeof nameOrOptions === "string"
64
+ ? { name: nameOrOptions, value: value ?? "" }
65
+ : nameOrOptions;
66
+ const existing = this.#cookies.find((c) => c.name === init.name);
67
+ const cookie = {
68
+ name: init.name,
69
+ value: init.value,
70
+ domain: init.domain ?? existing?.domain ?? null,
71
+ path: init.path ?? existing?.path ?? "/",
72
+ expires: init.expires ?? existing?.expires ?? null,
73
+ secure: existing?.secure ?? false,
74
+ sameSite: init.sameSite ?? existing?.sameSite ?? "lax",
75
+ partitioned: init.partitioned ?? existing?.partitioned ?? false,
76
+ };
77
+ if (existing) {
78
+ const idx = this.#cookies.indexOf(existing);
79
+ this.#cookies[idx] = cookie;
80
+ }
81
+ else {
82
+ this.#cookies.push(cookie);
83
+ }
84
+ this.#deleted.delete(init.name);
85
+ this.#changed.add(init.name);
86
+ }
87
+ async delete(nameOrOptions) {
88
+ const opts = typeof nameOrOptions === "string"
89
+ ? { name: nameOrOptions }
90
+ : nameOrOptions;
91
+ const idx = this.#cookies.findIndex((c) => c.name === opts.name);
92
+ if (idx !== -1) {
93
+ this.#cookies.splice(idx, 1);
94
+ }
95
+ this.#changed.delete(opts.name);
96
+ this.#deleted.add(opts.name);
97
+ }
98
+ write(headers) {
99
+ for (const name of this.#changed) {
100
+ const cookie = this.#cookies.find((c) => c.name === name);
101
+ if (cookie) {
102
+ headers.append("Set-Cookie", serializeSetCookie(cookie));
103
+ }
104
+ }
105
+ for (const name of this.#deleted) {
106
+ headers.append("Set-Cookie", `${name}=; Path=/; Expires=${new Date(0).toUTCString()}`);
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,9 @@
1
+ import type { Schema } from "./schema.js";
2
+ import type { TRequest } from "./t-request.js";
3
+ import type { TResponse } from "./t-response.js";
4
+ export type HandlerFn<Response, AuthData, Params, Query, Body> = (request: TRequest<AuthData, Params, Query, Body>) => Promise<TResponse<Response>>;
5
+ export type Handler<Response, Params extends Record<string, string>, Query extends Record<string, unknown>, Body> = {
6
+ schema: Schema<Response, unknown, Params, Query, Body>;
7
+ handler: HandlerFn<Response, any, Params, Query, Body>;
8
+ };
9
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,MAAM,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAC/D,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAC7C,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AAElC,MAAM,MAAM,OAAO,CACjB,QAAQ,EACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,IAAI,IACF;IACF,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACvD,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;CACxD,CAAC"}
File without changes
@@ -0,0 +1,6 @@
1
+ export declare class HttpError<Data = any> extends Error {
2
+ status: number;
3
+ data?: Data;
4
+ constructor(status: number, message: string, data?: Data);
5
+ }
6
+ //# sourceMappingURL=http-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-error.d.ts","sourceRoot":"","sources":["../src/http-error.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAS,CAAC,IAAI,GAAG,GAAG,CAAE,SAAQ,KAAK;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,CAAC;gBAEA,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI;CAKzD"}
@@ -0,0 +1,9 @@
1
+ export class HttpError extends Error {
2
+ status;
3
+ data;
4
+ constructor(status, message, data) {
5
+ super(message);
6
+ this.status = status;
7
+ this.data = data;
8
+ }
9
+ }
@@ -0,0 +1,13 @@
1
+ export * from "./constants.js";
2
+ export * from "./http-error.js";
3
+ export * from "./is-mutation.js";
4
+ export type * from "./logger.js";
5
+ export type * from "./maybe-promise.js";
6
+ export type * from "./path.js";
7
+ export type * from "./route.js";
8
+ export type * from "./handler.js";
9
+ export type * from "./schema.js";
10
+ export type * from "./t-request.js";
11
+ export * from "./t-response.js";
12
+ export * from "./cookie-store.js";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,mBAAmB,aAAa,CAAC;AACjC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,WAAW,CAAC;AAC/B,mBAAmB,YAAY,CAAC;AAChC,mBAAmB,cAAc,CAAC;AAClC,mBAAmB,aAAa,CAAC;AACjC,mBAAmB,gBAAgB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./constants.js";
2
+ export * from "./http-error.js";
3
+ export * from "./is-mutation.js";
4
+ export * from "./t-response.js";
5
+ export * from "./cookie-store.js";
@@ -0,0 +1,2 @@
1
+ export declare function isMutation(req: Request): boolean;
2
+ //# sourceMappingURL=is-mutation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-mutation.d.ts","sourceRoot":"","sources":["../src/is-mutation.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,WAOtC"}
@@ -0,0 +1,6 @@
1
+ export function isMutation(req) {
2
+ return (req.method === "POST" ||
3
+ req.method === "PUT" ||
4
+ req.method === "PATCH" ||
5
+ req.method === "DELETE");
6
+ }
@@ -0,0 +1,5 @@
1
+ import type { MaybePromise } from "./maybe-promise.js";
2
+ export interface Logger {
3
+ error?: (error: unknown) => MaybePromise<void>;
4
+ }
5
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CAChD"}
package/dist/logger.js ADDED
File without changes
@@ -0,0 +1,2 @@
1
+ export type MaybePromise<T> = T | Promise<T>;
2
+ //# sourceMappingURL=maybe-promise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maybe-promise.d.ts","sourceRoot":"","sources":["../src/maybe-promise.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC"}
File without changes
package/dist/path.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export type Path = `/${string}`;
2
+ type ReadFrom<Path> = Path extends `${string}*${infer Rest}` ? ReadWildcard<Rest> : Path extends `${string}:${infer Rest}` ? ReadUntil<Rest> : [];
3
+ type ReadWildcard<Path> = Path extends `${infer Match}/${infer Rest}` ? [`*${Match}`, ...ReadFrom<Rest>] : Path extends `${infer Match}` ? [`*${Match}`] : ["*"];
4
+ type ReadUntil<Path> = Path extends `${infer Match}/${infer Rest}` ? [Match, ...ReadFrom<Rest>] : Path extends `${infer Match}` ? [Match] : [];
5
+ type RemovePrefixes<Key> = Key extends "*" ? never : Key extends `*${infer Name}` ? Name : Key;
6
+ export type StrictParams<Pathname> = Pathname extends `${string}:${string}` | `${string}*${string}` ? {
7
+ [Key in ReadFrom<Pathname>[number] as RemovePrefixes<Key>]: string;
8
+ } : {};
9
+ export {};
10
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;AAEhC,KAAK,QAAQ,CAAC,IAAI,IAAI,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,EAAE,GACxD,YAAY,CAAC,IAAI,CAAC,GAClB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,EAAE,GACtC,SAAS,CAAC,IAAI,CAAC,GACf,EAAE,CAAC;AAEP,KAAK,YAAY,CAAC,IAAI,IAAI,IAAI,SAAS,GAAG,MAAM,KAAK,IAAI,MAAM,IAAI,EAAE,GACjE,CAAC,IAAI,KAAK,EAAE,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,GAChC,IAAI,SAAS,GAAG,MAAM,KAAK,EAAE,GAC7B,CAAC,IAAI,KAAK,EAAE,CAAC,GACb,CAAC,GAAG,CAAC,CAAC;AAEV,KAAK,SAAS,CAAC,IAAI,IAAI,IAAI,SAAS,GAAG,MAAM,KAAK,IAAI,MAAM,IAAI,EAAE,GAC9D,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,GAC1B,IAAI,SAAS,GAAG,MAAM,KAAK,EAAE,GAC7B,CAAC,KAAK,CAAC,GACP,EAAE,CAAC;AAEP,KAAK,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,GACtC,KAAK,GACL,GAAG,SAAS,IAAI,MAAM,IAAI,EAAE,GAC5B,IAAI,GACJ,GAAG,CAAC;AAER,MAAM,MAAM,YAAY,CAAC,QAAQ,IAAI,QAAQ,SACzC,GAAG,MAAM,IAAI,MAAM,EAAE,GACrB,GAAG,MAAM,IAAI,MAAM,EAAE,GACrB;KACG,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,MAAM;CACnE,GACD,EAAE,CAAC"}
package/dist/path.js ADDED
File without changes
@@ -0,0 +1,18 @@
1
+ import type { Handler } from "./handler.js";
2
+ export type Route<Params extends Record<string, string>, GetResponse, GetQuery extends Record<string, unknown>, PostResponse, PostQuery extends Record<string, unknown>, PostBody, DeleteResponse, DeleteQuery extends Record<string, unknown>, PutResponse, PutQuery extends Record<string, unknown>, PutBody, PatchResponse, PatchQuery extends Record<string, unknown>, PatchBody> = {
3
+ GET?: GetQuery extends never ? never : Handler<GetResponse, Params, GetQuery, undefined>;
4
+ HEAD?: GetQuery extends never ? never : Handler<undefined, Params, GetQuery, undefined>;
5
+ POST?: PostQuery extends never ? never : Handler<PostResponse, Params, PostQuery, PostBody>;
6
+ DELETE?: DeleteQuery extends never ? never : Handler<DeleteResponse, Params, DeleteQuery, undefined>;
7
+ PUT?: PutQuery extends never ? never : Handler<PutResponse, Params, PutQuery, PutBody>;
8
+ PATCH?: PatchQuery extends never ? never : Handler<PatchResponse, Params, PatchQuery, PatchBody>;
9
+ };
10
+ export type BaseRoute = {
11
+ GET?: Handler<any, any, any, undefined>;
12
+ HEAD?: Handler<undefined, any, any, undefined>;
13
+ POST?: Handler<any, any, any, any>;
14
+ DELETE?: Handler<any, any, any, undefined>;
15
+ PUT?: Handler<any, any, any, any>;
16
+ PATCH?: Handler<any, any, any, any>;
17
+ };
18
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,MAAM,KAAK,CACf,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,WAAW,EACX,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,YAAY,EACZ,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzC,QAAQ,EACR,cAAc,EACd,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3C,WAAW,EACX,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,OAAO,EACP,aAAa,EACb,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1C,SAAS,IACP;IACF,GAAG,CAAC,EAAE,QAAQ,SAAS,KAAK,GACxB,KAAK,GACL,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,EAAE,QAAQ,SAAS,KAAK,GACzB,KAAK,GACL,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,EAAE,SAAS,SAAS,KAAK,GAC1B,KAAK,GACL,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,CAAC,EAAE,WAAW,SAAS,KAAK,GAC9B,KAAK,GACL,OAAO,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAC5D,GAAG,CAAC,EAAE,QAAQ,SAAS,KAAK,GACxB,KAAK,GACL,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,UAAU,SAAS,KAAK,GAC5B,KAAK,GACL,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;CACrC,CAAC"}
package/dist/route.js ADDED
File without changes
@@ -0,0 +1,18 @@
1
+ import type { ZodType } from "zod/v4";
2
+ import type { MaybePromise } from "./maybe-promise.js";
3
+ import type { TRequest } from "./t-request.js";
4
+ export type Schema<Response, AuthData, Params extends Record<string, string>, Query extends Record<string, unknown>, Body> = {
5
+ __r?: Response;
6
+ __q?: Query;
7
+ __b?: Body;
8
+ params?: {
9
+ [key in keyof Params]: ZodType<Params[key], string>;
10
+ };
11
+ query?: {
12
+ [key in keyof Query]: ZodType<Query[key], string | string[] | undefined>;
13
+ };
14
+ body?: ZodType<Body>;
15
+ response?: ZodType<Response>;
16
+ authorize: (req: TRequest<never, Params, Query, never>) => MaybePromise<AuthData>;
17
+ };
18
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,MAAM,MAAM,CAChB,QAAQ,EACR,QAAQ,EACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,IAAI,IACF;IACF,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,GAAG,CAAC,EAAE,KAAK,CAAC;IACZ,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE;SAAG,GAAG,IAAI,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;KAAE,CAAC;IACjE,KAAK,CAAC,EAAE;SACL,GAAG,IAAI,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;KACzE,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,SAAS,EAAE,CACT,GAAG,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KACvC,YAAY,CAAC,QAAQ,CAAC,CAAC;CAC7B,CAAC"}
package/dist/schema.js ADDED
File without changes
@@ -0,0 +1,10 @@
1
+ import type { CookieStore } from "./cookie-store.js";
2
+ export type TRequest<AuthData, Params, Query, Body> = Request & {
3
+ params: () => Params;
4
+ query: () => Query;
5
+ data: () => Promise<Body>;
6
+ auth: () => NonNullable<AuthData>;
7
+ cookies: () => CookieStore;
8
+ invalidate: (tags: string[]) => Promise<void>;
9
+ };
10
+ //# sourceMappingURL=t-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"t-request.d.ts","sourceRoot":"","sources":["../src/t-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,OAAO,GAAG;IAC9D,MAAM,EAAE,MAAM,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,KAAK,CAAC;IACnB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,EAAE,MAAM,WAAW,CAAC;IAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C,CAAC"}
File without changes
@@ -0,0 +1,21 @@
1
+ import type { CookieStore } from "./cookie-store.js";
2
+ interface TResponseInit extends ResponseInit {
3
+ cache?: {
4
+ tags?: string[];
5
+ ttl?: number;
6
+ };
7
+ cookies?: CookieStore;
8
+ }
9
+ export declare class TResponse<T = unknown> extends Response {
10
+ data?: T;
11
+ cache?: {
12
+ tags?: string[];
13
+ ttl?: number;
14
+ };
15
+ constructor(body?: BodyInit | null, init?: TResponseInit);
16
+ static json<T>(data: T, init?: TResponseInit): TResponse<T>;
17
+ static ndjson<T>(gen: AsyncGenerator<T, void, unknown>, init?: TResponseInit): TResponse<AsyncGenerator<T, void, unknown>>;
18
+ static void(init?: TResponseInit): TResponse<void>;
19
+ }
20
+ export {};
21
+ //# sourceMappingURL=t-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"t-response.d.ts","sourceRoot":"","sources":["../src/t-response.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,UAAU,aAAc,SAAQ,YAAY;IAC1C,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,qBAAa,SAAS,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,QAAQ;IAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE;QACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;gBAEU,IAAI,GAAE,QAAQ,GAAG,IAAW,EAAE,IAAI,GAAE,aAAkB;WAuBlD,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAE,aAAkB,GAAG,SAAS,CAAC,CAAC,CAAC;IAOxE,MAAM,CAAC,MAAM,CAAC,CAAC,EACb,GAAG,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EACrC,IAAI,GAAE,aAAkB,GACvB,SAAS,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAgB9C,MAAM,CAAC,IAAI,CAAC,IAAI,GAAE,aAAkB,GAAG,SAAS,CAAC,IAAI,CAAC;CAMvD"}
@@ -0,0 +1,57 @@
1
+ import { EXPIRES_AT_HEADER, TAGS_HEADER } from "./constants.js";
2
+ export class TResponse extends Response {
3
+ data;
4
+ cache;
5
+ constructor(body = null, init = {}) {
6
+ const { cache, cookies, ...rawInit } = init;
7
+ if (cache?.tags) {
8
+ setHeader(rawInit, TAGS_HEADER, cache.tags.join(" "));
9
+ }
10
+ if (cache?.ttl) {
11
+ setHeader(rawInit, EXPIRES_AT_HEADER, (Date.now() + cache.ttl * 1000).toFixed(0));
12
+ }
13
+ if (cookies) {
14
+ init.headers =
15
+ init.headers instanceof Headers
16
+ ? init.headers
17
+ : new Headers(init.headers);
18
+ cookies.write(init.headers);
19
+ }
20
+ super(body, rawInit);
21
+ this.cache = cache;
22
+ }
23
+ static json(data, init = {}) {
24
+ setHeader(init, "Content-Type", "application/json");
25
+ const res = new TResponse(JSON.stringify(data), init);
26
+ res.data = data;
27
+ return res;
28
+ }
29
+ static ndjson(gen, init = {}) {
30
+ const encoder = new TextEncoder();
31
+ const stream = new ReadableStream({
32
+ async start(controller) {
33
+ for await (const item of gen) {
34
+ controller.enqueue(encoder.encode(`${JSON.stringify(item)}\n`));
35
+ }
36
+ controller.close();
37
+ },
38
+ });
39
+ setHeader(init, "Content-Type", "application/x-ndjson");
40
+ const res = new TResponse(stream, init);
41
+ res.data = gen;
42
+ return res;
43
+ }
44
+ static void(init = {}) {
45
+ setHeader(init, "Content-Length", "0");
46
+ const res = new TResponse(null, init);
47
+ res.data = undefined;
48
+ return res;
49
+ }
50
+ }
51
+ function setHeader(init, key, value) {
52
+ init.headers =
53
+ init.headers instanceof Headers ? init.headers : new Headers(init.headers);
54
+ if (!init.headers.has(key)) {
55
+ init.headers.set(key, value);
56
+ }
57
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@toapi/common",
3
+ "version": "0.12.1",
4
+ "author": {
5
+ "name": "Michel Smola",
6
+ "email": "michel.smola@farbenmeer.de"
7
+ },
8
+ "type": "module",
9
+ "module": "dist/index.js",
10
+ "main": "dist/index.js",
11
+ "private": false,
12
+ "license": "MIT",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ }
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^25.0.3",
24
+ "vitest": "^4.0.16",
25
+ "zod": "^4.0.17"
26
+ },
27
+ "peerDependencies": {
28
+ "typescript": "^5 || ^6.0.0",
29
+ "zod": "^4.0.17"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/farbenmeer/tapi.git"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc --noEmit false",
37
+ "release": "pnpm build && pnpm publish --no-git-checks",
38
+ "test": "vitest"
39
+ }
40
+ }