@kosmojs/fetch-generator 0.0.20 → 0.0.21
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/LICENSE +21 -0
- package/package.json +17 -4
- package/pkg/index.js +134 -28
- package/pkg/index.js.map +3 -3
- package/pkg/templates/@fetch/lib.d.ts +5 -0
- /package/pkg/{src/factory.d.ts → factory.d.ts} +0 -0
- /package/pkg/{src/index.d.ts → index.d.ts} +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present, Slee Woo and KosmoJS contributors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@kosmojs/fetch-generator",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.21",
|
|
5
5
|
"author": "Slee Woo",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
@@ -12,14 +12,27 @@
|
|
|
12
12
|
],
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
|
-
"types": "./pkg/
|
|
15
|
+
"types": "./pkg/index.d.ts",
|
|
16
16
|
"default": "./pkg/index.js"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@kosmojs/dev": "^0.0.
|
|
20
|
+
"@kosmojs/dev": "^0.0.21"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/mime-types": "^3.0.1",
|
|
24
|
+
"@types/qs": "^6.15.0",
|
|
25
|
+
"mime-types": "^3.0.2",
|
|
26
|
+
"path-to-regexp": "^8.3.0",
|
|
27
|
+
"qs": "^6.15.0",
|
|
28
|
+
"typebox": "^1.1.6",
|
|
29
|
+
"@kosmojs/api": "^0.0.21",
|
|
30
|
+
"@kosmojs/fetch": "^0.0.21",
|
|
31
|
+
"@kosmojs/koa-generator": "^0.0.21",
|
|
32
|
+
"@kosmojs/typebox-generator": "^0.0.21"
|
|
21
33
|
},
|
|
22
34
|
"scripts": {
|
|
23
|
-
"build": "esbuilder src/index.ts"
|
|
35
|
+
"build": "esbuilder src/index.ts",
|
|
36
|
+
"test": "vitest --root ../../.. --project generators/fetch-generator"
|
|
24
37
|
}
|
|
25
38
|
}
|
package/pkg/index.js
CHANGED
|
@@ -1,63 +1,166 @@
|
|
|
1
|
+
// package.json
|
|
2
|
+
var package_default = {
|
|
3
|
+
type: "module",
|
|
4
|
+
name: "@kosmojs/fetch-generator",
|
|
5
|
+
version: "0.0.20",
|
|
6
|
+
author: "Slee Woo",
|
|
7
|
+
license: "MIT",
|
|
8
|
+
publishConfig: {
|
|
9
|
+
access: "public"
|
|
10
|
+
},
|
|
11
|
+
files: [
|
|
12
|
+
"pkg/*"
|
|
13
|
+
],
|
|
14
|
+
exports: {
|
|
15
|
+
".": {
|
|
16
|
+
types: "./pkg/index.d.ts",
|
|
17
|
+
default: "./pkg/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
scripts: {
|
|
21
|
+
build: "esbuilder src/index.ts",
|
|
22
|
+
test: "vitest --root ../../.. --project generators/fetch-generator"
|
|
23
|
+
},
|
|
24
|
+
dependencies: {
|
|
25
|
+
"@kosmojs/dev": "workspace:^"
|
|
26
|
+
},
|
|
27
|
+
devDependencies: {
|
|
28
|
+
"@kosmojs/api": "workspace:^",
|
|
29
|
+
"@kosmojs/fetch": "workspace:^",
|
|
30
|
+
"@kosmojs/koa-generator": "workspace:^",
|
|
31
|
+
"@kosmojs/typebox-generator": "workspace:^",
|
|
32
|
+
"@types/mime-types": "^3.0.1",
|
|
33
|
+
"@types/qs": "^6.15.0",
|
|
34
|
+
"mime-types": "^3.0.2",
|
|
35
|
+
"path-to-regexp": "^8.3.0",
|
|
36
|
+
qs: "^6.15.0",
|
|
37
|
+
typebox: "^1.1.6"
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
1
41
|
// src/factory.ts
|
|
42
|
+
import { RequestValidationTargets } from "@kosmojs/api";
|
|
2
43
|
import {
|
|
3
44
|
pathResolver,
|
|
4
45
|
renderFactory,
|
|
46
|
+
renderHelpers,
|
|
5
47
|
sortRoutes
|
|
6
48
|
} from "@kosmojs/dev";
|
|
7
49
|
|
|
50
|
+
// load-as-text:/volumes/studio/OpenSource/KosmoJS/Kosmo/packages/generators/fetch-generator/src/templates/@fetch/lib.ts
|
|
51
|
+
var lib_default = 'import { compile } from "path-to-regexp";\n\nexport const fetchClientFactory = <ParamsT extends Array<unknown>>(\n routeName: string,\n pathPattern: string,\n paramsMap: Array<[name: string, kind: string]>,\n numericParams: Array<string>,\n) => {\n const toPath = compile(pathPattern);\n\n const paramsMapper = (params: ParamsT) => {\n return paramsMap.reduce<Record<string, unknown>>((map, [name, kind], i) => {\n if (kind === "splat") {\n if (Array.isArray(params[i]) && params[i].length) {\n map[name] = numericParams.includes(name)\n ? params[i].map(Number)\n : params[i].map(String);\n }\n } else if (params[i] !== undefined) {\n map[name] = numericParams.includes(name)\n ? Number(params[i])\n : String(params[i]);\n }\n return map;\n }, {});\n };\n\n return {\n paramsMapper,\n parametrize(params: ParamsT) {\n try {\n return toPath(paramsMapper(params) as never);\n } catch (error: any) {\n console.error(`\u2757ERROR: Failed building path for ${routeName}`);\n console.error(error);\n return "";\n }\n },\n resolvePayload(payload: unknown, target: string) {\n const data = payload?.[target as never] as unknown;\n if (!data) {\n return data;\n }\n if (data instanceof FormData) {\n const obj: Record<\n string,\n FormDataEntryValue | Array<FormDataEntryValue>\n > = {};\n for (const [key, value] of data.entries()) {\n if (key in obj) {\n obj[key] = [obj[key]].flat().concat(value);\n } else {\n obj[key] = value;\n }\n }\n return obj;\n }\n return data;\n },\n };\n};\n';
|
|
52
|
+
|
|
8
53
|
// src/templates/fetch.hbs
|
|
9
|
-
var fetch_default = '{{#each routes}}\nimport {{id}} from "{{ createImport "
|
|
54
|
+
var fetch_default = '{{#each routes}}\nimport * as {{id}} from "{{ createImport "libApi" name "fetch" }}";\n{{/each}}\n\nexport { ValidationError } from "@kosmojs/api/errors";\n\nexport type ResponseT = {\n{{#each routes}} "{{name}}": {{id}}.ResponseT;\n{{/each}}\n}\n\nexport default {\n{{#each routes}} "{{name}}": {{id}},\n{{#each alias }} "{{this}}": {{../id}},\n{{/each}}\n{{/each}}\n}\n';
|
|
10
55
|
|
|
11
56
|
// src/templates/route.hbs
|
|
12
|
-
var route_default = 'import fetchFactory, {\n type HostOpt,\n join,\n stringify,\n createHost,\n} from "@kosmojs/fetch";\n\nimport { baseurl, apiurl } from "{{ createImport "config" }}";\nimport {
|
|
57
|
+
var route_default = 'import fetchFactory, {\n type HostOpt,\n join,\n stringify,\n createHost,\n} from "@kosmojs/fetch";\n\nimport { baseurl, apiurl } from "{{ createImport "config" }}";\n\nimport {\n type MaybeWrapped,\n unwrap,\n} from "{{ createImport "lib" "unwrap" }}";\n\nimport { fetchClientFactory } from "{{ createImport "lib" "@fetch/lib" }}";\n\n{{#each validationTypes}}\nimport type { {{id}} } from "./types";\n{{/each}}\n\nimport { validationSchemas } from "./schemas";\n\nexport { ValidationError } from "@kosmojs/api/errors";\n\nexport { validationSchemas };\n\nexport type ParamsT = [\n {{createParamsLiteral route.params}}\n];\n\n{{#each payloadTypes}}\nexport type {{name}} = {\n {{#each types}}{{method}}: {{id}};\n {{/each}}\n}\n{{/each}}\n\nexport type ResponseT = {\n {{#each responseTypes}}\n {{method}}: {{#each types}}{{#unless @first}}|{{/unless}} {{id}}{{/each}};\n {{/each}}\n}\n\nconst {\n paramsMapper,\n parametrize,\n resolvePayload,\n} = fetchClientFactory(\n "{{route.name}}",\n "{{route.pathPattern}}",\n [{{#each route.params.schema}}["{{name}}", "{{kind}}"], {{/each}}],\n [{{#each route.numericParams}}"{{.}}", {{/each}}],\n);\n\nconst fetchApi = fetchFactory(join(baseurl, apiurl), { stringify });\n\n{{#each routeMethods}}\nexport const {{method}} = (\n _params{{#if ../route.optionalParams}}?{{/if}}: MaybeWrapped<ParamsT>,\n _payload?: {\n {{#each ../payloadTargets}}\n {{#if payloadType}}\n {{target}}: {{payloadType.name}} extends { {{../method}}: unknown }\n ? MaybeWrapped<{{payloadType.name}}["{{../method}}"]>\n : unknown,\n {{else}}\n {{target}}?: unknown;\n {{/if}}\n {{/each}}\n },\n opt?: {\n unwrap?: <T>(data: MaybeWrapped<T>) => T;\n },\n): Promise<\n {{#if responseType}}\n ResponseT["{{method}}"]\n {{else}}\n unknown\n {{/if}}\n> => {\n const [params, payload] = [_params, _payload].map((data) => {\n return typeof opt?.unwrap === "function" ? opt.unwrap(data) : unwrap(data);\n })\n if (validationSchemas.params) {\n validationSchemas.params.validate(paramsMapper(params as never));\n }\n {{#each ../payloadTypes}}\n if (validationSchemas.{{target}}?.{{../method}}) {\n validationSchemas.{{target}}.{{../method}}.validate(\n resolvePayload(payload, "{{target}}")\n );\n }\n {{/each}}\n return fetchApi.{{method}}(parametrize(params as never), payload as never);\n};\n{{/each}}\n\nexport const path = (\n params: ParamsT,\n query?: Record<string, unknown>,\n) => {\n const path = join(\n baseurl,\n {{#if route.base}}"{{route.base}}"{{else}}apiurl{{/if}},\n parametrize(params)\n );\n return query\n ? [ path, stringify(query) ].join("?")\n : path;\n}\n\nexport const href = (\n host: HostOpt,\n params: ParamsT,\n query?: Record<string, unknown>,\n) => createHost(host) + path(params, query);\n\nexport default {\n {{#each routeMethods}}\n {{method}},\n {{/each}}\n path,\n href,\n {{#if runtimeValidation}}\n validationSchemas,\n {{/if}}\n};\n';
|
|
13
58
|
|
|
14
59
|
// src/templates/unwrap.hbs
|
|
15
60
|
var unwrap_default = "export type MaybeWrapped<T> = T;\nexport const unwrap = <T>(data: T) => data;\n";
|
|
16
61
|
|
|
17
62
|
// src/factory.ts
|
|
18
|
-
var factory = async ({
|
|
19
|
-
appRoot,
|
|
20
|
-
sourceFolder,
|
|
21
|
-
formatters
|
|
22
|
-
}) => {
|
|
63
|
+
var factory = async ({ appRoot, sourceFolder }) => {
|
|
23
64
|
const { createPath, createImportHelper } = pathResolver({
|
|
24
65
|
appRoot,
|
|
25
66
|
sourceFolder
|
|
26
67
|
});
|
|
27
68
|
const { renderToFile } = renderFactory({
|
|
28
|
-
formatters,
|
|
29
69
|
helpers: {
|
|
30
|
-
createImport: createImportHelper
|
|
70
|
+
createImport: createImportHelper,
|
|
71
|
+
createParamsLiteral: renderHelpers.createParamsLiteral
|
|
31
72
|
}
|
|
32
73
|
});
|
|
33
74
|
await renderToFile(createPath.lib("unwrap.ts"), unwrap_default, {});
|
|
34
75
|
const generateLibFiles = async (entries, updatedEntries) => {
|
|
35
76
|
const routes = entries.flatMap(({ kind, entry }) => kind === "apiRoute" ? [entry] : []).sort(sortRoutes);
|
|
36
|
-
|
|
77
|
+
for (const [file, template] of [
|
|
78
|
+
["fetch.ts", fetch_default],
|
|
79
|
+
["@fetch/lib.ts", lib_default]
|
|
80
|
+
]) {
|
|
81
|
+
await renderToFile(createPath.lib(file), template, {
|
|
82
|
+
routes
|
|
83
|
+
});
|
|
84
|
+
}
|
|
37
85
|
for (const { kind, entry } of updatedEntries) {
|
|
38
86
|
if (kind === "apiRoute") {
|
|
87
|
+
const validationTypes = [];
|
|
88
|
+
for (const def of entry.validationDefinitions) {
|
|
89
|
+
if (def.target === "response") {
|
|
90
|
+
for (const { id, body, resolvedType } of def.variants) {
|
|
91
|
+
if (body) {
|
|
92
|
+
validationTypes.push({
|
|
93
|
+
id,
|
|
94
|
+
target: def.target,
|
|
95
|
+
method: def.method,
|
|
96
|
+
resolvedType
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
const { id, resolvedType } = def.schema;
|
|
102
|
+
validationTypes.push({
|
|
103
|
+
id,
|
|
104
|
+
target: def.target,
|
|
105
|
+
method: def.method,
|
|
106
|
+
resolvedType
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
39
110
|
const routeMethods = entry.methods.map((method) => {
|
|
40
|
-
const payloadType = entry.payloadTypes.find(
|
|
41
|
-
(e) => e.method === method
|
|
42
|
-
);
|
|
43
|
-
const responseType = entry.responseTypes.find(
|
|
44
|
-
(e) => e.method === method
|
|
45
|
-
);
|
|
46
111
|
return {
|
|
47
112
|
method,
|
|
48
|
-
|
|
49
|
-
|
|
113
|
+
responseType: validationTypes.find((e) => {
|
|
114
|
+
return e.target === "response" ? e.method === method : false;
|
|
115
|
+
})
|
|
50
116
|
};
|
|
51
117
|
});
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
118
|
+
const payloadTypes = Object.entries(
|
|
119
|
+
validationTypes.reduce((map, { id, target, method, resolvedType }) => {
|
|
120
|
+
if (target !== "response") {
|
|
121
|
+
const key = `${target.replace(/^./, (c) => c.toUpperCase())}T`;
|
|
122
|
+
if (!map[key]) {
|
|
123
|
+
map[key] = [];
|
|
124
|
+
}
|
|
125
|
+
map[key].push({ id, target, method, resolvedType });
|
|
126
|
+
}
|
|
127
|
+
return map;
|
|
128
|
+
}, {})
|
|
129
|
+
).map(([name, types]) => {
|
|
130
|
+
return { name, types, target: types[0].target };
|
|
60
131
|
});
|
|
132
|
+
const payloadTargets = Object.keys(RequestValidationTargets).map(
|
|
133
|
+
(target) => {
|
|
134
|
+
const payloadType = payloadTypes.find((e) => e.target === target);
|
|
135
|
+
return {
|
|
136
|
+
target,
|
|
137
|
+
payloadType
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
const responseTypes = Object.values(
|
|
142
|
+
validationTypes.reduce((map, { id, target, method, resolvedType }) => {
|
|
143
|
+
if (target === "response") {
|
|
144
|
+
if (!map[method]) {
|
|
145
|
+
map[method] = { method, types: [] };
|
|
146
|
+
}
|
|
147
|
+
map[method].types.push({ id, target, method, resolvedType });
|
|
148
|
+
}
|
|
149
|
+
return map;
|
|
150
|
+
}, {})
|
|
151
|
+
);
|
|
152
|
+
await renderToFile(
|
|
153
|
+
createPath.libApi(entry.name, "fetch.ts"),
|
|
154
|
+
route_default,
|
|
155
|
+
{
|
|
156
|
+
route: entry,
|
|
157
|
+
validationTypes,
|
|
158
|
+
routeMethods,
|
|
159
|
+
payloadTypes,
|
|
160
|
+
payloadTargets,
|
|
161
|
+
responseTypes
|
|
162
|
+
}
|
|
163
|
+
);
|
|
61
164
|
}
|
|
62
165
|
}
|
|
63
166
|
};
|
|
@@ -84,10 +187,13 @@ var factory = async ({
|
|
|
84
187
|
var index_default = () => {
|
|
85
188
|
return {
|
|
86
189
|
name: "Fetch",
|
|
87
|
-
|
|
190
|
+
slot: "fetch",
|
|
88
191
|
moduleImport: import.meta.filename,
|
|
89
192
|
moduleConfig: void 0,
|
|
90
|
-
factory
|
|
193
|
+
factory,
|
|
194
|
+
dependencies: {
|
|
195
|
+
"path-to-regexp": package_default.devDependencies["path-to-regexp"]
|
|
196
|
+
}
|
|
91
197
|
};
|
|
92
198
|
};
|
|
93
199
|
export {
|
package/pkg/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/factory.ts", "../src/templates/fetch.hbs", "../src/templates/route.hbs", "../src/templates/unwrap.hbs", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type GeneratorFactory,\n pathResolver,\n type ResolvedEntry,\n renderFactory,\n sortRoutes,\n} from \"@kosmojs/dev\";\n\nimport fetchTpl from \"./templates/fetch.hbs\";\nimport routeTpl from \"./templates/route.hbs\";\nimport unwrapTpl from \"./templates/unwrap.hbs\";\n\nexport const factory: GeneratorFactory = async ({\n appRoot,\n sourceFolder,\n formatters,\n}) => {\n const { createPath, createImportHelper } = pathResolver({\n appRoot,\n sourceFolder,\n });\n\n const { renderToFile } = renderFactory({\n formatters,\n helpers: {\n createImport: createImportHelper,\n },\n });\n\n // supposed to be replaced by specialized generators, write it only at initialization.\n // fetch generator always runs before other generators\n // so it is safe to re-initialize this file before specialized generators update it.\n await renderToFile(createPath.lib(\"unwrap.ts\"), unwrapTpl, {});\n\n const generateLibFiles = async (\n entries: Array<ResolvedEntry>,\n updatedEntries: Array<ResolvedEntry>,\n ) => {\n const routes = entries\n .flatMap(({ kind, entry }) => (kind === \"apiRoute\" ? [entry] : []))\n .sort(sortRoutes);\n\n await renderToFile(`${createPath.fetch()}.ts`, fetchTpl, { routes });\n\n for (const { kind, entry } of updatedEntries) {\n if (kind === \"apiRoute\") {\n const routeMethods = entry.methods.map((method) => {\n const payloadType = entry.payloadTypes.find(\n (e) => e.method === method,\n );\n const responseType = entry.responseTypes.find(\n (e) => e.method === method,\n );\n return {\n method,\n payloadType,\n responseType,\n };\n });\n\n const paramsMapper = entry.params.schema.map(({ name }, idx) => ({\n name,\n idx,\n }));\n\n await renderToFile(createPath.fetch(entry.file), routeTpl, {\n route: entry,\n routeMethods,\n paramsMapper,\n });\n }\n }\n };\n\n return {\n async watch(entries, event) {\n await generateLibFiles(\n entries,\n // create/overwrite lib files with proper content.\n // handle 2 cases:\n // - event is undefined (means initial call): process all routes\n // - `update` event given: process updated route\n event\n ? entries.filter(({ kind, entry }) => {\n return event.kind === \"update\"\n ? kind === \"apiRoute\"\n ? entry.fileFullpath === event.file\n : false\n : false;\n })\n : entries,\n );\n\n // TODO: handle `delete` event, cleanup lib files\n },\n async build(entries) {\n await generateLibFiles(entries, entries);\n },\n };\n};\n", "{{#each routes}}\nimport {{id}} from \"{{ createImport \"fetch\" name }}\";\n{{/each}}\n\nexport { ValidationError } from \"@kosmojs/api/errors\";\n\nexport type PayloadT = {\n{{#each routes}} \"{{name}}\": import(\"{{ createImport \"fetch\" name }}\").PayloadT;\n{{/each}}\n}\n\nexport type ResponseT = {\n{{#each routes}} \"{{name}}\": import(\"{{ createImport \"fetch\" name }}\").ResponseT;\n{{/each}}\n}\n\nexport default {\n{{#each routes}} \"{{name}}\": {{id}},\n{{#each alias }} \"{{this}}\": {{../id}},\n{{/each}}\n{{/each}}\n}\n", "import fetchFactory, {\n type HostOpt,\n join,\n stringify,\n createHost,\n} from \"@kosmojs/fetch\";\n\nimport { baseurl, apiurl } from \"{{ createImport \"config\" }}\";\nimport { validationSchemas } from \"{{ createImport \"libApi\" route.name \"schemas\" }}\";\n\nimport {\n type MaybeWrapped,\n unwrap,\n} from \"{{ createImport \"lib\" \"unwrap\" }}\";\n\nimport type {\n {{route.params.id}},\n{{#each route.payloadTypes}} {{id}},\n{{/each}}\n{{#each route.responseTypes}} {{id}},\n{{/each}}\n} from \"{{ createImport \"libApi\" route.name \"types\" }}\";\n\nexport { ValidationError } from \"@kosmojs/api/errors\";\n\nexport type ParamsT = [\n {{#each route.params.schema}}\n {{#if isRest}}\n ...{{const}}: Array<string | number>\n {{else}}\n {{const}}{{#unless isRequired}}?{{/unless}}: {{../route.params.id}}[\"{{name}}\"],\n {{/if}}\n {{/each}}\n];\n\nexport type PayloadT = {\n {{#each route.payloadTypes}}\n {{method}}: {{id}};\n {{/each}}\n}\n\nexport type ResponseT = {\n {{#each route.responseTypes}}\n {{method}}: {{id}};\n {{/each}}\n}\n\nconst paramsMapper = (params: ParamsT) => {\n return {\n {{#each paramsMapper}}\n \"{{name}}\": params[{{idx}}],\n {{/each}}\n }\n}\n\nconst pathTokens: Array<[ path: string, param?: { isRest: boolean } ]> = [\n {{#each route.pathTokens}}\n [\n \"{{path}}\",{{#if param}}\n { isRest: {{#if param.isRest}}true{{else}}false{{/if}} }{{/if}}\n ],\n {{/each}}\n];\n\nconst parametrize = (params: ParamsT) => {\n const paramsClone = structuredClone(params);\n return pathTokens\n .flatMap(([ path, param ]) => {\n if (param?.isRest) {\n return paramsClone;\n }\n if (param) {\n return paramsClone.splice(0, 1);\n }\n return [path];\n })\n .join(\"/\");\n}\n\nconst fetchApi = fetchFactory(join(baseurl, apiurl), { stringify });\n\n{{#each routeMethods}}\nexport const {{method}} = (\n _params{{#if ../route.optionalParams}}?{{/if}}: MaybeWrapped<ParamsT>,\n {{#if payloadType}}\n _payload{{#if payloadType.isOptional}}?{{/if}}: MaybeWrapped<\n PayloadT[\"{{method}}\"]\n >,\n {{else}}\n _payload?: unknown,\n {{/if}}\n): Promise<\n {{#if responseType}}\n ResponseT[\"{{method}}\"]\n {{else}}\n unknown\n {{/if}}\n> => {\n const [params, payload] = [unwrap(_params || []), unwrap(_payload || {})];\n if (validationSchemas.params) {\n validationSchemas.params.validate(paramsMapper(params as never));\n }\n if (validationSchemas.payload?.{{method}}) {\n validationSchemas.payload.{{method}}.validate(payload);\n }\n return fetchApi.{{method}}(\n parametrize(params as never),\n payload,\n )\n};\n{{/each}}\n\nexport const path = (\n params: ParamsT,\n query?: Record<string, unknown>,\n) => {\n const path = join(\n baseurl,\n {{#if route.base}}\"{{route.base}}\"{{else}}apiurl{{/if}},\n parametrize(params)\n );\n return query\n ? [ path, stringify(query) ].join(\"?\")\n : path;\n}\n\nexport const href = (\n host: HostOpt,\n params: ParamsT,\n query?: Record<string, unknown>,\n) => createHost(host) + path(params, query);\n\nexport default {\n {{#each routeMethods}}\n {{method}},\n {{/each}}\n path,\n href,\n validationSchemas,\n};\n", "export type MaybeWrapped<T> = T;\nexport const unwrap = <T>(data: T) => data;\n", "import type { GeneratorConstructor } from \"@kosmojs/dev\";\n\nimport { factory } from \"./factory\";\n\nexport default (): GeneratorConstructor => {\n return {\n name: \"Fetch\",\n kind: \"fetch\",\n moduleImport: import.meta.filename,\n moduleConfig: undefined,\n factory,\n };\n};\n"],
|
|
5
|
-
"mappings": ";AAAA;AAAA,EAEE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;;;
|
|
3
|
+
"sources": ["../package.json", "../src/factory.ts", "load-as-text:/volumes/studio/OpenSource/KosmoJS/Kosmo/packages/generators/fetch-generator/src/templates/@fetch/lib.ts", "../src/templates/fetch.hbs", "../src/templates/route.hbs", "../src/templates/unwrap.hbs", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["{\n \"type\": \"module\",\n \"name\": \"@kosmojs/fetch-generator\",\n \"version\": \"0.0.20\",\n \"author\": \"Slee Woo\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"pkg/*\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./pkg/index.d.ts\",\n \"default\": \"./pkg/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"esbuilder src/index.ts\",\n \"test\": \"vitest --root ../../.. --project generators/fetch-generator\"\n },\n \"dependencies\": {\n \"@kosmojs/dev\": \"workspace:^\"\n },\n \"devDependencies\": {\n \"@kosmojs/api\": \"workspace:^\",\n \"@kosmojs/fetch\": \"workspace:^\",\n \"@kosmojs/koa-generator\": \"workspace:^\",\n \"@kosmojs/typebox-generator\": \"workspace:^\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/qs\": \"^6.15.0\",\n \"mime-types\": \"^3.0.2\",\n \"path-to-regexp\": \"^8.3.0\",\n \"qs\": \"^6.15.0\",\n \"typebox\": \"^1.1.6\"\n }\n}\n", "import { RequestValidationTargets, type ValidationTarget } from \"@kosmojs/api\";\nimport {\n type GeneratorFactory,\n pathResolver,\n type ResolvedEntry,\n renderFactory,\n renderHelpers,\n sortRoutes,\n} from \"@kosmojs/dev\";\n\nimport fetchLibTpl from \"./templates/@fetch/lib.ts?as=text\";\nimport fetchTpl from \"./templates/fetch.hbs\";\nimport routeTpl from \"./templates/route.hbs\";\nimport unwrapTpl from \"./templates/unwrap.hbs\";\n\nexport const factory: GeneratorFactory = async ({ appRoot, sourceFolder }) => {\n const { createPath, createImportHelper } = pathResolver({\n appRoot,\n sourceFolder,\n });\n\n const { renderToFile } = renderFactory({\n helpers: {\n createImport: createImportHelper,\n createParamsLiteral: renderHelpers.createParamsLiteral,\n },\n });\n\n // supposed to be replaced by specialized generators, write it only at initialization.\n // fetch generator always runs before other generators\n // so it is safe to re-initialize this file before specialized generators update it.\n await renderToFile(createPath.lib(\"unwrap.ts\"), unwrapTpl, {});\n\n const generateLibFiles = async (\n entries: Array<ResolvedEntry>,\n updatedEntries: Array<ResolvedEntry>,\n ) => {\n const routes = entries\n .flatMap(({ kind, entry }) => (kind === \"apiRoute\" ? [entry] : []))\n .sort(sortRoutes);\n\n for (const [file, template] of [\n [\"fetch.ts\", fetchTpl],\n [\"@fetch/lib.ts\", fetchLibTpl],\n ]) {\n await renderToFile(createPath.lib(file), template, {\n routes,\n });\n }\n\n for (const { kind, entry } of updatedEntries) {\n if (kind === \"apiRoute\") {\n const validationTypes: Array<{\n id: string;\n target: ValidationTarget;\n method: string;\n resolvedType: unknown;\n }> = [];\n\n for (const def of entry.validationDefinitions) {\n if (def.target === \"response\") {\n for (const { id, body, resolvedType } of def.variants) {\n if (body) {\n validationTypes.push({\n id,\n target: def.target,\n method: def.method,\n resolvedType,\n });\n }\n }\n } else {\n const { id, resolvedType } = def.schema;\n validationTypes.push({\n id,\n target: def.target,\n method: def.method,\n resolvedType,\n });\n }\n }\n\n const routeMethods = entry.methods.map((method) => {\n return {\n method,\n responseType: validationTypes.find((e) => {\n return e.target === \"response\" ? e.method === method : false;\n }),\n };\n });\n\n const payloadTypes = Object.entries(\n validationTypes.reduce<\n Record<string, Array<(typeof validationTypes)[number]>>\n >((map, { id, target, method, resolvedType }) => {\n if (target !== \"response\") {\n const key = `${target.replace(/^./, (c) => c.toUpperCase())}T`;\n if (!map[key]) {\n map[key] = [];\n }\n map[key].push({ id, target, method, resolvedType });\n }\n return map;\n }, {}),\n ).map(([name, types]) => {\n return { name, types, target: types[0].target };\n });\n\n const payloadTargets = Object.keys(RequestValidationTargets).map(\n (target) => {\n const payloadType = payloadTypes.find((e) => e.target === target);\n return {\n target,\n payloadType,\n };\n },\n );\n\n const responseTypes = Object.values(\n validationTypes.reduce<\n Record<\n string,\n { method: string; types: Array<(typeof validationTypes)[number]> }\n >\n >((map, { id, target, method, resolvedType }) => {\n if (target === \"response\") {\n if (!map[method]) {\n map[method] = { method, types: [] };\n }\n map[method].types.push({ id, target, method, resolvedType });\n }\n return map;\n }, {}),\n );\n\n await renderToFile(\n createPath.libApi(entry.name, \"fetch.ts\"),\n routeTpl,\n {\n route: entry,\n validationTypes,\n routeMethods,\n payloadTypes,\n payloadTargets,\n responseTypes,\n },\n );\n }\n }\n };\n\n return {\n async watch(entries, event) {\n await generateLibFiles(\n entries,\n // create/overwrite lib files with proper content.\n // handle 2 cases:\n // - event is undefined (means initial call): process all routes\n // - `update` event given: process updated route\n event\n ? entries.filter(({ kind, entry }) => {\n return event.kind === \"update\"\n ? kind === \"apiRoute\"\n ? entry.fileFullpath === event.file\n : false\n : false;\n })\n : entries,\n );\n\n // TODO: handle `delete` event, cleanup lib files\n },\n async build(entries) {\n await generateLibFiles(entries, entries);\n },\n };\n};\n", "import { compile } from \"path-to-regexp\";\n\nexport const fetchClientFactory = <ParamsT extends Array<unknown>>(\n routeName: string,\n pathPattern: string,\n paramsMap: Array<[name: string, kind: string]>,\n numericParams: Array<string>,\n) => {\n const toPath = compile(pathPattern);\n\n const paramsMapper = (params: ParamsT) => {\n return paramsMap.reduce<Record<string, unknown>>((map, [name, kind], i) => {\n if (kind === \"splat\") {\n if (Array.isArray(params[i]) && params[i].length) {\n map[name] = numericParams.includes(name)\n ? params[i].map(Number)\n : params[i].map(String);\n }\n } else if (params[i] !== undefined) {\n map[name] = numericParams.includes(name)\n ? Number(params[i])\n : String(params[i]);\n }\n return map;\n }, {});\n };\n\n return {\n paramsMapper,\n parametrize(params: ParamsT) {\n try {\n return toPath(paramsMapper(params) as never);\n } catch (error: any) {\n console.error(`\u2757ERROR: Failed building path for ${routeName}`);\n console.error(error);\n return \"\";\n }\n },\n resolvePayload(payload: unknown, target: string) {\n const data = payload?.[target as never] as unknown;\n if (!data) {\n return data;\n }\n if (data instanceof FormData) {\n const obj: Record<\n string,\n FormDataEntryValue | Array<FormDataEntryValue>\n > = {};\n for (const [key, value] of data.entries()) {\n if (key in obj) {\n obj[key] = [obj[key]].flat().concat(value);\n } else {\n obj[key] = value;\n }\n }\n return obj;\n }\n return data;\n },\n };\n};\n", "{{#each routes}}\nimport * as {{id}} from \"{{ createImport \"libApi\" name \"fetch\" }}\";\n{{/each}}\n\nexport { ValidationError } from \"@kosmojs/api/errors\";\n\nexport type ResponseT = {\n{{#each routes}} \"{{name}}\": {{id}}.ResponseT;\n{{/each}}\n}\n\nexport default {\n{{#each routes}} \"{{name}}\": {{id}},\n{{#each alias }} \"{{this}}\": {{../id}},\n{{/each}}\n{{/each}}\n}\n", "import fetchFactory, {\n type HostOpt,\n join,\n stringify,\n createHost,\n} from \"@kosmojs/fetch\";\n\nimport { baseurl, apiurl } from \"{{ createImport \"config\" }}\";\n\nimport {\n type MaybeWrapped,\n unwrap,\n} from \"{{ createImport \"lib\" \"unwrap\" }}\";\n\nimport { fetchClientFactory } from \"{{ createImport \"lib\" \"@fetch/lib\" }}\";\n\n{{#each validationTypes}}\nimport type { {{id}} } from \"./types\";\n{{/each}}\n\nimport { validationSchemas } from \"./schemas\";\n\nexport { ValidationError } from \"@kosmojs/api/errors\";\n\nexport { validationSchemas };\n\nexport type ParamsT = [\n {{createParamsLiteral route.params}}\n];\n\n{{#each payloadTypes}}\nexport type {{name}} = {\n {{#each types}}{{method}}: {{id}};\n {{/each}}\n}\n{{/each}}\n\nexport type ResponseT = {\n {{#each responseTypes}}\n {{method}}: {{#each types}}{{#unless @first}}|{{/unless}} {{id}}{{/each}};\n {{/each}}\n}\n\nconst {\n paramsMapper,\n parametrize,\n resolvePayload,\n} = fetchClientFactory(\n \"{{route.name}}\",\n \"{{route.pathPattern}}\",\n [{{#each route.params.schema}}[\"{{name}}\", \"{{kind}}\"], {{/each}}],\n [{{#each route.numericParams}}\"{{.}}\", {{/each}}],\n);\n\nconst fetchApi = fetchFactory(join(baseurl, apiurl), { stringify });\n\n{{#each routeMethods}}\nexport const {{method}} = (\n _params{{#if ../route.optionalParams}}?{{/if}}: MaybeWrapped<ParamsT>,\n _payload?: {\n {{#each ../payloadTargets}}\n {{#if payloadType}}\n {{target}}: {{payloadType.name}} extends { {{../method}}: unknown }\n ? MaybeWrapped<{{payloadType.name}}[\"{{../method}}\"]>\n : unknown,\n {{else}}\n {{target}}?: unknown;\n {{/if}}\n {{/each}}\n },\n opt?: {\n unwrap?: <T>(data: MaybeWrapped<T>) => T;\n },\n): Promise<\n {{#if responseType}}\n ResponseT[\"{{method}}\"]\n {{else}}\n unknown\n {{/if}}\n> => {\n const [params, payload] = [_params, _payload].map((data) => {\n return typeof opt?.unwrap === \"function\" ? opt.unwrap(data) : unwrap(data);\n })\n if (validationSchemas.params) {\n validationSchemas.params.validate(paramsMapper(params as never));\n }\n {{#each ../payloadTypes}}\n if (validationSchemas.{{target}}?.{{../method}}) {\n validationSchemas.{{target}}.{{../method}}.validate(\n resolvePayload(payload, \"{{target}}\")\n );\n }\n {{/each}}\n return fetchApi.{{method}}(parametrize(params as never), payload as never);\n};\n{{/each}}\n\nexport const path = (\n params: ParamsT,\n query?: Record<string, unknown>,\n) => {\n const path = join(\n baseurl,\n {{#if route.base}}\"{{route.base}}\"{{else}}apiurl{{/if}},\n parametrize(params)\n );\n return query\n ? [ path, stringify(query) ].join(\"?\")\n : path;\n}\n\nexport const href = (\n host: HostOpt,\n params: ParamsT,\n query?: Record<string, unknown>,\n) => createHost(host) + path(params, query);\n\nexport default {\n {{#each routeMethods}}\n {{method}},\n {{/each}}\n path,\n href,\n {{#if runtimeValidation}}\n validationSchemas,\n {{/if}}\n};\n", "export type MaybeWrapped<T> = T;\nexport const unwrap = <T>(data: T) => data;\n", "import type { GeneratorConstructor } from \"@kosmojs/dev\";\n\nimport self from \"../package.json\" with { type: \"json\" };\nimport { factory } from \"./factory\";\n\nexport default (): GeneratorConstructor => {\n return {\n name: \"Fetch\",\n slot: \"fetch\",\n moduleImport: import.meta.filename,\n moduleConfig: undefined,\n factory,\n dependencies: {\n \"path-to-regexp\": self.devDependencies[\"path-to-regexp\"],\n },\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const fetchClientFactory: <ParamsT extends Array<unknown>>(routeName: string, pathPattern: string, paramsMap: Array<[name: string, kind: string]>, numericParams: Array<string>) => {
|
|
2
|
+
paramsMapper: (params: ParamsT) => Record<string, unknown>;
|
|
3
|
+
parametrize(params: ParamsT): string;
|
|
4
|
+
resolvePayload(payload: unknown, target: string): unknown;
|
|
5
|
+
};
|
|
File without changes
|
|
File without changes
|