@yunarch/config-web 0.5.0 → 0.5.2

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.
@@ -1,16 +1,133 @@
1
1
  #!/usr/bin/env node
2
- import{f as r,g as d,h as n,i as h}from"../chunk-OOETI6RK.js";r();import{existsSync as y}from"fs";import{mkdir as I,readFile as T,writeFile as b}from"fs/promises";import m from"path";import{styleText as l}from"util";import N from"@inquirer/confirm";r();async function x(e,t){await n({name:"Generating models",command:`npx openapi-typescript-codegen --input ${e} --output ${t} --client fetch`})}r();import{copyFile as k}from"fs/promises";import w from"path";import{fileURLToPath as v}from"url";async function O(e){await n({name:"Generating openapi MSW utils",command:async()=>{let t=v(import.meta.url),o=w.dirname(t),a=w.join(o,"openapi-msw-http.ts");await k(a,w.join(e,"openapi-msw-http.ts"))}})}r();import{readFile as E,writeFile as F}from"fs/promises";async function $(e,t){await n({name:"Generating schema types",command:async()=>{await d(`npx openapi-typescript ${e} -o ${t}`);let o=await E(t,"utf8");await F(t,`/* eslint-disable -- Autogenerated file */
3
- ${o}`)}})}async function j(e){if(m.extname(e)!=="")throw new Error("Output must be a directory.");let t=process.cwd(),o=m.resolve(e),i=o.startsWith(t)?o:m.resolve(t,m.relative(m.parse(e).root,e));return y(i)||await n({name:"Generating output directory",command:async()=>{await I(i,{recursive:!0})}}),i}async function J(e,t){let[o,a]=await Promise.all([n({name:"Reading input openapi schema",command:async()=>{if(!e.endsWith(".json"))throw new Error(`Input file must be a JSON file: ${e}`);if(e.startsWith("http"))try{let{stdout:i}=await d(`curl -s ${e} --fail`);return i}catch{throw new Error(`Failed to fetch remote OpenAPI file: ${e}`)}if(!y(e))throw new Error(`Input file does not exist: ${e}`);return await T(e,"utf8")}}),n({name:"Reading output openapi schema",command:async()=>{if(!t.endsWith(".json"))throw new Error(`Output file must be a JSON file: ${t}`);return y(t)?await T(t,"utf8"):!1}})]);return[JSON.stringify(JSON.parse(o)),a?JSON.stringify(JSON.parse(a)):!1]}h().name("openapi-sync").description("A CLI tool to convert OpenAPI 3.0/3.1 schemas to TypeScript types and create type-safe fetching based on a openapi file and keep them in sync.").requiredOption("-i, --input <path>","The input (local or remote) openapi schema (JSON).").requiredOption("-o, --output <folder>","The output folder to save the generated models and openapi schema and type definitions.").option("-f, --force-gen","Force generation of typescript schemas and fetching code even if the input and output schemas are identical.").option("--include-msw-utils","Include MSW mocking utilities based on the generated typescript types.").option("--post-script <script>","A package.json script to run after the code generation.").addHelpText("after",`
4
- Example usage:
2
+ import{a as f,b as o,c as u}from"../chunk-3QWYGBKZ.js";import{existsSync as y}from"fs";import{mkdir as H,readFile as T,writeFile as M}from"fs/promises";import c from"path";import{styleText as n}from"util";import E from"@inquirer/confirm";async function g(e,t){await o({name:"Generating models",command:`npx openapi-typescript-codegen --input ${e} --output ${t} --client fetch`})}import{writeFile as O}from"fs/promises";var w=`
3
+ import {
4
+ http as mswHttp,
5
+ type DefaultBodyType,
6
+ type HttpHandler,
7
+ type HttpResponseResolver,
8
+ type PathParams,
9
+ type RequestHandlerOptions,
10
+ } from 'msw';
11
+ import type { paths as ImportedPaths } from './schema';
12
+
13
+ // Type definitions
14
+ type Paths = ImportedPaths;
15
+ type HttpMethod =
16
+ | 'get'
17
+ | 'put'
18
+ | 'post'
19
+ | 'delete'
20
+ | 'options'
21
+ | 'head'
22
+ | 'patch'
23
+ | 'trace';
24
+
25
+ /**
26
+ * Type guard to get the http methods available for a given path.
27
+ */
28
+ type Methods<Path extends keyof Paths> = Extract<keyof Paths[Path], HttpMethod>;
29
+
30
+ /**
31
+ * Type guard to get the content type 'application/json' or 'multipart/form-data' of a type.
32
+ */
33
+ type ExtractContent<T> = T extends { content?: infer C }
34
+ ? undefined extends C
35
+ ? DefaultBodyType
36
+ : 'application/json' extends keyof C
37
+ ? C['application/json']
38
+ : 'multipart/form-data' extends keyof C
39
+ ? C['multipart/form-data']
40
+ : DefaultBodyType
41
+ : DefaultBodyType;
5
42
 
6
- $ openapi-sync -i ./input.json -o ./src/api/gen --include-msw-utils`).action(async({input:e,output:t,forceGen:o,includeMswUtils:a,postScript:i})=>{try{console.log(l("magenta",`
43
+ /**
44
+ * Type guard to get the parameters of a path.
45
+ */
46
+ export type OpenapiPathParams<
47
+ P extends keyof Paths,
48
+ M extends keyof Paths[P],
49
+ > = 'parameters' extends keyof Paths[P][M]
50
+ ? 'path' extends keyof Paths[P][M]['parameters']
51
+ ? PathParams<keyof Paths[P][M]['parameters']['path']>
52
+ : PathParams
53
+ : PathParams;
54
+
55
+ /**
56
+ * Type guard to get the request body of a path.
57
+ */
58
+ export type OpenapiPathRequestBody<
59
+ P extends keyof Paths,
60
+ M extends keyof Paths[P],
61
+ > = Paths[P][M] extends { requestBody?: infer RB }
62
+ ? undefined extends RB
63
+ ? DefaultBodyType
64
+ : ExtractContent<RB>
65
+ : DefaultBodyType;
66
+
67
+ /**
68
+ * Type guard to get the response body of a path.
69
+ */
70
+ export type OpenapiPathResponseBody<
71
+ P extends keyof Paths,
72
+ M extends keyof Paths[P],
73
+ > = Paths[P][M] extends { responses?: infer R }
74
+ ? undefined extends R
75
+ ? DefaultBodyType
76
+ : 200 extends keyof R
77
+ ? ExtractContent<R[200]>
78
+ : 201 extends keyof R
79
+ ? ExtractContent<R[201]>
80
+ : DefaultBodyType
81
+ : DefaultBodyType;
82
+
83
+ /**
84
+ * Wrapper around MSW http function so we can have "typesafe" handlers against an openapi schema.
85
+ *
86
+ * @param path - The path to use from the openapi definition.
87
+ * @param method - The method to use on the handler.
88
+ * @param resolver - The MSW resolver function.
89
+ * @param options - The MSW http request handler options.
90
+ * @returns a typesafe wrapper for MSW http function.
91
+ *
92
+ * @throws Error if the method is not supported.
93
+ */
94
+ export function http<P extends keyof Paths, M extends Methods<P>>(
95
+ path: P,
96
+ method: M,
97
+ resolver: HttpResponseResolver<
98
+ OpenapiPathParams<P, M>,
99
+ OpenapiPathRequestBody<P, M>,
100
+ OpenapiPathResponseBody<P, M>
101
+ >,
102
+ options?: RequestHandlerOptions
103
+ ): HttpHandler {
104
+ const uri = \`*\${path.toString().replaceAll(/{(?<temp1>[^}]+)}/g, ':$1')}\`;
105
+ const handlers = {
106
+ head: mswHttp.head,
107
+ get: mswHttp.get,
108
+ post: mswHttp.post,
109
+ put: mswHttp.put,
110
+ delete: mswHttp.delete,
111
+ patch: mswHttp.patch,
112
+ options: mswHttp.options,
113
+ } as const;
114
+ if (typeof method !== 'string' || !Object.hasOwn(handlers, method)) {
115
+ throw new Error('Unsupported Http Method');
116
+ }
117
+ return handlers[method as keyof typeof handlers](uri, resolver, options);
118
+ }
119
+ `;async function P(e){await o({name:"Generating openapi MSW utils",command:async()=>{await O(`${e}/openapi-msw-http.ts`,w)}})}import{readFile as $,writeFile as R}from"fs/promises";async function x(e,t){await o({name:"Generating schema types",command:async()=>{await f(`npx openapi-typescript ${e} -o ${t}`);let a=await $(t,"utf8");await R(t,`/* eslint-disable -- Autogenerated file */
120
+ ${a}`)}})}async function v(e){if(c.extname(e)!=="")throw new Error("Output must be a directory.");let t=process.cwd(),a=c.resolve(e),s=a.startsWith(t)?a:c.resolve(t,c.relative(c.parse(e).root,e));return y(s)||await o({name:"Generating output directory",command:async()=>{await H(s,{recursive:!0})}}),s}async function B(e,t){let[a,p]=await Promise.all([o({name:"Reading input openapi schema",command:async()=>{if(!e.endsWith(".json"))throw new Error(`Input file must be a JSON file: ${e}`);if(e.startsWith("http"))try{let{stdout:s}=await f(`curl -s ${e} --fail`);return s}catch{throw new Error(`Failed to fetch remote OpenAPI file: ${e}`)}if(!y(e))throw new Error(`Input file does not exist: ${e}`);return await T(e,"utf8")}}),o({name:"Reading output openapi schema",command:async()=>{if(!t.endsWith(".json"))throw new Error(`Output file must be a JSON file: ${t}`);return y(t)?await T(t,"utf8"):!1}})]);return[JSON.stringify(JSON.parse(a)),p?JSON.stringify(JSON.parse(p)):!1]}u().name("openapi-sync").description("A CLI tool to convert OpenAPI 3.0/3.1 schemas to TypeScript types and create type-safe fetching based on a openapi file and keep them in sync.").requiredOption("-i, --input <path>","The input (local or remote) openapi schema (JSON).").requiredOption("-o, --output <folder>","The output folder to save the generated models and openapi schema and type definitions.").option("-f, --force-gen","Force generation of typescript schemas and fetching code even if the input and output schemas are identical.").option("--include-msw-utils","Include MSW mocking utilities based on the generated typescript types.").option("--post-script <script>","A package.json script to run after the code generation.").addHelpText("after",`
121
+ Example usage:
122
+ ${n("dim","$")} ${n("cyan","openapi-sync")} ${n("green","-i")} ${n("yellow","./openapi.json")} ${n("green","-o")} ${n("yellow","./src/api/gen")} ${n("green","--include-msw-utils")}
123
+ `).action(async({input:e,output:t,forceGen:a,includeMswUtils:p,postScript:s})=>{try{console.log(n("magenta",`
7
124
  \u{1F680} openapi-sync
8
- `));let s=await j(t),c=`${s}/openapi.json`,S=`${s}/schema.d.ts`,[u,p]=await J(e,c);p&&u===p&&!o?(console.log(l("blue",`
125
+ `));let r=await v(t),i=`${r}/openapi.json`,k=`${r}/schema.d.ts`,[m,d]=await B(e,i);d&&m===d&&!a?(console.log(n("blue",`
9
126
  No updates required.
10
- `)),process.exit(0)):p?p&&u!==p&&(console.log(l("yellow",`
127
+ `)),process.exit(0)):d?d&&m!==d&&(console.log(n("yellow",`
11
128
  \u26A0\uFE0F Local and remote schemas does not match!
12
- `)),await N({message:"Do you want to use the remote schema? (y/n)?"})?await n({name:"Replacing local schema with input schema",command:b(c,u)}):(console.log(l("yellow",`
129
+ `)),await E({message:"Do you want to use the remote schema? (y/n)?"})?await o({name:"Replacing local schema with input schema",command:M(i,m)}):(console.log(n("yellow",`
13
130
  \u26A0\uFE0F Sync remote schemas skipped.
14
- `)),o||process.exit(0))):await n({name:"Creating local schema",command:b(c,u)}),await Promise.all([$(c,S),x(c,s)]),a&&await O(s),i&&await n({name:"Running post script",command:`node --run ${i}`}),console.log(l("green",`
131
+ `)),a||process.exit(0))):await o({name:"Creating local schema",command:M(i,m)}),await Promise.all([x(i,k),g(i,r)]),p&&await P(r),s&&await o({name:"Running post script",command:`node --run ${s}`}),console.log(n("green",`
15
132
  \u2705 openapi-sync process completed!
16
- `))}catch(s){console.error(s),process.exit(1)}}).parseAsync(process.argv);
133
+ `))}catch(r){console.error(r),process.exit(1)}}).parseAsync(process.argv);
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{f as t,i as a}from"../chunk-OOETI6RK.js";t();import{execSync as u}from"child_process";import{styleText as d}from"util";t();import{execSync as p}from"child_process";import i from"@inquirer/select";async function c(){let n=p("npx turbo ls",{encoding:"utf8",stdio:"pipe"}).split(`
2
+ import{c as a}from"../chunk-3QWYGBKZ.js";import{execSync as u}from"child_process";import{styleText as t}from"util";import{execSync as p}from"child_process";import i from"@inquirer/select";async function c(){let n=p("npx turbo ls",{encoding:"utf8",stdio:"pipe"}).split(`
3
3
  `).slice(1).map(e=>e.trim()).filter(Boolean).map(e=>e.split(" ")[0]);return await i({message:"Select a package to run the script:",choices:n.map(e=>({name:e,value:e}))})}async function s(){return await i({message:"Select a mode to load different env files:",choices:[{name:"development",value:"development"},{name:"staging",value:"staging"},{name:"production",value:"production"}]})}a().name("turbo-select").description(`A CLI tool to filter and select a single package from the Turborepo package list and run a script command.
4
4
  Additionally, allow to prompt environment mode (development, staging, production), for example, when using Vite.`).requiredOption("--run <script>","The package script command to execute (e.g., --run=dev).").option("--select-env","An environment mode (development, staging, production) If using for example vite.").addHelpText("after",`
5
5
  Example usage:
6
-
7
- $ turbo-select --run dev --select-env`).action(async({run:o,selectEnv:n})=>{try{console.log(d("magenta",`
6
+ ${t("dim","$")} ${t("cyan","turbo-select")} ${t("green","--run")} ${t("yellow","dev")} ${t("green","--select-env")}
7
+ `).action(async({run:o,selectEnv:n})=>{try{console.log(t("magenta",`
8
8
  \u{1F680} Turbo-Select
9
9
  `));let e=await c(),r=n?await s():void 0;u(`turbo run ${o} --ui stream ${e?`--filter=${e}`:""} ${r?`-- --mode ${r}`:""}`,{encoding:"utf8",stdio:"inherit"})}catch(e){console.error(e),process.exit(1)}}).parseAsync(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "name": "@yunarch/config-web",
5
5
  "description": "Shared configurations for web projects.",
6
6
  "license": "MIT",
@@ -102,6 +102,7 @@
102
102
  "dependencies": {
103
103
  "commander": "14.0.0",
104
104
  "ora": "8.2.0",
105
+ "fast-glob": "3.3.3",
105
106
  "@inquirer/confirm": "5.1.14",
106
107
  "@inquirer/select": "4.3.1",
107
108
  "@total-typescript/ts-reset": "0.6.1",
@@ -122,7 +123,7 @@
122
123
  "eslint-plugin-react-hooks": "5.2.0",
123
124
  "eslint-plugin-react-refresh": "0.4.20",
124
125
  "@tanstack/eslint-plugin-query": "5.83.1",
125
- "@tanstack/eslint-plugin-router": "1.129.7",
126
+ "@tanstack/eslint-plugin-router": "1.130.12",
126
127
  "@vitest/eslint-plugin": "1.3.4"
127
128
  },
128
129
  "devDependencies": {
@@ -134,7 +135,7 @@
134
135
  "eslint-typegen": "2.3.0",
135
136
  "oxlint": "1.9.0",
136
137
  "husky": "9.1.7",
137
- "lint-staged": "16.1.2",
138
+ "lint-staged": "16.1.4",
138
139
  "rimraf": "6.0.1",
139
140
  "tsup": "8.5.0",
140
141
  "typescript": "5.9.2",
@@ -1 +0,0 @@
1
- var u=Object.create;var p=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty;var k=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,o)=>(typeof require<"u"?require:t)[o]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var A=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var x=(e,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of y(t))!g.call(e,r)&&r!==o&&p(e,r,{get:()=>t[r],enumerable:!(i=d(t,r))||i.enumerable});return e};var B=(e,t,o)=>(o=e!=null?u(f(e)):{},x(t||!e||!e.__esModule?p(o,"default",{value:e,enumerable:!0}):o,e));import w from"path";import{fileURLToPath as h}from"url";var c,P,b,D,a=T(()=>{"use strict";c=()=>h(import.meta.url),P=()=>w.dirname(c()),b=P(),D=c()});a();import{exec as O}from"child_process";import{promisify as _,styleText as n,types as C}from"util";import{Command as $}from"commander";import E from"ora";var j=_(O);async function z(e){let{command:t,name:o,options:i}=e,r=E(o);r.spinner=i?.spinner??"aesthetic";let l=Date.now();r.start();try{let s=typeof t=="string"?await j(t):C.isPromise(t)?await t:await t();return r.succeed(i?.showTime?`${n("dim",`${Date.now()-l}ms`)} ${o}`:void 0),await new Promise(m=>{setTimeout(m,0)}),typeof s=="object"&&s&&"stdout"in s?s.stdout:s}catch(s){let m=s;throw r.fail(n("red",m.stderr??m.message??"")),s}}function G(){let e=new $;return e.configureHelp({styleTitle:t=>n("bold",t),styleCommandText:t=>n("cyan",t),styleCommandDescription:t=>n("magenta",t),styleDescriptionText:t=>n("italic",t),styleOptionText:t=>n("green",t),styleArgumentText:t=>n("yellow",t),styleSubcommandText:t=>n("blue",t)}).configureOutput({outputError:(t,o)=>{o(n("red",t))}}),e}export{k as a,A as b,B as c,b as d,D as e,a as f,j as g,z as h,G as i};