-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate-routes.ts
107 lines (85 loc) · 3.01 KB
/
create-routes.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { Handler } from "./handler";
const imports = `import type { ApiRouteProps } from 'sst/constructs';\n\n`;
const routeType = `export type Route = keyof typeof routes;\n\n`;
const paramRouteType = `type ParamRoute = keyof {
[R in Route as (typeof routes)[R]['params'] extends readonly [] ? never : R]: (typeof routes[R]);
};\n\n`;
const routeParamsType = `type RouteParams<R extends ParamRoute> = {
[RouteName in ParamRoute]: {
[K in (typeof routes)[R]['params'][number]]: string;
};
}[R];\n\n`;
const eventWithPathParametersType = `type EventWithPathParameters = {
pathParameters?: {
[name: string]: string | undefined;
};
};\n\n`;
const getPathParametersFunction = `export function getPathParameters<R extends ParamRoute>(
route: R,
event: EventWithPathParameters
): RouteParams<R> {
if (!event.pathParameters) {
throw new Error('No path parameters present!');
}
const params: Record<string, string> = {};
for (const param of routes[route].params) {
if (event.pathParameters[param]) {
params[param] = event.pathParameters[param]!;
}
}
if (routes[route].params.length !== Object.keys(params).length) {
throw new Error('Could not find all required path parameters.');
}
return params as RouteParams<R>;
}\n\n`;
const routeConfigType = `type RouteConfig = Record<Route, ApiRouteProps<string>> & {
configureRoute(
route: Route,
configFn: (current: ApiRouteProps<string>) => ApiRouteProps<string>,
): RouteConfig;
routes(): Record<Route, ApiRouteProps<string>>;
};\n\n`;
const routeConfigBuild = `export const routeConfig: RouteConfig = {} as RouteConfig;
for (const [name, { path }] of Object.entries(routes)) {
routeConfig[name as Route] = path;
}
routeConfig.configureRoute = function (route, configFn) {
this[route] = configFn(this[route]);
return this;
};
routeConfig.routes = function () {
const config: Record<string, ApiRouteProps<string>> = {};
for (const [key, val] of Object.entries(this)) {
if (key !== 'routes' && key !== 'configureRoute') {
config[key] = val as ApiRouteProps<string>;
}
}
return config;
};\n`;
export function createRoutesFile(baseDirectory: string, handlerFilePaths: string[]): string {
let hasRoutesWithParams = false;
const handlers: Handler[] = [];
let routes = "const routes = {";
for (const filePath of handlerFilePaths) {
const handler = new Handler(filePath, baseDirectory);
if (handler.params.length) {
hasRoutesWithParams = true;
}
routes = `${routes}\n\t'${handler.pathString()}': { params: [${handler.params
.map((param) => `'${param}'`)
.join(", ")}], path: '${handler.handlerPath}' },`;
handlers.push(handler);
}
routes = `${routes}\n} as const;\n\n`;
let fileContents = "".concat(imports, routes, routeType);
if (hasRoutesWithParams) {
fileContents = fileContents.concat(
paramRouteType,
routeParamsType,
eventWithPathParametersType,
getPathParametersFunction,
);
}
fileContents = fileContents.concat(routeConfigType, routeConfigBuild);
return fileContents;
}