runtypex 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/esm/core/index.js +5 -5
  2. package/dist/esm/index.js +3 -3
  3. package/dist/esm/transformer/ts-transformer.js +1 -1
  4. package/dist/esm/transformer/vite-plugin.js +1 -1
  5. package/package.json +20 -21
  6. package/dist/cjs/core/emitArrayOrTuple.d.ts +0 -6
  7. package/dist/cjs/core/emitArrayOrTuple.js +0 -40
  8. package/dist/cjs/core/emitLiteralOrEnum.d.ts +0 -4
  9. package/dist/cjs/core/emitLiteralOrEnum.js +0 -47
  10. package/dist/cjs/core/emitObject.d.ts +0 -6
  11. package/dist/cjs/core/emitObject.js +0 -28
  12. package/dist/cjs/core/emitPrimitive.d.ts +0 -6
  13. package/dist/cjs/core/emitPrimitive.js +0 -29
  14. package/dist/cjs/core/emitUnionOrIntersection.d.ts +0 -6
  15. package/dist/cjs/core/emitUnionOrIntersection.js +0 -15
  16. package/dist/cjs/core/index.d.ts +0 -17
  17. package/dist/cjs/core/index.js +0 -41
  18. package/dist/cjs/index.d.ts +0 -3
  19. package/dist/cjs/index.js +0 -13
  20. package/dist/cjs/runtime/validate.d.ts +0 -10
  21. package/dist/cjs/runtime/validate.js +0 -18
  22. package/dist/cjs/transformer/ts-transformer.d.ts +0 -25
  23. package/dist/cjs/transformer/ts-transformer.js +0 -103
  24. package/dist/cjs/transformer/vite-plugin.d.ts +0 -18
  25. package/dist/cjs/transformer/vite-plugin.js +0 -137
  26. package/dist/core/emitArrayOrTuple.d.ts +0 -6
  27. package/dist/core/emitArrayOrTuple.js +0 -38
  28. package/dist/core/emitArrayOrTuple.js.map +0 -1
  29. package/dist/core/emitLiteralOrEnum.d.ts +0 -4
  30. package/dist/core/emitLiteralOrEnum.js +0 -42
  31. package/dist/core/emitLiteralOrEnum.js.map +0 -1
  32. package/dist/core/emitObject.d.ts +0 -6
  33. package/dist/core/emitObject.js +0 -23
  34. package/dist/core/emitObject.js.map +0 -1
  35. package/dist/core/emitPrimitive.d.ts +0 -6
  36. package/dist/core/emitPrimitive.js +0 -24
  37. package/dist/core/emitPrimitive.js.map +0 -1
  38. package/dist/core/emitUnionOrIntersection.d.ts +0 -6
  39. package/dist/core/emitUnionOrIntersection.js +0 -13
  40. package/dist/core/emitUnionOrIntersection.js.map +0 -1
  41. package/dist/core/index.d.ts +0 -17
  42. package/dist/core/index.js +0 -37
  43. package/dist/core/index.js.map +0 -1
  44. package/dist/index.d.ts +0 -3
  45. package/dist/index.js +0 -4
  46. package/dist/index.js.map +0 -1
  47. package/dist/runtime/validate.d.ts +0 -10
  48. package/dist/runtime/validate.js +0 -15
  49. package/dist/runtime/validate.js.map +0 -1
  50. package/dist/transformer/ts-transformer.d.ts +0 -25
  51. package/dist/transformer/ts-transformer.js +0 -98
  52. package/dist/transformer/ts-transformer.js.map +0 -1
  53. package/dist/transformer/vite-plugin.d.ts +0 -18
  54. package/dist/transformer/vite-plugin.js +0 -132
  55. package/dist/transformer/vite-plugin.js.map +0 -1
