fossyl 0.1.6 → 0.10.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 +107 -0
- package/LICENSE +674 -0
- package/README.md +3 -99
- package/bin/fossyl.js +2 -0
- package/dist/index.d.mts +1 -203
- package/dist/index.d.ts +1 -203
- package/dist/index.js +1247 -69
- package/dist/index.mjs +1239 -60
- package/package.json +26 -24
- package/fossyl.svg +0 -2
- package/src/example.ts +0 -31
- package/src/index.ts +0 -22
- package/src/router/router.ts +0 -277
- package/src/router/tmp.sh +0 -15
- package/src/router/types/configuration.types.ts +0 -143
- package/src/router/types/params.types.ts +0 -13
- package/src/router/types/router-creation.types.ts +0 -36
- package/src/router/types/routes.types.ts +0 -124
package/README.md
CHANGED
|
@@ -1,101 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
<img
|
|
3
|
-
src="https://raw.githubusercontent.com/YoyoSaur/fossyl/main/packages/core/fossyl.svg"
|
|
4
|
-
alt="Fossyl Logo"
|
|
5
|
-
width="200"
|
|
6
|
-
/>
|
|
1
|
+
# fossyl
|
|
7
2
|
|
|
8
|
-
|
|
3
|
+
CLI for scaffolding fossyl projects.
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
[](https://www.npmjs.com/package/fossyl)
|
|
13
|
-
[](https://opensource.org/licenses/MIT)
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
## Overview
|
|
17
|
-
|
|
18
|
-
Fossyl is a type-safe REST API framework built with TypeScript, specifically designed to work seamlessly with AI-assisted development tools like Claude. It provides inference-heavy APIs with crystal clear error messages, making it easy to build robust REST APIs with full type safety.
|
|
19
|
-
|
|
20
|
-
## Features
|
|
21
|
-
|
|
22
|
-
- **Type-Safe Routes**: Full TypeScript type inference for routes, parameters, and responses
|
|
23
|
-
- **REST Semantics Enforcement**: Compile-time validation of REST patterns (e.g., GET can't have body, POST requires body)
|
|
24
|
-
- **Pure Functional Design**: Validator-library agnostic with simple function types
|
|
25
|
-
- **Query Parameter Validation**: Optional type-safe query parameter validation
|
|
26
|
-
- **Authentication Support**: Type-safe authentication with custom authentication functions
|
|
27
|
-
- **AI-First Development**: Designed for seamless integration with AI coding assistants
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
npm install fossyl
|
|
33
|
-
# or
|
|
34
|
-
pnpm add fossyl
|
|
35
|
-
# or
|
|
36
|
-
yarn add fossyl
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Quick Start
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { createRouter } from 'fossyl';
|
|
43
|
-
|
|
44
|
-
// Create a router
|
|
45
|
-
const router = createRouter();
|
|
46
|
-
|
|
47
|
-
// Define routes with full type safety
|
|
48
|
-
const userRoute = router.endpoint('/users/:id').get({
|
|
49
|
-
handler: async ({ url }) => {
|
|
50
|
-
const userId = url.id; // Fully typed!
|
|
51
|
-
return { id: userId, name: 'John Doe' };
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Routes with authentication
|
|
56
|
-
const authenticatedRoute = router.endpoint('/protected').get({
|
|
57
|
-
authenticator: async (headers) => {
|
|
58
|
-
// Your auth logic here
|
|
59
|
-
return { userId: headers['user-id'] };
|
|
60
|
-
},
|
|
61
|
-
handler: async ({ url }, auth) => {
|
|
62
|
-
// auth is fully typed based on your authenticator!
|
|
63
|
-
return { message: `Hello, user ${auth.userId}` };
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Routes with request body validation
|
|
68
|
-
const createUserRoute = router.endpoint('/users').post({
|
|
69
|
-
bodyValidator: (data) => {
|
|
70
|
-
// Your validation logic here
|
|
71
|
-
return data as { name: string; email: string };
|
|
72
|
-
},
|
|
73
|
-
handler: async ({ url, body }) => {
|
|
74
|
-
// body is fully typed based on your validator!
|
|
75
|
-
return { id: '123', ...body };
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Routes with query parameters
|
|
80
|
-
const searchRoute = router.endpoint('/search').get({
|
|
81
|
-
queryValidator: (data) => {
|
|
82
|
-
return data as { q: string; limit?: number };
|
|
83
|
-
},
|
|
84
|
-
handler: async ({ url, query }) => {
|
|
85
|
-
// query is fully typed!
|
|
86
|
-
return { results: [], query: query.q };
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Documentation
|
|
92
|
-
|
|
93
|
-
For more detailed documentation, visit the [GitHub repository](https://github.com/YoyoSaur/fossyl).
|
|
94
|
-
|
|
95
|
-
## Contributing
|
|
96
|
-
|
|
97
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
98
|
-
|
|
99
|
-
## License
|
|
100
|
-
|
|
101
|
-
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
5
|
+
For AI-assisted development, see [CLAUDE.md](./CLAUDE.md). Full documentation at [github.com/YoyoSaur/fossyl](https://github.com/YoyoSaur/fossyl).
|
package/bin/fossyl.js
ADDED
package/dist/index.d.mts
CHANGED
|
@@ -1,204 +1,2 @@
|
|
|
1
|
-
type ExtractUrlParams<Path extends string> = Path extends `${string}/:${infer Param}/${infer Rest}` ? Param | ExtractUrlParams<Rest> : Path extends `${string}/:${infer Param}` ? Param : never;
|
|
2
|
-
type Expand<T> = T extends infer O ? {
|
|
3
|
-
[K in keyof O]: O[K];
|
|
4
|
-
} : never;
|
|
5
|
-
type Params<Path extends string> = Expand<{
|
|
6
|
-
[K in ExtractUrlParams<Path>]: string;
|
|
7
|
-
}>;
|
|
8
1
|
|
|
9
|
-
|
|
10
|
-
type Authentication = {
|
|
11
|
-
readonly [authBrand]: "Auth";
|
|
12
|
-
};
|
|
13
|
-
declare function authWrapper<T>(auth: T): T & Authentication;
|
|
14
|
-
type RestMethod = "GET" | "POST" | "PUT" | "DELETE";
|
|
15
|
-
type OpenRoute<Path extends string, Method extends RestMethod, Res extends unknown, Query extends unknown | undefined = undefined> = {
|
|
16
|
-
type: "open";
|
|
17
|
-
path: Path;
|
|
18
|
-
method: Method;
|
|
19
|
-
validator?: never;
|
|
20
|
-
authenticator?: never;
|
|
21
|
-
handler: (params: {
|
|
22
|
-
url: Params<Path>;
|
|
23
|
-
query: Query;
|
|
24
|
-
}) => Promise<Res>;
|
|
25
|
-
};
|
|
26
|
-
type AuthenticatedRoute<Path extends string, Method extends RestMethod, Res extends unknown, Auth extends Authentication, Query extends unknown | undefined = undefined> = {
|
|
27
|
-
type: "authenticated";
|
|
28
|
-
path: Path;
|
|
29
|
-
method: Method;
|
|
30
|
-
validator?: never;
|
|
31
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
32
|
-
handler: (params: {
|
|
33
|
-
url: Params<Path>;
|
|
34
|
-
query: Query;
|
|
35
|
-
}, auth: Auth) => Promise<Res>;
|
|
36
|
-
};
|
|
37
|
-
type ValidatedRoute<Path extends string, Method extends RestMethod, Res extends unknown, RequestBody extends unknown, Query extends unknown | undefined = undefined> = {
|
|
38
|
-
type: "validated";
|
|
39
|
-
path: Path;
|
|
40
|
-
method: Method;
|
|
41
|
-
validator: ValidatorFunction<RequestBody>;
|
|
42
|
-
authenticator?: never;
|
|
43
|
-
handler: (params: {
|
|
44
|
-
url: Params<Path>;
|
|
45
|
-
query: Query;
|
|
46
|
-
}, body: RequestBody) => Promise<Res>;
|
|
47
|
-
};
|
|
48
|
-
type FullRoute<Path extends string, Method extends RestMethod, Res extends unknown, RequestBody extends unknown, Auth extends Authentication, Query extends unknown | undefined = undefined> = {
|
|
49
|
-
type: "full";
|
|
50
|
-
path: Path;
|
|
51
|
-
method: Method;
|
|
52
|
-
validator: ValidatorFunction<RequestBody>;
|
|
53
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
54
|
-
handler: Query extends undefined ? (params: {
|
|
55
|
-
url: Params<Path>;
|
|
56
|
-
}, auth: Authentication, body: RequestBody) => Promise<Res> : (params: {
|
|
57
|
-
url: Params<Path>;
|
|
58
|
-
query: Query;
|
|
59
|
-
}, auth: Authentication, body: RequestBody) => Promise<Res>;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
type ValidatorFunction<T extends unknown = unknown> = (data: unknown) => T;
|
|
63
|
-
type AuthenticationFunction<T extends Authentication> = (headers: Record<string, string>) => T;
|
|
64
|
-
/**
|
|
65
|
-
* This is the most confusing part of the type system, but also key.
|
|
66
|
-
* This type is used to force type inferenece when creating your endpoints.
|
|
67
|
-
* This is the structure to provide `function overload`s. This is so you can have the same function
|
|
68
|
-
* (in our case get,put,post,delete) but allow differnt configurations.
|
|
69
|
-
*
|
|
70
|
-
* These configurations need to be strongly typed force the developers into using the tools.
|
|
71
|
-
*
|
|
72
|
-
* Want to allow Auth? - Gotta pass in authenticator and the type system handles it
|
|
73
|
-
*
|
|
74
|
-
* Also, this is where the core of the Zod system is. We force the body to be a zod validated input.
|
|
75
|
-
* Luckily, this is pretty easy to replace.
|
|
76
|
-
* PART of me wanted to further abstract it such that you needed a translation function but
|
|
77
|
-
* that seemed overengineerd
|
|
78
|
-
*
|
|
79
|
-
*/
|
|
80
|
-
/**
|
|
81
|
-
* Configuration type for POST/PUT/DELETE endpoints.
|
|
82
|
-
* These methods require a request body, so they always need a validator.
|
|
83
|
-
*
|
|
84
|
-
* Four variants (with/without auth × with/without query):
|
|
85
|
-
* 1. Validated only, no query: validator + handler(params, body)
|
|
86
|
-
* 2. Validated only, with query: validator + queryValidator + handler(params, body)
|
|
87
|
-
* 3. Full (auth + validated), no query: authenticator + validator + handler(params, auth, body)
|
|
88
|
-
* 4. Full (auth + validated), with query: authenticator + validator + queryValidator + handler(params, auth, body)
|
|
89
|
-
*/
|
|
90
|
-
type EndpointCreationFunction<Path extends string, Method extends RestMethod> = {
|
|
91
|
-
<Res extends unknown, RequestBody extends unknown>(config: {
|
|
92
|
-
authenticator?: never;
|
|
93
|
-
validator: ValidatorFunction<RequestBody>;
|
|
94
|
-
queryValidator?: never;
|
|
95
|
-
handler: (params: {
|
|
96
|
-
url: Params<Path>;
|
|
97
|
-
}, body: RequestBody) => Promise<Res>;
|
|
98
|
-
}): ValidatedRoute<Path, Method, Res, RequestBody, undefined>;
|
|
99
|
-
<Res extends unknown, RequestBody extends unknown, Query extends unknown>(config: {
|
|
100
|
-
authenticator?: never;
|
|
101
|
-
validator: ValidatorFunction<RequestBody>;
|
|
102
|
-
queryValidator: ValidatorFunction<Query>;
|
|
103
|
-
handler: (params: {
|
|
104
|
-
url: Params<Path>;
|
|
105
|
-
query: Query;
|
|
106
|
-
}, body: RequestBody) => Promise<Res>;
|
|
107
|
-
}): ValidatedRoute<Path, Method, Res, RequestBody, Query>;
|
|
108
|
-
<Res extends unknown, RequestBody extends unknown, Auth extends Authentication>(config: {
|
|
109
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
110
|
-
validator: ValidatorFunction<RequestBody>;
|
|
111
|
-
queryValidator?: never;
|
|
112
|
-
handler: (params: {
|
|
113
|
-
url: Params<Path>;
|
|
114
|
-
}, auth: Auth, body: RequestBody) => Promise<Res>;
|
|
115
|
-
}): FullRoute<Path, Method, Res, RequestBody, Auth, undefined>;
|
|
116
|
-
<Res extends unknown, RequestBody extends unknown, Auth extends Authentication, Query extends unknown>(config: {
|
|
117
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
118
|
-
validator: ValidatorFunction<RequestBody>;
|
|
119
|
-
queryValidator: ValidatorFunction<Query>;
|
|
120
|
-
handler: (params: {
|
|
121
|
-
url: Params<Path>;
|
|
122
|
-
query: Query;
|
|
123
|
-
}, auth: Auth, body: RequestBody) => Promise<Res>;
|
|
124
|
-
}): FullRoute<Path, Method, Res, RequestBody, Auth, Query>;
|
|
125
|
-
};
|
|
126
|
-
/**
|
|
127
|
-
* Configuration type for GET/DELETE endpoints.
|
|
128
|
-
* These methods cannot have a request body, so no validator.
|
|
129
|
-
*
|
|
130
|
-
* Four variants (with/without auth × with/without query):
|
|
131
|
-
* 1. Open, no query: just handler(params)
|
|
132
|
-
* 2. Open, with query: queryValidator + handler(params)
|
|
133
|
-
* 3. Authenticated, no query: authenticator + handler(params, auth)
|
|
134
|
-
* 4. Authenticated, with query: authenticator + queryValidator + handler(params, auth)
|
|
135
|
-
*/
|
|
136
|
-
type GetEndpointCreationFunction<Path extends string, Method extends RestMethod> = {
|
|
137
|
-
<Res extends unknown>(config: {
|
|
138
|
-
authenticator?: never;
|
|
139
|
-
queryValidator?: never;
|
|
140
|
-
handler: (params: {
|
|
141
|
-
url: Params<Path>;
|
|
142
|
-
}) => Promise<Res>;
|
|
143
|
-
}): OpenRoute<Path, Method, Res, undefined>;
|
|
144
|
-
<Res extends unknown, Query extends unknown>(config: {
|
|
145
|
-
authenticator?: never;
|
|
146
|
-
queryValidator: ValidatorFunction<Query>;
|
|
147
|
-
handler: (params: {
|
|
148
|
-
url: Params<Path>;
|
|
149
|
-
query: Query;
|
|
150
|
-
}) => Promise<Res>;
|
|
151
|
-
}): OpenRoute<Path, Method, Res, Query>;
|
|
152
|
-
<Res extends unknown, Auth extends Authentication>(config: {
|
|
153
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
154
|
-
queryValidator?: never;
|
|
155
|
-
handler: (params: {
|
|
156
|
-
url: Params<Path>;
|
|
157
|
-
}, auth: Auth) => Promise<Res>;
|
|
158
|
-
}): AuthenticatedRoute<Path, Method, Res, Auth, undefined>;
|
|
159
|
-
<Res extends unknown, Auth extends Authentication, Query extends unknown>(config: {
|
|
160
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
161
|
-
queryValidator: ValidatorFunction<Query>;
|
|
162
|
-
handler: (params: {
|
|
163
|
-
url: Params<Path>;
|
|
164
|
-
query: Query;
|
|
165
|
-
}, auth: Auth) => Promise<Res>;
|
|
166
|
-
}): AuthenticatedRoute<Path, Method, Res, Auth, Query>;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
type Endpoint<Path extends string> = {
|
|
170
|
-
get: GetEndpointCreationFunction<Path, "GET">;
|
|
171
|
-
post: EndpointCreationFunction<Path, "POST">;
|
|
172
|
-
put: EndpointCreationFunction<Path, "PUT">;
|
|
173
|
-
delete: GetEndpointCreationFunction<Path, "DELETE">;
|
|
174
|
-
};
|
|
175
|
-
/**
|
|
176
|
-
* Creates a router that ensures all endpoints extend the route.
|
|
177
|
-
* IDK if this is actually useful, but I kinda like it.
|
|
178
|
-
*
|
|
179
|
-
* There def was a part of me that thought about pure generator functions.
|
|
180
|
-
* In fact... they're provided!
|
|
181
|
-
*
|
|
182
|
-
* We can discuss that.
|
|
183
|
-
*/
|
|
184
|
-
type Router<BasePath extends string> = {
|
|
185
|
-
/**
|
|
186
|
-
* Creates an endpoint
|
|
187
|
-
* @param path string, must extend Router's string
|
|
188
|
-
*/
|
|
189
|
-
createEndpoint: <Path extends `${BasePath}${string}`>(path: Path) => Endpoint<Path>;
|
|
190
|
-
/**
|
|
191
|
-
* Creates a subrouter
|
|
192
|
-
* @param path string, must extend Router's string
|
|
193
|
-
*/
|
|
194
|
-
createSubrouter: <Path extends `${BasePath}${string}`>(path: Path) => Router<Path>;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Provides an Ednpoint creater. Would maybe like some other internal stuff? Lowkey... I think we
|
|
199
|
-
* all might just end up using the helper functions of get and del and such.
|
|
200
|
-
* @param _ - this param is still needed because the type is determined at compile time.
|
|
201
|
-
*/
|
|
202
|
-
declare function createRouter<BasePath extends string>(_: BasePath): Router<BasePath>;
|
|
203
|
-
|
|
204
|
-
export { type AuthenticatedRoute, type Authentication, type AuthenticationFunction, type Endpoint, type FullRoute, type OpenRoute, type RestMethod, type Router, type ValidatedRoute, type ValidatorFunction, authWrapper, createRouter };
|
|
2
|
+
export { }
|
package/dist/index.d.ts
CHANGED
|
@@ -1,204 +1,2 @@
|
|
|
1
|
-
type ExtractUrlParams<Path extends string> = Path extends `${string}/:${infer Param}/${infer Rest}` ? Param | ExtractUrlParams<Rest> : Path extends `${string}/:${infer Param}` ? Param : never;
|
|
2
|
-
type Expand<T> = T extends infer O ? {
|
|
3
|
-
[K in keyof O]: O[K];
|
|
4
|
-
} : never;
|
|
5
|
-
type Params<Path extends string> = Expand<{
|
|
6
|
-
[K in ExtractUrlParams<Path>]: string;
|
|
7
|
-
}>;
|
|
8
1
|
|
|
9
|
-
|
|
10
|
-
type Authentication = {
|
|
11
|
-
readonly [authBrand]: "Auth";
|
|
12
|
-
};
|
|
13
|
-
declare function authWrapper<T>(auth: T): T & Authentication;
|
|
14
|
-
type RestMethod = "GET" | "POST" | "PUT" | "DELETE";
|
|
15
|
-
type OpenRoute<Path extends string, Method extends RestMethod, Res extends unknown, Query extends unknown | undefined = undefined> = {
|
|
16
|
-
type: "open";
|
|
17
|
-
path: Path;
|
|
18
|
-
method: Method;
|
|
19
|
-
validator?: never;
|
|
20
|
-
authenticator?: never;
|
|
21
|
-
handler: (params: {
|
|
22
|
-
url: Params<Path>;
|
|
23
|
-
query: Query;
|
|
24
|
-
}) => Promise<Res>;
|
|
25
|
-
};
|
|
26
|
-
type AuthenticatedRoute<Path extends string, Method extends RestMethod, Res extends unknown, Auth extends Authentication, Query extends unknown | undefined = undefined> = {
|
|
27
|
-
type: "authenticated";
|
|
28
|
-
path: Path;
|
|
29
|
-
method: Method;
|
|
30
|
-
validator?: never;
|
|
31
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
32
|
-
handler: (params: {
|
|
33
|
-
url: Params<Path>;
|
|
34
|
-
query: Query;
|
|
35
|
-
}, auth: Auth) => Promise<Res>;
|
|
36
|
-
};
|
|
37
|
-
type ValidatedRoute<Path extends string, Method extends RestMethod, Res extends unknown, RequestBody extends unknown, Query extends unknown | undefined = undefined> = {
|
|
38
|
-
type: "validated";
|
|
39
|
-
path: Path;
|
|
40
|
-
method: Method;
|
|
41
|
-
validator: ValidatorFunction<RequestBody>;
|
|
42
|
-
authenticator?: never;
|
|
43
|
-
handler: (params: {
|
|
44
|
-
url: Params<Path>;
|
|
45
|
-
query: Query;
|
|
46
|
-
}, body: RequestBody) => Promise<Res>;
|
|
47
|
-
};
|
|
48
|
-
type FullRoute<Path extends string, Method extends RestMethod, Res extends unknown, RequestBody extends unknown, Auth extends Authentication, Query extends unknown | undefined = undefined> = {
|
|
49
|
-
type: "full";
|
|
50
|
-
path: Path;
|
|
51
|
-
method: Method;
|
|
52
|
-
validator: ValidatorFunction<RequestBody>;
|
|
53
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
54
|
-
handler: Query extends undefined ? (params: {
|
|
55
|
-
url: Params<Path>;
|
|
56
|
-
}, auth: Authentication, body: RequestBody) => Promise<Res> : (params: {
|
|
57
|
-
url: Params<Path>;
|
|
58
|
-
query: Query;
|
|
59
|
-
}, auth: Authentication, body: RequestBody) => Promise<Res>;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
type ValidatorFunction<T extends unknown = unknown> = (data: unknown) => T;
|
|
63
|
-
type AuthenticationFunction<T extends Authentication> = (headers: Record<string, string>) => T;
|
|
64
|
-
/**
|
|
65
|
-
* This is the most confusing part of the type system, but also key.
|
|
66
|
-
* This type is used to force type inferenece when creating your endpoints.
|
|
67
|
-
* This is the structure to provide `function overload`s. This is so you can have the same function
|
|
68
|
-
* (in our case get,put,post,delete) but allow differnt configurations.
|
|
69
|
-
*
|
|
70
|
-
* These configurations need to be strongly typed force the developers into using the tools.
|
|
71
|
-
*
|
|
72
|
-
* Want to allow Auth? - Gotta pass in authenticator and the type system handles it
|
|
73
|
-
*
|
|
74
|
-
* Also, this is where the core of the Zod system is. We force the body to be a zod validated input.
|
|
75
|
-
* Luckily, this is pretty easy to replace.
|
|
76
|
-
* PART of me wanted to further abstract it such that you needed a translation function but
|
|
77
|
-
* that seemed overengineerd
|
|
78
|
-
*
|
|
79
|
-
*/
|
|
80
|
-
/**
|
|
81
|
-
* Configuration type for POST/PUT/DELETE endpoints.
|
|
82
|
-
* These methods require a request body, so they always need a validator.
|
|
83
|
-
*
|
|
84
|
-
* Four variants (with/without auth × with/without query):
|
|
85
|
-
* 1. Validated only, no query: validator + handler(params, body)
|
|
86
|
-
* 2. Validated only, with query: validator + queryValidator + handler(params, body)
|
|
87
|
-
* 3. Full (auth + validated), no query: authenticator + validator + handler(params, auth, body)
|
|
88
|
-
* 4. Full (auth + validated), with query: authenticator + validator + queryValidator + handler(params, auth, body)
|
|
89
|
-
*/
|
|
90
|
-
type EndpointCreationFunction<Path extends string, Method extends RestMethod> = {
|
|
91
|
-
<Res extends unknown, RequestBody extends unknown>(config: {
|
|
92
|
-
authenticator?: never;
|
|
93
|
-
validator: ValidatorFunction<RequestBody>;
|
|
94
|
-
queryValidator?: never;
|
|
95
|
-
handler: (params: {
|
|
96
|
-
url: Params<Path>;
|
|
97
|
-
}, body: RequestBody) => Promise<Res>;
|
|
98
|
-
}): ValidatedRoute<Path, Method, Res, RequestBody, undefined>;
|
|
99
|
-
<Res extends unknown, RequestBody extends unknown, Query extends unknown>(config: {
|
|
100
|
-
authenticator?: never;
|
|
101
|
-
validator: ValidatorFunction<RequestBody>;
|
|
102
|
-
queryValidator: ValidatorFunction<Query>;
|
|
103
|
-
handler: (params: {
|
|
104
|
-
url: Params<Path>;
|
|
105
|
-
query: Query;
|
|
106
|
-
}, body: RequestBody) => Promise<Res>;
|
|
107
|
-
}): ValidatedRoute<Path, Method, Res, RequestBody, Query>;
|
|
108
|
-
<Res extends unknown, RequestBody extends unknown, Auth extends Authentication>(config: {
|
|
109
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
110
|
-
validator: ValidatorFunction<RequestBody>;
|
|
111
|
-
queryValidator?: never;
|
|
112
|
-
handler: (params: {
|
|
113
|
-
url: Params<Path>;
|
|
114
|
-
}, auth: Auth, body: RequestBody) => Promise<Res>;
|
|
115
|
-
}): FullRoute<Path, Method, Res, RequestBody, Auth, undefined>;
|
|
116
|
-
<Res extends unknown, RequestBody extends unknown, Auth extends Authentication, Query extends unknown>(config: {
|
|
117
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
118
|
-
validator: ValidatorFunction<RequestBody>;
|
|
119
|
-
queryValidator: ValidatorFunction<Query>;
|
|
120
|
-
handler: (params: {
|
|
121
|
-
url: Params<Path>;
|
|
122
|
-
query: Query;
|
|
123
|
-
}, auth: Auth, body: RequestBody) => Promise<Res>;
|
|
124
|
-
}): FullRoute<Path, Method, Res, RequestBody, Auth, Query>;
|
|
125
|
-
};
|
|
126
|
-
/**
|
|
127
|
-
* Configuration type for GET/DELETE endpoints.
|
|
128
|
-
* These methods cannot have a request body, so no validator.
|
|
129
|
-
*
|
|
130
|
-
* Four variants (with/without auth × with/without query):
|
|
131
|
-
* 1. Open, no query: just handler(params)
|
|
132
|
-
* 2. Open, with query: queryValidator + handler(params)
|
|
133
|
-
* 3. Authenticated, no query: authenticator + handler(params, auth)
|
|
134
|
-
* 4. Authenticated, with query: authenticator + queryValidator + handler(params, auth)
|
|
135
|
-
*/
|
|
136
|
-
type GetEndpointCreationFunction<Path extends string, Method extends RestMethod> = {
|
|
137
|
-
<Res extends unknown>(config: {
|
|
138
|
-
authenticator?: never;
|
|
139
|
-
queryValidator?: never;
|
|
140
|
-
handler: (params: {
|
|
141
|
-
url: Params<Path>;
|
|
142
|
-
}) => Promise<Res>;
|
|
143
|
-
}): OpenRoute<Path, Method, Res, undefined>;
|
|
144
|
-
<Res extends unknown, Query extends unknown>(config: {
|
|
145
|
-
authenticator?: never;
|
|
146
|
-
queryValidator: ValidatorFunction<Query>;
|
|
147
|
-
handler: (params: {
|
|
148
|
-
url: Params<Path>;
|
|
149
|
-
query: Query;
|
|
150
|
-
}) => Promise<Res>;
|
|
151
|
-
}): OpenRoute<Path, Method, Res, Query>;
|
|
152
|
-
<Res extends unknown, Auth extends Authentication>(config: {
|
|
153
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
154
|
-
queryValidator?: never;
|
|
155
|
-
handler: (params: {
|
|
156
|
-
url: Params<Path>;
|
|
157
|
-
}, auth: Auth) => Promise<Res>;
|
|
158
|
-
}): AuthenticatedRoute<Path, Method, Res, Auth, undefined>;
|
|
159
|
-
<Res extends unknown, Auth extends Authentication, Query extends unknown>(config: {
|
|
160
|
-
authenticator: AuthenticationFunction<Auth>;
|
|
161
|
-
queryValidator: ValidatorFunction<Query>;
|
|
162
|
-
handler: (params: {
|
|
163
|
-
url: Params<Path>;
|
|
164
|
-
query: Query;
|
|
165
|
-
}, auth: Auth) => Promise<Res>;
|
|
166
|
-
}): AuthenticatedRoute<Path, Method, Res, Auth, Query>;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
type Endpoint<Path extends string> = {
|
|
170
|
-
get: GetEndpointCreationFunction<Path, "GET">;
|
|
171
|
-
post: EndpointCreationFunction<Path, "POST">;
|
|
172
|
-
put: EndpointCreationFunction<Path, "PUT">;
|
|
173
|
-
delete: GetEndpointCreationFunction<Path, "DELETE">;
|
|
174
|
-
};
|
|
175
|
-
/**
|
|
176
|
-
* Creates a router that ensures all endpoints extend the route.
|
|
177
|
-
* IDK if this is actually useful, but I kinda like it.
|
|
178
|
-
*
|
|
179
|
-
* There def was a part of me that thought about pure generator functions.
|
|
180
|
-
* In fact... they're provided!
|
|
181
|
-
*
|
|
182
|
-
* We can discuss that.
|
|
183
|
-
*/
|
|
184
|
-
type Router<BasePath extends string> = {
|
|
185
|
-
/**
|
|
186
|
-
* Creates an endpoint
|
|
187
|
-
* @param path string, must extend Router's string
|
|
188
|
-
*/
|
|
189
|
-
createEndpoint: <Path extends `${BasePath}${string}`>(path: Path) => Endpoint<Path>;
|
|
190
|
-
/**
|
|
191
|
-
* Creates a subrouter
|
|
192
|
-
* @param path string, must extend Router's string
|
|
193
|
-
*/
|
|
194
|
-
createSubrouter: <Path extends `${BasePath}${string}`>(path: Path) => Router<Path>;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Provides an Ednpoint creater. Would maybe like some other internal stuff? Lowkey... I think we
|
|
199
|
-
* all might just end up using the helper functions of get and del and such.
|
|
200
|
-
* @param _ - this param is still needed because the type is determined at compile time.
|
|
201
|
-
*/
|
|
202
|
-
declare function createRouter<BasePath extends string>(_: BasePath): Router<BasePath>;
|
|
203
|
-
|
|
204
|
-
export { type AuthenticatedRoute, type Authentication, type AuthenticationFunction, type Endpoint, type FullRoute, type OpenRoute, type RestMethod, type Router, type ValidatedRoute, type ValidatorFunction, authWrapper, createRouter };
|
|
2
|
+
export { }
|