Skip to content

Commit

Permalink
feat: implement cli
Browse files Browse the repository at this point in the history
  • Loading branch information
windchime-yk committed Jan 3, 2024
1 parent 9b7dfa5 commit a01330a
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 363 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
.DS_Store
dist/
bid_output/
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ Created by Deno.
## Feature

- [ ] API
- [ ] CLI
- [x] CLI
- [ ] Web App

## Build dictionary workflow sample
## Build dictionary workflow example
``` yml
name: Build IME dictionary
on:
Expand All @@ -48,11 +48,12 @@ jobs:
deno-version: v1.x
- name: Output dictionary data
run: |
deno task build
deno install --allow-read --allow-write -n bid https://deno.land/x/bid/cli.ts
bid --dir=test/mock --all
- name: Archive production artifacts
uses: actions/upload-artifact@v2
with:
name: dictionary
path: dist
path: bid_output
retention-days: 30
```
75 changes: 75 additions & 0 deletions cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { ensureDir, join, parseArgs, walk } from "./deps.ts";
import { isValidFileExtention, isValidJson } from "./core/validation.ts";
import {
convertJsonToTextData,
parsedCsvToJson,
readFile,
} from "./core/convert.ts";
import { generateDictionaryFile } from "./core/build.ts";
import { CliError } from "./core/error.ts";
import type { ImeType } from "./model.ts";

const args = parseArgs(Deno.args, {
boolean: ["all", "google", "macos", "microsoft", "gboard"],
string: ["dir"],
});

if (!args.dir) throw new CliError("--dirでディレクトリを指定してください");

for await (const dirEntry of walk(join(Deno.cwd(), args.dir))) {
if (dirEntry.isFile) {
const isValidFileExtentionResult = isValidFileExtention(dirEntry.name);

if (!isValidFileExtentionResult.success) {
throw isValidFileExtentionResult.error;
}

let data: Record<string, string | undefined>[] = [];

switch (isValidFileExtentionResult.result) {
case "csv": {
data = parsedCsvToJson(await readFile(dirEntry.path));
break;
}
default:
data = JSON.parse(await readFile(dirEntry.path));
break;
}

const isValidJsonResult = isValidJson(data);

if (!isValidJsonResult.success) {
throw isValidJsonResult.error;
}

let imeTypeList: ImeType[] = [];

if (args.all) {
imeTypeList = ["Google IME", "macOS IME", "Microsoft IME", "GBoard"];
} else {
if (args.google) imeTypeList.push("Google IME");
if (args.macos) imeTypeList.push("macOS IME");
if (args.microsoft) imeTypeList.push("Microsoft IME");
if (args.gboard) imeTypeList.push("GBoard");
if (imeTypeList.length === 0) {
throw new CliError("--allや--googleなどでIMEを指定してください");
}
}

const OUTPUT_FILE_PREFIX = dirEntry.name.split(".").at(0)!;
const OUTPUT_BASE_DIR_NAME = "bid_output";
const OUTPUT_DIR_NAME = join(OUTPUT_BASE_DIR_NAME, OUTPUT_FILE_PREFIX);

await ensureDir(OUTPUT_DIR_NAME);

for await (const imeType of imeTypeList) {
await generateDictionaryFile(
convertJsonToTextData(isValidJsonResult.result, imeType),
`${OUTPUT_DIR_NAME}/${OUTPUT_FILE_PREFIX}-${
imeType.toLowerCase().replace(" ", "")
}.txt`,
imeType,
);
}
}
}
6 changes: 6 additions & 0 deletions core/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,9 @@ export const convertJsonToTextData = (
return insertDelimiter(orderd, imeType).join("");
}).join(NEW_LINE);
};

export const readFile = async (path: string): Promise<string> => {
const decoder = new TextDecoder();
const data = await Deno.readFile(path);
return decoder.decode(data);
};
29 changes: 29 additions & 0 deletions core/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @see https://uga-box.hatenablog.com/entry/2022/01/07/000000
*/
class BaseError extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}

export class FileTypeError extends BaseError {
constructor(filename: string) {
super(
`${filename}は想定したファイル形式ではありません。CSVかJSONを使ってください`,
);
}
}

export class DataPropertyError extends BaseError {
constructor() {
super(`想定していないプロパティが存在します。データを再確認してください`);
}
}

export class CliError extends BaseError {
constructor(message: string) {
super(message);
}
}
5 changes: 3 additions & 2 deletions core/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
YesOrNo,
} from "../model.ts";
import { COMMA, TAB } from "./config.ts";
import { DataPropertyError, FileTypeError } from "./error.ts";

/**
* ファイル名がCSVかJSONか確認する
Expand All @@ -24,7 +25,7 @@ export const isValidFileExtention = (filename: string): Result<string> => {
} else {
return {
success: false,
error: new Error("File Type Error"),
error: new FileTypeError(filename),
};
}
};
Expand All @@ -49,7 +50,7 @@ export const isValidJson = (
if (!InputuserDictionarySchema.safeParse(jsonData).success) {
return {
success: false,
error: new Error("Data Proptry Error"),
error: new DataPropertyError(),
};
}

Expand Down
2 changes: 1 addition & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"tasks": {
"build": "deno run --allow-write=dist/ example/main.ts"
"build": "deno run --allow-read --allow-write cli.ts"
},
"exclude": ["README.md"]
}
98 changes: 98 additions & 0 deletions deno.lock

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

6 changes: 6 additions & 0 deletions deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ export { parse } from "https://deno.land/[email protected]/csv/parse.ts";
export { z } from "https://deno.land/x/[email protected]/mod.ts";
export { compress } from "https://deno.land/x/[email protected]/mod.ts";

/* --- cli --- */
export { ensureDir } from "https://deno.land/[email protected]/fs/mod.ts";
export { parseArgs } from "https://deno.land/[email protected]/cli/parse_args.ts";
export { walk } from "https://deno.land/[email protected]/fs/walk.ts";
export { join } from "https://deno.land/[email protected]/path/mod.ts";

/* --- test --- */
export { assertEquals } from "https://deno.land/[email protected]/assert/assert_equals.ts";
Loading

0 comments on commit a01330a

Please sign in to comment.