@@ -1,8 +1,8 @@
1
- import { emitPrimitive } from "./emitPrimitive";
2
- import { emitLiteralOrEnum } from "./emitLiteralOrEnum";
3
- import { emitUnionOrIntersection } from "./emitUnionOrIntersection";
4
- import { emitArrayOrTuple } from "./emitArrayOrTuple";
5
- import { emitObject } from "./emitObject";
1
+ import { emitPrimitive } from "./emitPrimitive.js";
2
+ import { emitLiteralOrEnum } from "./emitLiteralOrEnum.js";
3
+ import { emitUnionOrIntersection } from "./emitUnionOrIntersection.js";
4
+ import { emitArrayOrTuple } from "./emitArrayOrTuple.js";
5
+ import { emitObject } from "./emitObject.js";
6
6
  /**
7
7
  * ✅ emitGuardFromType
8
8
  * Converts a TypeScript type to a JavaScript runtime validation function string.
package/dist/esm/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { makeValidate, makeAssert } from "./runtime/validate";
2
- export { default as vitePlugin } from "./transformer/vite-plugin";
3
- export { default as tsTransformer } from "./transformer/ts-transformer";
1
+ export { makeValidate, makeAssert } from "./runtime/validate.js";
2
+ export { default as vitePlugin } from "./transformer/vite-plugin.js";
3
+ export { default as tsTransformer } from "./transformer/ts-transformer.js";
@@ -1,5 +1,5 @@
1
1
  import ts from "typescript";
2
- import { emitGuardFromType } from "../core";
2
+ import { emitGuardFromType } from "../core/index.js";
3
3
  /**
4
4
  * 🧩 tsTransformer
5
5
  * TypeScript custom transformer (BEFORE) factory.
@@ -1,6 +1,6 @@
1
1
  import ts from "typescript";
2
2
  import path from "node:path";
3
- import { emitGuardFromType } from "../core";
3
+ import { emitGuardFromType } from "../core/index.js";
4
4
  /**
5
5
  * 🧩 vitePluginRuntypex
6
6
  * A Vite plugin that performs build-time type → runtime validation transformation.
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "runtypex",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Runtime type guards compiled from TypeScript types. Fast, zero-schema, transformer-based.",
5
5
  "license": "MIT",
6
6
  "author": "KumJunMin",
7
- "type": "module",
8
7
  "sideEffects": false,
9
8
  "main": "./dist/cjs/index.js",
10
9
  "module": "./dist/esm/index.js",
@@ -13,27 +12,24 @@
13
12
  "type": "git",
14
13
  "url": "https://example.com/runtypex.git"
15
14
  },
16
- "bugs": {
15
+ "bugs": {
17
16
  "url": "https://github.com/KumJungMin/runtypex/issues"
18
17
  },
19
18
  "exports": {
20
19
  ".": {
21
- "import": "./dist/esm/index.js",
22
- "require": "./dist/cjs/index.js",
23
- "types": "./dist/esm/index.d.ts"
20
+ "import": "./dist/esm/index.js",
21
+ "types": "./dist/esm/index.d.ts"
22
+ },
23
+ "./runtime": {
24
+ "import": "./dist/esm/runtime/index.js",
25
+ "types": "./dist/esm/runtime/index.d.ts"
26
+ },
27
+ "./transformer": {
28
+ "import": "./dist/esm/transformer/index.js",
29
+ "types": "./dist/esm/transformer/index.d.ts"
30
+ }
24
31
  },
25
- "./runtime": {
26
- "import": "./dist/esm/runtime/index.js",
27
- "require": "./dist/cjs/runtime/index.js",
28
- "types": "./dist/esm/runtime/index.d.ts"
29
- },
30
- "./transformer": {
31
- "import": "./dist/esm/transformer/index.js",
32
- "require": "./dist/cjs/transformer/index.js",
33
- "types": "./dist/esm/transformer/index.d.ts"
34
- }
35
- },
36
- "keywords": [
32
+ "keywords": [
37
33
  "typescript",
38
34
  "runtime",
39
35
  "type-check",
@@ -45,12 +41,13 @@
45
41
  "files": [
46
42
  "dist"
47
43
  ],
48
- "publishConfig": {
44
+ "publishConfig": {
49
45
  "access": "public"
50
46
  },
51
47
  "scripts": {
52
48
  "clean": "rm -rf dist",
53
- "build": "tsc && tsc -p tsconfig.build.json",
49
+ "build:transformer": "tsc -p scripts/tsconfig.json",
50
+ "build": "npm run build:transformer && tsc -p tsconfig.build.json",
54
51
  "test": "jest --passWithNoTests"
55
52
  },
56
53
  "peerDependencies": {
@@ -61,6 +58,8 @@
61
58
  "@types/node": "^22.8.0",
62
59
  "jest": "^29.7.0",
63
60
  "ts-jest": "^29.2.5",
64
- "typescript": "^5.6.3"
61
+ "ts-node": "^10.9.2",
62
+ "ts-patch": "^3.3.0",
63
+ "typescript": "^5.9.3"
65
64
  }
66
65
  }
@@ -1,6 +0,0 @@
1
- import ts from "typescript";
2
- import type { GenContext } from "./index";
3
- /**
4
- * Handles array (T[]) and tuple ([A, B]) types.
5
- */
6
- export declare function emitArrayOrTuple(ctx: GenContext, expr: string, t: ts.Type): string | null;
@@ -1,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.emitArrayOrTuple = emitArrayOrTuple;
4
- /**
5
- * Handles array (T[]) and tuple ([A, B]) types.
6
- */
7
- function emitArrayOrTuple(ctx, expr, t) {
8
- if (ctx.checker.isTupleType(t)) {
9
- return _emitTuple(t, expr, ctx);
10
- }
11
- if (ctx.checker.isArrayType(t)) {
12
- return _emitArray(ctx, expr, t);
13
- }
14
- return null;
15
- }
16
- /**
17
- * Generate validation for Array<T>
18
- */
19
- function _emitArray(ctx, expr, t) {
20
- const arrayCheck = `Array.isArray(${expr})`;
21
- // Try extracting element type
22
- const element = ctx.checker.getElementTypeOfArrayType?.(t) ||
23
- t.typeArguments?.[0] ||
24
- t.getNumberIndexType?.();
25
- if (!element)
26
- return arrayCheck;
27
- const eachCheck = `${expr}.every(e=>${ctx.emit("e", element)})`;
28
- return `(${arrayCheck}&&${eachCheck})`;
29
- }
30
- /**
31
- * Generate validation for Tuple [A, B, ...]
32
- */
33
- function _emitTuple(ref, expr, ctx) {
34
- const elements = ref.typeArguments ?? ctx.checker.getTypeArguments?.(ref) ?? [];
35
- const arrayCheck = `Array.isArray(${expr})`;
36
- const lenCheck = `${expr}.length===${elements.length}`;
37
- const elementChecks = elements.map((el, i) => ctx.emit(`${expr}[${i}]`, el));
38
- const parts = [arrayCheck, lenCheck, ...elementChecks];
39
- return `(${parts.join("&&")})`;
40
- }
@@ -1,4 +0,0 @@
1
- import ts from "typescript";
2
- import type { GenContext } from "./index";
3
- /** Handles literal types and enum-like types. */
4
- export declare function emitLiteralOrEnum(_: GenContext, expr: string, t: ts.Type): string | null;
@@ -1,47 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.emitLiteralOrEnum = emitLiteralOrEnum;
7
- const typescript_1 = __importDefault(require("typescript"));
8
- /** Handles literal types and enum-like types. */
9
- function emitLiteralOrEnum(_, expr, t) {
10
- if (t.isLiteral()) {
11
- const value = t.value;
12
- const isString = typeof value === "string";
13
- const newValue = isString ? JSON.stringify(value) : String(value);
14
- return `${expr}===${newValue}`;
15
- }
16
- const isEnum = t.flags & typescript_1.default.TypeFlags.EnumLike;
17
- if (isEnum) {
18
- const enumValues = _extractEnumValues(t);
19
- if (enumValues.length) {
20
- return `(${enumValues.map(v => `${expr}===${v}`).join("||")})`;
21
- }
22
- }
23
- return null;
24
- }
25
- // Extracts numeric or string values from an Enum declaration.
26
- function _extractEnumValues(t) {
27
- const symbol = t.getSymbol();
28
- if (!symbol)
29
- return [];
30
- const values = [];
31
- const declarations = symbol.getDeclarations() ?? [];
32
- for (const declaration of declarations) {
33
- const isEnum = typescript_1.default.isEnumDeclaration(declaration);
34
- if (!isEnum)
35
- continue;
36
- for (const member of declaration.members) {
37
- const init = member.initializer;
38
- if (!init)
39
- continue;
40
- if (typescript_1.default.isStringLiteral(init) || typescript_1.default.isNumericLiteral(init)) {
41
- const value = typescript_1.default.isStringLiteral(init) ? JSON.stringify(init.text) : init.text;
42
- values.push(value);
43
- }
44
- }
45
- }
46
- return values;
47
- }
@@ -1,6 +0,0 @@
1
- import ts from "typescript";
2
- import type { GenContext } from "./index";
3
- /**
4
- * Handles interfaces, classes, and object-like structures.
5
- */
6
- export declare function emitObject(ctx: GenContext, expr: string, t: ts.Type): string | null;
@@ -1,28 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.emitObject = emitObject;
7
- const typescript_1 = __importDefault(require("typescript"));
8
- /**
9
- * Handles interfaces, classes, and object-like structures.
10
- */
11
- function emitObject(ctx, expr, t) {
12
- const isObject = (t.getFlags() & typescript_1.default.TypeFlags.Object) !== 0;
13
- if (!isObject)
14
- return null;
15
- const props = ctx.checker.getPropertiesOfType(t);
16
- const parts = [`typeof ${expr}==="object"`, `${expr}!==null`];
17
- for (const prop of props) {
18
- const declaration = prop.valueDeclaration ?? prop.declarations?.[0];
19
- if (!declaration)
20
- continue;
21
- const propType = ctx.checker.getTypeOfSymbolAtLocation(prop, declaration);
22
- const isOptional = (prop.getFlags() & typescript_1.default.SymbolFlags.Optional) !== 0;
23
- const condition = ctx.emit(`${expr}.${prop.name}`, propType);
24
- const checkExpr = isOptional ? `(${expr}.${prop.name}===undefined||${condition})` : condition;
25
- parts.push(checkExpr);
26
- }
27
- return `(${parts.join("&&")})`;
28
- }
@@ -1,6 +0,0 @@
1
- import ts from "typescript";
2
- import type { GenContext } from "./index";
3
- /**
4
- * Handles primitive types like number, string, boolean...
5
- */
6
- export declare function emitPrimitive(ctx: GenContext, expr: string, t: ts.Type): string | null;
@@ -1,29 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.emitPrimitive = emitPrimitive;
7
- const typescript_1 = __importDefault(require("typescript"));
8
- /**
9
- * Handles primitive types like number, string, boolean...
10
- */
11
- function emitPrimitive(ctx, expr, t) {
12
- if ((t.flags & (typescript_1.default.TypeFlags.Any | typescript_1.default.TypeFlags.Unknown)) !== 0)
13
- return "true";
14
- if (t.flags & typescript_1.default.TypeFlags.Null)
15
- return `${expr}===null`;
16
- if (t.flags & typescript_1.default.TypeFlags.Undefined)
17
- return `${expr}===undefined`;
18
- if (t.flags & typescript_1.default.TypeFlags.BooleanLike)
19
- return `typeof ${expr}==="boolean"`;
20
- if (t.flags & typescript_1.default.TypeFlags.NumberLike)
21
- return `typeof ${expr}==="number"`;
22
- if (t.flags & typescript_1.default.TypeFlags.StringLike)
23
- return `typeof ${expr}==="string"`;
24
- if (t.flags & typescript_1.default.TypeFlags.BigIntLike)
25
- return `typeof ${expr}==="bigint"`;
26
- if (t.flags & typescript_1.default.TypeFlags.ESSymbolLike)
27
- return `typeof ${expr}==="symbol"`;
28
- return null;
29
- }
@@ -1,6 +0,0 @@
1
- import ts from "typescript";
2
- import type { GenContext } from "./index";
3
- /**
4
- * Handles union (A | B) and intersection (A & B) types.
5
- */
6
- export declare function emitUnionOrIntersection(ctx: GenContext, expr: string, t: ts.Type): string | null;
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.emitUnionOrIntersection = emitUnionOrIntersection;
4
- /**
5
- * Handles union (A | B) and intersection (A & B) types.
6
- */
7
- function emitUnionOrIntersection(ctx, expr, t) {
8
- if (t.isUnion()) {
9
- return `(${t.types.map(tt => ctx.emit(expr, tt)).join("||")})`;
10
- }
11
- if (t.isIntersection()) {
12
- return `(${t.types.map(tt => ctx.emit(expr, tt)).join("&&")})`;
13
- }
14
- return null;
15
- }
@@ -1,17 +0,0 @@
1
- import ts from "typescript";
2
- /**
3
- * ✅ emitGuardFromType
4
- * Converts a TypeScript type to a JavaScript runtime validation function string.
5
- */
6
- export declare function emitGuardFromType(checker: ts.TypeChecker, type: ts.Type): string;
7
- /**
8
- * ✅ GenContext
9
- * Internal helper for converting TypeScript types to JS validation expressions.
10
- */
11
- export declare class GenContext {
12
- checker: ts.TypeChecker;
13
- private seen;
14
- constructor(checker: ts.TypeChecker);
15
- /** Top-level router — delegates each type to the correct handler. */
16
- emit(expr: string, t: ts.Type): string;
17
- }
@@ -1,41 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GenContext = void 0;
4
- exports.emitGuardFromType = emitGuardFromType;
5
- const emitPrimitive_1 = require("./emitPrimitive");
6
- const emitLiteralOrEnum_1 = require("./emitLiteralOrEnum");
7
- const emitUnionOrIntersection_1 = require("./emitUnionOrIntersection");
8
- const emitArrayOrTuple_1 = require("./emitArrayOrTuple");
9
- const emitObject_1 = require("./emitObject");
10
- /**
11
- * ✅ emitGuardFromType
12
- * Converts a TypeScript type to a JavaScript runtime validation function string.
13
- */
14
- function emitGuardFromType(checker, type) {
15
- const ctx = new GenContext(checker);
16
- const condition = ctx.emit("input", type);
17
- return `(input)=>${condition}`;
18
- }
19
- /**
20
- * ✅ GenContext
21
- * Internal helper for converting TypeScript types to JS validation expressions.
22
- */
23
- class GenContext {
24
- checker;
25
- seen = new Map();
26
- constructor(checker) {
27
- this.checker = checker;
28
- }
29
- /** Top-level router — delegates each type to the correct handler. */
30
- emit(expr, t) {
31
- if (this.seen.has(t))
32
- return this.seen.get(t);
33
- return ((0, emitPrimitive_1.emitPrimitive)(this, expr, t) ??
34
- (0, emitLiteralOrEnum_1.emitLiteralOrEnum)(this, expr, t) ??
35
- (0, emitUnionOrIntersection_1.emitUnionOrIntersection)(this, expr, t) ??
36
- (0, emitArrayOrTuple_1.emitArrayOrTuple)(this, expr, t) ??
37
- (0, emitObject_1.emitObject)(this, expr, t) ??
38
- "true");
39
- }
40
- }
41
- exports.GenContext = GenContext;
@@ -1,3 +0,0 @@
1
- export { makeValidate, makeAssert, type ValidateFn } from "./runtime/validate";
2
- export { default as vitePlugin } from "./transformer/vite-plugin";
3
- export { default as tsTransformer } from "./transformer/ts-transformer";
package/dist/cjs/index.js DELETED
@@ -1,13 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.tsTransformer = exports.vitePlugin = exports.makeAssert = exports.makeValidate = void 0;
7
- var validate_1 = require("./runtime/validate");
8
- Object.defineProperty(exports, "makeValidate", { enumerable: true, get: function () { return validate_1.makeValidate; } });
9
- Object.defineProperty(exports, "makeAssert", { enumerable: true, get: function () { return validate_1.makeAssert; } });
10
- var vite_plugin_1 = require("./transformer/vite-plugin");
11
- Object.defineProperty(exports, "vitePlugin", { enumerable: true, get: function () { return __importDefault(vite_plugin_1).default; } });
12
- var ts_transformer_1 = require("./transformer/ts-transformer");
13
- Object.defineProperty(exports, "tsTransformer", { enumerable: true, get: function () { return __importDefault(ts_transformer_1).default; } });
@@ -1,10 +0,0 @@
1
- /**
2
- * runtypex — runtime APIs
3
- * 1) makeValidate<T>() : (v) => v is T
4
- * 2) makeAssert<T>() : throws on invalid
5
- *
6
- * NOTE: These factories are replaced at build-time by the transformer.
7
- */
8
- export type ValidateFn<T> = (value: unknown) => value is T;
9
- export declare function makeValidate<T>(): ValidateFn<T>;
10
- export declare function makeAssert<T>(): (value: unknown) => asserts value is T;
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeValidate = makeValidate;
4
- exports.makeAssert = makeAssert;
5
- // Replaced by transformer to generated guard
6
- function __validate(_value) {
7
- throw new Error("[runtypex] makeValidate() was not transformed. Add the plugin/transformer.");
8
- }
9
- function makeValidate() {
10
- return (value) => __validate(value);
11
- }
12
- function makeAssert() {
13
- const validate = makeValidate();
14
- return (value) => {
15
- if (!validate(value))
16
- throw new TypeError("[runtypex] Validation failed.");
17
- };
18
- }
@@ -1,25 +0,0 @@
1
- import ts from "typescript";
2
- /**
3
- * 🧩 tsTransformer
4
- * TypeScript custom transformer (BEFORE) factory.
5
- *
6
- * 📘 Usage (ts-loader / ttypescript):
7
- * ```ts
8
- * getCustomTransformers: (program) => ({
9
- * before: [ tsTransformer({ program, removeInProd: true }) ]
10
- * })
11
- * ```
12
- *
13
- * 🧠 Purpose:
14
- * - Replace makeValidate<T>(), makeAssert<T>() calls
15
- * with *pre-generated runtime validation code* derived from T.
16
- *
17
- * 💡 Effect:
18
- * ✅ No reflection or runtime type parsing
19
- * ✅ Validation logic embedded at build-time
20
- * ✅ Optionally removed in production builds
21
- */
22
- export default function tsTransformer(options: {
23
- program: ts.Program;
24
- removeInProd?: boolean;
25
- }): (context: ts.TransformationContext) => (sf: ts.SourceFile) => ts.Node | undefined;
@@ -1,103 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.default = tsTransformer;
7
- const typescript_1 = __importDefault(require("typescript"));
8
- const core_1 = require("../core");
9
- /**
10
- * 🧩 tsTransformer
11
- * TypeScript custom transformer (BEFORE) factory.
12
- *
13
- * 📘 Usage (ts-loader / ttypescript):
14
- * ```ts
15
- * getCustomTransformers: (program) => ({
16
- * before: [ tsTransformer({ program, removeInProd: true }) ]
17
- * })
18
- * ```
19
- *
20
- * 🧠 Purpose:
21
- * - Replace makeValidate<T>(), makeAssert<T>() calls
22
- * with *pre-generated runtime validation code* derived from T.
23
- *
24
- * 💡 Effect:
25
- * ✅ No reflection or runtime type parsing
26
- * ✅ Validation logic embedded at build-time
27
- * ✅ Optionally removed in production builds
28
- */
29
- function tsTransformer(options) {
30
- const { program } = options;
31
- const checker = options.program.getTypeChecker();
32
- const removeInProd = !!options.removeInProd;
33
- const prod = process.env.NODE_ENV === "production";
34
- return (context) => {
35
- const visit = (node) => {
36
- if (typescript_1.default.isCallExpression(node) && typescript_1.default.isIdentifier(node.expression)) {
37
- const name = node.expression.text;
38
- const targetFunctions = ["makeValidate", "makeAssert"];
39
- if (targetFunctions.includes(name) && node.typeArguments?.length) {
40
- const typeNode = node.typeArguments[0];
41
- const typeName = typeNode.getText();
42
- const type = _resolveTypeByName(program, node.getSourceFile(), checker, typeName);
43
- if (!type)
44
- return node;
45
- const isRemovedInProd = removeInProd && prod;
46
- switch (name) {
47
- case "makeValidate":
48
- return _emitMakeValidate(checker, type, isRemovedInProd);
49
- case "makeAssert":
50
- return _emitMakeAssert(checker, type, isRemovedInProd);
51
- }
52
- }
53
- }
54
- return typescript_1.default.visitEachChild(node, visit, context);
55
- };
56
- return (sf) => typescript_1.default.visitNode(sf, visit);
57
- };
58
- }
59
- function _resolveTypeByName(program, sf, checker, name) {
60
- for (const file of program.getSourceFiles()) {
61
- const decl = _findLocalDeclaration(file, name);
62
- if (!decl)
63
- continue;
64
- if (typescript_1.default.isInterfaceDeclaration(decl) || typescript_1.default.isClassDeclaration(decl) || typescript_1.default.isEnumDeclaration(decl)) {
65
- // @ts-ignore
66
- const sym = checker.getSymbolAtLocation(decl.name);
67
- if (sym)
68
- return checker.getDeclaredTypeOfSymbol(sym);
69
- }
70
- if (typescript_1.default.isTypeAliasDeclaration(decl)) {
71
- return checker.getTypeFromTypeNode(decl.type);
72
- }
73
- }
74
- const sym = checker
75
- .getSymbolsInScope(sf, typescript_1.default.SymbolFlags.Type | typescript_1.default.SymbolFlags.Alias | typescript_1.default.SymbolFlags.Interface)
76
- .find((s) => s.name === name);
77
- return sym ? checker.getDeclaredTypeOfSymbol(sym) : null;
78
- }
79
- function _findLocalDeclaration(sf, name) {
80
- let found;
81
- (function walk(node) {
82
- if ((typescript_1.default.isInterfaceDeclaration(node) ||
83
- typescript_1.default.isTypeAliasDeclaration(node) ||
84
- typescript_1.default.isEnumDeclaration(node) ||
85
- typescript_1.default.isClassDeclaration(node)) &&
86
- node.name?.text === name) {
87
- found = node;
88
- return;
89
- }
90
- if (!found)
91
- node.forEachChild(walk);
92
- })(sf);
93
- return found;
94
- }
95
- function _emitMakeValidate(checker, type, isRemovedInProd) {
96
- const guard = isRemovedInProd ? "((_)=>true)" : (0, core_1.emitGuardFromType)(checker, type);
97
- return typescript_1.default.factory.createIdentifier(guard);
98
- }
99
- function _emitMakeAssert(checker, type, isRemovedInProd) {
100
- const guard = isRemovedInProd ? "((_)=>{})" : (0, core_1.emitGuardFromType)(checker, type);
101
- const txt = `(function(){const G=${guard};return(i)=>{if(!G(i))throw new TypeError("[runtypex] Validation failed.");};})()`;
102
- return typescript_1.default.factory.createIdentifier(txt);
103
- }
@@ -1,18 +0,0 @@
1
- import type { Plugin } from "vite";
2
- /**
3
- * 🧩 vitePluginRuntypex
4
- * A Vite plugin that performs build-time type → runtime validation transformation.
5
- *
6
- * 📘 Purpose
7
- * - Replace calls like:
8
- * makeValidate<T>(), makeAssert<T>()
9
- * with *inline JavaScript guard functions* derived from TypeScript types.
10
- *
11
- * 💡 Features
12
- * - Works in both dev & build mode
13
- * - Optional: remove validation code in production (`removeInProd`)
14
- * - Compatible with Rollup / Webpack (via Vite plugin API)
15
- */
16
- export default function vitePluginRuntypex(options?: {
17
- removeInProd?: boolean;
18
- }): Plugin;