diff --git a/package.json b/package.json index fc174c85..77d79952 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "node-fetch": "2.6.1" }, "dependencies": { + "@himenon/path-oriented-data-structure": "0.1.0", "@types/json-schema": "7.0.6", "ajv": "7.0.3", "dot-prop": "6.0.1", diff --git a/src/Converter/v3/Context.ts b/src/Converter/v3/Context.ts index 24a8a8dc..57fc8903 100644 --- a/src/Converter/v3/Context.ts +++ b/src/Converter/v3/Context.ts @@ -88,7 +88,7 @@ export const create = (entryPoint: string, store: Store.Type, factory: TypeScrip }); if (ts.isTypeLiteralNode(typeNode)) { store.addStatement(reference.path, { - type: "interface", + kind: "interface", name: reference.name, value: factory.InterfaceDeclaration.create({ export: true, @@ -107,7 +107,7 @@ export const create = (entryPoint: string, store: Store.Type, factory: TypeScrip }); store.addStatement(reference.path, { name: reference.name, - type: "typeAlias", + kind: "typeAlias", value, }); } @@ -123,7 +123,7 @@ export const create = (entryPoint: string, store: Store.Type, factory: TypeScrip }); store.addStatement(reference.path, { name: reference.name, - type: "typeAlias", + kind: "typeAlias", value, }); } diff --git a/src/Converter/v3/components/Headers.ts b/src/Converter/v3/components/Headers.ts index e36b8ab9..a69aa253 100644 --- a/src/Converter/v3/components/Headers.ts +++ b/src/Converter/v3/components/Headers.ts @@ -18,15 +18,9 @@ export const generateNamespace = ( context: ToTypeNode.Context, ): void => { store.addComponent("headers", { - type: "namespace", + kind: "namespace", name: Name.Components.Headers, - value: factory.Namespace.create({ - export: true, - name: Name.Components.Headers, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject`, }); Object.entries(headers).forEach(([name, header]) => { if (Guard.isReference(header)) { @@ -40,7 +34,7 @@ export const generateNamespace = ( } } else { store.addStatement(`components/headers/${name}`, { - type: "typeAlias", + kind: "typeAlias", name: name, value: Header.generateTypeNode(entryPoint, currentPoint, factory, name, header, context), }); diff --git a/src/Converter/v3/components/Operation.ts b/src/Converter/v3/components/Operation.ts index 039e655f..80542a4a 100644 --- a/src/Converter/v3/components/Operation.ts +++ b/src/Converter/v3/components/Operation.ts @@ -47,22 +47,16 @@ export const generateNamespace = ( throw new Error("not setting operationId\n" + JSON.stringify(operation)); } store.addStatement(basePath, { - type: "namespace", + kind: "namespace", name, - value: factory.Namespace.create({ - export: true, - name, - comment: ExternalDocumentation.addComment(Servers.addComment([generateComment(operation)], operation.servers), operation.externalDocs), - deprecated: operation.deprecated, - statements: [], - }), - statements: {}, + comment: ExternalDocumentation.addComment(Servers.addComment([generateComment(operation)], operation.servers), operation.externalDocs), + deprecated: operation.deprecated, }); if (operation.parameters) { const parameterName = "Parameter"; store.addStatement(`${basePath}/Parameter`, { - type: "interface", + kind: "interface", name: parameterName, value: Parameter.generateInterface(entryPoint, currentPoint, factory, parameterName, operation.parameters, context), }); @@ -79,13 +73,13 @@ export const generateNamespace = ( const contentPath = path.join(reference.path, "Content"); // requestBodyはNamespaceを形成するため const name = "Content"; store.addStatement(contentPath, { - type: "interface", + kind: "interface", name: name, value: RequestBody.generateInterface(entryPoint, reference.referencePoint, factory, name, reference.data, context), }); const typeAliasName = context.resolveReferencePath(currentPoint, contentPath).name; store.addStatement(`${basePath}/RequestBody`, { - type: "typeAlias", + kind: "typeAlias", name: typeAliasName, value: factory.TypeAliasDeclaration.create({ export: true, @@ -143,7 +137,7 @@ export const generateStatements = ( const contentPath = path.join(reference.path, "Content"); // requestBodyはNamespaceを形成するため const name = "Content"; store.addStatement(contentPath, { - type: "interface", + kind: "interface", name: name, value: RequestBody.generateInterface(entryPoint, reference.referencePoint, factory, name, reference.data, context), }); diff --git a/src/Converter/v3/components/Parameters.ts b/src/Converter/v3/components/Parameters.ts index 5e1e4bbf..8b624c99 100644 --- a/src/Converter/v3/components/Parameters.ts +++ b/src/Converter/v3/components/Parameters.ts @@ -19,15 +19,9 @@ export const generateNamespace = ( ): void => { const basePath = "components/parameters"; store.addComponent("parameters", { - type: "namespace", + kind: "namespace", name: Name.Components.Parameters, - value: factory.Namespace.create({ - export: true, - name: Name.Components.Parameters, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#parameterObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#parameterObject`, }); Object.entries(parameters).forEach(([name, parameter]) => { @@ -41,7 +35,7 @@ export const generateNamespace = ( } Schema.addSchema(entryPoint, currentPoint, store, factory, reference.path, reference.name, reference.data.schema, context); store.addStatement(`${basePath}/${name}`, { - type: "typeAlias", + kind: "typeAlias", name: name, value: factory.TypeAliasDeclaration.create({ export: true, @@ -55,7 +49,7 @@ export const generateNamespace = ( } else { const path = `${basePath}/${name}`; store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name: name, value: Paramter.generateTypeAlias(entryPoint, currentPoint, factory, name, parameter, context), }); @@ -72,15 +66,9 @@ export const generateNamespaceWithList = ( context: ToTypeNode.Context, ): void => { store.addComponent("parameters", { - type: "namespace", + kind: "namespace", name: Name.Components.Parameters, - value: factory.Namespace.create({ - export: true, - name: Name.Components.Parameters, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#parameterObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#parameterObject`, }); parameters.forEach(parameter => { @@ -91,14 +79,14 @@ export const generateNamespaceWithList = ( } const path = `components/parameters/${reference.name}`; return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name: reference.name, value: Paramter.generateTypeAlias(entryPoint, reference.referencePoint, factory, reference.name, reference.data, context), }); } const path = `components/parameters/${parameter.name}`; return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name: parameter.name, value: Paramter.generateTypeAlias(entryPoint, currentPoint, factory, parameter.name, parameter, context), }); diff --git a/src/Converter/v3/components/PathItem.ts b/src/Converter/v3/components/PathItem.ts index 3aa9c5ed..42d138e8 100644 --- a/src/Converter/v3/components/PathItem.ts +++ b/src/Converter/v3/components/PathItem.ts @@ -22,15 +22,9 @@ export const generateNamespace = ( const basePath = `${parentPath}/${name}`; const topComment = options && options.topComment && options.topComment; store.addStatement(basePath, { - type: "namespace", + kind: "namespace", name, - value: factory.Namespace.create({ - export: true, - name, - statements: [], - comment: Servers.addComment([topComment, pathItem.description], pathItem.servers), - }), - statements: {}, + comment: Servers.addComment([topComment, pathItem.description], pathItem.servers), }); if (pathItem.get) { Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "GET", pathItem.get, context); diff --git a/src/Converter/v3/components/PathItems.ts b/src/Converter/v3/components/PathItems.ts index b98924b4..64984b79 100644 --- a/src/Converter/v3/components/PathItems.ts +++ b/src/Converter/v3/components/PathItems.ts @@ -20,15 +20,9 @@ export const generateNamespace = ( const basePath = "components/pathItems"; store.addComponent("pathItems", { - type: "namespace", + kind: "namespace", name: Name.Components.PathItems, - value: factory.Namespace.create({ - export: true, - name: Name.Components.PathItems, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject`, }); Object.entries(pathItems).forEach(([key, pathItem]) => { diff --git a/src/Converter/v3/components/RequestBodies.ts b/src/Converter/v3/components/RequestBodies.ts index bff069e9..9b68d5ea 100644 --- a/src/Converter/v3/components/RequestBodies.ts +++ b/src/Converter/v3/components/RequestBodies.ts @@ -19,15 +19,9 @@ export const generateNamespace = ( ): void => { const basePath = "components/requestBodies"; store.addComponent("requestBodies", { - type: "namespace", + kind: "namespace", name: Name.Components.RequestBodies, - value: factory.Namespace.create({ - export: true, - name: Name.Components.RequestBodies, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject`, }); Object.entries(requestBodies).forEach(([name, requestBody]) => { diff --git a/src/Converter/v3/components/RequestBody.ts b/src/Converter/v3/components/RequestBody.ts index 33811a24..ddb22a49 100644 --- a/src/Converter/v3/components/RequestBody.ts +++ b/src/Converter/v3/components/RequestBody.ts @@ -35,14 +35,13 @@ export const generateNamespace = ( ): void => { const basePath = `${parentName}/${name}`; store.addStatement(basePath, { - type: "namespace", + kind: "namespace", name, - value: factory.Namespace.create({ - export: true, - name, - comment: requestBody.description, - statements: [generateInterface(entryPoint, currentPoint, factory, "Content", requestBody, context)], - }), - statements: {}, + comment: requestBody.description, + }); + store.addStatement(`${basePath}/Content`, { + kind: "interface", + name: "Content", + value: generateInterface(entryPoint, currentPoint, factory, "Content", requestBody, context), }); }; diff --git a/src/Converter/v3/components/Response.ts b/src/Converter/v3/components/Response.ts index 99d3132b..07f87882 100644 --- a/src/Converter/v3/components/Response.ts +++ b/src/Converter/v3/components/Response.ts @@ -2,7 +2,7 @@ import * as path from "path"; import { Factory } from "../../../CodeGenerator"; import * as Name from "../Name"; -import { Def, State, Store } from "../store"; +import { Store } from "../store"; import * as ToTypeNode from "../toTypeNode"; import { OpenApi } from "../types"; import * as Header from "./Header"; @@ -20,20 +20,14 @@ export const generateNamespace = ( ): void => { const basePath = `${parentPath}/${name}`; store.addStatement(basePath, { - type: "namespace", + kind: "namespace", name, - value: factory.Namespace.create({ - export: true, - name: name, - comment: response.description, - statements: [], - }), - statements: {}, + comment: response.description, }); if (response.headers) { store.addStatement(`${basePath}/Header`, { - type: "interface", + kind: "interface", name: Name.ComponentChild.Header, value: Header.generateInterface(entryPoint, currentPoint, factory, Name.ComponentChild.Header, response.headers, context), }); @@ -41,7 +35,7 @@ export const generateNamespace = ( if (response.content) { store.addStatement(`${basePath}/Content`, { - type: "interface", + kind: "interface", name: Name.ComponentChild.Content, value: MediaType.generateInterface(entryPoint, currentPoint, factory, Name.ComponentChild.Content, response.content, context), }); @@ -61,42 +55,27 @@ export const generateReferenceNamespace = ( const basePath = `${parentPath}/${nameWithStatusCode}`; const referenceNamespaceName = context.resolveReferencePath(currentPoint, responseReference.path).name; store.addStatement(basePath, { - type: "namespace", + kind: "namespace", name: nameWithStatusCode, - value: factory.Namespace.create({ - export: true, - name: nameWithStatusCode, - statements: [], - }), - statements: {}, }); - // TODO Type Guard - const headerNamespace = store.getStatement(path.join(responseReference.path, "Header"), "namespace") as - | Def.NamespaceStatement - | undefined; + const headerNamespace = store.getStatement(path.join(responseReference.path, "Header"), "namespace"); if (headerNamespace) { store.addStatement(`${basePath}/Header`, { - type: "namespace", + kind: "namespace", name: Name.ComponentChild.Header, - value: factory.Namespace.create({ - export: true, - name: Name.ComponentChild.Header, - statements: [], - }), - statements: {}, }); - Object.values(headerNamespace.statements).forEach(statement => { + Object.values(headerNamespace.getChildren()).forEach(statement => { if (!statement) { return; } - if (statement.type === "interface" || statement.type === "typeAlias") { + if (statement.kind === "interface" || statement.kind === "typeAlias") { const aliasName = [referenceNamespaceName, Name.ComponentChild.Header, statement.name].join("."); - store.addStatement(`${basePath}/Header/${statement.value.name.text}`, { - type: "typeAlias", + store.addStatement(`${basePath}/Header/${statement.name}`, { + kind: "typeAlias", name: aliasName, value: factory.TypeAliasDeclaration.create({ export: true, - name: statement.value.name.text, + name: statement.name, type: factory.TypeReferenceNode.create({ name: aliasName, }), @@ -106,7 +85,7 @@ export const generateReferenceNamespace = ( }); } store.addStatement(`${basePath}/Content`, { - type: "typeAlias", + kind: "typeAlias", name: Name.ComponentChild.Content, value: factory.TypeAliasDeclaration.create({ export: true, diff --git a/src/Converter/v3/components/Responses.ts b/src/Converter/v3/components/Responses.ts index 773dfded..4b014aa9 100644 --- a/src/Converter/v3/components/Responses.ts +++ b/src/Converter/v3/components/Responses.ts @@ -23,15 +23,9 @@ export const generateNamespace = ( ): void => { const basePath = "components/responses"; store.addComponent("responses", { - type: "namespace", + kind: "namespace", name: Name.Components.Responses, - value: factory.Namespace.create({ - export: true, - name: Name.Components.Responses, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject`, }); Object.entries(responses).forEach(([name, response]) => { if (Guard.isReference(response)) { @@ -69,15 +63,9 @@ export const generateNamespaceWithStatusCode = ( ): void => { const basePath = `${parentPath}/responses`; store.addStatement(basePath, { - type: "namespace", + kind: "namespace", name: Name.ComponentChild.Response, - value: factory.Namespace.create({ - export: true, - name: Name.ComponentChild.Response, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject`, }); Object.entries(responses).forEach(([statusCode, response]) => { diff --git a/src/Converter/v3/components/Schema.ts b/src/Converter/v3/components/Schema.ts index da221013..0d64e56f 100644 --- a/src/Converter/v3/components/Schema.ts +++ b/src/Converter/v3/components/Schema.ts @@ -145,37 +145,37 @@ export const addSchema = ( } if (Guard.isAllOfSchema(schema)) { store.addStatement(targetPoint, { - type: "typeAlias", + kind: "typeAlias", name: declarationName, value: generateMultiTypeAlias(entryPoint, currentPoint, factory, declarationName, schema.allOf, context, "allOf"), }); } else if (Guard.isOneOfSchema(schema)) { store.addStatement(targetPoint, { - type: "typeAlias", + kind: "typeAlias", name: declarationName, value: generateMultiTypeAlias(entryPoint, currentPoint, factory, declarationName, schema.oneOf, context, "oneOf"), }); } else if (Guard.isAnyOfSchema(schema)) { store.addStatement(targetPoint, { - type: "typeAlias", + kind: "typeAlias", name: declarationName, value: generateMultiTypeAlias(entryPoint, currentPoint, factory, declarationName, schema.anyOf, context, "allOf"), }); } else if (Guard.isArraySchema(schema)) { store.addStatement(targetPoint, { - type: "typeAlias", + kind: "typeAlias", name: declarationName, value: generateArrayTypeAlias(entryPoint, currentPoint, factory, declarationName, schema, context), }); } else if (Guard.isObjectSchema(schema)) { store.addStatement(targetPoint, { - type: "interface", + kind: "interface", name: declarationName, value: generateInterface(entryPoint, currentPoint, factory, declarationName, schema, context), }); } else if (Guard.isPrimitiveSchema(schema)) { store.addStatement(targetPoint, { - type: "typeAlias", + kind: "typeAlias", name: declarationName, value: generateTypeAlias(entryPoint, currentPoint, factory, declarationName, schema), }); diff --git a/src/Converter/v3/components/Schemas.ts b/src/Converter/v3/components/Schemas.ts index fba3e4d8..b67c8ca5 100644 --- a/src/Converter/v3/components/Schemas.ts +++ b/src/Converter/v3/components/Schemas.ts @@ -18,15 +18,9 @@ export const generateNamespace = ( ): void => { const basePath = "components/schemas"; store.addComponent("schemas", { - type: "namespace", + kind: "namespace", name: Name.Components.Schemas, - value: factory.Namespace.create({ - export: true, - name: Name.Components.Schemas, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject`, }); Object.entries(schemas).forEach(([name, schema]) => { if (Guard.isReference(schema)) { @@ -34,7 +28,7 @@ export const generateNamespace = ( if (reference.type === "local") { const { maybeResolvedName } = context.resolveReferencePath(currentPoint, reference.path); store.addStatement(`${basePath}/${name}`, { - type: "typeAlias", + kind: "typeAlias", name: name, value: factory.TypeAliasDeclaration.create({ export: true, @@ -51,7 +45,7 @@ export const generateNamespace = ( return; } return store.addStatement(`${basePath}/${name}`, { - type: "typeAlias", + kind: "typeAlias", name, value: factory.TypeAliasDeclaration.create({ export: true, @@ -66,49 +60,49 @@ export const generateNamespace = ( const path = `${basePath}/${name}`; if (Guard.isAllOfSchema(schema)) { return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name, value: Schema.generateMultiTypeAlias(entryPoint, currentPoint, factory, name, schema.allOf, context, "allOf"), }); } if (Guard.isOneOfSchema(schema)) { return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name, value: Schema.generateMultiTypeAlias(entryPoint, currentPoint, factory, name, schema.oneOf, context, "oneOf"), }); } if (Guard.isAnyOfSchema(schema)) { return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name, value: Schema.generateMultiTypeAlias(entryPoint, currentPoint, factory, name, schema.anyOf, context, "anyOf"), }); } if (Guard.isArraySchema(schema)) { return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name, value: Schema.generateArrayTypeAlias(entryPoint, currentPoint, factory, name, schema, context), }); } if (Guard.isObjectSchema(schema)) { return store.addStatement(path, { - type: "interface", + kind: "interface", name, value: Schema.generateInterface(entryPoint, currentPoint, factory, name, schema, context), }); } if (Guard.isObjectSchema(schema)) { return store.addStatement(path, { - type: "interface", + kind: "interface", name, value: Schema.generateInterface(entryPoint, currentPoint, factory, name, schema, context), }); } if (Guard.isPrimitiveSchema(schema)) { return store.addStatement(path, { - type: "typeAlias", + kind: "typeAlias", name, value: Schema.generateTypeAlias(entryPoint, currentPoint, factory, name, schema), }); diff --git a/src/Converter/v3/components/SecuritySchemas.ts b/src/Converter/v3/components/SecuritySchemas.ts index 71df8fe2..06f8a089 100644 --- a/src/Converter/v3/components/SecuritySchemas.ts +++ b/src/Converter/v3/components/SecuritySchemas.ts @@ -15,15 +15,9 @@ export const generateNamespace = ( requestBodies: OpenApi.MapLike, ): void => { store.addComponent("securitySchemes", { - type: "namespace", + kind: "namespace", name: Name.Components.SecuritySchemas, - value: factory.Namespace.create({ - export: true, - name: Name.Components.SecuritySchemas, - statements: [], - comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#securitySchemeObject`, - }), - statements: {}, + comment: `@see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#securitySchemeObject`, }); Object.entries(requestBodies).forEach(([name, requestBody]) => { if (Guard.isReference(requestBody)) { @@ -36,14 +30,14 @@ export const generateNamespace = ( } const path = `components/securitySchemes/${reference.name}`; return store.addStatement(path, { - type: "interface", + kind: "interface", name, value: SecuritySchema.generateInterface(entryPoint, reference.referencePoint, factory, name, reference.data), }); } const path = `components/securitySchemes/${name}`; return store.addStatement(path, { - type: "interface", + kind: "interface", name: name, value: SecuritySchema.generateInterface(entryPoint, currentPoint, factory, name, requestBody), }); diff --git a/src/Converter/v3/store/Definition.ts b/src/Converter/v3/store/Definition.ts index 18db9bc3..c5ce0bbd 100644 --- a/src/Converter/v3/store/Definition.ts +++ b/src/Converter/v3/store/Definition.ts @@ -1,51 +1,5 @@ -export type InterfaceKey = string; -export type NamespaceKey = string; -export type Keys = InterfaceKey | NamespaceKey; - -export interface NamespaceStatement { - type: "namespace"; - name: string; - value: T; - statements: StatementMap; -} - -export interface TypeAliasStatement { - type: "typeAlias"; - name: string; - value: T; -} - -export interface InterfaceStatement { - type: "interface"; - name: string; - value: T; -} - -export type Statement = NamespaceStatement | InterfaceStatement | TypeAliasStatement; - -export interface StatementMap { - [key: string]: Statement | undefined; -} - export type ComponentName = "schemas" | "headers" | "responses" | "parameters" | "requestBodies" | "securitySchemes" | "pathItems"; -export type GenerateKey["type"]> = T extends "namespace" - ? NamespaceKey - : T extends "interface" - ? InterfaceKey - : never; -export type GetStatement["type"]> = T extends "namespace" - ? NamespaceStatement - : T extends "interface" - ? InterfaceStatement - : T extends "typeAlias" - ? TypeAliasStatement - : never; - -export const generateKey = ["type"]>(type: T, key: string): GenerateKey => { - return `${type}:${key}` as GenerateKey; -}; - export const componentNames: ComponentName[] = [ "schemas", "headers", diff --git a/src/Converter/v3/store/PropAccess.ts b/src/Converter/v3/store/PropAccess.ts deleted file mode 100644 index 53e179df..00000000 --- a/src/Converter/v3/store/PropAccess.ts +++ /dev/null @@ -1,60 +0,0 @@ -import * as Def from "./Definition"; - -const SLASH_DELIMITER = "/" as const; - -export const get = ["type"]>( - obj: Def.StatementMap, - type: T, - path: string, - delimiter = SLASH_DELIMITER, -): Def.GetStatement | undefined => { - const pathArray = path.split(delimiter); - const firstKey = pathArray[0]; - const nextPath = pathArray.slice(1, pathArray.length); - const isFinal = nextPath.length === 0; - const nextType = nextPath.length >= 1 ? "namespace" : "interface"; - const key = Def.generateKey(isFinal ? type : nextType, firstKey); - const target = obj[key]; - - if (!target) { - return; - } - - if (target.type === "namespace") { - if (isFinal) { - return target as Def.GetStatement; - } else { - return get(target.statements, type, nextPath.join(delimiter), delimiter); - } - } - - if (target.type === "interface") { - return target as Def.GetStatement; - } - - if (target.type === "typeAlias") { - return target as Def.GetStatement; - } - - return undefined; -}; - -export const set = >( - obj: T, - path: string, - statement: Def.Statement, - createNamespace: (name: string) => Def.NamespaceStatement, - delimiter = SLASH_DELIMITER, -): T => { - const [firstPath, ...pathArray] = path.split(delimiter); - if (!firstPath) { - return obj; - } - const isBottom = pathArray.length === 0; - const childObj = get(obj, "namespace", firstPath, delimiter); - const target = childObj ? childObj : createNamespace(firstPath); - target.statements = set(target.statements, pathArray.join(delimiter), statement, createNamespace, delimiter); - const key = Def.generateKey(isBottom ? statement.type : target.type, firstPath); - (obj as Def.StatementMap)[key] = isBottom ? statement : target; - return obj; -}; diff --git a/src/Converter/v3/store/State.ts b/src/Converter/v3/store/State.ts index c548f762..d9cd594c 100644 --- a/src/Converter/v3/store/State.ts +++ b/src/Converter/v3/store/State.ts @@ -1,11 +1,6 @@ import ts from "typescript"; import { OpenApi } from "../types"; -import * as Def from "./Definition"; - -export type A = ts.ModuleDeclaration; -export type B = ts.InterfaceDeclaration; -export type C = ts.TypeAliasDeclaration; export interface OperationState { requestUri: string; @@ -16,14 +11,6 @@ export interface OperationState { export interface Type { document: OpenApi.Document; - components: Def.StatementMap; - paths: { - // "/a/b/c1": { ref: "components/pathItems/$hoge" } - // "/a/b/c2": { ref: "components/pathItems/HogeCRUD" } - [pathString: string]: { - ref: string; - }; - }; additionalStatements: ts.Statement[]; operations: { [operationId: string]: OperationState; @@ -41,8 +28,6 @@ export const createDefaultOperationState = (httpMethod: string, requestUri: stri export const createDefaultState = (rootDocument: OpenApi.Document): Type => ({ document: rootDocument, - components: {}, - paths: {}, additionalStatements: [], operations: {}, }); diff --git a/src/Converter/v3/store/Store.ts b/src/Converter/v3/store/Store.ts index c0624c47..fb533d18 100644 --- a/src/Converter/v3/store/Store.ts +++ b/src/Converter/v3/store/Store.ts @@ -1,40 +1,31 @@ -import * as fs from "fs"; import { relative } from "path"; +import { Tree } from "@himenon/path-oriented-data-structure"; import Dot from "dot-prop"; -import yaml from "js-yaml"; import ts from "typescript"; import { Factory } from "../../../CodeGenerator"; import { UnSupportError } from "../../../Exception"; import { OpenApi } from "../types"; import * as Def from "./Definition"; -import * as Masking from "./masking"; import * as Operation from "./Operation"; -import * as PropAccess from "./PropAccess"; import * as State from "./State"; - -export type A = State.A; -export type B = State.B; -export type C = State.C; +import * as Structure from "./structure"; export interface Type { - addComponent: (componentName: Def.ComponentName, statement: Def.Statement) => void; + addComponent: (componentName: Def.ComponentName, statement: Structure.ComponentParams) => void; /** * @params path: "components/headers/hoge" */ - addStatement: (path: string, statement: Def.Statement) => void; - getStatement: (path: string, types: Def.Statement["type"]) => Def.Statement | undefined; + addStatement: (path: string, statement: Structure.ComponentParams) => void; + getStatement: (path: string, kind: T) => Structure.DataStructure.GetChild | undefined; /** * @params path: "components/headers/hoge" */ - hasStatement: (path: string, types: Def.Statement["type"][]) => boolean; + hasStatement: (path: string, types: Structure.DataStructure.Kind[]) => boolean; addAdditionalStatement: (statements: ts.Statement[]) => void; getRootStatements: () => ts.Statement[]; updateOperationState: (httpMethod: string, requestUri: string, operationId: string, state: Partial) => void; - getOperationState: (operationId: string) => State.OperationState; - dump: (filename: string) => void; - dumpOperationState: (filename: string) => void; getNoReferenceOperationState: () => Operation.State; getPathItem: (localPath: string) => OpenApi.PathItem; isAfterDefined: (referencePath: string) => boolean; @@ -42,160 +33,93 @@ export interface Type { export const create = (factory: Factory.Type, rootDocument: OpenApi.Document): Type => { const state: State.Type = State.createDefaultState(rootDocument); - - const getPathItem = (localPath: string): OpenApi.PathItem => { - if (!localPath.startsWith("components/pathItem")) { - throw new Error("Only use start with 'component/pathItems': " + localPath); - } - const result = Dot.get(state.document, localPath.replace(/\//g, ".")); - if (!result) { - throw new Error(`Not found ${localPath}`); - } - return result; - }; - - const createNamespace = (name: string): Def.NamespaceStatement => { - const value = factory.Namespace.create({ - export: true, - name, - statements: [], - }); - return { - type: "namespace", - name, - value, - statements: {}, - }; - }; - - const addComponent = (componentName: Def.ComponentName, statement: Def.Statement): void => { - const key = Def.generateKey("namespace", componentName); - state.components[key] = statement; - }; - - const getStatement = (path: string, type: Def.Statement["type"]) => { - const targetPath = relative("components", path); - const result = PropAccess.get(state.components, type, targetPath); - return result; - }; - - const hasStatement = (path: string, types: Def.Statement["type"][]): boolean => { - const alreadyRegistered = types.some(type => !!getStatement(path, type)); - return alreadyRegistered; - }; - + const { operator, getChildByPaths } = Structure.create(); const isAfterDefined = (referencePath: string) => { return !!Dot.get(state.document, referencePath.replace(/\//g, ".")); }; - const addStatement = (path: string, statement: Def.Statement): void => { - if (!path.startsWith("components")) { - throw new UnSupportError(`componentsから始まっていません。path=${path}`); - } - const targetPath = relative("components", path); - state.components = PropAccess.set(state.components, targetPath, statement, createNamespace); - }; - - const interfaceToStatement = (node: Def.InterfaceStatement): ts.Statement => { - return node.value; - }; - - const typeAliasToStatement = (node: Def.TypeAliasStatement): ts.Statement => { - return node.value; - }; - - const namespaceToTsStatement = (node: Def.NamespaceStatement): ts.Statement => { - const statements = Object.values(node.statements).reduce((previous, childStatement) => { - if (!childStatement) { - return previous; - } - if (childStatement.type === "namespace") { - return previous.concat(namespaceToTsStatement(childStatement)); - } - if (childStatement.type === "typeAlias") { - return previous.concat(typeAliasToStatement(childStatement)); + const convertNamespace = (tree: Tree | Structure.NamespaceTree.Item): ts.Statement => { + const statements: ts.Statement[] = []; + Object.values(tree.getChildren()).map(child => { + if (child instanceof Tree || child instanceof Structure.NamespaceTree.Item) { + statements.push(convertNamespace(child)); + } else if (child instanceof Structure.InterfaceNode.Item) { + statements.push(child.value); + } else if (child instanceof Structure.TypeAliasNode.Item) { + statements.push(child.value); } - return previous.concat(interfaceToStatement(childStatement)); - }, []); - return factory.Namespace.addStatements({ - node: node.value, + }); + if (tree instanceof Structure.NamespaceTree.Item) { + return factory.Namespace.create({ + export: true, + name: tree.params.name, + statements, + comment: tree.params.comment, + deprecated: tree.params.deprecated, + }); + } + return factory.Namespace.create({ + export: true, + name: tree.name, statements, }); }; - const dump = (filename: string) => { - fs.writeFileSync(filename, yaml.dump(Masking.maskValue(state)), { encoding: "utf-8" }); - }; - - const dumpOperationState = (filename: string) => { - fs.writeFileSync(filename, JSON.stringify(state.operations, null, 2), { encoding: "utf-8" }); - }; - - const addAdditionalStatement = (statements: ts.Statement[]) => { - state.additionalStatements = state.additionalStatements.concat(statements); - }; - const getRootStatements = (): ts.Statement[] => { + // fs.writeFileSync("debug/tree.json", JSON.stringify(operator.getHierarchy(), null, 2), { encoding: "utf-8" }); const statements = Def.componentNames.reduce((statements, componentName) => { - const component = state.components[Def.generateKey("namespace", componentName)]; - if (!component) { - return statements; - } - if (component.type === "interface") { - return statements.concat(interfaceToStatement(component)); - } - if (component.type === "namespace") { - return statements.concat(namespaceToTsStatement(component)); - } - if (component.type === "typeAlias") { - return statements.concat(typeAliasToStatement(component)); + const treeOfNamespace = getChildByPaths(componentName, "namespace"); + if (treeOfNamespace) { + return statements.concat(convertNamespace(treeOfNamespace)); } return statements; }, []); return statements.concat(state.additionalStatements); }; - const updateOperationState = ( - httpMethod: string, - requestUri: string, - operationId: string, - newOperationState: Partial, - ) => { - let operationState = state.operations[operationId]; - if (operationState) { - operationState = { ...operationState, ...newOperationState }; - } else { - operationState = State.createDefaultOperationState(httpMethod, requestUri, newOperationState); - } - state.operations[operationId] = operationState; - }; - - const getOperationState = (operationId: string): State.OperationState => { - const operationState = state.operations[operationId]; - if (operationState) { - return operationState; - } - dumpOperationState("debug/error-getOperationState.json"); - throw new Error(`Not found ${operationId}`); - }; - - const getNoReferenceOperationState = (): Operation.State => { - return Operation.create(state.document); - }; - return { - hasStatement, - addStatement, - getStatement, + hasStatement: (path: string, types: Structure.DataStructure.Kind[]): boolean => { + const alreadyRegistered = types.some(type => !!operator.getChildByPaths(path, type)); + return alreadyRegistered; + }, + addStatement: (path: string, statement: Structure.ComponentParams): void => { + if (!path.startsWith("components")) { + throw new UnSupportError(`componentsから始まっていません。path=${path}`); + } + const targetPath = relative("components", path); + operator.set(targetPath, Structure.createInstance(statement)); + }, + getStatement: (path: string, kind: T): Structure.DataStructure.GetChild | undefined => { + const targetPath = relative("components", path); + return getChildByPaths(targetPath, kind); + }, getRootStatements, - addComponent, - dump, - getNoReferenceOperationState, - updateOperationState, - getOperationState, - addAdditionalStatement, - dumpOperationState, - getPathItem, + addComponent: (componentName: Def.ComponentName, statement: Structure.ComponentParams): void => { + operator.set(`${componentName}`, Structure.createInstance(statement)); + }, + getNoReferenceOperationState: () => Operation.create(state.document), + updateOperationState: (httpMethod: string, requestUri: string, operationId: string, newOperationState: Partial) => { + let operationState = state.operations[operationId]; + if (operationState) { + operationState = { ...operationState, ...newOperationState }; + } else { + operationState = State.createDefaultOperationState(httpMethod, requestUri, newOperationState); + } + state.operations[operationId] = operationState; + }, + addAdditionalStatement: (statements: ts.Statement[]) => { + state.additionalStatements = state.additionalStatements.concat(statements); + }, + getPathItem: (localPath: string): OpenApi.PathItem => { + if (!localPath.startsWith("components/pathItem")) { + throw new Error("Only use start with 'component/pathItems': " + localPath); + } + const result = Dot.get(state.document, localPath.replace(/\//g, ".")); + if (!result) { + throw new Error(`Not found ${localPath}`); + } + return result; + }, isAfterDefined, }; }; diff --git a/src/Converter/v3/store/__tests__/PropAccess-test.ts b/src/Converter/v3/store/__tests__/PropAccess-test.ts deleted file mode 100644 index 5c0cab47..00000000 --- a/src/Converter/v3/store/__tests__/PropAccess-test.ts +++ /dev/null @@ -1,252 +0,0 @@ -import * as Def from "../Definition"; -import * as PropAccess from "../PropAccess"; - -export type A = { name: string }; -export type B = { name: string }; -export type C = { name: string }; - -const createDummyModuleDeclaration = (name: string): A => { - return { name }; -}; - -const createDummyInterfaceDeclaration = (name: string): B => { - return { name }; -}; - -const testStatementMap = { - "namespace:level1": { - type: "namespace", - name: "level1", - value: createDummyModuleDeclaration("level1"), - statements: { - "namespace:level2": { - type: "namespace", - name: "level2", - value: createDummyModuleDeclaration("level2"), - statements: { - "interface:level3": { - name: "level3", - type: "interface", - value: createDummyInterfaceDeclaration("level3"), - }, - }, - }, - "interface:level2": { - type: "interface", - name: "level2", - value: createDummyInterfaceDeclaration("level2"), - }, - }, - }, -}; - -const createNamespace = (name: string): Def.NamespaceStatement => { - return { - type: "namespace", - name, - value: createDummyModuleDeclaration(name), - statements: {}, - }; -}; - -describe("PropAccessTest", () => { - test("get: level 1", () => { - const result1 = PropAccess.get(testStatementMap as Def.StatementMap, "namespace", "level1"); - expect(result1).toBeTruthy(); - if (!result1) { - throw new Error("Failed result"); - } - expect(result1.type).toBe("namespace"); - expect(result1.statements).toBe(testStatementMap["namespace:level1"].statements); - - const result2 = PropAccess.get(testStatementMap as Def.StatementMap, "interface", "level1"); - expect(result2).toBeUndefined(); - }); - test("get: level 2", () => { - const result1 = PropAccess.get(testStatementMap as Def.StatementMap, "namespace", "level1/level2"); - if (!result1) { - throw new Error("Failed result"); - } - expect(result1).toStrictEqual(testStatementMap["namespace:level1"].statements["namespace:level2"]); - const result2 = PropAccess.get(testStatementMap as Def.StatementMap, "interface", "level1/level2"); - if (!result2) { - throw new Error("Failed result"); - } - expect(result2).toStrictEqual(testStatementMap["namespace:level1"].statements["interface:level2"]); - }); - test("get: level 3", () => { - const result1 = PropAccess.get(testStatementMap as Def.StatementMap, "interface", "level1/level2/level3"); - if (!result1) { - throw new Error("Failed result"); - } - expect(result1).toStrictEqual(testStatementMap["namespace:level1"].statements["namespace:level2"].statements["interface:level3"]); - }); - test("get: not found test", () => { - const result1 = PropAccess.get(testStatementMap as Def.StatementMap, "interface", "level1"); - expect(result1).toBeUndefined(); - - const result2 = PropAccess.get(testStatementMap as Def.StatementMap, "interface", "level1/level3"); - expect(result2).toBeUndefined(); - }); - test("set: level1 & target: empty namespace", () => { - const obj: Def.StatementMap = {}; - const statement: Def.NamespaceStatement = { - type: "namespace", - name: "level1", - value: createDummyModuleDeclaration("level1"), - statements: {}, - }; - const result = PropAccess.set(obj, "level1", statement, createNamespace); - expect(result).toStrictEqual({ - "namespace:level1": statement, - }); - }); - test("set: level2 & target: empty namespace", () => { - const obj: Def.StatementMap = {}; - const statement: Def.NamespaceStatement = { - type: "namespace", - name: "level2", - value: createDummyModuleDeclaration("level2"), - statements: {}, - }; - const result = PropAccess.set(obj, "level1/level2", statement, createNamespace); - - const expectResult: Def.StatementMap = { - "namespace:level1": { - type: "namespace", - name: "level1", - value: createDummyModuleDeclaration("level1"), - statements: { - "namespace:level2": { - type: "namespace", - name: "level2", - value: createDummyModuleDeclaration("level2"), - statements: {}, - }, - }, - }, - }; - expect(result).toStrictEqual(expectResult); - }); - - test("set: level3 & target: empty namespace", () => { - const obj: Def.StatementMap = {}; - const statement: Def.NamespaceStatement = { - type: "namespace", - name: "mostDepth", - value: createDummyModuleDeclaration("mostDepth"), - statements: {}, - }; - const result = PropAccess.set(obj, "level1/level2/level3", statement, createNamespace); - const expectResult: Def.StatementMap = { - "namespace:level1": { - type: "namespace", - name: "level1", - value: createDummyModuleDeclaration("level1"), - statements: { - "namespace:level2": { - type: "namespace", - name: "level2", - value: createDummyModuleDeclaration("level2"), - statements: { - "namespace:level3": statement, - }, - }, - }, - }, - }; - expect(result).toStrictEqual(expectResult); - }); - - test("set: level2 & target: exist namespace", () => { - const obj: Def.StatementMap = { - "namespace:level1": { - type: "namespace", - name: "Hello", - value: createDummyModuleDeclaration("Hello"), - statements: { - "namespace:level2": { - type: "namespace", - name: "World", - value: createDummyModuleDeclaration("World"), - statements: {}, - }, - }, - }, - }; - const statement: Def.InterfaceStatement = { - type: "interface", - name: "dummyInterface", - value: createDummyInterfaceDeclaration("dummyInterface"), - }; - const result = PropAccess.set(obj, "level1/level2", statement, createNamespace); - const expectResult: Def.StatementMap = { - "namespace:level1": { - type: "namespace", - name: "Hello", - value: createDummyModuleDeclaration("Hello"), - statements: { - "namespace:level2": { - type: "namespace", - name: "World", - value: createDummyModuleDeclaration("World"), - statements: {}, - }, - "interface:level2": statement, - }, - }, - }; - expect(result).toStrictEqual(expectResult); - }); - - test("set: level3 & target: exist namespace", () => { - const obj: Def.StatementMap = { - "namespace:level1": { - type: "namespace", - name: "Hello", - value: createDummyModuleDeclaration("Hello"), - statements: { - "namespace:level2": { - type: "namespace", - name: "World", - value: createDummyModuleDeclaration("World"), - statements: { - "namespace:level3": createNamespace("level3"), - }, - }, - }, - }, - }; - const statement: Def.InterfaceStatement = { - type: "interface", - name: "dummyInterface", - value: createDummyInterfaceDeclaration("dummyInterface"), - }; - const result = PropAccess.set(obj, "level1/level2/level3/level4", statement, createNamespace); - const expectResult: Def.StatementMap = { - "namespace:level1": { - type: "namespace", - name: "Hello", - value: createDummyModuleDeclaration("Hello"), - statements: { - "namespace:level2": { - type: "namespace", - name: "World", - value: createDummyModuleDeclaration("World"), - statements: { - "namespace:level3": { - type: "namespace", - name: "level3", - value: createDummyModuleDeclaration("level3"), - statements: { - "interface:level4": statement, - }, - }, - }, - }, - }, - }, - }; - expect(result).toStrictEqual(expectResult); - }); -}); diff --git a/src/Converter/v3/store/masking.ts b/src/Converter/v3/store/masking.ts deleted file mode 100644 index ac1e7720..00000000 --- a/src/Converter/v3/store/masking.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as Def from "./Definition"; -import * as State from "./State"; - -const maskingNamespace = ( - namespaceStatement: Def.NamespaceStatement, -): Def.NamespaceStatement => { - const statements = Object.entries(namespaceStatement.statements).reduce>( - (newStatement, [key, statement]) => { - if (statement) { - newStatement[key] = maskingStatement(statement); - } - return newStatement; - }, - {}, - ); - return { - type: "namespace", - name: namespaceStatement.name, - value: namespaceStatement.value.name.text as any, - statements, - }; -}; - -const maskingInterface = (statement: Def.InterfaceStatement): Def.InterfaceStatement => { - return { - type: "interface", - name: statement.name, - value: statement.value.name.text as any, - }; -}; - -const maskingTypeAlias = (statement: Def.TypeAliasStatement): Def.TypeAliasStatement => { - return { - type: "typeAlias", - name: statement.name, - value: statement.value.name.text as any, - }; -}; - -const maskingStatement = (statement: Def.Statement): Def.Statement => { - if (statement.type === "interface") { - return maskingInterface(statement); - } - if (statement.type === "typeAlias") { - return maskingTypeAlias(statement); - } - return maskingNamespace(statement); -}; - -export const maskValue = (state: State.Type): State.Type => { - const kinds: Def.Statement["type"][] = ["namespace", "typeAlias", "interface"]; - return Def.componentNames.reduce((newState, componentName) => { - kinds.forEach(kind => { - const key = Def.generateKey(kind, componentName); - const component = state.components[key]; - if (!component) { - return; - } - newState.components[key] = maskingStatement(component); - }); - return newState; - }, state); -}; diff --git a/src/Converter/v3/store/structure/DataStructure.ts b/src/Converter/v3/store/structure/DataStructure.ts new file mode 100644 index 00000000..db656e86 --- /dev/null +++ b/src/Converter/v3/store/structure/DataStructure.ts @@ -0,0 +1,22 @@ +import type { Operator } from "@himenon/path-oriented-data-structure"; + +import * as InterfaceNode from "./InterfaceNode"; +import * as NamespaceTree from "./NamespaceTree"; +import * as TypeAliasNode from "./TypeAliasNode"; + +export { InterfaceNode, NamespaceTree, TypeAliasNode }; + +export type Kind = NamespaceTree.Kind | InterfaceNode.Kind | TypeAliasNode.Kind; + +export type GetChild = T extends NamespaceTree.Kind + ? NamespaceTree.Item + : T extends InterfaceNode.Kind + ? InterfaceNode.Item + : T extends TypeAliasNode.Kind + ? TypeAliasNode.Item + : never; + +// Type Safe method +export const createGetChildByPaths = (operator: Operator) => (path: string, kind: T): GetChild | undefined => { + return operator.getChildByPaths(path, kind) as GetChild | undefined; +}; diff --git a/src/Converter/v3/store/structure/InterfaceNode.ts b/src/Converter/v3/store/structure/InterfaceNode.ts new file mode 100644 index 00000000..0e3404a4 --- /dev/null +++ b/src/Converter/v3/store/structure/InterfaceNode.ts @@ -0,0 +1,17 @@ +import { Node as BaseNode } from "@himenon/path-oriented-data-structure"; +import ts from "typescript"; + +export type Kind = "interface"; + +export interface Params { + name: string; + value: ts.InterfaceDeclaration; +} + +export class Item extends BaseNode { + public value: ts.InterfaceDeclaration; + constructor(params: Params) { + super("interface", params.name); + this.value = params.value; + } +} diff --git a/src/Converter/v3/store/structure/NamespaceTree.ts b/src/Converter/v3/store/structure/NamespaceTree.ts new file mode 100644 index 00000000..b400dcc9 --- /dev/null +++ b/src/Converter/v3/store/structure/NamespaceTree.ts @@ -0,0 +1,15 @@ +import { Tree as BaseTree } from "@himenon/path-oriented-data-structure"; + +export type Kind = "namespace"; + +export interface Params { + name: string; + comment?: string; + deprecated?: boolean; +} + +export class Item extends BaseTree { + constructor(public params: Params) { + super("namespace", params.name); + } +} diff --git a/src/Converter/v3/store/structure/TypeAliasNode.ts b/src/Converter/v3/store/structure/TypeAliasNode.ts new file mode 100644 index 00000000..74924998 --- /dev/null +++ b/src/Converter/v3/store/structure/TypeAliasNode.ts @@ -0,0 +1,17 @@ +import { Node as BaseNode } from "@himenon/path-oriented-data-structure"; +import ts from "typescript"; + +export type Kind = "typeAlias"; + +export interface Params { + name: string; + value: ts.TypeAliasDeclaration; +} + +export class Item extends BaseNode { + public value: ts.TypeAliasDeclaration; + constructor(params: Params) { + super("typeAlias", params.name); + this.value = params.value; + } +} diff --git a/src/Converter/v3/store/structure/index.ts b/src/Converter/v3/store/structure/index.ts new file mode 100644 index 00000000..3b052733 --- /dev/null +++ b/src/Converter/v3/store/structure/index.ts @@ -0,0 +1,45 @@ +import { Operator } from "@himenon/path-oriented-data-structure"; + +import * as DataStructure from "./DataStructure"; +import * as InterfaceNode from "./InterfaceNode"; +import * as NamespaceTree from "./NamespaceTree"; +import * as TypeAliasNode from "./TypeAliasNode"; + +export { DataStructure, InterfaceNode, NamespaceTree, TypeAliasNode }; + +export interface NamespaceTreeParams extends NamespaceTree.Params { + kind: NamespaceTree.Kind; +} + +export interface InterfaceNodeParams extends InterfaceNode.Params { + kind: InterfaceNode.Kind; +} + +export interface TypeAliasNodeParams extends TypeAliasNode.Params { + kind: TypeAliasNode.Kind; +} + +export type ComponentParams = NamespaceTreeParams | InterfaceNodeParams | TypeAliasNodeParams; + +export type Instance = NamespaceTree.Item | InterfaceNode.Item | TypeAliasNode.Item; + +export const createInstance = (component: ComponentParams): Instance => { + if (component.kind === "interface") { + return new InterfaceNode.Item(component); + } + if (component.kind === "typeAlias") { + return new TypeAliasNode.Item(component); + } + if (component.kind === "namespace") { + return new NamespaceTree.Item(component); + } + throw new Error("not registers"); +}; + +export const create = () => { + const operator = new Operator("namespace"); + return { + operator, + getChildByPaths: DataStructure.createGetChildByPaths(operator), + }; +}; diff --git a/src/Converter/v3/types/OpenApiSchemaV3.ts b/src/Converter/v3/types/OpenApiSchemaV3.ts index c05b5f34..c3f8ac3b 100644 --- a/src/Converter/v3/types/OpenApiSchemaV3.ts +++ b/src/Converter/v3/types/OpenApiSchemaV3.ts @@ -1,4 +1,4 @@ -import { JSONSchema7, JSONSchema7Type as JSONSchemaType, JSONSchema7TypeName as JSONSchemaTypeName } from "json-schema"; +import type { JSONSchema7, JSONSchema7Type as JSONSchemaType, JSONSchema7TypeName as JSONSchemaTypeName } from "json-schema"; export interface JSONSchema extends JSONSchema7 { nullable?: boolean; diff --git a/yarn.lock b/yarn.lock index 2a0226bf..11aae788 100644 --- a/yarn.lock +++ b/yarn.lock @@ -633,6 +633,11 @@ unique-filename "^1.1.1" which "^1.3.1" +"@himenon/path-oriented-data-structure@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@himenon/path-oriented-data-structure/-/path-oriented-data-structure-0.1.0.tgz#b417a3cb46e3bbc409c4fc5216c42d924f2e7433" + integrity sha512-pU4wymQPvBbtPDyeVP8RekOUsQbUiztEae38BIPLFRSqOM68xCNcFzng71HhI2ZdD0kbt+zK1HgQKwB/nv8VkA== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b"