runtypex 0.1.12 → 0.2.0

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 (74) hide show
  1. package/README.md +112 -69
  2. package/dist/cjs/core/emitArrayOrTuple.d.ts +6 -0
  3. package/dist/cjs/core/emitArrayOrTuple.js +40 -0
  4. package/dist/cjs/core/emitLiteralOrEnum.d.ts +4 -0
  5. package/dist/cjs/core/emitLiteralOrEnum.js +47 -0
  6. package/dist/cjs/core/emitMapperFromSpec.d.ts +32 -0
  7. package/dist/cjs/core/emitMapperFromSpec.js +199 -0
  8. package/dist/cjs/core/emitObject.d.ts +6 -0
  9. package/dist/cjs/core/emitObject.js +30 -0
  10. package/dist/cjs/core/emitPrimitive.d.ts +6 -0
  11. package/dist/cjs/core/emitPrimitive.js +29 -0
  12. package/dist/cjs/core/emitUnionOrIntersection.d.ts +6 -0
  13. package/dist/cjs/core/emitUnionOrIntersection.js +15 -0
  14. package/dist/cjs/core/index.d.ts +17 -0
  15. package/dist/cjs/core/index.js +41 -0
  16. package/dist/cjs/core/path.d.ts +9 -0
  17. package/dist/cjs/core/path.js +42 -0
  18. package/dist/cjs/generator/generate-jsdoc.d.ts +13 -0
  19. package/dist/cjs/generator/generate-jsdoc.js +69 -0
  20. package/dist/cjs/generator/index.d.ts +1 -0
  21. package/dist/cjs/generator/index.js +17 -0
  22. package/dist/cjs/index.d.ts +4 -0
  23. package/dist/cjs/index.js +20 -0
  24. package/dist/cjs/mapper/index.d.ts +1 -0
  25. package/dist/cjs/mapper/index.js +17 -0
  26. package/dist/cjs/runtime/index.d.ts +2 -0
  27. package/dist/cjs/runtime/index.js +18 -0
  28. package/dist/cjs/runtime/mapper.d.ts +71 -0
  29. package/dist/cjs/runtime/mapper.js +79 -0
  30. package/dist/cjs/runtime/validate.d.ts +11 -0
  31. package/dist/cjs/runtime/validate.js +18 -0
  32. package/dist/cjs/transformer/helper.d.ts +2 -0
  33. package/dist/cjs/transformer/helper.js +63 -0
  34. package/dist/cjs/transformer/index.d.ts +3 -0
  35. package/dist/cjs/transformer/index.js +12 -0
  36. package/dist/cjs/transformer/ts-transformer.d.ts +29 -0
  37. package/dist/cjs/transformer/ts-transformer.js +109 -0
  38. package/dist/cjs/transformer/vite-plugin.d.ts +18 -0
  39. package/dist/cjs/transformer/vite-plugin.js +72 -0
  40. package/dist/esm/core/emitArrayOrTuple.d.ts +1 -1
  41. package/dist/esm/core/emitLiteralOrEnum.d.ts +1 -1
  42. package/dist/esm/core/emitMapperFromSpec.d.ts +32 -0
  43. package/dist/esm/core/emitMapperFromSpec.js +189 -0
  44. package/dist/esm/core/emitObject.d.ts +1 -1
  45. package/dist/esm/core/emitObject.js +4 -2
  46. package/dist/esm/core/emitPrimitive.d.ts +1 -1
  47. package/dist/esm/core/emitUnionOrIntersection.d.ts +1 -1
  48. package/dist/esm/core/path.d.ts +9 -0
  49. package/dist/esm/core/path.js +36 -0
  50. package/dist/esm/generator/generate-jsdoc.d.ts +13 -0
  51. package/dist/esm/generator/generate-jsdoc.js +63 -0
  52. package/dist/esm/generator/index.d.ts +1 -0
  53. package/dist/esm/generator/index.js +1 -0
  54. package/dist/esm/index.d.ts +4 -3
  55. package/dist/esm/index.js +1 -0
  56. package/dist/esm/mapper/index.d.ts +1 -0
  57. package/dist/esm/mapper/index.js +1 -0
  58. package/dist/esm/runtime/index.d.ts +2 -0
  59. package/dist/esm/runtime/index.js +2 -0
  60. package/dist/esm/runtime/mapper.d.ts +71 -0
  61. package/dist/esm/runtime/mapper.js +71 -0
  62. package/dist/esm/transformer/helper.d.ts +2 -0
  63. package/dist/esm/transformer/helper.js +57 -0
  64. package/dist/esm/transformer/index.d.ts +3 -0
  65. package/dist/esm/transformer/index.js +3 -0
  66. package/dist/esm/transformer/ts-transformer.d.ts +8 -4
  67. package/dist/esm/transformer/ts-transformer.js +46 -55
  68. package/dist/esm/transformer/vite-plugin.js +7 -93
  69. package/docs/build-integrations.md +89 -0
  70. package/docs/jsdoc-generation.md +88 -0
  71. package/docs/mapper.md +104 -0
  72. package/docs/mapping-policy.md +78 -0
  73. package/docs/runtime-validation.md +84 -0
  74. package/package.json +76 -36
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GenContext = void 0;
4
+ exports.emitGuardFromType = emitGuardFromType;
5
+ const emitPrimitive_js_1 = require("./emitPrimitive.js");
6
+ const emitLiteralOrEnum_js_1 = require("./emitLiteralOrEnum.js");
7
+ const emitUnionOrIntersection_js_1 = require("./emitUnionOrIntersection.js");
8
+ const emitArrayOrTuple_js_1 = require("./emitArrayOrTuple.js");
9
+ const emitObject_js_1 = require("./emitObject.js");
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_js_1.emitPrimitive)(this, expr, t) ??
34
+ (0, emitLiteralOrEnum_js_1.emitLiteralOrEnum)(this, expr, t) ??
35
+ (0, emitUnionOrIntersection_js_1.emitUnionOrIntersection)(this, expr, t) ??
36
+ (0, emitArrayOrTuple_js_1.emitArrayOrTuple)(this, expr, t) ??
37
+ (0, emitObject_js_1.emitObject)(this, expr, t) ??
38
+ "true");
39
+ }
40
+ }
41
+ exports.GenContext = GenContext;
@@ -0,0 +1,9 @@
1
+ export type PathSegment = string | number;
2
+ /** Splits a mapper path into object keys and numeric array indexes. */
3
+ export declare function parsePath(path: string): PathSegment[];
4
+ /** Runtime fallback reader used when mapper calls are not transformed. */
5
+ export declare function getByPath(value: unknown, path: string): unknown;
6
+ /** Emits bracket-only access for user-authored DTO paths. */
7
+ export declare function emitPathAccess(root: string, path: string): string;
8
+ /** Emits compact dot access when safe, with bracket fallback for quoted keys. */
9
+ export declare function emitPropertyAccess(root: string, property: string | number): string;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePath = parsePath;
4
+ exports.getByPath = getByPath;
5
+ exports.emitPathAccess = emitPathAccess;
6
+ exports.emitPropertyAccess = emitPropertyAccess;
7
+ /** Splits a mapper path into object keys and numeric array indexes. */
8
+ function parsePath(path) {
9
+ if (!path)
10
+ return [];
11
+ return path.split(".").map((segment) => {
12
+ if (/^(0|[1-9]\d*)$/.test(segment))
13
+ return Number(segment);
14
+ return segment;
15
+ });
16
+ }
17
+ /** Runtime fallback reader used when mapper calls are not transformed. */
18
+ function getByPath(value, path) {
19
+ let current = value;
20
+ for (const segment of parsePath(path)) {
21
+ if (current == null)
22
+ return undefined;
23
+ current = current[segment];
24
+ }
25
+ return current;
26
+ }
27
+ /** Emits bracket-only access for user-authored DTO paths. */
28
+ function emitPathAccess(root, path) {
29
+ return parsePath(path).reduce((expr, segment) => {
30
+ if (typeof segment === "number")
31
+ return `${expr}[${segment}]`;
32
+ return `${expr}[${JSON.stringify(segment)}]`;
33
+ }, root);
34
+ }
35
+ /** Emits compact dot access when safe, with bracket fallback for quoted keys. */
36
+ function emitPropertyAccess(root, property) {
37
+ if (typeof property === "number")
38
+ return `${root}[${property}]`;
39
+ if (/^[A-Za-z_$][\w$]*$/.test(property))
40
+ return `${root}.${property}`;
41
+ return `${root}[${JSON.stringify(property)}]`;
42
+ }
@@ -0,0 +1,13 @@
1
+ import ts from "typescript";
2
+ export type GenerateJSDocOptions = {
3
+ name?: string;
4
+ mappingPolicy?: ts.Expression;
5
+ policyMode?: "warn" | "error";
6
+ };
7
+ export declare function generateJSDocFromSpec(params: {
8
+ checker: ts.TypeChecker;
9
+ dtoType: ts.Type;
10
+ domainType: ts.Type;
11
+ specNode: ts.Expression;
12
+ options?: GenerateJSDocOptions;
13
+ }): string;
@@ -0,0 +1,69 @@
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.generateJSDocFromSpec = generateJSDocFromSpec;
7
+ const typescript_1 = __importDefault(require("typescript"));
8
+ const path_js_1 = require("../core/path.js");
9
+ const emitMapperFromSpec_js_1 = require("../core/emitMapperFromSpec.js");
10
+ function generateJSDocFromSpec(params) {
11
+ const checker = params.checker;
12
+ const dtoName = params.dtoType.symbol?.name ?? "Dto";
13
+ const name = params.options?.name ?? params.domainType.symbol?.name ?? "GeneratedDomain";
14
+ const rules = (0, emitMapperFromSpec_js_1.readMapRules)(checker, params.specNode);
15
+ const lines = [`export interface ${name} {`];
16
+ (0, emitMapperFromSpec_js_1.handleMapPolicyViolations)((0, emitMapperFromSpec_js_1.findMapPolicyViolations)(checker, params.specNode, params.options?.mappingPolicy), params.options?.policyMode ?? "warn");
17
+ // Each domain property gets source metadata that editors can show on hover.
18
+ for (const prop of checker.getPropertiesOfType(params.domainType)) {
19
+ const rule = rules.get(prop.name);
20
+ if (!rule)
21
+ throw new Error(`[runtypex/generator] ${name}.${prop.name} is not mapped.`);
22
+ const declaration = prop.valueDeclaration ?? prop.declarations?.[0];
23
+ const domainType = declaration ? checker.getTypeOfSymbolAtLocation(prop, declaration) : checker.getAnyType();
24
+ const dtoPathType = _getTypeAtPath(checker, params.dtoType, rule.from);
25
+ const optional = (prop.getFlags() & typescript_1.default.SymbolFlags.Optional) !== 0 ? "?" : "";
26
+ lines.push(" /**");
27
+ if (rule.description) {
28
+ lines.push(` * ${_escapeComment(rule.description)}`);
29
+ lines.push(" *");
30
+ }
31
+ const dtoDescription = rule.dtoDescription ? ` ${_escapeComment(rule.dtoDescription)}` : "";
32
+ lines.push(` * DTO: ${dtoName}.${rule.from}${dtoDescription}`);
33
+ lines.push(` * DTO type: ${dtoPathType ? checker.typeToString(dtoPathType) : "unknown"}`);
34
+ if (rule.db)
35
+ lines.push(` * DB: ${_escapeComment(rule.db)}`);
36
+ lines.push(` * Domain type: ${checker.typeToString(domainType)}`);
37
+ lines.push(" */");
38
+ lines.push(` ${_propertyName(prop.name)}${optional}: ${checker.typeToString(domainType)};`);
39
+ lines.push("");
40
+ }
41
+ lines.push("}");
42
+ return lines.join("\n");
43
+ }
44
+ /** Resolves the DTO type reached by a mapping path such as profile.name or items.0.id. */
45
+ function _getTypeAtPath(checker, root, path) {
46
+ let current = root;
47
+ for (const segment of (0, path_js_1.parsePath)(path)) {
48
+ if (!current)
49
+ return null;
50
+ if (typeof segment === "number") {
51
+ current =
52
+ checker.getElementTypeOfArrayType?.(current) ??
53
+ current.typeArguments?.[segment] ??
54
+ current.getNumberIndexType?.() ??
55
+ null;
56
+ continue;
57
+ }
58
+ const prop = checker.getPropertyOfType(current, segment);
59
+ const declaration = prop?.valueDeclaration ?? prop?.declarations?.[0];
60
+ current = prop && declaration ? checker.getTypeOfSymbolAtLocation(prop, declaration) : null;
61
+ }
62
+ return current;
63
+ }
64
+ function _propertyName(name) {
65
+ return /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name);
66
+ }
67
+ function _escapeComment(value) {
68
+ return value.replace(/\*\//g, "* /");
69
+ }
@@ -0,0 +1 @@
1
+ export * from "./generate-jsdoc.js";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./generate-jsdoc.js"), exports);
@@ -0,0 +1,4 @@
1
+ export { makeValidate, makeAssert, type ValidateFn, type AssertFn } from "./runtime/validate.js";
2
+ export { defineMap, defineMappingPolicy, mapperHelpers, makeMapper, source, transform, type DefinedMap, type Mapper, type MapperOptions, type MapperMetadata, type MapRule, type MapSpec, type MappingPolicy, type MappingPolicyMode, type PathOf, } from "./runtime/mapper.js";
3
+ export { default as vitePlugin } from "./transformer/vite-plugin.js";
4
+ export { default as tsTransformer } from "./transformer/ts-transformer.js";
@@ -0,0 +1,20 @@
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.transform = exports.source = exports.makeMapper = exports.mapperHelpers = exports.defineMappingPolicy = exports.defineMap = exports.makeAssert = exports.makeValidate = void 0;
7
+ var validate_js_1 = require("./runtime/validate.js");
8
+ Object.defineProperty(exports, "makeValidate", { enumerable: true, get: function () { return validate_js_1.makeValidate; } });
9
+ Object.defineProperty(exports, "makeAssert", { enumerable: true, get: function () { return validate_js_1.makeAssert; } });
10
+ var mapper_js_1 = require("./runtime/mapper.js");
11
+ Object.defineProperty(exports, "defineMap", { enumerable: true, get: function () { return mapper_js_1.defineMap; } });
12
+ Object.defineProperty(exports, "defineMappingPolicy", { enumerable: true, get: function () { return mapper_js_1.defineMappingPolicy; } });
13
+ Object.defineProperty(exports, "mapperHelpers", { enumerable: true, get: function () { return mapper_js_1.mapperHelpers; } });
14
+ Object.defineProperty(exports, "makeMapper", { enumerable: true, get: function () { return mapper_js_1.makeMapper; } });
15
+ Object.defineProperty(exports, "source", { enumerable: true, get: function () { return mapper_js_1.source; } });
16
+ Object.defineProperty(exports, "transform", { enumerable: true, get: function () { return mapper_js_1.transform; } });
17
+ var vite_plugin_js_1 = require("./transformer/vite-plugin.js");
18
+ Object.defineProperty(exports, "vitePlugin", { enumerable: true, get: function () { return __importDefault(vite_plugin_js_1).default; } });
19
+ var ts_transformer_js_1 = require("./transformer/ts-transformer.js");
20
+ Object.defineProperty(exports, "tsTransformer", { enumerable: true, get: function () { return __importDefault(ts_transformer_js_1).default; } });
@@ -0,0 +1 @@
1
+ export * from "../runtime/mapper.js";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("../runtime/mapper.js"), exports);
@@ -0,0 +1,2 @@
1
+ export * from "./validate.js";
2
+ export * from "./mapper.js";
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./validate.js"), exports);
18
+ __exportStar(require("./mapper.js"), exports);
@@ -0,0 +1,71 @@
1
+ type Primitive = string | number | boolean | bigint | symbol | null | undefined | Date;
2
+ export type PathOf<T> = T extends Primitive ? never : T extends readonly (infer U)[] ? `${number}` | `${number}.${PathOf<U>}` : {
3
+ [K in Extract<keyof T, string>]: T[K] extends Primitive ? K : T[K] extends readonly (infer U)[] ? K | `${K}.${number}` | `${K}.${number}.${PathOf<U>}` : K | `${K}.${PathOf<T[K]>}`;
4
+ }[Extract<keyof T, string>];
5
+ export type Mapper<TDto, TDomain> = (dto: TDto) => TDomain;
6
+ export type MapperMetadata<TValue = never> = {
7
+ db?: string;
8
+ description?: string;
9
+ dtoDescription?: string;
10
+ default?: TValue;
11
+ };
12
+ export type MapRule<TDto, TValue> = MapperMetadata<TValue> & {
13
+ from: PathOf<TDto>;
14
+ transform?: (value: unknown, dto: TDto) => TValue;
15
+ };
16
+ export type MapSpec<TDto, TDomain> = {
17
+ [K in keyof TDomain]-?: MapRule<TDto, TDomain[K]>;
18
+ };
19
+ export type MappingPolicy<TDto> = Record<string, MapRule<TDto, unknown>>;
20
+ export type MappingPolicyMode = "warn" | "error";
21
+ export type MapperOptions<TDto> = {
22
+ policy?: MappingPolicy<TDto>;
23
+ policyMode?: MappingPolicyMode;
24
+ };
25
+ declare const DTO_TYPE: unique symbol;
26
+ declare const DOMAIN_TYPE: unique symbol;
27
+ export type DefinedMap<TDto, TDomain> = MapSpec<TDto, TDomain> & {
28
+ readonly [DTO_TYPE]?: TDto;
29
+ readonly [DOMAIN_TYPE]?: TDomain;
30
+ };
31
+ export declare function defineMap<TDto, TDomain>(): <const TSpec extends MapSpec<TDto, TDomain>>(spec: TSpec) => TSpec & DefinedMap<TDto, TDomain>;
32
+ /** Declares canonical DTO path -> Domain field names for consistency checks. */
33
+ export declare function defineMappingPolicy<TDto>(): <const TSpec extends MappingPolicy<TDto>>(spec: TSpec) => TSpec;
34
+ /** Shorthand rule for direct DTO path reads. */
35
+ export declare function source<const TPath extends string, TValue = never>(from: TPath, metadata?: MapperMetadata<TValue>): {
36
+ db?: string;
37
+ description?: string;
38
+ dtoDescription?: string;
39
+ default?: TValue | undefined;
40
+ from: TPath;
41
+ };
42
+ /** Shorthand rule for DTO path reads that require a value conversion. */
43
+ export declare function transform<const TPath extends string, TValue>(from: TPath, transform: (value: unknown, dto: unknown) => TValue, metadata?: MapperMetadata<TValue>): {
44
+ db?: string;
45
+ description?: string;
46
+ dtoDescription?: string;
47
+ default?: TValue | undefined;
48
+ from: TPath;
49
+ transform: (value: unknown, dto: unknown) => TValue;
50
+ };
51
+ /** Typed helpers for callbacks that need access to the source DTO shape. */
52
+ export declare function mapperHelpers<TDto>(): {
53
+ source: <const TPath extends PathOf<TDto>, TValue = never>(from: TPath, metadata?: MapperMetadata<TValue>) => {
54
+ db?: string;
55
+ description?: string;
56
+ dtoDescription?: string;
57
+ default?: TValue | undefined;
58
+ from: TPath;
59
+ };
60
+ transform: <const TPath extends PathOf<TDto>, TValue>(from: TPath, transform: (value: unknown, dto: TDto) => TValue, metadata?: MapperMetadata<TValue>) => {
61
+ db?: string;
62
+ description?: string;
63
+ dtoDescription?: string;
64
+ default?: TValue | undefined;
65
+ from: TPath;
66
+ transform: (value: unknown, dto: TDto) => TValue;
67
+ };
68
+ };
69
+ /** Runtime interpreter used as fallback when the transformer is not configured. */
70
+ export declare function makeMapper<TDto, TDomain>(spec: DefinedMap<TDto, TDomain> | MapSpec<TDto, TDomain>, options?: MapperOptions<TDto>): Mapper<TDto, TDomain>;
71
+ export {};
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineMap = defineMap;
4
+ exports.defineMappingPolicy = defineMappingPolicy;
5
+ exports.source = source;
6
+ exports.transform = transform;
7
+ exports.mapperHelpers = mapperHelpers;
8
+ exports.makeMapper = makeMapper;
9
+ const path_js_1 = require("../core/path.js");
10
+ function defineMap() {
11
+ return (spec) => spec;
12
+ }
13
+ /** Declares canonical DTO path -> Domain field names for consistency checks. */
14
+ function defineMappingPolicy() {
15
+ return (spec) => spec;
16
+ }
17
+ /** Shorthand rule for direct DTO path reads. */
18
+ function source(from, metadata) {
19
+ return { from, ...metadata };
20
+ }
21
+ /** Shorthand rule for DTO path reads that require a value conversion. */
22
+ function transform(from, transform, metadata) {
23
+ return { from, transform, ...metadata };
24
+ }
25
+ /** Typed helpers for callbacks that need access to the source DTO shape. */
26
+ function mapperHelpers() {
27
+ return {
28
+ source: (from, metadata) => source(from, metadata),
29
+ transform: (from, transform, metadata) => ({ from, transform, ...metadata }),
30
+ };
31
+ }
32
+ /** Runtime interpreter used as fallback when the transformer is not configured. */
33
+ function makeMapper(spec, options) {
34
+ _handlePolicyViolations(_findPolicyViolations(spec, options?.policy), options?.policyMode ?? "warn");
35
+ return ((dto) => {
36
+ const output = {};
37
+ for (const key of Object.keys(spec)) {
38
+ const rule = spec[key];
39
+ const raw = (0, path_js_1.getByPath)(dto, String(rule.from));
40
+ const value = raw === undefined && _hasOwn(rule, "default") ? rule.default : raw;
41
+ output[key] = rule.transform ? rule.transform(value, dto) : value;
42
+ }
43
+ return output;
44
+ });
45
+ }
46
+ function _hasOwn(value, key) {
47
+ return Object.prototype.hasOwnProperty.call(value, key);
48
+ }
49
+ function _findPolicyViolations(spec, policy) {
50
+ if (!policy)
51
+ return [];
52
+ const canonicalByPath = new Map();
53
+ const violations = [];
54
+ for (const key of Object.keys(policy)) {
55
+ const from = String(policy[key].from);
56
+ const existing = canonicalByPath.get(from);
57
+ if (existing && existing !== key) {
58
+ violations.push(`DTO path "${from}" is canonically mapped as "${existing}", but this map uses "${key}".`);
59
+ continue;
60
+ }
61
+ canonicalByPath.set(from, key);
62
+ }
63
+ violations.push(...Object.keys(spec).flatMap((key) => {
64
+ const from = String(spec[key].from);
65
+ const expected = canonicalByPath.get(from);
66
+ return expected && expected !== key
67
+ ? [`DTO path "${from}" is canonically mapped as "${expected}", but this map uses "${key}".`]
68
+ : [];
69
+ }));
70
+ return violations;
71
+ }
72
+ function _handlePolicyViolations(violations, mode) {
73
+ if (!violations.length)
74
+ return;
75
+ const message = `[runtypex/mapper] Mapping policy violation:\n${violations.join("\n")}`;
76
+ if (mode === "error")
77
+ throw new Error(message);
78
+ console.warn(message);
79
+ }
@@ -0,0 +1,11 @@
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 type AssertFn<T> = (value: unknown) => asserts value is T;
10
+ export declare function makeValidate<T>(): ValidateFn<T>;
11
+ export declare function makeAssert<T>(): AssertFn<T>;
@@ -0,0 +1,18 @@
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
+ return true;
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
+ }
@@ -0,0 +1,2 @@
1
+ import ts from "typescript";
2
+ export declare function resolveTypeByName(program: ts.Program, sf: ts.SourceFile, checker: ts.TypeChecker, name: string): ts.Type | null;
@@ -0,0 +1,63 @@
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.resolveTypeByName = resolveTypeByName;
7
+ const typescript_1 = __importDefault(require("typescript"));
8
+ function resolveTypeByName(program, sf, checker, name) {
9
+ // -1️⃣ Primitive type fallback
10
+ const primitiveNames = ["string", "number", "boolean", "bigint", "symbol", "null", "undefined"];
11
+ if (primitiveNames.includes(name)) {
12
+ const map = {
13
+ string: checker.getStringType(),
14
+ number: checker.getNumberType(),
15
+ boolean: checker.getBooleanType(),
16
+ bigint: checker.getBigIntType(),
17
+ symbol: checker.getESSymbolType(),
18
+ null: checker.getNullType(),
19
+ undefined: checker.getUndefinedType(),
20
+ };
21
+ return map[name];
22
+ }
23
+ // 2️⃣ Scan source files
24
+ for (const file of program.getSourceFiles()) {
25
+ const decl = _findLocalDeclaration(file, name);
26
+ if (!decl)
27
+ continue;
28
+ // ✅ type, interface, enum, class
29
+ if (typescript_1.default.isInterfaceDeclaration(decl) ||
30
+ typescript_1.default.isClassDeclaration(decl) ||
31
+ typescript_1.default.isEnumDeclaration(decl)) {
32
+ if (decl.name) {
33
+ const symbol = checker.getSymbolAtLocation(decl.name);
34
+ if (symbol)
35
+ return checker.getDeclaredTypeOfSymbol(symbol);
36
+ }
37
+ }
38
+ if (typescript_1.default.isTypeAliasDeclaration(decl)) {
39
+ return checker.getTypeFromTypeNode(decl.type);
40
+ }
41
+ }
42
+ // 3️⃣ Scope-based fallback
43
+ const symbol = checker
44
+ .getSymbolsInScope(sf, typescript_1.default.SymbolFlags.Type | typescript_1.default.SymbolFlags.Alias | typescript_1.default.SymbolFlags.Interface)
45
+ .find((s) => s.name === name);
46
+ return symbol ? checker.getDeclaredTypeOfSymbol(symbol) : null;
47
+ }
48
+ function _findLocalDeclaration(sf, name) {
49
+ let found;
50
+ (function walk(node) {
51
+ if ((typescript_1.default.isInterfaceDeclaration(node) ||
52
+ typescript_1.default.isTypeAliasDeclaration(node) ||
53
+ typescript_1.default.isEnumDeclaration(node) ||
54
+ typescript_1.default.isClassDeclaration(node)) &&
55
+ node.name?.text === name) {
56
+ found = node;
57
+ return;
58
+ }
59
+ if (!found)
60
+ node.forEachChild(walk);
61
+ })(sf);
62
+ return found;
63
+ }
@@ -0,0 +1,3 @@
1
+ export { default } from "./ts-transformer.js";
2
+ export { default as tsTransformer } from "./ts-transformer.js";
3
+ export { default as vitePlugin } from "./vite-plugin.js";
@@ -0,0 +1,12 @@
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.vitePlugin = exports.tsTransformer = exports.default = void 0;
7
+ var ts_transformer_js_1 = require("./ts-transformer.js");
8
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(ts_transformer_js_1).default; } });
9
+ var ts_transformer_js_2 = require("./ts-transformer.js");
10
+ Object.defineProperty(exports, "tsTransformer", { enumerable: true, get: function () { return __importDefault(ts_transformer_js_2).default; } });
11
+ var vite_plugin_js_1 = require("./vite-plugin.js");
12
+ Object.defineProperty(exports, "vitePlugin", { enumerable: true, get: function () { return __importDefault(vite_plugin_js_1).default; } });
@@ -0,0 +1,29 @@
1
+ import ts from "typescript";
2
+ type TransformerOptions = {
3
+ program: ts.Program;
4
+ removeInProd?: boolean;
5
+ validateDto?: boolean;
6
+ validateDomain?: boolean;
7
+ };
8
+ /**
9
+ * 🧩 tsTransformer
10
+ * TypeScript custom transformer (BEFORE) factory.
11
+ *
12
+ * 📘 Usage (ts-loader / ttypescript):
13
+ * ```ts
14
+ * getCustomTransformers: (program) => ({
15
+ * before: [ tsTransformer({ program, removeInProd: true }) ]
16
+ * })
17
+ * ```
18
+ *
19
+ * 🧠 Purpose:
20
+ * - Replace makeValidate<T>(), makeAssert<T>() calls
21
+ * with *pre-generated runtime validation code* derived from T.
22
+ *
23
+ * 💡 Effect:
24
+ * ✅ No reflection or runtime type parsing
25
+ * ✅ Validation logic embedded at build-time
26
+ * ✅ Optionally removed in production builds
27
+ */
28
+ export default function tsTransformer(options: TransformerOptions): ts.TransformerFactory<ts.SourceFile>;
29
+ export {};