Skip to content

Commit

Permalink
Merge pull request #44 from mistlog/feature/cli
Browse files Browse the repository at this point in the history
Feature/cli
  • Loading branch information
mistlog committed Apr 4, 2021
2 parents 6370d85 + ea07f16 commit 7f5fda9
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 5 deletions.
41 changes: 41 additions & 0 deletions README.md
Expand Up @@ -10,6 +10,21 @@ TypeType is designed to generate complex typescript type with ease.
> npm i -D @mistlog/typetype
```

### CLI

> example: [typetype-examples/package.json](https://github.com/mistlog/typetype-examples/blob/main/package.json)
```bash
typetype build <dir>: build all *.type files in <dir>
typetype build -w <dir>: watch all *.type files in <dir>
typetype clean <dir>: remove all generated *.ts files in <dir>
typetype debug <file>: build <file> in debug mode(backtrace will be available)
```

### API

> example: [typetype-examples/index.ts](https://github.com/mistlog/typetype-examples/blob/main/index.ts)
```ts
import { transform } from "@mistlog/typetype";

Expand All @@ -27,6 +42,32 @@ console.log(output);
// output: type TypeName<T> = T extends string ? "string" : "number";
```

Debug mode:

```ts
const output = transform(input, { debug: true }).code;
```

when `debug` is true, backtrace will be available:

```log
Expected end of input but ";" found.
x 1:11-1:11 MultiLineComment
| type a = 1;
| ^
o 1:11-1:11 _
| type a = 1;
| ^
x 1:11-1:11 TypeFunctionDeclaration
| type a = 1;
...
|/ /
| |
|/
o 1:1-1:11 TypeFile
type a = 1;
```

## Examples

- all examples: https://github.com/mistlog/typetype-examples
Expand Down
54 changes: 54 additions & 0 deletions cli/cli.ts
@@ -0,0 +1,54 @@
import { default as traverse } from "filewalker";
import { default as watch } from "node-watch";
import { readFileSync } from "fs";
import { transform } from "../src"
import { outputFileSync, removeSync } from "fs-extra";

function TraverseDirectory(path: string, callback: (relative: string, absolute: string) => void) {
const action = (relative: string, stats, absolute: string) => callback(relative, absolute);
traverse(path)
.on("file", action)
.on("error", error => console.log(error))
.walk();
}

function transformFile(absolute: string, config = { debug: false }) {
const input = readFileSync(absolute, "utf8");
const output = transform(input, config).code;
outputFileSync(absolute.replace(".type", ".ts"), output, "utf8");
}

export function build(dir: string, options: { watch: boolean }) {
if (options.watch) {
watch(dir, { recursive: true }, (event, absolute: string) => {
if (absolute.endsWith(".type")) {
console.log(event, absolute);
debug(absolute);
}
});
} else {
TraverseDirectory(dir, (relative, absolute) => {
if (absolute.endsWith(".type")) {
transformFile(absolute);
}
})
}
}

export function clean(dir: string) {
TraverseDirectory(dir, (relative, absolute) => {
if (absolute.endsWith(".type")) {
removeSync(absolute.replace(".type", ".ts"));
}
})
}

export function debug(absolute: string) {
try {
transformFile(absolute, { debug: true });
} catch (error) {
console.log(`build type failed: ${absolute}`);
console.log(error.message);
console.log(error.backtrace);
}
}
44 changes: 44 additions & 0 deletions cli/index.ts
@@ -0,0 +1,44 @@
#!/usr/bin/env node
import { default as program } from "commander";
import { readJSONSync, lstatSync } from "fs-extra";
import { resolve } from "path";
import { build, clean, debug } from "./cli";

const packageJSON = readJSONSync(resolve(__dirname, "../../package.json"));
program.version(packageJSON.version);

program
.option('-w, --watch', "watch mode")

program
.command("build <dir>")
.description("build ts type")
.action((dir: string) => {
const path = resolve(process.cwd(), dir);
if (lstatSync(path).isDirectory()) {
const options = program.opts();
build(path, { watch: options.watch });
}
});

program
.command("clean <dir>")
.description("clean ts type")
.action((dir: string) => {
const path = resolve(process.cwd(), dir);
if (lstatSync(path).isDirectory()) {
clean(path);
}
});

program
.command("debug <file>")
.description("debug ts type")
.action((file: string) => {
const path = resolve(process.cwd(), file);
if (!lstatSync(path).isDirectory()) {
debug(path);
}
});

program.parse(process.argv);
65 changes: 63 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions package.json
Expand Up @@ -22,8 +22,12 @@
"files": [
"build"
],
"bin": {
"typetype": "build/cli/index.js"
},
"license": "MIT",
"devDependencies": {
"@types/fs-extra": "^9.0.10",
"@types/jest": "^24.0.17",
"@types/node": "^14.14.22",
"jest": "^24.8.0",
Expand All @@ -33,6 +37,10 @@
},
"dependencies": {
"@babel/core": "^7.12.10",
"commander": "^7.2.0",
"filewalker": "^0.1.3",
"fs-extra": "^9.1.0",
"node-watch": "^0.7.1",
"pegjs-backtrace": "^0.2.0",
"react-peg": "^0.1.7"
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/core.tsx
Expand Up @@ -2,7 +2,7 @@ import { ReactPeg } from "react-peg";
import { TypeFile } from "../parser";
import { TSFile } from "../generator";
import generate from "@babel/generator";
import * as Tracer from "pegjs-backtrace";
import { default as Tracer } from "pegjs-backtrace";
import { IRenderConfig } from "react-peg/build/renderer/renderer";

export interface ITypeTypeConfig {
Expand Down
6 changes: 4 additions & 2 deletions tsconfig.json
Expand Up @@ -6,9 +6,11 @@
"sourceMap": false,
"outDir": "./build",
"declaration": true,
"module": "commonjs"
"module": "commonjs",
"esModuleInterop": true
},
"include": [
"src/**/*"
"src/**/*",
"cli/**/*"
]
}

0 comments on commit 7f5fda9

Please sign in to comment.