-
-
Notifications
You must be signed in to change notification settings - Fork 635
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement TypeScript transformer to auto-implement argument che…
…cks based on types (#4394)
- Loading branch information
Showing
30 changed files
with
5,763 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "@zwave-js/transformers", | ||
"version": "9.0.0-beta.7", | ||
"description": "zwave-js: compile-time transformers", | ||
"private": true, | ||
"keywords": [], | ||
"main": "build/index.js", | ||
"types": "build/index.d.ts", | ||
"files": [ | ||
"build/**/*.{js,d.ts,map}" | ||
], | ||
"author": { | ||
"name": "AlCalzone", | ||
"email": "[email protected]" | ||
}, | ||
"license": "MIT", | ||
"homepage": "https://github.com/AlCalzone/node-zwave-js#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/AlCalzone/node-zwave-js.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/AlCalzone/node-zwave-js/issues" | ||
}, | ||
"funding": { | ||
"url": "https://github.com/sponsors/AlCalzone/" | ||
}, | ||
"engines": { | ||
"node": ">=12.22.2 <13 || >=14.13.0 <15 || >= 16 <16.9.0 || >16.9.0" | ||
}, | ||
"scripts": { | ||
"build": "tsc -b tsconfig.build.json --verbose", | ||
"clean": "yarn run build --clean", | ||
"watch": "yarn run build --watch --pretty", | ||
"test": "yarn run build && tsc -p tsconfig.test.json; node test/test1" | ||
}, | ||
"devDependencies": { | ||
"tsutils": "^3.21.0", | ||
"typescript": "4.6.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// function checkGetErrorObject( | ||
// getErrorObject: unknown, | ||
// ): asserts getErrorObject is (obj: any) => any { | ||
// if (typeof getErrorObject !== "function") { | ||
// throw new Error( | ||
// "This module should not be used in runtime. Instead, use a transformer during compilation.", | ||
// ); | ||
// } | ||
// } | ||
|
||
// /** | ||
// * Checks if the given argument is assignable to the given type-argument. | ||
// * | ||
// * @param object object whose type needs to be checked. | ||
// * @returns `true` if `object` is assignable to `T`, false otherwise. | ||
// * @example | ||
// ``` | ||
// is<number>(42); // -> true | ||
// is<number>('foo'); // -> false | ||
// ``` | ||
// */ | ||
// export function is<T>(object: any): object is T; | ||
// export function is<T>(obj: any, getErrorObject?: (obj: any) => any): obj is T { | ||
// checkGetErrorObject(getErrorObject); | ||
// const errorObject = getErrorObject(obj); | ||
// return errorObject === null; | ||
// } | ||
|
||
// /** | ||
// * Creates a function similar to `is<T>` that can be invoked at a later point. | ||
// * | ||
// * This is useful, for example, if you want to re-use the function multiple times. | ||
// * | ||
// * @example | ||
// ``` | ||
// const checkNumber = createIs<number>(); | ||
// checkNumber(42); // -> true | ||
// checkNumber('foo'); // -> false | ||
// ``` | ||
// */ | ||
// export function createIs<T>(): (object: any) => object is T; | ||
// export function createIs<T>( | ||
// getErrorObject = undefined, | ||
// ): (object: any) => object is T { | ||
// checkGetErrorObject(getErrorObject); | ||
// // @ts-expect-error We're using an internal signature | ||
// return (obj) => is(obj, getErrorObject); | ||
// } | ||
|
||
/** Generates code at build time which validates all arguments of this method */ | ||
export function validateArgs(): PropertyDecorator { | ||
return (_target: unknown, _property: string | number | symbol) => { | ||
// this is a no-op that gets replaced during the build process using the transformer below | ||
// Throw an error when this doesn't get transformed | ||
throw new Error( | ||
"validateArgs is a compile-time decorator and must be compiled with a transformer", | ||
); | ||
}; | ||
} | ||
|
||
import transformer from "./validateArgs/transformer"; | ||
export default transformer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# validateArgs | ||
|
||
TypeScript transformer that generates run-time type-checks, based on https://github.com/woutervh-/typescript-is | ||
|
||
Usage: | ||
|
||
```ts | ||
import { validateArgs } from "@zwave-js/transformers"; | ||
|
||
class Test { | ||
@validateArgs() | ||
foo(arg1: number, arg2: Foo, arg3: Foo & Bar): void { | ||
// implementation | ||
} | ||
} | ||
``` | ||
|
||
The import and the decorator call will be removed and the function body of `foo` will be prepended with assertions for each of the arguments. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
export interface ExpectedFunction { | ||
type: "function"; | ||
} | ||
|
||
export interface ExpectedString { | ||
type: "string"; | ||
} | ||
|
||
export interface ExpectedNumber { | ||
type: "number"; | ||
} | ||
|
||
export interface ExpectedBigInt { | ||
type: "big-int"; | ||
} | ||
|
||
export interface ExpectedBoolean { | ||
type: "boolean"; | ||
} | ||
|
||
export interface ExpectedStringLiteral { | ||
type: "string-literal"; | ||
value: string; | ||
} | ||
|
||
export interface ExpectedNumberLiteral { | ||
type: "number-literal"; | ||
value: number; | ||
} | ||
|
||
export interface ExpectedBooleanLiteral { | ||
type: "boolean-literal"; | ||
value: boolean; | ||
} | ||
|
||
export interface ExpectedObject { | ||
type: "object"; | ||
} | ||
|
||
export interface ExpectedDate { | ||
type: "date"; | ||
} | ||
|
||
export interface ExpectedNonPrimitive { | ||
type: "non-primitive"; | ||
} | ||
|
||
export interface MissingObjectProperty { | ||
type: "missing-property"; | ||
property: string; | ||
} | ||
|
||
export interface SuperfluousObjectProperty { | ||
type: "superfluous-property"; | ||
} | ||
|
||
export interface ExpectedObjectKeyof { | ||
type: "object-keyof"; | ||
properties: string[]; | ||
} | ||
|
||
export interface ExpectedArray { | ||
type: "array"; | ||
} | ||
|
||
export interface NeverType { | ||
type: "never"; | ||
} | ||
|
||
export interface ExpectedTuple { | ||
type: "tuple"; | ||
minLength: number; | ||
maxLength: number; | ||
} | ||
|
||
export interface NoValidUnionAlternatives { | ||
type: "union"; | ||
} | ||
|
||
export interface ExpectedUndefined { | ||
type: "undefined"; | ||
} | ||
|
||
export interface ExpectedNull { | ||
type: "null"; | ||
} | ||
|
||
export type TemplateLiteralPair = [ | ||
string, | ||
"string" | "number" | "bigint" | "any" | "undefined" | "null" | undefined, | ||
]; | ||
|
||
export interface ExpectedTemplateLiteral { | ||
type: "template-literal"; | ||
value: TemplateLiteralPair[]; | ||
} | ||
|
||
export type Reason = | ||
| ExpectedFunction | ||
| ExpectedString | ||
| ExpectedNumber | ||
| ExpectedBigInt | ||
| ExpectedBoolean | ||
| ExpectedObject | ||
| ExpectedDate | ||
| ExpectedNonPrimitive | ||
| MissingObjectProperty | ||
| SuperfluousObjectProperty | ||
| ExpectedObjectKeyof | ||
| ExpectedArray | ||
| ExpectedTuple | ||
| NeverType | ||
| NoValidUnionAlternatives | ||
| ExpectedUndefined | ||
| ExpectedNull | ||
| ExpectedStringLiteral | ||
| ExpectedNumberLiteral | ||
| ExpectedBooleanLiteral | ||
| ExpectedTemplateLiteral; |
Oops, something went wrong.