Skip to content

refactor: remove typescript dependency from walker #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
886d35c
refactor: remove typescript dependency from walker
Himenon Apr 26, 2021
68a6fd3
feat: Define pure schema
Himenon Apr 26, 2021
bc619b2
feat: create to intermediate schema
Himenon Apr 26, 2021
71d4b1a
feat: add types
Himenon Apr 27, 2021
a3f0e62
Merge branch 'main' of https://github.com/Himenon/openapi-typescript-…
Himenon Apr 27, 2021
c8a7bb1
chore: rename
Himenon Apr 29, 2021
9bab4cb
chore: update
Himenon Apr 30, 2021
4c21ba8
chore: update
Himenon Apr 30, 2021
cb9d359
chore: update
Himenon Apr 30, 2021
549778b
chore: update
Himenon Apr 30, 2021
6d13b01
chore: update
Himenon Apr 30, 2021
581744b
chore: update
Himenon Apr 30, 2021
34489de
chore: update
Himenon Apr 30, 2021
e9de1f1
chore: update
Himenon May 2, 2021
8154a09
chore: update
Himenon May 2, 2021
32b544b
feat: update code template
Himenon May 2, 2021
615853c
chore: update
Himenon May 2, 2021
e81bcda
chore: add path to reference
Himenon May 4, 2021
925e4e2
Merge branch 'main' of https://github.com/Himenon/openapi-typescript-…
Himenon May 10, 2021
f022488
style: update prettier format
Himenon May 10, 2021
bf57029
fix: update
Himenon May 11, 2021
91c023b
fix: schema location
Himenon May 15, 2021
d7fc151
fix: reset
Himenon May 16, 2021
d598214
refactor: rename
Himenon May 16, 2021
d1f72ba
fix: logic
Himenon May 16, 2021
c400152
fix: code format
Himenon May 16, 2021
39d2e48
chore: add name
Himenon May 16, 2021
e6b6494
chore: update
Himenon May 16, 2021
7439726
chore: update
Himenon May 16, 2021
b97b49e
chore: update
Himenon May 16, 2021
1b1783e
chore: update
Himenon May 16, 2021
7f6a4fd
chore: update
Himenon May 16, 2021
baf2f92
chore: update
Himenon May 16, 2021
3dc6ffb
chore: update
Himenon May 16, 2021
cbece40
chore: update
Himenon May 16, 2021
90ea01f
chore: update
Himenon May 17, 2021
5f3b338
chore: update resolve reference
Himenon May 17, 2021
3b34325
chore: update reference resolver
Himenon May 22, 2021
517e683
chore: update
Himenon May 23, 2021
b60d795
feat: success generate remote schema
Himenon May 23, 2021
ab1964c
fix: name test
Himenon May 25, 2021
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
10 changes: 10 additions & 0 deletions .dependency-cruiser.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ module.exports = {
path: "^src/internal",
},
},
{
name: "Don't dependent on typescript from Walker",
severity: "error",
from: {
path: "^src/internal/OpenApiTools",
},
to: {
path: "typescript",
},
},
{
name: "not-to-test",
comment:
Expand Down
10 changes: 0 additions & 10 deletions .prettierrc.cjs

This file was deleted.

10 changes: 10 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"printWidth": 144,
"trailingComma": "all",
"tabWidth": 2,
"useTabs": false,
"arrowParens": "avoid",
"bracketSpacing": true,
"singleQuote": false,
"semi": true
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"scripts": {
"build": "yarn ts ./scripts/build.ts",
"clean": "yarn ts ./scripts/clean.ts",
"generate:test:code": "yarn build && yarn test:code:gen",
"format:code": "prettier \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md,html}\" --write",
"format:code:eslint": "eslint \"**/*.{ts,tsx}\" --fix",
"format:yarn:lock": "yarn-deduplicate yarn.lock --strategy highest",
Expand Down Expand Up @@ -73,7 +74,7 @@
"node-fetch": "2.6.1"
},
"dependencies": {
"@himenon/path-oriented-data-structure": "0.1.3",
"@himenon/path-oriented-data-structure": "0.2.1",
"@types/json-schema": "7.0.7",
"ajv": "8.0.5",
"dot-prop": "6.0.1",
Expand Down
68 changes: 51 additions & 17 deletions scripts/testCodeGen.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import * as fs from "fs";
import { posix as path } from "path";

import prettier from "prettier";

import { CodeGenerator } from "../lib";
import * as Templates from "../lib/templates";
import type * as Types from "../lib/types";

const prettierConfig = require("../.prettierrc.json");

const codeFormat = (code: string): string => {
try {
return prettier.format(code, {
...prettierConfig,
parser: "babel",
});
} catch (error) {
console.log("Failed code format");
return code;
}
};

const writeText = (filename: string, text: string): void => {
fs.mkdirSync(path.dirname(filename), { recursive: true });
fs.writeFileSync(filename, text, { encoding: "utf-8" });
fs.writeFileSync(filename, codeFormat(text), { encoding: "utf-8" });
console.log(`Generate Code : ${filename}`);
};

Expand Down Expand Up @@ -97,26 +113,44 @@ const generateParameter = (inputFilename: string, outputFilename: string) => {
writeText(outputFilename, JSON.stringify(codeGenerator.getCodeGeneratorParamsArray(), null, 2));
};

const main = () => {
const generateAdvancedTestCode = async (inputFilename: string, outputDir: string): Promise<void> => {
const codeGenerator = new CodeGenerator(inputFilename);

await codeGenerator.init();

const typeDefCode = codeGenerator.generateCode([
{
kind: "advanced",
generator: Templates.TypeDef.generator,
},
]);
writeText(path.join(outputDir, "types.ts"), typeDefCode);
};

const main = async () => {
generateTypedefCodeOnly("test/api.test.domain/index.yml", "test/code/typedef-only/api.test.domain.ts", true);
generateTypedefCodeOnly("test/infer.domain/index.yml", "test/code/typedef-only/infer.domain.ts", false);
await generateAdvancedTestCode("test/api.test.domain/index.yml", "test/code/advanced/api.test.domain.ts");
// generateTypedefCodeOnly("test/infer.domain/index.yml", "test/code/typedef-only/infer.domain.ts", false);

generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/api.test.domain.ts", true, { sync: false });
generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/sync-api.test.domain.ts", true, { sync: true });
generateTemplateCodeOnly("test/infer.domain/index.yml", "test/code/template-only/infer.domain.ts", false, { sync: true });
// generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/api.test.domain.ts", true, { sync: false });
// generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/sync-api.test.domain.ts", true, { sync: true });
// generateTemplateCodeOnly("test/infer.domain/index.yml", "test/code/template-only/infer.domain.ts", false, { sync: true });

generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/api.test.domain.ts", true, {
sync: false,
});
generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/sync-api.test.domain.ts", true, {
sync: true,
});
generateTypedefWithTemplateCode("test/infer.domain/index.yml", "test/code/typedef-with-template/infer.domain.ts", false, { sync: false });
// generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/api.test.domain.ts", true, {
// sync: false,
// });
// generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/sync-api.test.domain.ts", true, {
// sync: true,
// });
// generateTypedefWithTemplateCode("test/infer.domain/index.yml", "test/code/typedef-with-template/infer.domain.ts", false, { sync: false });

generateSplitCode("test/api.test.domain/index.yml", "test/code/split");
// generateSplitCode("test/api.test.domain/index.yml", "test/code/split");

generateParameter("test/api.test.domain/index.yml", "test/code/parameter/api.test.domain.json");
generateParameter("test/infer.domain/index.yml", "test/code/parameter/infer.domain.json");
// generateParameter("test/api.test.domain/index.yml", "test/code/parameter/api.test.domain.json");
// generateParameter("test/infer.domain/index.yml", "test/code/parameter/infer.domain.json");
};

main();
main().catch(error => {
console.error(error);
process.exit(1);
});
1 change: 1 addition & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * as OpenApiTools from "./internal/OpenApiTools";
export { FileSystem } from "./internal/FileSystem";
export * as ResolveReference from "./internal/ResolveReference";
export * as Validator from "./internal/Validator";
export * as Reference from "./reference-resolver";
Empty file.
14 changes: 14 additions & 0 deletions src/code-templates/typedef/components/ConvertToolKit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ts from "typescript";

import type { OpenApi } from "../../../types";
import { JsonSchemaToTypeDefinition } from "../../../utils";

export interface ConvertToolkit {
generateTypeNode: (schema: OpenApi.Schema | OpenApi.Reference | OpenApi.JSONSchemaDefinition) => ts.TypeNode;
}

