Skip to content

Commit

Permalink
feat: support directories
Browse files Browse the repository at this point in the history
  • Loading branch information
elyukai committed Feb 22, 2022
1 parent 9d0e862 commit c8905cd
Showing 1 changed file with 53 additions and 40 deletions.
93 changes: 53 additions & 40 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Dirent, mkdirSync, readdirSync, writeFileSync } from "fs"
import { basename, extname, join, sep } from "path"
import { basename, dirname, extname, format, join, relative, sep } from "path"
import * as ts from "typescript"
import { fileToAst } from "./ast"
import { astToJsonSchema, jsonSchemaToFileContent } from "./jsonSchema"
Expand All @@ -22,65 +22,78 @@ if (!tsDir || !jsonSchemaDir || !mdDir) {
console.log(`\
Usage:
node -r ts-node/register/transpile-only createSchema.ts --tsdir "src/entity" --jsondir "json" --mddir "docs"`)
node -r ts-node/register/transpile-only src/main.ts --tsdir "src/entity" --jsondir "json" --mddir "docs"`)
}
else {
const prepareSplitCLIPath = (path: string) => path.split(/[\/\\]/)
const toAbsolutePath = (relativePath: string[]) =>
join(__dirname, "..", relativePath.join(sep)).split(sep)
const joinPath = (path: string[]) => path.join(sep)
const splitPath = (path: string) => path.split(sep)
const makeAbsolutePathSplit = (path: string) => toAbsolutePath(prepareSplitCLIPath(path))

const rootPaths = joinPath(makeAbsolutePathSplit(tsDir))

const dirEntryToFilePath = (dirEntry: Dirent) =>
join(rootPaths, dirEntry.name).split(sep).join("/")

const tsFiles = readdirSync(rootPaths, { withFileTypes: true })
.flatMap(dirEntry => {
if (dirEntry.isFile() && extname(dirEntry.name) === ".ts") {
return [dirEntryToFilePath(dirEntry)]
}
else {
return []
}
})
const fromCLIPath = (path: string) => join(...path.split(/[\/\\]/))
const toForwardSlashPath = (path: string) => path.split(sep).join("/")

const toAbsolutePath = (relativePath: string) => join(__dirname, "..", relativePath)

const absolutePathFromCLI = (path: string) => toAbsolutePath(fromCLIPath(path))

const typesRootPath = absolutePathFromCLI(tsDir)
const jsonSchemaRootPath = absolutePathFromCLI(jsonSchemaDir)
const markdownRootPath = absolutePathFromCLI(mdDir)

const flattenTypeScriptFileNamesFromDir = (dirPath: string): string[] => {
const dirEntryToFilePath = (dirEntry: Dirent) =>
join(dirPath, dirEntry.name).split(sep).join("/")

return readdirSync(dirPath, { withFileTypes: true })
.flatMap(dirEntry => {
if (dirEntry.isDirectory()) {
return flattenTypeScriptFileNamesFromDir(dirEntryToFilePath(dirEntry))
}
else if (dirEntry.isFile() && extname(dirEntry.name) === ".ts") {
return [dirEntryToFilePath(dirEntry)]
}
else {
return []
}
})
}

const tsFiles = flattenTypeScriptFileNamesFromDir(typesRootPath)

const program = ts.createProgram(tsFiles, { strict: true })

// KEEP ALWAYS, SIDE EFFECT: it fills the parent references of nodes
const checker = program.getTypeChecker()

const jsonSchemaRoot = makeAbsolutePathSplit(jsonSchemaDir)
const markdownRoot = makeAbsolutePathSplit(mdDir)

mkdirSync(jsonSchemaRoot.join(sep), { recursive: true })
mkdirSync(markdownRoot.join(sep), { recursive: true })
mkdirSync(jsonSchemaRootPath, { recursive: true })
mkdirSync(markdownRootPath, { recursive: true })

program
.getSourceFiles()
.filter(file => tsFiles.includes(file.fileName))
// .filter(file => file.fileName.includes("_Prerequisite"))
.forEach(file => {
const base = basename(file.fileName, ".ts")
const schemaFilePath = [...jsonSchemaRoot, `${base}.schema.json`]
const schemaId = [
...prepareSplitCLIPath(jsonSchemaDir).filter(part => part !== "." && part !== ".."),
`${base}.schema.json`
].join("/")
const markdownFilePath = [...markdownRoot, `${base}.md`]
const relativePath = relative(typesRootPath, file.fileName)
const dir = dirname(relativePath)
const name = basename(relativePath, ".ts")

const jsonSchemaDir = join(jsonSchemaRootPath, dir)
const markdownDir = join(markdownRootPath, dir)

mkdirSync(jsonSchemaDir, { recursive: true })
mkdirSync(markdownDir, { recursive: true })

const jsonSchemaFilePath = format({ dir: jsonSchemaDir, name, ext: ".schema.json" })
const jsonSchemaId = toForwardSlashPath(relative(jsonSchemaRootPath, jsonSchemaFilePath))
const markdownFilePath = format({ dir: markdownDir, name, ext: ".md" })

try {
const ast = fileToAst(file, checker)
const schema = jsonSchemaToFileContent(astToJsonSchema(ast, schemaId))
const docs = astToMarkdown(ast)
const ast = fileToAst(file, checker)
const schema = jsonSchemaToFileContent(astToJsonSchema(ast, jsonSchemaId))
const docs = astToMarkdown(ast)

if (debug) {
writeFileSync(`${file.fileName}.ast.json`, JSON.stringify(ast, undefined, 2))
}
writeFileSync(schemaFilePath.join(sep), schema)
writeFileSync(markdownFilePath.join(sep), docs)

writeFileSync(jsonSchemaFilePath, schema)
writeFileSync(markdownFilePath, docs)
} catch (error) {
if (error instanceof Error) {
error.message = `${error.message} in TS file "${file.fileName}"`
Expand Down

0 comments on commit c8905cd

Please sign in to comment.