@devup-api/generator 0.1.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/README.md +26 -0
- package/dist/__tests__/convert-case.test.d.ts +2 -0
- package/dist/__tests__/convert-case.test.d.ts.map +1 -0
- package/dist/__tests__/create-url-map.test.d.ts +2 -0
- package/dist/__tests__/create-url-map.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/wrap-interface-key-guard.test.d.ts +2 -0
- package/dist/__tests__/wrap-interface-key-guard.test.d.ts.map +1 -0
- package/dist/convert-case.d.ts +5 -0
- package/dist/convert-case.d.ts.map +1 -0
- package/dist/create-url-map.d.ts +4 -0
- package/dist/create-url-map.d.ts.map +1 -0
- package/dist/generate-interface.d.ts +15 -0
- package/dist/generate-interface.d.ts.map +1 -0
- package/dist/generate-schema.d.ts +44 -0
- package/dist/generate-schema.d.ts.map +1 -0
- package/dist/index.cjs +36 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/wrap-interface-key-guard.d.ts +2 -0
- package/dist/wrap-interface-key-guard.d.ts.map +1 -0
- package/package.json +27 -0
- package/src/__tests__/convert-case.test.ts +125 -0
- package/src/__tests__/create-url-map.test.ts +318 -0
- package/src/__tests__/index.test.ts +9 -0
- package/src/__tests__/wrap-interface-key-guard.test.ts +42 -0
- package/src/convert-case.ts +22 -0
- package/src/create-url-map.ts +43 -0
- package/src/generate-interface.ts +594 -0
- package/src/generate-schema.ts +482 -0
- package/src/index.ts +2 -0
- package/src/wrap-interface-key-guard.ts +6 -0
- package/tsconfig.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @devup-api/generator
|
|
2
|
+
|
|
3
|
+
devup API Type Generator
|
|
4
|
+
|
|
5
|
+
Type generation package that generates TypeScript types from schemas.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @devup-api/generator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { generateTypes, generateTypeFromSchema } from '@devup-api/generator';
|
|
17
|
+
|
|
18
|
+
// Generate types
|
|
19
|
+
await generateTypes({
|
|
20
|
+
outputPath: './types',
|
|
21
|
+
format: 'typescript',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Generate type from schema
|
|
25
|
+
const typeString = generateTypeFromSchema(schema);
|
|
26
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-case.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/convert-case.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-url-map.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/create-url-map.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-interface-key-guard.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/wrap-interface-key-guard.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-case.d.ts","sourceRoot":"","sources":["../src/convert-case.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAoB,GAC5D,MAAM,CAaR"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DevupApiTypeGeneratorOptions, UrlMapValue } from '@devup-api/core';
|
|
2
|
+
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
3
|
+
export declare function createUrlMap(schema: OpenAPIV3_1.Document, options?: DevupApiTypeGeneratorOptions): Record<string, UrlMapValue>;
|
|
4
|
+
//# sourceMappingURL=create-url-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-url-map.d.ts","sourceRoot":"","sources":["../src/create-url-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGhD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,CAAC,QAAQ,EAC5B,OAAO,CAAC,EAAE,4BAA4B,+BAoCvC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DevupApiTypeGeneratorOptions } from '@devup-api/core';
|
|
2
|
+
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
3
|
+
export interface ParameterDefinition extends Omit<OpenAPIV3_1.ParameterObject, 'schema'> {
|
|
4
|
+
type: unknown;
|
|
5
|
+
default?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export interface EndpointDefinition {
|
|
8
|
+
params?: Record<string, ParameterDefinition>;
|
|
9
|
+
body?: unknown;
|
|
10
|
+
query?: Record<string, ParameterDefinition>;
|
|
11
|
+
response?: unknown;
|
|
12
|
+
error?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export declare function generateInterface(schema: OpenAPIV3_1.Document, options?: DevupApiTypeGeneratorOptions): string;
|
|
15
|
+
//# sourceMappingURL=generate-interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-interface.d.ts","sourceRoot":"","sources":["../src/generate-interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAA;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAUhD,MAAM,WAAW,mBACf,SAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC;IACnD,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC5C,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AASD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,CAAC,QAAQ,EAC5B,OAAO,CAAC,EAAE,4BAA4B,GACrC,MAAM,CA6iBR"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
+
import type { ParameterDefinition } from './generate-interface';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve $ref reference in OpenAPI parameter
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveParameterRef(ref: string, document: OpenAPIV3_1.Document): OpenAPIV3_1.ParameterObject | null;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve $ref reference in OpenAPI schema
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveSchemaRef(ref: string, document: OpenAPIV3_1.Document): OpenAPIV3_1.SchemaObject | null;
|
|
11
|
+
/**
|
|
12
|
+
* Convert OpenAPI schema to TypeScript type representation
|
|
13
|
+
*/
|
|
14
|
+
export declare function getTypeFromSchema(schema: OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject, document: OpenAPIV3_1.Document, options?: {
|
|
15
|
+
defaultNonNullable?: boolean;
|
|
16
|
+
}): {
|
|
17
|
+
type: unknown;
|
|
18
|
+
default?: unknown;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Check if all properties in an object are optional
|
|
22
|
+
*/
|
|
23
|
+
export declare function areAllPropertiesOptional(obj: Record<string, unknown>): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Format a type object to TypeScript interface/type string
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatType(obj: Record<string, unknown>, indent?: number): string;
|
|
28
|
+
/**
|
|
29
|
+
* Format a type value to TypeScript type string
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatTypeValue(value: unknown, indent?: number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Extract parameters from OpenAPI operation
|
|
34
|
+
*/
|
|
35
|
+
export declare function extractParameters(pathItem: OpenAPIV3_1.PathItemObject | undefined, operation: OpenAPIV3_1.OperationObject | undefined, document: OpenAPIV3_1.Document): {
|
|
36
|
+
pathParams: Record<string, ParameterDefinition>;
|
|
37
|
+
queryParams: Record<string, ParameterDefinition>;
|
|
38
|
+
headerParams: Record<string, ParameterDefinition>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Extract request body from OpenAPI operation
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractRequestBody(requestBody: OpenAPIV3_1.RequestBodyObject | OpenAPIV3_1.ReferenceObject | undefined, document: OpenAPIV3_1.Document): unknown;
|
|
44
|
+
//# sourceMappingURL=generate-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-schema.d.ts","sourceRoot":"","sources":["../src/generate-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAE/D;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,WAAW,CAAC,QAAQ,GAC7B,WAAW,CAAC,eAAe,GAAG,IAAI,CAqBpC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,WAAW,CAAC,QAAQ,GAC7B,WAAW,CAAC,YAAY,GAAG,IAAI,CAqBjC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC,eAAe,EAC9D,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,OAAO,CAAC,EAAE;IACR,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,GACA;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAqItC;AAeD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAqCT;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,MAAM,GAAE,MAAU,GACjB,MAAM,CAyDR;AAiBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAe1E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,WAAW,CAAC,cAAc,GAAG,SAAS,EAChD,SAAS,EAAE,WAAW,CAAC,eAAe,GAAG,SAAS,EAClD,QAAQ,EAAE,WAAW,CAAC,QAAQ,GAC7B;IACD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC/C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAChD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;CAClD,CAkEA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EACP,WAAW,CAAC,iBAAiB,GAC7B,WAAW,CAAC,eAAe,GAC3B,SAAS,EACb,QAAQ,EAAE,WAAW,CAAC,QAAQ,GAC7B,OAAO,CA+BT"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var{defineProperty:p,getOwnPropertyNames:H$,getOwnPropertyDescriptor:J$}=Object,L$=Object.prototype.hasOwnProperty;var o=new WeakMap,U$=($)=>{var L=o.get($),Y;if(L)return L;if(L=p({},"__esModule",{value:!0}),$&&typeof $==="object"||typeof $==="function")H$($).map((J)=>!L$.call(L,J)&&p(L,J,{get:()=>$[J],enumerable:!(Y=J$($,J))||Y.enumerable}));return o.set($,L),L};var X$=($,L)=>{for(var Y in L)p($,Y,{get:L[Y],enumerable:!0,configurable:!0,set:(J)=>L[Y]=()=>J})};var Q$={};X$(Q$,{generateInterface:()=>W$,createUrlMap:()=>Y$});module.exports=U$(Q$);var i=require("@devup-api/utils");function O($,L="camel"){switch(L){case"snake":return i.toSnake($);case"camel":return i.toCamel($);case"pascal":return i.toPascal($);case"maintain":return $;default:return $}}function Y$($,L){let Y=L?.convertCase??"camel",J={};for(let[H,X]of Object.entries($.paths??{})){if(!X)continue;for(let W of["get","post","put","delete","patch"]){let U=X[W];if(!U)continue;let x=H.replace(/\{([^}]+)\}/g,(P,R)=>{return`{${O(R,Y)}}`});if(U.operationId)J[O(U.operationId,Y)]={method:W.toUpperCase(),url:x};J[x]={method:W.toUpperCase(),url:x}}}return J}var e=require("@devup-api/utils");function Z$($,L){if(!$.startsWith("#/"))return null;let Y=$.slice(2).split("/"),J=L;for(let H of Y)if(J&&typeof J==="object"&&H in J)J=J[H];else return null;if(J&&typeof J==="object"&&!("$ref"in J))return J;return null}function c($,L){if(!$.startsWith("#/"))return null;let Y=$.slice(2).split("/"),J=L;for(let H of Y)if(J&&typeof J==="object"&&H in J)J=J[H];else return null;if(J&&typeof J==="object"&&!("$ref"in J))return J;return null}function D($,L,Y){let J=Y?.defaultNonNullable??!1;if("$ref"in $){let X=c($.$ref,L);if(X)return D(X,L,Y);return{type:"unknown",default:void 0}}let H=$;if(H.allOf){let X=H.allOf.map((W)=>D(W,L,Y));return{type:X.length>0?X.map((W)=>k(W.type)).join(" & "):"unknown",default:H.default}}if(H.anyOf||H.oneOf){let X=(H.anyOf||H.oneOf||[]).map((W)=>D(W,L,Y));return{type:X.length>0?`(${X.map((W)=>k(W.type)).join(" | ")})`:"unknown",default:H.default}}if(H.enum)return{type:H.enum.map((X)=>`"${String(X)}"`).join(" | "),default:H.default};if(H.type==="string"){if(H.format==="date"||H.format==="date-time")return{type:"string",default:H.default};return{type:"string",default:H.default}}if(H.type==="number"||H.type==="integer")return{type:"number",default:H.default};if(H.type==="boolean")return{type:"boolean",default:H.default};if(H.type==="array"){let X=H.items;if(X){let W=D(X,L,Y);return{type:`Array<${k(W.type)}>`,default:H.default}}return{type:"unknown[]",default:H.default}}if(H.type==="object"||H.properties){let X={},W=H.required||[];if(H.properties)for(let[U,x]of Object.entries(H.properties)){let P=D(x,L,Y),R=!1;if("$ref"in x){let G=c(x.$ref,L);if(G)R=G.default!==void 0}else R=x.default!==void 0;let F=W.includes(U);if(J&&R&&!F)X[U]=P;else if(!F)X[`${U}?`]=P;else X[U]=P}if(H.additionalProperties){if(H.additionalProperties===!0)X["[key: string]"]={type:"unknown",default:void 0};else if(typeof H.additionalProperties==="object"){let U=D(H.additionalProperties,L,Y);X["[key: string]"]={type:U.type,default:U.default}}}return{type:{...X},default:H.default}}return{type:"unknown",default:void 0}}function t($){return typeof $==="object"&&$!==null&&"type"in $&&"in"in $&&"name"in $}function m($){let L=Object.entries($);if(L.length===0)return!0;return L.every(([Y,J])=>{if(Y.endsWith("?"))return!0;if(t(J))return J.required===!1;if(n(J)){if(typeof J.type==="object"&&J.type!==null&&!Array.isArray(J.type))return m(J.type);return!1}if(typeof J==="object"&&J!==null&&!Array.isArray(J))return m(J);return!1})}function _$($,L=0){let Y=" ".repeat(L),J=L+1,H=" ".repeat(J),X=Object.entries($).map(([W,U])=>{if(typeof U==="string")return`${H}${W}: ${U}`;if(t(U)){let F=k(U.type,J),S=U.required===!1?`${W}?`:W,g="";if(U.description){if(g+=`${H}/**
|
|
2
|
+
${H} * ${U.description}`,typeof U.default<"u")g+=`
|
|
3
|
+
${H} * @default {${U.default}}`;g=`${g}
|
|
4
|
+
${H} */
|
|
5
|
+
${H}`}else if(typeof U.default<"u")g+=`${H}/** @default {${U.default}} */
|
|
6
|
+
${H}`;else g=H;return`${g}${S}: ${F}`}if(n(U)){let F=k(U.type,J);return`${H}${W}: ${F}`}let P=typeof U==="object"&&U!==null&&!Array.isArray(U)&&m(U)?"?":"",R=k(U,J);return`${H}${W}${P}: ${R}`}).join(`;
|
|
7
|
+
`);if(X.length===0)return"{}";return`{
|
|
8
|
+
${X};
|
|
9
|
+
${Y}}`}function n($){return typeof $==="object"&&$!==null&&"type"in $&&Object.keys($).length<=2&&(!("default"in $)||Object.keys($).length===2)}function k($,L=0){if(typeof $==="string")return $;if(n($))return k($.type,L);if(typeof $==="object"&&$!==null&&!Array.isArray($))return _$($,L);return String($)}function a($,L,Y){let J={},H={},X={},W=[...$?.parameters||[],...L?.parameters||[]];for(let U of W){if("$ref"in U){let G=Z$(U.$ref,Y);if(G&&"in"in G&&"name"in G&&typeof G.in==="string"&&typeof G.name==="string"){let S="schema"in G&&G.schema?G.schema:{},{type:g,default:d}=D(S,Y,{defaultNonNullable:!1}),N={...G,type:g,default:d};if(G.in==="path")J[G.name]=N;else if(G.in==="query")H[G.name]=N;else if(G.in==="header")X[G.name]=N}continue}let x=U.schema||{},{type:P,default:R}=D(x,Y,{defaultNonNullable:!1}),F={...U,type:P,default:R};if(U.in==="path")J[U.name]=F;else if(U.in==="query")H[U.name]=F;else if(U.in==="header")X[U.name]=F}return{pathParams:J,queryParams:H,headerParams:X}}function l($,L){if(!$)return;if("$ref"in $){let J=c($.$ref,L);if(J&&"content"in J&&J.content){let X=J.content["application/json"];if(X&&"schema"in X&&X.schema)return D(X.schema,L,{defaultNonNullable:!1}).type}return"unknown"}let Y=$.content;if(Y){let J=Y["application/json"];if(J&&"schema"in J&&J.schema)return D(J.schema,L,{defaultNonNullable:!1}).type}return}function v($){if($.includes("/"))return`[\`${$}\`]`;return $}function f($){if($.startsWith("#/components/schemas/"))return $.replace("#/components/schemas/","");return null}function W$($,L){let Y={get:{},post:{},put:{},delete:{},patch:{}},J=L?.convertCase??"camel",H=(Q,z)=>{if("$ref"in Q){let A=f(Q.$ref);if(A)z.add(A);return}let w=Q;if(w.allOf)w.allOf.forEach((A)=>{H(A,z)});if(w.anyOf)w.anyOf.forEach((A)=>{H(A,z)});if(w.oneOf)w.oneOf.forEach((A)=>{H(A,z)});if(w.properties)Object.values(w.properties).forEach((A)=>{H(A,z)});if(w.type==="array"&&"items"in w&&w.items)H(w.items,z)},X=new Set,W=new Set,U=new Set,x=(Q)=>{if(Q==="default")return!0;let z=parseInt(Q,10);return z>=400&&z<600};if($.paths)for(let Q of Object.values($.paths)){if(!Q)continue;let z=["get","post","put","delete","patch"];for(let w of z){let A=Q[w];if(!A)continue;if(A.requestBody)if("$ref"in A.requestBody){let Z=f(A.requestBody.$ref);if(Z)X.add(Z)}else{let M=A.requestBody.content?.["application/json"];if(M&&"schema"in M&&M.schema)H(M.schema,X)}if(A.responses)for(let[Z,M]of Object.entries(A.responses)){let C=x(Z);if("$ref"in M){let j=f(M.$ref);if(j)if(C)U.add(j);else W.add(j)}else if("content"in M){let q=M.content?.["application/json"];if(q&&"schema"in q&&q.schema)if(C)H(q.schema,U);else H(q.schema,W)}}}}if($.paths)for(let[Q,z]of Object.entries($.paths)){if(!z)continue;let w=["get","post","put","delete","patch"];for(let A of w){let Z=z[A];if(!Z)continue;let M={},{pathParams:C,queryParams:j}=a(z,Z,$),q={};for(let[E,B]of Object.entries(C)){let _=O(E,J);q[_]=B}let h={};for(let[E,B]of Object.entries(j)){let _=O(E,J);h[_]=B}if(Object.keys(q).length>0)M.params=q;if(Object.keys(h).length>0)M.query=h;let y;if(Z.requestBody)if("$ref"in Z.requestBody){let E=l(Z.requestBody,$);if(E!==void 0)y=E}else{let B=Z.requestBody.content?.["application/json"];if(B&&"schema"in B&&B.schema)if("$ref"in B.schema){let _=f(B.schema.$ref);if(_&&$.components?.schemas?.[_]&&X.has(_))y=`DevupRequestComponentStruct['${_}']`;else{let K=l(Z.requestBody,$);if(K!==void 0)y=K}}else{let _=l(Z.requestBody,$);if(_!==void 0)y=_}}if(y!==void 0)M.body=y;let b;if(Z.responses){let E=Z.responses["200"]||Z.responses["201"]||Object.values(Z.responses)[0];if(E){if("$ref"in E);else if("content"in E){let _=E.content?.["application/json"];if(_&&"schema"in _&&_.schema)if("$ref"in _.schema){let K=f(_.schema.$ref);if(K&&$.components?.schemas?.[K]&&W.has(K))b=`DevupResponseComponentStruct['${K}']`;else{let V=L?.responseDefaultNonNullable??!0,{type:I}=D(_.schema,$,{defaultNonNullable:V});b=I}}else{let K=_.schema;if(K.type==="array"&&K.items&&"$ref"in K.items){let V=f(K.items.$ref);if(V&&$.components?.schemas?.[V]&&W.has(V))b=`Array<DevupResponseComponentStruct['${V}']>`;else{let I=L?.responseDefaultNonNullable??!0,{type:u}=D(_.schema,$,{defaultNonNullable:I});b=u}}else{let V=L?.responseDefaultNonNullable??!0,{type:I}=D(_.schema,$,{defaultNonNullable:V});b=I}}}}}if(b!==void 0)M.response=b;let T;if(Z.responses){let E=Z.responses["400"]||Z.responses["401"]||Z.responses["403"]||Z.responses["404"]||Z.responses["422"]||Z.responses["500"]||Z.responses.default||Object.entries(Z.responses).find(([B])=>x(B))?.[1];if(E){if("$ref"in E);else if("content"in E){let _=E.content?.["application/json"];if(_&&"schema"in _&&_.schema)if("$ref"in _.schema){let K=f(_.schema.$ref);if(K&&$.components?.schemas?.[K]&&U.has(K))T=`DevupErrorComponentStruct['${K}']`;else{let V=L?.responseDefaultNonNullable??!0,{type:I}=D(_.schema,$,{defaultNonNullable:V});T=I}}else{let K=_.schema;if(K.type==="array"&&K.items&&"$ref"in K.items){let V=f(K.items.$ref);if(V&&$.components?.schemas?.[V]&&U.has(V))T=`Array<DevupErrorComponentStruct['${V}']>`;else{let I=L?.responseDefaultNonNullable??!0,{type:u}=D(_.schema,$,{defaultNonNullable:I});T=u}}else{let V=L?.responseDefaultNonNullable??!0,{type:I}=D(_.schema,$,{defaultNonNullable:V});T=I}}}}}if(T!==void 0)M.error=T;let $$=Q.replace(/\{([^}]+)\}/g,(E,B)=>{return`{${O(B,J)}}`});if(Y[A][$$]=M,Z.operationId){let E=O(Z.operationId,J);Y[A][E]=M}}}let P={},R={},F={};if($.components?.schemas){for(let[Q,z]of Object.entries($.components.schemas))if(z){let w=L?.requestDefaultNonNullable??!1,Z=L?.responseDefaultNonNullable??!0;if(X.has(Q))Z=w;let{type:M}=D(z,$,{defaultNonNullable:Z});if(X.has(Q))P[Q]=M;if(W.has(Q))R[Q]=M;if(U.has(Q))F[Q]=M}}let G=Object.entries(Y).flatMap(([Q,z])=>{let w=Object.entries(z);if(w.length>0){let A=w.map(([Z,M])=>{let C=k(M,2);return` ${v(Z)}: ${C}`}).join(`;
|
|
10
|
+
`);return[` interface Devup${e.toPascal(Q)}ApiStruct {
|
|
11
|
+
${A};
|
|
12
|
+
}`]}return[]}).join(`
|
|
13
|
+
`),S=Object.entries(P).map(([Q,z])=>{let w=k(z,2);return` ${v(Q)}: ${w}`}).join(`;
|
|
14
|
+
`),g=S.length>0?` interface DevupRequestComponentStruct {
|
|
15
|
+
${S};
|
|
16
|
+
}`:" interface DevupRequestComponentStruct {}",d=Object.entries(R).map(([Q,z])=>{let w=k(z,2);return` ${v(Q)}: ${w}`}).join(`;
|
|
17
|
+
`),N=d.length>0?` interface DevupResponseComponentStruct {
|
|
18
|
+
${d};
|
|
19
|
+
}`:" interface DevupResponseComponentStruct {}",r=Object.entries(F).map(([Q,z])=>{let w=k(z,2);return` ${v(Q)}: ${w}`}).join(`;
|
|
20
|
+
`),s=r.length>0?` interface DevupErrorComponentStruct {
|
|
21
|
+
${r};
|
|
22
|
+
}`:" interface DevupErrorComponentStruct {}";return`import "@devup-api/fetch";
|
|
23
|
+
|
|
24
|
+
declare module "@devup-api/fetch" {
|
|
25
|
+
${G?`${G}
|
|
26
|
+
|
|
27
|
+
${g}
|
|
28
|
+
|
|
29
|
+
${N}
|
|
30
|
+
|
|
31
|
+
${s}`:`${g}
|
|
32
|
+
|
|
33
|
+
${N}
|
|
34
|
+
|
|
35
|
+
${s}`}
|
|
36
|
+
}`}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import{toCamel as t,toPascal as a,toSnake as e}from"@devup-api/utils";function O($,U="camel"){switch(U){case"snake":return e($);case"camel":return t($);case"pascal":return a($);case"maintain":return $;default:return $}}function Z$($,U){let _=U?.convertCase??"camel",J={};for(let[H,X]of Object.entries($.paths??{})){if(!X)continue;for(let W of["get","post","put","delete","patch"]){let L=X[W];if(!L)continue;let x=H.replace(/\{([^}]+)\}/g,(P,R)=>{return`{${O(R,_)}}`});if(L.operationId)J[O(L.operationId,_)]={method:W.toUpperCase(),url:x};J[x]={method:W.toUpperCase(),url:x}}}return J}import{toPascal as J$}from"@devup-api/utils";function $$($,U){if(!$.startsWith("#/"))return null;let _=$.slice(2).split("/"),J=U;for(let H of _)if(J&&typeof J==="object"&&H in J)J=J[H];else return null;if(J&&typeof J==="object"&&!("$ref"in J))return J;return null}function u($,U){if(!$.startsWith("#/"))return null;let _=$.slice(2).split("/"),J=U;for(let H of _)if(J&&typeof J==="object"&&H in J)J=J[H];else return null;if(J&&typeof J==="object"&&!("$ref"in J))return J;return null}function D($,U,_){let J=_?.defaultNonNullable??!1;if("$ref"in $){let X=u($.$ref,U);if(X)return D(X,U,_);return{type:"unknown",default:void 0}}let H=$;if(H.allOf){let X=H.allOf.map((W)=>D(W,U,_));return{type:X.length>0?X.map((W)=>k(W.type)).join(" & "):"unknown",default:H.default}}if(H.anyOf||H.oneOf){let X=(H.anyOf||H.oneOf||[]).map((W)=>D(W,U,_));return{type:X.length>0?`(${X.map((W)=>k(W.type)).join(" | ")})`:"unknown",default:H.default}}if(H.enum)return{type:H.enum.map((X)=>`"${String(X)}"`).join(" | "),default:H.default};if(H.type==="string"){if(H.format==="date"||H.format==="date-time")return{type:"string",default:H.default};return{type:"string",default:H.default}}if(H.type==="number"||H.type==="integer")return{type:"number",default:H.default};if(H.type==="boolean")return{type:"boolean",default:H.default};if(H.type==="array"){let X=H.items;if(X){let W=D(X,U,_);return{type:`Array<${k(W.type)}>`,default:H.default}}return{type:"unknown[]",default:H.default}}if(H.type==="object"||H.properties){let X={},W=H.required||[];if(H.properties)for(let[L,x]of Object.entries(H.properties)){let P=D(x,U,_),R=!1;if("$ref"in x){let G=u(x.$ref,U);if(G)R=G.default!==void 0}else R=x.default!==void 0;let F=W.includes(L);if(J&&R&&!F)X[L]=P;else if(!F)X[`${L}?`]=P;else X[L]=P}if(H.additionalProperties){if(H.additionalProperties===!0)X["[key: string]"]={type:"unknown",default:void 0};else if(typeof H.additionalProperties==="object"){let L=D(H.additionalProperties,U,_);X["[key: string]"]={type:L.type,default:L.default}}}return{type:{...X},default:H.default}}return{type:"unknown",default:void 0}}function r($){return typeof $==="object"&&$!==null&&"type"in $&&"in"in $&&"name"in $}function p($){let U=Object.entries($);if(U.length===0)return!0;return U.every(([_,J])=>{if(_.endsWith("?"))return!0;if(r(J))return J.required===!1;if(c(J)){if(typeof J.type==="object"&&J.type!==null&&!Array.isArray(J.type))return p(J.type);return!1}if(typeof J==="object"&&J!==null&&!Array.isArray(J))return p(J);return!1})}function H$($,U=0){let _=" ".repeat(U),J=U+1,H=" ".repeat(J),X=Object.entries($).map(([W,L])=>{if(typeof L==="string")return`${H}${W}: ${L}`;if(r(L)){let F=k(L.type,J),S=L.required===!1?`${W}?`:W,g="";if(L.description){if(g+=`${H}/**
|
|
2
|
+
${H} * ${L.description}`,typeof L.default<"u")g+=`
|
|
3
|
+
${H} * @default {${L.default}}`;g=`${g}
|
|
4
|
+
${H} */
|
|
5
|
+
${H}`}else if(typeof L.default<"u")g+=`${H}/** @default {${L.default}} */
|
|
6
|
+
${H}`;else g=H;return`${g}${S}: ${F}`}if(c(L)){let F=k(L.type,J);return`${H}${W}: ${F}`}let P=typeof L==="object"&&L!==null&&!Array.isArray(L)&&p(L)?"?":"",R=k(L,J);return`${H}${W}${P}: ${R}`}).join(`;
|
|
7
|
+
`);if(X.length===0)return"{}";return`{
|
|
8
|
+
${X};
|
|
9
|
+
${_}}`}function c($){return typeof $==="object"&&$!==null&&"type"in $&&Object.keys($).length<=2&&(!("default"in $)||Object.keys($).length===2)}function k($,U=0){if(typeof $==="string")return $;if(c($))return k($.type,U);if(typeof $==="object"&&$!==null&&!Array.isArray($))return H$($,U);return String($)}function s($,U,_){let J={},H={},X={},W=[...$?.parameters||[],...U?.parameters||[]];for(let L of W){if("$ref"in L){let G=$$(L.$ref,_);if(G&&"in"in G&&"name"in G&&typeof G.in==="string"&&typeof G.name==="string"){let S="schema"in G&&G.schema?G.schema:{},{type:g,default:v}=D(S,_,{defaultNonNullable:!1}),N={...G,type:g,default:v};if(G.in==="path")J[G.name]=N;else if(G.in==="query")H[G.name]=N;else if(G.in==="header")X[G.name]=N}continue}let x=L.schema||{},{type:P,default:R}=D(x,_,{defaultNonNullable:!1}),F={...L,type:P,default:R};if(L.in==="path")J[L.name]=F;else if(L.in==="query")H[L.name]=F;else if(L.in==="header")X[L.name]=F}return{pathParams:J,queryParams:H,headerParams:X}}function d($,U){if(!$)return;if("$ref"in $){let J=u($.$ref,U);if(J&&"content"in J&&J.content){let X=J.content["application/json"];if(X&&"schema"in X&&X.schema)return D(X.schema,U,{defaultNonNullable:!1}).type}return"unknown"}let _=$.content;if(_){let J=_["application/json"];if(J&&"schema"in J&&J.schema)return D(J.schema,U,{defaultNonNullable:!1}).type}return}function i($){if($.includes("/"))return`[\`${$}\`]`;return $}function f($){if($.startsWith("#/components/schemas/"))return $.replace("#/components/schemas/","");return null}function M$($,U){let _={get:{},post:{},put:{},delete:{},patch:{}},J=U?.convertCase??"camel",H=(Q,z)=>{if("$ref"in Q){let A=f(Q.$ref);if(A)z.add(A);return}let w=Q;if(w.allOf)w.allOf.forEach((A)=>{H(A,z)});if(w.anyOf)w.anyOf.forEach((A)=>{H(A,z)});if(w.oneOf)w.oneOf.forEach((A)=>{H(A,z)});if(w.properties)Object.values(w.properties).forEach((A)=>{H(A,z)});if(w.type==="array"&&"items"in w&&w.items)H(w.items,z)},X=new Set,W=new Set,L=new Set,x=(Q)=>{if(Q==="default")return!0;let z=parseInt(Q,10);return z>=400&&z<600};if($.paths)for(let Q of Object.values($.paths)){if(!Q)continue;let z=["get","post","put","delete","patch"];for(let w of z){let A=Q[w];if(!A)continue;if(A.requestBody)if("$ref"in A.requestBody){let Y=f(A.requestBody.$ref);if(Y)X.add(Y)}else{let M=A.requestBody.content?.["application/json"];if(M&&"schema"in M&&M.schema)H(M.schema,X)}if(A.responses)for(let[Y,M]of Object.entries(A.responses)){let C=x(Y);if("$ref"in M){let j=f(M.$ref);if(j)if(C)L.add(j);else W.add(j)}else if("content"in M){let q=M.content?.["application/json"];if(q&&"schema"in q&&q.schema)if(C)H(q.schema,L);else H(q.schema,W)}}}}if($.paths)for(let[Q,z]of Object.entries($.paths)){if(!z)continue;let w=["get","post","put","delete","patch"];for(let A of w){let Y=z[A];if(!Y)continue;let M={},{pathParams:C,queryParams:j}=s(z,Y,$),q={};for(let[E,B]of Object.entries(C)){let Z=O(E,J);q[Z]=B}let l={};for(let[E,B]of Object.entries(j)){let Z=O(E,J);l[Z]=B}if(Object.keys(q).length>0)M.params=q;if(Object.keys(l).length>0)M.query=l;let y;if(Y.requestBody)if("$ref"in Y.requestBody){let E=d(Y.requestBody,$);if(E!==void 0)y=E}else{let B=Y.requestBody.content?.["application/json"];if(B&&"schema"in B&&B.schema)if("$ref"in B.schema){let Z=f(B.schema.$ref);if(Z&&$.components?.schemas?.[Z]&&X.has(Z))y=`DevupRequestComponentStruct['${Z}']`;else{let K=d(Y.requestBody,$);if(K!==void 0)y=K}}else{let Z=d(Y.requestBody,$);if(Z!==void 0)y=Z}}if(y!==void 0)M.body=y;let b;if(Y.responses){let E=Y.responses["200"]||Y.responses["201"]||Object.values(Y.responses)[0];if(E){if("$ref"in E);else if("content"in E){let Z=E.content?.["application/json"];if(Z&&"schema"in Z&&Z.schema)if("$ref"in Z.schema){let K=f(Z.schema.$ref);if(K&&$.components?.schemas?.[K]&&W.has(K))b=`DevupResponseComponentStruct['${K}']`;else{let V=U?.responseDefaultNonNullable??!0,{type:I}=D(Z.schema,$,{defaultNonNullable:V});b=I}}else{let K=Z.schema;if(K.type==="array"&&K.items&&"$ref"in K.items){let V=f(K.items.$ref);if(V&&$.components?.schemas?.[V]&&W.has(V))b=`Array<DevupResponseComponentStruct['${V}']>`;else{let I=U?.responseDefaultNonNullable??!0,{type:h}=D(Z.schema,$,{defaultNonNullable:I});b=h}}else{let V=U?.responseDefaultNonNullable??!0,{type:I}=D(Z.schema,$,{defaultNonNullable:V});b=I}}}}}if(b!==void 0)M.response=b;let T;if(Y.responses){let E=Y.responses["400"]||Y.responses["401"]||Y.responses["403"]||Y.responses["404"]||Y.responses["422"]||Y.responses["500"]||Y.responses.default||Object.entries(Y.responses).find(([B])=>x(B))?.[1];if(E){if("$ref"in E);else if("content"in E){let Z=E.content?.["application/json"];if(Z&&"schema"in Z&&Z.schema)if("$ref"in Z.schema){let K=f(Z.schema.$ref);if(K&&$.components?.schemas?.[K]&&L.has(K))T=`DevupErrorComponentStruct['${K}']`;else{let V=U?.responseDefaultNonNullable??!0,{type:I}=D(Z.schema,$,{defaultNonNullable:V});T=I}}else{let K=Z.schema;if(K.type==="array"&&K.items&&"$ref"in K.items){let V=f(K.items.$ref);if(V&&$.components?.schemas?.[V]&&L.has(V))T=`Array<DevupErrorComponentStruct['${V}']>`;else{let I=U?.responseDefaultNonNullable??!0,{type:h}=D(Z.schema,$,{defaultNonNullable:I});T=h}}else{let V=U?.responseDefaultNonNullable??!0,{type:I}=D(Z.schema,$,{defaultNonNullable:V});T=I}}}}}if(T!==void 0)M.error=T;let o=Q.replace(/\{([^}]+)\}/g,(E,B)=>{return`{${O(B,J)}}`});if(_[A][o]=M,Y.operationId){let E=O(Y.operationId,J);_[A][E]=M}}}let P={},R={},F={};if($.components?.schemas){for(let[Q,z]of Object.entries($.components.schemas))if(z){let w=U?.requestDefaultNonNullable??!1,Y=U?.responseDefaultNonNullable??!0;if(X.has(Q))Y=w;let{type:M}=D(z,$,{defaultNonNullable:Y});if(X.has(Q))P[Q]=M;if(W.has(Q))R[Q]=M;if(L.has(Q))F[Q]=M}}let G=Object.entries(_).flatMap(([Q,z])=>{let w=Object.entries(z);if(w.length>0){let A=w.map(([Y,M])=>{let C=k(M,2);return` ${i(Y)}: ${C}`}).join(`;
|
|
10
|
+
`);return[` interface Devup${J$(Q)}ApiStruct {
|
|
11
|
+
${A};
|
|
12
|
+
}`]}return[]}).join(`
|
|
13
|
+
`),S=Object.entries(P).map(([Q,z])=>{let w=k(z,2);return` ${i(Q)}: ${w}`}).join(`;
|
|
14
|
+
`),g=S.length>0?` interface DevupRequestComponentStruct {
|
|
15
|
+
${S};
|
|
16
|
+
}`:" interface DevupRequestComponentStruct {}",v=Object.entries(R).map(([Q,z])=>{let w=k(z,2);return` ${i(Q)}: ${w}`}).join(`;
|
|
17
|
+
`),N=v.length>0?` interface DevupResponseComponentStruct {
|
|
18
|
+
${v};
|
|
19
|
+
}`:" interface DevupResponseComponentStruct {}",m=Object.entries(F).map(([Q,z])=>{let w=k(z,2);return` ${i(Q)}: ${w}`}).join(`;
|
|
20
|
+
`),n=m.length>0?` interface DevupErrorComponentStruct {
|
|
21
|
+
${m};
|
|
22
|
+
}`:" interface DevupErrorComponentStruct {}";return`import "@devup-api/fetch";
|
|
23
|
+
|
|
24
|
+
declare module "@devup-api/fetch" {
|
|
25
|
+
${G?`${G}
|
|
26
|
+
|
|
27
|
+
${g}
|
|
28
|
+
|
|
29
|
+
${N}
|
|
30
|
+
|
|
31
|
+
${n}`:`${g}
|
|
32
|
+
|
|
33
|
+
${N}
|
|
34
|
+
|
|
35
|
+
${n}`}
|
|
36
|
+
}`}export{M$ as generateInterface,Z$ as createUrlMap};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-interface-key-guard.d.ts","sourceRoot":"","sources":["../src/wrap-interface-key-guard.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKzD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devup-api/generator",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./dist/index.js",
|
|
8
|
+
"require": "./dist/index.cjs",
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc && bun build --target node --outfile=dist/index.js src/index.ts --production --packages=external && bun build --target node --outfile=dist/index.cjs --format=cjs src/index.ts --production --packages=external"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@devup-api/core": "0.1.0",
|
|
20
|
+
"@devup-api/utils": "0.1.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^24.10",
|
|
24
|
+
"typescript": "^5.9",
|
|
25
|
+
"openapi-types": "^12.1"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test'
|
|
2
|
+
import { convertCase } from '../convert-case'
|
|
3
|
+
|
|
4
|
+
test.each([
|
|
5
|
+
['hello_world', 'snake', 'hello_world'],
|
|
6
|
+
['my_variable_name', 'snake', 'my_variable_name'],
|
|
7
|
+
['snake_case_string', 'snake', 'snake_case_string'],
|
|
8
|
+
])('converts to snake_case: %s -> %s', (input, caseType, expected) => {
|
|
9
|
+
expect(convertCase(input, caseType as 'snake')).toBe(expected)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test.each([
|
|
13
|
+
['HelloWorld', 'snake', 'hello_world'],
|
|
14
|
+
['MyVariableName', 'snake', 'my_variable_name'],
|
|
15
|
+
['PascalCaseString', 'snake', 'pascal_case_string'],
|
|
16
|
+
])('converts PascalCase to snake_case: %s -> %s', (input, caseType, expected) => {
|
|
17
|
+
expect(convertCase(input, caseType as 'snake')).toBe(expected)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test.each([
|
|
21
|
+
['helloWorld', 'snake', 'hello_world'],
|
|
22
|
+
['myVariableName', 'snake', 'my_variable_name'],
|
|
23
|
+
['camelCaseString', 'snake', 'camel_case_string'],
|
|
24
|
+
])('converts camelCase to snake_case: %s -> %s', (input, caseType, expected) => {
|
|
25
|
+
expect(convertCase(input, caseType as 'snake')).toBe(expected)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test.each([
|
|
29
|
+
['hello_world', 'camel', 'helloWorld'],
|
|
30
|
+
['my_variable_name', 'camel', 'myVariableName'],
|
|
31
|
+
['snake_case_string', 'camel', 'snakeCaseString'],
|
|
32
|
+
])('converts to camelCase: %s -> %s', (input, caseType, expected) => {
|
|
33
|
+
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test.each([
|
|
37
|
+
['HelloWorld', 'camel', 'helloWorld'],
|
|
38
|
+
['MyVariableName', 'camel', 'myVariableName'],
|
|
39
|
+
['PascalCaseString', 'camel', 'pascalCaseString'],
|
|
40
|
+
])('converts PascalCase to camelCase: %s -> %s', (input, caseType, expected) => {
|
|
41
|
+
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test.each([
|
|
45
|
+
['helloWorld', 'camel', 'helloWorld'],
|
|
46
|
+
['myVariableName', 'camel', 'myVariableName'],
|
|
47
|
+
['camelCaseString', 'camel', 'camelCaseString'],
|
|
48
|
+
])('returns camelCase strings unchanged: %s -> %s', (input, caseType, expected) => {
|
|
49
|
+
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test.each([
|
|
53
|
+
['hello_world', 'pascal', 'HelloWorld'],
|
|
54
|
+
['my_variable_name', 'pascal', 'MyVariableName'],
|
|
55
|
+
['snake_case_string', 'pascal', 'SnakeCaseString'],
|
|
56
|
+
])('converts to PascalCase: %s -> %s', (input, caseType, expected) => {
|
|
57
|
+
expect(convertCase(input, caseType as 'pascal')).toBe(expected)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test.each([
|
|
61
|
+
['helloWorld', 'pascal', 'HelloWorld'],
|
|
62
|
+
['myVariableName', 'pascal', 'MyVariableName'],
|
|
63
|
+
['camelCaseString', 'pascal', 'CamelCaseString'],
|
|
64
|
+
])('converts camelCase to PascalCase: %s -> %s', (input, caseType, expected) => {
|
|
65
|
+
expect(convertCase(input, caseType as 'pascal')).toBe(expected)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test.each([
|
|
69
|
+
['HelloWorld', 'pascal', 'HelloWorld'],
|
|
70
|
+
['MyVariableName', 'pascal', 'MyVariableName'],
|
|
71
|
+
['PascalCaseString', 'pascal', 'PascalCaseString'],
|
|
72
|
+
])('returns PascalCase strings unchanged: %s -> %s', (input, caseType, expected) => {
|
|
73
|
+
expect(convertCase(input, caseType as 'pascal')).toBe(expected)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test.each([
|
|
77
|
+
['hello_world', 'maintain', 'hello_world'],
|
|
78
|
+
['myVariableName', 'maintain', 'myVariableName'],
|
|
79
|
+
['HelloWorld', 'maintain', 'HelloWorld'],
|
|
80
|
+
['any_string-here', 'maintain', 'any_string-here'],
|
|
81
|
+
])('maintains original case: %s -> %s', (input, caseType, expected) => {
|
|
82
|
+
expect(convertCase(input, caseType as 'maintain')).toBe(expected)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test.each([
|
|
86
|
+
['hello_world', undefined, 'helloWorld'],
|
|
87
|
+
['my_variable_name', undefined, 'myVariableName'],
|
|
88
|
+
['snake_case_string', undefined, 'snakeCaseString'],
|
|
89
|
+
])('defaults to camelCase when caseType is undefined: %s -> %s', (input, caseType, expected) => {
|
|
90
|
+
// biome-ignore lint/suspicious/noExplicitAny: Testing default behavior with undefined caseType
|
|
91
|
+
expect(convertCase(input, caseType as any)).toBe(expected)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test.each([
|
|
95
|
+
['hello_world', 'helloWorld'],
|
|
96
|
+
['my_variable_name', 'myVariableName'],
|
|
97
|
+
['snake_case_string', 'snakeCaseString'],
|
|
98
|
+
])('defaults to camelCase when caseType is not provided: %s -> %s', (input, expected) => {
|
|
99
|
+
expect(convertCase(input)).toBe(expected)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test.each([
|
|
103
|
+
['', 'camel', ''],
|
|
104
|
+
['a', 'camel', 'a'],
|
|
105
|
+
['A', 'camel', 'a'],
|
|
106
|
+
])('handles empty string and single characters: %s -> %s', (input, caseType, expected) => {
|
|
107
|
+
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test.each([
|
|
111
|
+
['hello_world123', 'camel', 'helloWorld123'],
|
|
112
|
+
['my_variable2_name', 'camel', 'myVariable2Name'],
|
|
113
|
+
['test123_case', 'camel', 'test123Case'],
|
|
114
|
+
])('handles strings with numbers: %s -> %s', (input, caseType, expected) => {
|
|
115
|
+
expect(convertCase(input, caseType as 'camel')).toBe(expected)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
test.each([
|
|
119
|
+
['hello_world', 'invalid', 'hello_world'],
|
|
120
|
+
['myVariableName', 'unknown', 'myVariableName'],
|
|
121
|
+
['HelloWorld', 'wrong', 'HelloWorld'],
|
|
122
|
+
])('default case returns original string for invalid caseType: %s -> %s', (input, caseType, expected) => {
|
|
123
|
+
// biome-ignore lint/suspicious/noExplicitAny: Testing default case with invalid caseType values
|
|
124
|
+
expect(convertCase(input, caseType as any)).toBe(expected)
|
|
125
|
+
})
|