Skip to content

Commit 20e5b8b

Browse files
authored
feat: cli for syntax transformer (#105)
* feat: cli for syntax transformer Close #40
1 parent 5dd865a commit 20e5b8b

File tree

8 files changed

+106
-6
lines changed

8 files changed

+106
-6
lines changed

package-lock.json

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
"build:grammar": "npx nearleyc src/parser/openfga.ne > src/parser/grammar.ts",
1010
"build:ts": "rm -rf dist/ && tsc --outDir dist/",
1111
"build": "npm run build:grammar; npm run build:ts",
12+
"build:npx": "tsc --build tsconfig.json",
13+
"clean": "rm -r dist/",
1214
"prepublishOnly": "npm run build",
1315
"test": "npm run build:grammar; jest --config ./tests/jest.config.js",
1416
"typecheck": "npm run build:grammar; tsc --skipLibCheck",
@@ -17,6 +19,9 @@
1719
"format:check": "prettier --check {src,tests}/**",
1820
"format:fix": "prettier --write {src,tests}/**"
1921
},
22+
"bin": {
23+
"@openfga/syntax-transformer": "./dist/bin/index.js"
24+
},
2025
"keywords": [
2126
"openfga",
2227
"authorization",
@@ -28,6 +33,7 @@
2833
"author": "OpenFGA",
2934
"dependencies": {
3035
"@openfga/sdk": "^0.2.0",
36+
"assert-never": "^1.2.1",
3137
"nearley": "^2.20.1"
3238
},
3339
"devDependencies": {

src/bin/index.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env node
2+
3+
import yargs from "yargs";
4+
import { hideBin } from "yargs/helpers";
5+
import { commands } from "../cmds";
6+
7+
yargs(hideBin(process.argv))
8+
.command(commands as any)
9+
.demandCommand()
10+
.recommendCommands()
11+
.strict()
12+
.help()
13+
.completion().argv;

src/cmds/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* eslint-disable import/namespace */
2+
import { CommandModule } from "yargs";
3+
import * as transform from "./transform";
4+
5+
export const commands: CommandModule[] = [transform as CommandModule];

src/cmds/transform.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { readFile } from "fs/promises";
2+
import { Options as YargsOptions } from "yargs";
3+
4+
import checkDSL from "../validator";
5+
import transformSyntax from "../transformer";
6+
import { assertNever } from "assert-never";
7+
8+
type fromOption = "dsl" | "json";
9+
10+
interface CommandArgs {
11+
from: fromOption;
12+
inputFile: string;
13+
}
14+
15+
exports.command = "transform";
16+
exports.desc = "Transform ";
17+
exports.builder = {
18+
from: {
19+
describe: "whether we want to transform from dsl or json",
20+
choices: ["dsl", "json"],
21+
required: true,
22+
},
23+
inputFile: {
24+
describe: "Configuration file. It must be in DSL syntax.",
25+
type: "string",
26+
required: true,
27+
},
28+
} as Record<keyof CommandArgs, YargsOptions>;
29+
30+
async function loadFile(inputFile: string) {
31+
return readFile(inputFile, "utf-8");
32+
}
33+
34+
exports.handler = async (argv: CommandArgs) => {
35+
try {
36+
const fileContents = await loadFile(argv.inputFile);
37+
switch (argv.from) {
38+
case "dsl": {
39+
const validateResult = checkDSL.checkDSL(fileContents);
40+
if (validateResult.length) {
41+
throw new Error(`Invalid DSL with error ${JSON.stringify(validateResult)}`);
42+
}
43+
const transformedResult = transformSyntax.friendlySyntaxToApiSyntax(fileContents);
44+
console.log(JSON.stringify(transformedResult, null, 4));
45+
break;
46+
}
47+
case "json": {
48+
const transformedResult = transformSyntax.apiSyntaxToFriendlySyntax(JSON.parse(fileContents));
49+
console.log(transformedResult);
50+
break;
51+
}
52+
default:
53+
assertNever(argv.from);
54+
}
55+
} catch (err) {
56+
console.error(err as Error);
57+
process.exitCode = 1;
58+
}
59+
};

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/usr/bin/env node
12
import constants, { enums } from "./constants";
23
import formatter from "./formatter";
34
import transformer from "./transformer";

src/samples/index.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ type AuthorizationModel = {
55
type_definitions: TypeDefinition[];
66
};
77

8-
const entitlements = import("./entitlements.json") as Promise<AuthorizationModel>;
8+
const entitlements = import("./entitlements.json") as unknown as Promise<AuthorizationModel>;
99
const expenses = import("./expenses.json") as any as Promise<AuthorizationModel>;
10-
const gdrive = import("./gdrive.json") as Promise<AuthorizationModel>;
11-
const generic = import("./generic.json") as Promise<AuthorizationModel>;
12-
const github = import("./github.json") as Promise<AuthorizationModel>;
10+
const gdrive = import("./gdrive.json") as unknown as Promise<AuthorizationModel>;
11+
const generic = import("./generic.json") as unknown as Promise<AuthorizationModel>;
12+
const github = import("./github.json") as unknown as Promise<AuthorizationModel>;
1313
const iot = import("./iot.json") as Promise<AuthorizationModel>;
14-
const slack = import("./slack.json") as Promise<AuthorizationModel>;
15-
const customRoles = import("./custom-roles.json") as Promise<AuthorizationModel>;
14+
const slack = import("./slack.json") as unknown as Promise<AuthorizationModel>;
15+
const customRoles = import("./custom-roles.json") as unknown as Promise<AuthorizationModel>;
1616

1717
const sampleAuthorizationModels: Record<string, Promise<Required<Omit<AuthorizationModel, "id">>>> = {
1818
entitlements,

tsconfig.json

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"compilerOptions": {
33
"declaration": true,
4+
"moduleResolution": "node",
5+
"esModuleInterop": true,
46
"target": "es6",
57
"module": "commonjs",
68
"resolveJsonModule": true,

0 commit comments

Comments
 (0)