@kosmojs/fetch-generator 0.0.25 → 0.0.26

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/README.md CHANGED
@@ -10,7 +10,7 @@ npm install -D @kosmojs/fetch-generator
10
10
 
11
11
  ## Documentation
12
12
 
13
- See [kosmojs.dev](https://kosmojs.dev/generators/writing-generators/intro.html)
13
+ See [kosmojs.dev](https://kosmojs.dev/generators/intro.html)
14
14
 
15
15
  ## License
16
16
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@kosmojs/fetch-generator",
4
- "version": "0.0.25",
4
+ "version": "0.0.26",
5
5
  "author": "Slee Woo",
6
6
  "license": "MIT",
7
7
  "publishConfig": {
@@ -14,11 +14,12 @@
14
14
  ".": {
15
15
  "types": "./pkg/index.d.ts",
16
16
  "default": "./pkg/index.js"
17
- }
17
+ },
18
+ "./package.json": "./package.json"
18
19
  },
19
20
  "dependencies": {
20
- "@kosmojs/api": "^0.0.25",
21
- "@kosmojs/dev": "^0.0.25"
21
+ "@kosmojs/api": "^0.0.26",
22
+ "@kosmojs/lib": "^0.0.26"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/mime-types": "^3.0.1",
@@ -27,9 +28,9 @@
27
28
  "path-to-regexp": "^8.3.0",
28
29
  "qs": "^6.15.0",
29
30
  "typebox": "^1.1.6",
30
- "@kosmojs/fetch": "^0.0.25",
31
- "@kosmojs/koa-generator": "^0.0.25",
32
- "@kosmojs/typebox-generator": "^0.0.25"
31
+ "@kosmojs/fetch": "^0.0.26",
32
+ "@kosmojs/koa-generator": "^0.0.26",
33
+ "@kosmojs/typebox-generator": "^0.0.26"
33
34
  },
34
35
  "scripts": {
35
36
  "build": "esbuilder src/index.ts",
package/pkg/factory.d.ts CHANGED
@@ -1,2 +1,6 @@
1
- import { type GeneratorFactory } from "@kosmojs/dev";
2
- export declare const factory: GeneratorFactory;
1
+ import { type ResolvedEntry } from "@kosmojs/lib";
2
+ declare const _default: (f: import("@kosmojs/lib").SourceFolder) => Promise<{
3
+ watch: import("@kosmojs/lib").WatchHandler;
4
+ build: (entries: Array<ResolvedEntry>) => Promise<void>;
5
+ }>;
6
+ export default _default;
package/pkg/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- import type { GeneratorConstructor } from "@kosmojs/dev";
2
- declare const _default: () => GeneratorConstructor;
1
+ declare const _default: () => import("@kosmojs/lib").GeneratorFactory;
3
2
  export default _default;
package/pkg/index.js CHANGED
@@ -1,51 +1,16 @@
1
- // package.json
2
- var package_default = {
3
- type: "module",
4
- name: "@kosmojs/fetch-generator",
5
- version: "0.0.24",
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/api": "workspace:^",
26
- "@kosmojs/dev": "workspace:^"
27
- },
28
- devDependencies: {
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
- };
1
+ // src/index.ts
2
+ import self from "@kosmojs/fetch-generator/package.json" with { type: "json" };
3
+ import { defineGenerator } from "@kosmojs/lib";
40
4
 
41
5
  // src/factory.ts
42
6
  import { RequestValidationTargets } from "@kosmojs/api";
43
7
  import {
8
+ defineGeneratorFactory,
44
9
  pathResolver,
45
10
  renderFactory,
46
11
  renderHelpers,
47
12
  sortRoutes
48
- } from "@kosmojs/dev";
13
+ } from "@kosmojs/lib";
49
14
 
50
15
  // load-as-text:/volumes/studio/OpenSource/KosmoJS/Kosmo/packages/generators/fetch-generator/src/templates/@fetch/lib.ts
51
16
  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';
@@ -60,11 +25,8 @@ var route_default = 'import fetchFactory, {\n type HostOpt,\n join,\n stringi
60
25
  var unwrap_default = "export type MaybeWrapped<T> = T;\nexport const unwrap = <T>(data: T) => data;\n";
61
26
 
62
27
  // src/factory.ts
63
- var factory = async ({ appRoot, sourceFolder }) => {
64
- const { createPath, createImportHelper } = pathResolver({
65
- appRoot,
66
- sourceFolder
67
- });
28
+ var factory_default = defineGeneratorFactory(async (sourceFolder) => {
29
+ const { createPath, createImportHelper } = pathResolver(sourceFolder);
68
30
  const { renderToFile } = renderFactory({
69
31
  helpers: {
70
32
  createImport: createImportHelper,
@@ -181,21 +143,19 @@ var factory = async ({ appRoot, sourceFolder }) => {
181
143
  await generateLibFiles(entries, entries);
182
144
  }
183
145
  };
184
- };
146
+ });
185
147
 
186
148
  // src/index.ts
187
- var index_default = () => {
188
- return {
189
- name: "Fetch",
190
- slot: "fetch",
191
- moduleImport: import.meta.filename,
192
- moduleConfig: void 0,
193
- factory,
194
- dependencies: {
195
- "path-to-regexp": package_default.devDependencies["path-to-regexp"]
196
- }
197
- };
198
- };
149
+ var index_default = defineGenerator(() => factory_default, {
150
+ name: "Fetch",
151
+ slot: "fetch",
152
+ dependencies: {
153
+ "path-to-regexp": self.devDependencies["path-to-regexp"]
154
+ },
155
+ devDependencies: {
156
+ "@kosmojs/fetch": self.version
157
+ }
158
+ });
199
159
  export {
200
160
  index_default as default
201
161
  };
package/pkg/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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.24\",\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/api\": \"workspace:^\",\n \"@kosmojs/dev\": \"workspace:^\"\n },\n \"devDependencies\": {\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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",
3
+ "sources": ["../src/index.ts", "../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"],
4
+ "sourcesContent": ["/**\n * Import from published package to ensure correct version at runtime.\n * Local import would be bundled with pre-bump version.\n * */\nimport self from \"@kosmojs/fetch-generator/package.json\" with { type: \"json\" };\nimport { defineGenerator } from \"@kosmojs/lib\";\n\nimport factory from \"./factory\";\n\nexport default defineGenerator(() => factory, {\n name: \"Fetch\",\n slot: \"fetch\",\n dependencies: {\n \"path-to-regexp\": self.devDependencies[\"path-to-regexp\"],\n },\n devDependencies: {\n \"@kosmojs/fetch\": self.version,\n },\n});\n", "import { RequestValidationTargets, type ValidationTarget } from \"@kosmojs/api\";\nimport {\n defineGeneratorFactory,\n pathResolver,\n type ResolvedEntry,\n renderFactory,\n renderHelpers,\n sortRoutes,\n} from \"@kosmojs/lib\";\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 default defineGeneratorFactory(async (sourceFolder) => {\n const { createPath, createImportHelper } = pathResolver(sourceFolder);\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"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }