Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .eslintignore

This file was deleted.

25 changes: 0 additions & 25 deletions .eslintrc.json

This file was deleted.

47 changes: 47 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"$schema": "node_modules/oxlint/configuration_schema.json",
"plugins": ["eslint", "typescript", "unicorn", "import", "oxc", "promise", "vitest"],
"categories": {
"correctness": "error",
"perf": "error",
"pedantic": "off",
"style": "error",
"restriction": "off",
"suspicious": "error",
"nursery": "off"
},
"env": {
"builtin": true,
"node": true,
"shared-node-browser": true
},
"rules": {
"eslint/*": "error",
"eslint/no-await-in-loop": "off",
"eslint/sort-keys": "off",
"eslint/sort-imports": "off",
"eslint/no-ternary": "off",
"eslint/no-magic-numbers": "off",
"eslint/eqeqeq": [
"error",
"always",
{
"null": "ignore"
}
],
"import/*": "error",
"import/no-unassigned-import": "off",
"import/no-named-export": "off",
"import/group-exports": "off",
"import/exports-last": "off",
"import/prefer-default-export": "off",
"import/consistent-type-specifier-style": "off",
"typescript/*": "error",
"unicorn/*": "error",
"oxc/*": "error",
"oxc/no-map-spread": "off",
"oxc/no-accumulating-spread": "off",
"promise/*": "error",
"vitest/*": "error"
}
}
9 changes: 2 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"build": "yarn build:clean && yarn build:types && node ./esbuild.mjs && chmod +x ./dist/sh.js",
"start:dist": "node ./dist/sh.js",
"typecheck": "tsc --noEmit",
"lint": "eslint ./src",
"lint": "oxlint ./src --deny-warnings",
"check": "yarn typecheck && yarn lint && yarn test",
"push": "yarn exec ./scripts/publish.sh",
"dev:generate": "rm -rf ./output && yarn start generate --config ./test/config.ts",
Expand Down Expand Up @@ -87,17 +87,12 @@
"@types/prompt-sync": "^4.2.3",
"@types/react": "^19.1.0",
"@types/yargs": "^17.0.32",
"@typescript-eslint/eslint-plugin": "^8.40.0",
"@typescript-eslint/parser": "^8.40.0",
"axios": "^1.13.1",
"chalk": "^5.3.0",
"esbuild": "^0.21.3",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-no-relative-import-paths": "^1.6.1",
"eslint-plugin-prettier": "^5.1.3",
"handlebars": "^4.7.8",
"openapi-types": "^12.1.3",
"oxlint": "^1.41.0",
"prettier": "^3.2.5",
"prompt-sync": "^4.2.0",
"react": "^19.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type CheckParams = {
verbose?: boolean;
} & Partial<Pick<GenerateOptions, "input" | "splitByTags" | "defaultTag">>;

export async function check({ verbose, config: configParam, excludeTags: excludeTagsParam, ...params }: CheckParams) {
export async function check({ verbose, config: configParam, excludeTags: _excludeTagsParam, ...params }: CheckParams) {
const start = Date.now();

if (verbose) {
Expand Down
13 changes: 6 additions & 7 deletions src/generators/core/SchemaResolver.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export class SchemaResolver {
getExtractedEnumZodSchemaNamesReferencedBySchemaRef(schemaRef: string) {
return this.extractedEnumZodSchemaData.reduce((acc, { zodSchemaName, meta }) => {
if (zodSchemaName && meta.schemaRefs.includes(schemaRef)) {
acc.push(zodSchemaName);
return [...acc, zodSchemaName];
}
return acc;
}, [] as string[]);
Expand Down Expand Up @@ -244,11 +244,10 @@ export class SchemaResolver {
return [...chain, currentRef, ref];
}
return Array.from(this.dependencyGraph.refsDependencyGraph[currentRef]?.values() ?? [])
.map((childRef) => {
.flatMap((childRef) => {
const childChain = this.getCircularSchemaChain(ref, childRef, chain, visited);
return childChain.length > 0 ? [currentRef, ...childChain] : childChain;
})
.flat();
});
}

getBaseUrl() {
Expand Down Expand Up @@ -417,8 +416,8 @@ export class SchemaResolver {
}

private handleDuplicateEnumZodSchemas() {
const codes = this.enumZodSchemas.map(({ code }) => code);
const duplicates = this.enumZodSchemas.filter(({ code }) => codes.includes(code));
const codes = new Set(this.enumZodSchemas.map(({ code }) => code));
const duplicates = this.enumZodSchemas.filter(({ code }) => codes.has(code));

this.schemaData.forEach((schemaData) => {
const duplicateCode = duplicates.find(({ zodSchemaName }) => zodSchemaName === schemaData.zodSchemaName)?.code;
Expand Down Expand Up @@ -449,7 +448,7 @@ export class SchemaResolver {
this.extractedEnumZodSchemaData.splice(
0,
this.extractedEnumZodSchemaData.length,
...this.extractedEnumZodSchemaData.filter(({ code }) => !codes.includes(code)),
...this.extractedEnumZodSchemaData.filter(({ code }) => !codes.has(code)),
);
}
}
8 changes: 5 additions & 3 deletions src/generators/core/getMetadataFromOpenAPIDoc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import { DEFAULT_GENERATE_OPTIONS } from "src/generators/const/options.const";
import { ModelMetadata, QueryMetadata, TsType } from "src/generators/types/metadata";
import { getMetadataFromOpenAPIDoc } from "./getMetadataFromOpenAPIDoc";

describe("getMetadataFromOpenAPIDoc", async () => {
const openApiDoc = (await SwaggerParser.bundle("./test/petstore.yaml")) as OpenAPIV3.Document;

describe("getMetadataFromOpenAPIDoc", () => {
const Category: TsType = {
type: "Category",
namespace: "PetModels",
Expand Down Expand Up @@ -404,6 +402,8 @@ describe("getMetadataFromOpenAPIDoc", async () => {
];

test("getMetadataFromOpenAPIDoc", async () => {
const openApiDoc = (await SwaggerParser.bundle("./test/petstore.yaml")) as OpenAPIV3.Document;

const metadata = await getMetadataFromOpenAPIDoc(openApiDoc, {
...DEFAULT_GENERATE_OPTIONS,
excludeRedundantZodSchemas: false,
Expand All @@ -414,6 +414,8 @@ describe("getMetadataFromOpenAPIDoc", async () => {
});

test("getMetadataFromOpenAPIDoc", async () => {
const openApiDoc = (await SwaggerParser.bundle("./test/petstore.yaml")) as OpenAPIV3.Document;

const extractEnums = false;
const metadata = await getMetadataFromOpenAPIDoc(openApiDoc, {
...DEFAULT_GENERATE_OPTIONS,
Expand Down
4 changes: 2 additions & 2 deletions src/generators/core/getMetadataFromOpenAPIDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ function getQueryMetadataParams({
paramType: param.type,
} as QueryMetadata["params"][0] & { paramType: EndpointParameter["type"] };
})
.sort((a, b) => {
.toSorted((a, b) => {
if (a.isRequired === b.isRequired) {
const sortedParamTypes = ["Path", "Body", "Query", "Header"];
return sortedParamTypes.indexOf(a.paramType) - sortedParamTypes.indexOf(b.paramType);
}
return a.isRequired ? -1 : 1;
})
.map(({ paramType, ...queryParam }) => queryParam);
.map(({ paramType: _paramType, ...queryParam }) => queryParam);
}

function getQueryMetadataResponse({
Expand Down
2 changes: 1 addition & 1 deletion src/generators/generate/generateQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function generateQueries({ resolver, data, tag }: GenerateTypeParams) {

const hasMutationEffectsImport = hasMutationEffects && mutationEndpoints.length > 0;
const mutationEffectsImport: Import = {
bindings: [...(mutationEndpoints.length > 0 ? [MUTATION_EFFECTS.optionsType, MUTATION_EFFECTS.hookName] : [])],
bindings: mutationEndpoints.length > 0 ? [MUTATION_EFFECTS.optionsType, MUTATION_EFFECTS.hookName] : [],
from: getMutationEffectsImportPath(resolver.options),
};

Expand Down
2 changes: 1 addition & 1 deletion src/generators/utils/generate/generate.configs.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function resolveBuilderConfigNames(endpoints: ExtendedEndpoint[]): Record<string
...endpoint,
namePathSegments: endpoint.pathSegments.filter((segment) => !isPathSegmentParam(segment)),
}))
.sort((a, b) => a.namePathSegments.length - b.namePathSegments.length);
.toSorted((a, b) => a.namePathSegments.length - b.namePathSegments.length);

const namedEndpoints: Record<string, ExtendedEndpoint> = {};
for (const endpoint of sortedEndpoints) {
Expand Down
2 changes: 1 addition & 1 deletion src/generators/utils/generate/generate.endpoints.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function mapEndpointParamsToFunctionParams(
}

return params
.sort((a, b) => {
.toSorted((a, b) => {
if (a.required === b.required) {
const sortedParamTypes = ["Path", "Body", "Query", "Header"];
return sortedParamTypes.indexOf(a.paramType) - sortedParamTypes.indexOf(b.paramType);
Expand Down
2 changes: 1 addition & 1 deletion src/generators/utils/generate/generate.openapi.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function getSchemaDescriptions(schemaObj: OpenAPIV3.SchemaObject) {
];

const schemaDescriptions = schemaKeys
.filter((key) => schemaObj[key])
.filter((key) => schemaObj[key] !== undefined)
.reduce((acc, key) => [...acc, `${capitalize(camelToSpaceSeparated(key))}: \`${schemaObj[key]}\``], [] as string[]);

return schemaDescriptions;
Expand Down
4 changes: 2 additions & 2 deletions src/generators/utils/hbs/hbs.partials.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ function registerGenerateCaslAbilityQueryHelper() {
function registerGenerateAclCheckCallHelper() {
Handlebars.registerHelper(PartialsHelpers.AclCheckCall, (endpoint: Endpoint) => {
const checkParams = getAbilityConditionsTypes(endpoint)?.map((condition) => condition.name);
const params = endpoint.parameters.map((param) => param.name);
const hasAllCheckParams = checkParams?.every((param) => params.includes(param));
const params = new Set(endpoint.parameters.map((param) => param.name));
const hasAllCheckParams = checkParams?.every((param) => params.has(param));

return getHbsPartialTemplateDelegate("acl-check-call")({
endpoint,
Expand Down
2 changes: 1 addition & 1 deletion src/generators/utils/openapi.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function pathToVariableName(path: string) {

const pathParams = [...path.matchAll(PATH_PARAM_WITH_BRACKETS_REGEX)];
if (pathParams.length > 0) {
const lastPathParam = pathParams.sort((a, b) => a.index - b.index)[pathParams.length - 1][0];
const lastPathParam = pathParams.toSorted((a, b) => a.index - b.index)[pathParams.length - 1][0];
path = `${path.replace(PATH_PARAM_WITH_BRACKETS_REGEX, "")}By${capitalize(lastPathParam.slice(1, -1))}`; // MediaObjects{id} => MediaObjectsById
}

Expand Down
2 changes: 1 addition & 1 deletion src/generators/utils/sort.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function sortObjKeysFromArray<T extends ObjectLiteral>(obj: T, orderedKey

const sortedEntries = entries
.filter(([key]) => orderedKeys.includes(key))
.sort(([a], [b]) => orderedKeys.indexOf(a) - orderedKeys.indexOf(b))
.toSorted(([a], [b]) => orderedKeys.indexOf(a) - orderedKeys.indexOf(b))
.concat(entries.filter(([key]) => !orderedKeys.includes(key)));
return Object.fromEntries(sortedEntries);
}
8 changes: 2 additions & 6 deletions src/generators/utils/string.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const removeSuffix = (text: string, suffix: string) => text.replace(new R

export const getLongestMostCommon = (strs: string[]): string | undefined => {
const counter = strs.reduce((acc, str) => ({ ...acc, [str]: (acc[str] ?? 0) + 1 }), {} as Record<string, number>);
const sortedEntries = Object.entries(counter).sort((a, b) => {
const sortedEntries = Object.entries(counter).toSorted((a, b) => {
if (a[1] === b[1]) {
return b[0].length - a[0].length;
}
Expand All @@ -25,11 +25,7 @@ export const getLongestMostCommon = (strs: string[]): string | undefined => {
};

export const getMostCommonAdjacentCombinationSplit = (strs: string[]): string | undefined => {
const splits = strs
.map(capitalize)
.map(splitByUppercase)
.map((split) => getAdjacentStringCombinations(split))
.flat();
const splits = strs.flatMap((str) => getAdjacentStringCombinations(splitByUppercase(capitalize(str))));
return getLongestMostCommon(splits);
};

Expand Down
4 changes: 2 additions & 2 deletions src/generators/utils/ts.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ export function getSchemaTsMetaType({
return {
metaType: "object",
objectProperties: (metaTypes as TsObjectMetaType[]).reduce((acc, { objectProperties }) => {
const objectPropertyNames = objectProperties.map(({ name }) => name);
return [...acc.filter(({ name }) => !objectPropertyNames.includes(name)), ...objectProperties];
const objectPropertyNames = new Set(objectProperties.map(({ name }) => name));
return [...acc.filter(({ name }) => !objectPropertyNames.has(name)), ...objectProperties];
}, [] as TsProperty[]),
};
} else {
Expand Down
5 changes: 2 additions & 3 deletions src/helpers/config.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,12 @@ async function loadTsConfig(filePath: string): Promise<OpenAPICodegenConfig> {
const transpiledFilepath = `${filePath.slice(0, -2)}cjs`;
try {
const tsConfig = resolveTsConfig(path.dirname(filePath)) ?? {};
tsConfig.compilerOptions = {
...tsConfig.compilerOptions,
tsConfig.compilerOptions = Object.assign({}, tsConfig.compilerOptions, {
module: typescript.ModuleKind.NodeNext,
moduleResolution: typescript.ModuleResolutionKind.NodeNext,
target: typescript.ScriptTarget.ES2022,
noEmit: false,
};
});

const fileContent = fs.readFileSync(filePath, "utf-8");

Expand Down
2 changes: 1 addition & 1 deletion src/helpers/yargs.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function YargOption(properties: IOptionProperties) {
return (target: object, propertyKey: string) => {
if (properties !== undefined && properties !== null) {
const newMetadata = {
...(Reflect.getMetadata(optionsKey, target) || {}),
...Reflect.getMetadata(optionsKey, target),
[propertyKey]: {
...properties,
describe: properties.envAlias ? `${properties.describe || ""} [${properties.envAlias}]` : properties.describe,
Expand Down
10 changes: 5 additions & 5 deletions src/lib/rest/error-handling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios from "axios";
import { isAxiosError, isCancel } from "axios";
import { z } from "zod";

import { RestUtils } from "./rest.utils";
Expand Down Expand Up @@ -56,7 +56,7 @@ export class ErrorHandler<CodeT extends string> {
const internalError: ErrorEntry<ICodeT> = {
code: "INTERNAL_ERROR",
condition: (e) => {
if (axios.isAxiosError(e)) {
if (isAxiosError(e)) {
return e.response?.status != null && e.response.status >= 500 && e.response.status < 600;
}

Expand All @@ -68,7 +68,7 @@ export class ErrorHandler<CodeT extends string> {
const networkError: ErrorEntry<ICodeT> = {
code: "NETWORK_ERROR",
condition: (e) => {
if (axios.isAxiosError(e)) {
if (isAxiosError(e)) {
return e.code === "ERR_NETWORK";
}

Expand All @@ -80,11 +80,11 @@ export class ErrorHandler<CodeT extends string> {
const canceledError: ErrorEntry<ICodeT> = {
code: "CANCELED_ERROR",
condition: (e) => {
if (axios.isCancel(e)) {
if (isCancel(e)) {
return true;
}

if (axios.isAxiosError(e) && e.code === "ECONNABORTED") {
if (isAxiosError(e) && e.code === "ECONNABORTED") {
return true;
}

Expand Down
7 changes: 4 additions & 3 deletions src/lib/rest/rest.utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import axios, { AxiosError, AxiosResponseHeaders } from "axios";
import { AxiosError, AxiosResponseHeaders } from "axios";
import { z } from "zod";
import { isAxiosError } from "axios";

export namespace RestUtils {
export const extractServerResponseCode = (e: unknown): string | null => {
if (e instanceof z.ZodError) {
return "validation-exception";
}

if (!axios.isAxiosError(e)) {
if (!isAxiosError(e)) {
return null;
}

Expand Down Expand Up @@ -38,7 +39,7 @@ export namespace RestUtils {
return e.message;
}

if (!axios.isAxiosError(e)) {
if (!isAxiosError(e)) {
return null;
}

Expand Down
5 changes: 0 additions & 5 deletions tsconfig.eslint.json

This file was deleted.

Loading