const converter = new JsonSchemaToTypeDefinition.Converter();

export const ConvertToolkit: ConvertToolkit = {
generateTypeNode: converter.generateTypeNode.bind(converter),
};
19 changes: 19 additions & 0 deletions src/code-templates/typedef/components/Reference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ts from "typescript";

import { OpenApi } from "../../../types";
import type { InitializeParams } from "./types";

export interface Payload {
entryPoint: string;
currentPoint: string;
schemas: Record<string, OpenApi.Schema | OpenApi.Reference>;
}

export class Convert {
constructor(private readonly params: InitializeParams) {}
public generateTypeNode(schema: OpenApi.Reference): ts.TypeNode {

this.params.accessor.getChildByPaths("", "OpenApiSchema");
return this.params.toolkit.generateTypeNode(schema);
}
}
16 changes: 16 additions & 0 deletions src/code-templates/typedef/components/Schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ts from "typescript";

import { TsGenerator } from "../../../api";
import { OpenApi } from "../../../types";
import type { InitializeParams } from "./types";

export class Convert {
constructor(private readonly params: InitializeParams) {}
public generateStatement(name: string, schema: OpenApi.Schema | OpenApi.Reference | boolean): ts.Statement {
return TsGenerator.factory.TypeAliasDeclaration.create({
export: true,
name: name,
type: this.params.toolkit.generateTypeNode(schema),
});
}
}
36 changes: 36 additions & 0 deletions src/code-templates/typedef/components/Schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type ts from "typescript";

import { TsGenerator } from "../../../api";
import { AbstractStruct, OpenApi } from "../../../types";
import * as Schema from "./Schema";
import type { InitializeParams } from "./types";

export interface Payload {
entryPoint: string;
currentPoint: string;
schemas: Record<string, OpenApi.Schema | OpenApi.Reference>;
}

export class Convert {
private readonly schema = new Schema.Convert(this.params);
constructor(private readonly params: InitializeParams) {}
public generateNamespace(schemaLocations: { [currentPoint: string]: AbstractStruct.SchemaLocation }): ts.Statement {
const statements: ts.Statement[] = Object.values(schemaLocations).map((schemaLocation) => {
if (schemaLocation.kind === "common") {
return this.schema.generateStatement(schemaLocation.name, schemaLocation.schema);
} else {
const ref = schemaLocation.schema.$ref;
const resolvedSchema = this.params.resolver.getSchema(schemaLocation.currentPoint, ref);
if (!resolvedSchema) {
throw new Error(resolvedSchema);
}
return this.schema.generateStatement("名前を決める関数を入れる", resolvedSchema);
}
});
return TsGenerator.factory.Namespace.create({
export: true,
name: "Schemas",
statements: statements,
});
}
}
1 change: 1 addition & 0 deletions src/code-templates/typedef/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as Schemas from "./Schemas";
10 changes: 10 additions & 0 deletions src/code-templates/typedef/components/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { ParsedSchema } from "../../../types";
import type { ConvertToolkit } from "./ConvertToolKit";
import type { Resolver } from "../../../reference-resolver";

export interface InitializeParams {
readonly entryPoint: string;
readonly accessor: ParsedSchema.Accessor;
readonly toolkit: ConvertToolkit;
readonly resolver: Resolver;
}
36 changes: 36 additions & 0 deletions src/code-templates/typedef/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { AbstractStruct, CodeGenerator } from "../../types";
import * as Components from "./components";
import { ConvertToolkit } from "./components/ConvertToolKit";
import type { InitializeParams } from "./components/types";

export interface Option {}

