|
1 |
| -import fs from "fs"; |
2 |
| -import glob from "glob"; |
3 |
| -import yaml from "js-yaml"; |
4 |
| -import { compile, Options as CompilerOptions } from "json-schema-to-typescript"; |
5 |
| -import path from "path"; |
6 |
| -import { promisify } from "util"; |
7 |
| - |
8 |
| -const compileOptions: Partial<CompilerOptions> = { bannerComment: "" }; |
9 |
| -const defaultSchema = { type: "object", additionalProperties: false }; |
10 |
| - |
11 |
| -export interface Options { |
12 |
| - glob: string; |
13 |
| - prefix: string; |
14 |
| - ext: string; |
15 |
| - module: string; |
16 |
| -} |
17 |
| - |
18 |
| -function addDefaultValueToSchema(schema: any) { |
19 |
| - return { |
20 |
| - ...schema, |
21 |
| - additionalProperties: schema.additionalProperties || false, |
22 |
| - }; |
23 |
| -} |
24 |
| - |
25 |
| -export async function generateReplyInterfaces( |
26 |
| - prefix: string, |
27 |
| - replies: Record<any, any> = {} |
28 |
| -) { |
29 |
| - const generatedInterfaces = []; |
30 |
| - const generatedReplyNames = []; |
31 |
| - for (const [replyCode, replySchema] of Object.entries(replies)) { |
32 |
| - generatedReplyNames.push(prefix + "Reply" + replyCode.toUpperCase()); |
33 |
| - generatedInterfaces.push( |
34 |
| - await compile( |
35 |
| - addDefaultValueToSchema(replySchema || defaultSchema), |
36 |
| - prefix + "Reply" + replyCode.toUpperCase(), |
37 |
| - compileOptions |
38 |
| - ) |
39 |
| - ); |
40 |
| - } |
41 |
| - |
42 |
| - return ` |
43 |
| -${generatedInterfaces.join("\n")} |
44 |
| -type ${prefix}Reply = ${generatedReplyNames.join(" | ") || "{}"} |
45 |
| -`.trim(); |
46 |
| -} |
47 |
| - |
48 |
| -function writeSchema(schema: any) { |
49 |
| - return `\ |
50 |
| -const schema = ${JSON.stringify(schema, null, 2)}\ |
51 |
| -`; |
52 |
| -} |
53 |
| - |
54 |
| -async function generateInterfaces(schema: any, options: Options) { |
55 |
| - return `\ |
56 |
| -/* tslint:disable */ |
57 |
| -/* eslint-disable */ |
58 |
| -/** |
59 |
| - * This file was automatically generated. DO NOT MODIFY IT BY HAND. |
60 |
| - * Instead, modify the corresponding JSONSchema file and regenerate the types. |
61 |
| - */ |
62 |
| -
|
63 |
| -import { RouteHandler } from "${options.module}" |
64 |
| -
|
65 |
| -${writeSchema(schema)} |
66 |
| -
|
67 |
| -${await compile( |
68 |
| - addDefaultValueToSchema(schema.params || defaultSchema), |
69 |
| - options.prefix + "Params", |
70 |
| - compileOptions |
71 |
| -)} |
72 |
| -${await compile( |
73 |
| - addDefaultValueToSchema(schema.querystring || schema.query || defaultSchema), |
74 |
| - options.prefix + "Query", |
75 |
| - compileOptions |
76 |
| -)} |
77 |
| -${await compile( |
78 |
| - addDefaultValueToSchema(schema.body || defaultSchema), |
79 |
| - options.prefix + "Body", |
80 |
| - compileOptions |
81 |
| -)} |
82 |
| -${await compile( |
83 |
| - schema.headers || defaultSchema, |
84 |
| - options.prefix + "Headers", |
85 |
| - compileOptions |
86 |
| -)} |
87 |
| -${await generateReplyInterfaces(options.prefix, schema.response)} |
88 |
| -
|
89 |
| -type ${options.prefix}RouteGeneric = { |
90 |
| - Querystring: ${options.prefix}Query; |
91 |
| - Body: ${options.prefix}Body; |
92 |
| - Params: ${options.prefix}Params; |
93 |
| - Headers: ${options.prefix}Headers; |
94 |
| - Reply: ${options.prefix}Reply; |
95 |
| -} |
96 |
| -
|
97 |
| -type ${options.prefix}Handler = RouteHandler<${options.prefix}RouteGeneric>; |
98 |
| -
|
99 |
| -export { ${options.prefix}Handler, ${options.prefix}RouteGeneric, schema }\ |
100 |
| -`; |
101 |
| -} |
102 |
| - |
103 |
| -async function writeFile( |
104 |
| - parsedPath: path.ParsedPath, |
105 |
| - template: string, |
106 |
| - options: Options |
107 |
| -) { |
108 |
| - const write = promisify(fs.writeFile); |
109 |
| - return write( |
110 |
| - path.join(parsedPath.dir, parsedPath.name + options.ext), |
111 |
| - template |
112 |
| - ); |
113 |
| -} |
114 |
| - |
115 |
| -export async function convert(options: Options) { |
116 |
| - const filePaths = glob.sync(options.glob); |
117 |
| - for (const filePath of filePaths) { |
118 |
| - const parsedPath = path.parse(filePath); |
119 |
| - try { |
120 |
| - if (parsedPath.ext === ".yaml" || parsedPath.ext === ".yml") { |
121 |
| - const schema = yaml.safeLoad(fs.readFileSync(filePath, "utf-8")); |
122 |
| - const template = await generateInterfaces(schema, options); |
123 |
| - await writeFile(parsedPath, template, options); |
124 |
| - } else { |
125 |
| - const schema = JSON.parse(fs.readFileSync(filePath, "utf-8")); |
126 |
| - const template = await generateInterfaces(schema, options); |
127 |
| - await writeFile(parsedPath, template, options); |
128 |
| - } |
129 |
| - } catch (err) { |
130 |
| - console.error( |
131 |
| - `Failed to process file ${filePath} with error ${JSON.stringify(err)}` |
132 |
| - ); |
133 |
| - } |
134 |
| - } |
135 |
| -} |
| 1 | +export { Options } from "./types"; |
| 2 | +export { convert, defaultOptions } from "./schema"; |
0 commit comments