Skip to content

Commit

Permalink
Merge pull request #60 from GoogleFeud/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
GoogleFeud authored Jul 19, 2024
2 parents b7cfc8d + dcd838c commit 488db2c
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 40 deletions.
8 changes: 4 additions & 4 deletions docs/package-lock.json

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

2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5"
"typescript": "^5.5.3"
},
"devDependencies": {
"@types/js-beautify": "^1.14.3"
Expand Down
46 changes: 23 additions & 23 deletions package-lock.json

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

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-runtime-checks",
"version": "0.6.0",
"version": "0.6.1",
"description": "A typescript transformer which automatically generates validation code from your types.",
"main": "dist/index.js",
"scripts": {
Expand Down Expand Up @@ -33,7 +33,7 @@
"@types/diff": "^5.0.2",
"@types/mocha": "^9.1.0",
"@types/node": "^20.3.0",
"@types/ts-expose-internals": "npm:ts-expose-internals@^5.4.3",
"@types/ts-expose-internals": "npm:ts-expose-internals@^5.5.3",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"chai": "^4.3.6",
Expand All @@ -43,7 +43,7 @@
"mitata": "^0.1.6",
"mocha": "^9.2.2",
"prettier": "^3.2.5",
"ts-patch": "^3.1.1",
"typescript": "^5.4.3"
"ts-patch": "^3.2.1",
"typescript": "^5.5.3"
}
}
1 change: 0 additions & 1 deletion src/gen/expressionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ export function _val(val: unknown) : ts.Expression {
}

export function _arr(array: Array<unknown>) : ts.Expression {
console.log(array.map(val => _val(val)));
return ts.factory.createArrayLiteralExpression(array.map(val => _val(val)));
}

Expand Down
11 changes: 7 additions & 4 deletions src/transformer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ts from "typescript";
import * as Block from "./block";
import {FnCallFn, Functions, MarkerCallData, MarkerFn, Markers} from "./markers";
import {TransformerError, getResolvedTypesFromCallSig, hasBit, importSymbol, resolveAsChain} from "./utils";
import {TransformerError, cloneNodeWithoutOriginal, getResolvedTypesFromCallSig, hasBit, importSymbol, resolveAsChain} from "./utils";
import {UNDEFINED, _var} from "./gen/expressionUtils";
import {CodeReference, ResolveTypeData, Validator, genValidator} from "./gen/validators";
import {ValidationResultType, createContext, fullValidate} from "./gen/nodes";
Expand Down Expand Up @@ -279,13 +279,16 @@ export class Transformer {
const result = ts.createSourceFile("expr", str, ts.ScriptTarget.ESNext, false, ts.ScriptKind.JS);
const firstStmt = result.statements[0];
if (!firstStmt || !ts.isExpressionStatement(firstStmt)) return UNDEFINED;
//console.dir(firstStmt, { depth: 3});
const visitor = (node: ts.Node): ts.Node => {
if (ts.isIdentifier(node)) {
if (replacements && replacements[node.text] && typeof replacements[node.text] === "object") return replacements[node.text] as ts.Expression;
if (replacements && replacements[node.text] && typeof replacements[node.text] === "object") return ts.factory.cloneNode(replacements[node.text] as ts.Expression);
return ts.factory.createIdentifier(node.text);
} else if (replacements && ts.isCallExpression(node) && ts.isIdentifier(node.expression) && replacements[node.expression.text] && typeof replacements[node.expression.text] === "function")
}
else if (replacements && ts.isCallExpression(node) && ts.isIdentifier(node.expression) && replacements[node.expression.text] && typeof replacements[node.expression.text] === "function") {
return (replacements[node.expression.text] as (...args: ts.Expression[]) => ts.Node)(...node.arguments);
return ts.visitEachChild(ts.factory.cloneNode(node), visitor, this.ctx);
}
return ts.visitEachChild(cloneNodeWithoutOriginal(node), visitor, this.ctx);
};
return ts.visitNode(firstStmt.expression, visitor) as ts.Expression;
}
Expand Down
6 changes: 6 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,9 @@ export function addArticle(msg: string): string {
if (firstLetter === "a" || firstLetter === "e" || firstLetter === "o" || firstLetter === "i" || firstLetter === "u") return `an ${msg}`;
return `a ${msg}`;
}