export const generator: CodeGenerator.AdvancedGenerateFunction<Option> = (payload, option?: Option): CodeGenerator.IntermediateCode[] => {
const { accessor, entryPoint } = payload;
const schemaPaths = accessor.operator.getNodePaths("OpenApiSchema");

// TODO 短くする
const schemaLocations: { [currentPath: string]: AbstractStruct.SchemaLocation } = {};
schemaPaths.map(currentPoint => {
const item = accessor.getChildByPaths(currentPoint, "OpenApiSchema");
if (!item) {
return;
}
if (item.value.kind === "common") {
schemaLocations[currentPoint] = item.value;
} else if (item.value.kind === "remote-reference") {
schemaLocations[currentPoint] = item.value;
}
});
const initializeParams: InitializeParams = {
accessor: payload.accessor,
entryPoint: payload.entryPoint,
toolkit: ConvertToolkit,
resolver: payload.resolver,
};
const converter = {
schemas: new Components.Schemas.Convert(initializeParams),
};

return [converter.schemas.generateNamespace(schemaLocations)];
};
35 changes: 32 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@ export interface Option {
export class CodeGenerator {
private rootSchema: Types.OpenApi.Document;
private resolvedReferenceDocument: Types.OpenApi.Document;
private referenceResolver: Api.Reference.Resolver;
private parser: Api.OpenApiTools.Parser;
constructor(private readonly entryPoint: string, option?: Option) {
this.rootSchema = Api.FileSystem.loadJsonOrYaml(entryPoint);
this.resolvedReferenceDocument = Api.ResolveReference.resolve(entryPoint, entryPoint, JSON.parse(JSON.stringify(this.rootSchema)));
this.parser = this.createParser();
this.referenceResolver = new Api.Reference.Resolver(this.entryPoint, {
loadJsonOrYaml: Api.FileSystem.loadJsonOrYaml.bind(Api.FileSystem),
});
}

public async init(): Promise<void> {
await this.referenceResolver.init();
}

private createParser(): Api.OpenApiTools.Parser {
Expand Down Expand Up @@ -42,9 +50,22 @@ export class CodeGenerator {
const create = () => {
const statements = this.parser.getOpenApiTypeDefinitionStatements();
generatorTemplates?.forEach(generatorTemplate => {
const payload = this.parser.getCodeGeneratorParamsArray(allowOperationIds);
const extraStatements = Api.TsGenerator.Utils.convertIntermediateCodes(generatorTemplate.generator(payload, generatorTemplate.option));
statements.push(...extraStatements);
if (generatorTemplate.kind === "advanced") {
const extraStatements = Api.TsGenerator.Utils.convertIntermediateCodes(
generatorTemplate.generator(
{ accessor: this.parser.accessor, entryPoint: this.entryPoint, resolver: this.referenceResolver },
generatorTemplate.option,
),
);
statements.push(...extraStatements);
} else {
const payload = this.parser.getCodeGeneratorParamsArray(allowOperationIds);
generatorTemplate.generator;
const extraStatements = Api.TsGenerator.Utils.convertIntermediateCodes(
generatorTemplate.generator(payload, generatorTemplate.option),
);
statements.push(...extraStatements);
}
});
return statements;
};
Expand All @@ -62,6 +83,14 @@ export class CodeGenerator {
const create = () => {
return generatorTemplates
.map(generatorTemplate => {
if (generatorTemplate.kind === "advanced") {
return Api.TsGenerator.Utils.convertIntermediateCodes(
generatorTemplate?.generator(
{ accessor: this.parser.accessor, entryPoint: this.entryPoint, resolver: this.referenceResolver },
generatorTemplate.option,
),
);
}
return Api.TsGenerator.Utils.convertIntermediateCodes(generatorTemplate?.generator(payload, generatorTemplate.option));
})
.flat();
Expand Down
5 changes: 0 additions & 5 deletions src/internal/FileSystem/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ import * as yaml from "js-yaml";

import { UnSupportError } from "../Exception";

export interface Type {
existSync: (entrypoint: string) => boolean;
loadJsonOrYaml: (entryPoint: string) => any;
}

export class FileSystem {
private static FRAGMENT = "#/";
private static internalLoadJsonOrYaml(filename: string): any {
Expand Down
Loading