export function cloneNodeWithoutOriginal(node: ts.Node) : ts.Node {
const cloned = ts.factory.cloneNode(node);
delete cloned.original;
return cloned;
}
28 changes: 25 additions & 3 deletions tests/integrated/utilities/check.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { Assert, Max, MaxLen, Min, Check } from "../../../dist/index";
import type { Assert, Max, MaxLen, Min, Check, MinLen } from "../../../dist/index";
import { call } from "../../utils";
import { expect } from "chai";

type StartsWith<T extends string> = Check<`$self.startsWith("${T}")`, `to start with "${T}"`, "startsWith", T>;
type AmountOfProps<T extends number> = Check<`Object.keys($self).length === ${T}`, `to have exactly ${T} keys`>;

describe("Check", () => {
describe("Assert", () => {
function test(a: Assert<number & Min<5> & Max<15>>) {
Expand All @@ -14,8 +17,6 @@ describe("Check", () => {
expect(call(test, 3)).to.throw("Expected a to be a number, to be greater than 5 & to be less than 15");
});

type AmountOfProps<T extends number> = Check<`Object.keys($self).length === ${T}`, `to have exactly ${T} keys`>;

function test1(a: Assert<{
one: (string & MaxLen<6>)[],
two: { a: string, b: number, c: boolean} & AmountOfProps<3>
Expand All @@ -37,6 +38,27 @@ describe("Check", () => {
two: { a: "a", b: 123, c: true, d: false }
})()).to.equal(false);
});

function test2(a: Assert<string & MinLen<3> | number & Min<3>, false>) {
return true;
}

it("Conditional checks between different types", () => {
expect(call(test2, "abcdef")()).to.equal(true);
expect(call(test2, 5)()).to.equal(true);
expect(call(test2, "ab")()).to.equal(false);
expect(call(test2, 1)()).to.equal(false);
});

function test3(a: Assert<string & (MaxLen<3> | StartsWith<"a">), false>) {
return true;
}

it("Conditional checks between the same type", () => {
expect(call(test3, "de")()).to.equal(true);
expect(call(test3, "abcdef")()).to.equal(true);
expect(call(test3, "efeew3e")()).to.equal(false);
expect(call(test3, 123)()).to.equal(false);
});
});
});
22 changes: 22 additions & 0 deletions tests/snapshots/artifacts/utilities_check.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,27 @@ describe("Check", () => {
two: { a: "a", b: 123, c: true, d: false }
})()).to.equal(false);
});
function test2(a) {
if ((typeof a !== "string" || a.length < 3) && (typeof a !== "number" || a < 3))
return false;
return true;
}
it("Conditional checks between different types", () => {
(0, chai_1.expect)((0, utils_1.call)(test2, "abcdef")()).to.equal(true);
(0, chai_1.expect)((0, utils_1.call)(test2, 5)()).to.equal(true);
(0, chai_1.expect)((0, utils_1.call)(test2, "ab")()).to.equal(false);
(0, chai_1.expect)((0, utils_1.call)(test2, 1)()).to.equal(false);
});
function test3(a) {
if (typeof a !== "string" || a.length > 3 && !a.startsWith("a"))
return false;
return true;
}
it("Conditional checks between the same type", () => {
(0, chai_1.expect)((0, utils_1.call)(test3, "de")()).to.equal(true);
(0, chai_1.expect)((0, utils_1.call)(test3, "abcdef")()).to.equal(true);
(0, chai_1.expect)((0, utils_1.call)(test3, "efeew3e")()).to.equal(false);
(0, chai_1.expect)((0, utils_1.call)(test3, 123)()).to.equal(false);
});
});
});

0 comments on commit 488db2c

Please sign in to comment.