@ir-kit/fn-schema-transformer 0.1.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.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ahmed Rowaihi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # @ir-kit/fn-schema-transformer
2
+
3
+ TypeScript compiler-API transformer that **inlines fn-schema results into emitted JS at compile time**. Replaces every `schemaOf(fn)` call with a literal JSON Schema object pulled from a pre-extracted bundle.
4
+
5
+ ## When to use this — and when not to
6
+
7
+ Use it when you want zero runtime cost: no `JSON.parse` on cold start, no `schemas.json` artifact at runtime, no ts-morph dep in your shipped bundle.
8
+
9
+ For 95% of users the [`loader`](../loader/README.md) is the right answer — simpler to set up and works in every TS toolchain. Only reach for the transformer when you've measured a real cost (cold-start latency, bundle size) or your deployment target forbids JSON files.
10
+
11
+ | | loader | transformer |
12
+ | ------------------------ | ------------------------- | ---------------------------------- |
13
+ | setup | `import` | `ts-patch` + tsconfig plugin entry |
14
+ | runtime cost | one `JSON.parse` | none |
15
+ | live updates | yes (re-extract + import) | no (rebuild required) |
16
+ | works with vanilla `tsc` | yes | no (needs `tspc`) |
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pnpm add -D @ir-kit/fn-schema-transformer ts-patch
22
+ ```
23
+
24
+ ## Setup
25
+
26
+ ### 1. Produce a bundle
27
+
28
+ Either path works — the transformer just needs a `schemas.json` on disk before tsc runs.
29
+
30
+ **Programmatic** (in a build script):
31
+
32
+ ```ts
33
+ import { extract } from "@ir-kit/fn-schema-typescript";
34
+ import { emit } from "@ir-kit/fn-schema-core";
35
+ import { writeFile, mkdir } from "node:fs/promises";
36
+
37
+ const result = await extract({ files: ["src/api/**/*.ts"] });
38
+ await mkdir("generated", { recursive: true });
39
+ await writeFile("generated/schemas.json", emit.toBundle(result));
40
+ ```
41
+
42
+ **CLI**:
43
+
44
+ ```bash
45
+ npx fn-schema extract 'src/api/**/*.ts' --bundle generated/schemas.json --pretty
46
+ ```
47
+
48
+ ### 2. Configure ts-patch
49
+
50
+ ```jsonc
51
+ // tsconfig.json
52
+ {
53
+ "compilerOptions": {
54
+ "plugins": [
55
+ {
56
+ "transform": "@ir-kit/fn-schema-transformer",
57
+ "bundlePath": "./generated/schemas.json",
58
+ },
59
+ ],
60
+ },
61
+ }
62
+ ```
63
+
64
+ ```jsonc
65
+ // package.json — bundle must exist before tspc runs
66
+ {
67
+ "scripts": {
68
+ "build:schemas": "node scripts/extract.mjs",
69
+ "build:ts": "tspc",
70
+ "build": "pnpm build:schemas && pnpm build:ts",
71
+ },
72
+ }
73
+ ```
74
+
75
+ `tspc` is `ts-patch`'s patched compiler (replaces `tsc`).
76
+
77
+ ### 3. Use the runtime markers
78
+
79
+ ```ts
80
+ import {
81
+ schemaOf,
82
+ inputSchemaOf,
83
+ outputSchemaOf,
84
+ } from "@ir-kit/fn-schema-transformer/runtime";
85
+ import { createUser } from "./api/handlers";
86
+
87
+ const meta = schemaOf(createUser);
88
+ const inputSchema = inputSchemaOf(createUser);
89
+ const outputSchema = outputSchemaOf(createUser);
90
+ ```
91
+
92
+ After transformation, the emitted JS has:
93
+
94
+ ```js
95
+ const meta = { input: { type: "object", properties: { ... } }, output: { ... } }
96
+ const inputSchema = { type: "object", properties: { ... } }
97
+ const outputSchema = { ... }
98
+ ```
99
+
100
+ The runtime stubs return `undefined` if the transformer is NOT applied, so dev tooling that doesn't run the transformer (`tsx`, `vitest`, etc.) doesn't break — calls just return `undefined`.
101
+
102
+ ## What gets replaced
103
+
104
+ Direct calls only:
105
+
106
+ ```ts
107
+ schemaOf(myFunction); // ✅ inlined
108
+ inputSchemaOf(myFunction); // ✅
109
+ outputSchemaOf(myFunction); // ✅
110
+
111
+ const fn = myFunction;
112
+ schemaOf(fn); // ❌ not inlined (argument is a binding, not the original identifier)
113
+
114
+ schemaOf(makeFn()); // ❌ not inlined (call expression)
115
+ ```
116
+
117
+ Lookup is by the argument identifier's name. If `myFunction` isn't in the bundle, the call is left alone — no error, but you get `undefined` at runtime via the stub.
118
+
119
+ ## Limitations
120
+
121
+ - TS transformers are **synchronous**. The bundle must exist on disk before tsc runs — wire your build chain so extraction completes first.
122
+ - Doesn't work with vanilla `tsc` — needs [`ts-patch`](https://github.com/nonara/ts-patch)'s `tspc` (or another tool supporting custom transformers).
123
+ - Source-map fidelity is best-effort.
@@ -0,0 +1,37 @@
1
+ import ts from "typescript";
2
+ export interface TransformerOptions {
3
+ /**
4
+ * Path to a bundle JSON produced by `fn-schema --bundle ...`. Resolved
5
+ * relative to `cwd` (default: process.cwd()) when not absolute.
6
+ */
7
+ bundlePath: string;
8
+ cwd?: string;
9
+ }
10
+ /**
11
+ * TypeScript transformer that inlines pre-extracted JSON Schemas at compile
12
+ * time. Replaces every `schemaOf(fn)` / `inputSchemaOf(fn)` / `outputSchemaOf(fn)`
13
+ * call with the literal schema object pulled from the bundle, so consuming code
14
+ * pays zero runtime cost and ships zero ts-morph dependency.
15
+ *
16
+ * Bundle lookup goes through three fallbacks: id-as-key (works when the
17
+ * extractor used `naming: "function-name"`), name field (set by core's
18
+ * `emit.toBundle` since 0.x — survives `naming: "file-function"` and renamed
19
+ * imports), and finally type-checker symbol resolution for aliased imports
20
+ * like `import { createUser as makeUser } from "./api"`.
21
+ *
22
+ * Usage with ts-patch:
23
+ * ```jsonc
24
+ * {
25
+ * "compilerOptions": {
26
+ * "plugins": [
27
+ * {
28
+ * "transform": "@ir-kit/fn-schema-transformer",
29
+ * "bundlePath": "./generated/schemas.json"
30
+ * }
31
+ * ]
32
+ * }
33
+ * }
34
+ * ```
35
+ */
36
+ export default function transformer(program: ts.Program, options: TransformerOptions): ts.TransformerFactory<ts.SourceFile>;
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CACjC,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,OAAO,EAAE,kBAAkB,GAC1B,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,UAAU,CAAC,CAuEtC"}
package/dist/index.js ADDED
@@ -0,0 +1,121 @@
1
+ import { readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import ts from "typescript";
4
+ const RUNTIME_FNS = new Set(["schemaOf", "inputSchemaOf", "outputSchemaOf"]);
5
+ /**
6
+ * TypeScript transformer that inlines pre-extracted JSON Schemas at compile
7
+ * time. Replaces every `schemaOf(fn)` / `inputSchemaOf(fn)` / `outputSchemaOf(fn)`
8
+ * call with the literal schema object pulled from the bundle, so consuming code
9
+ * pays zero runtime cost and ships zero ts-morph dependency.
10
+ *
11
+ * Bundle lookup goes through three fallbacks: id-as-key (works when the
12
+ * extractor used `naming: "function-name"`), name field (set by core's
13
+ * `emit.toBundle` since 0.x — survives `naming: "file-function"` and renamed
14
+ * imports), and finally type-checker symbol resolution for aliased imports
15
+ * like `import { createUser as makeUser } from "./api"`.
16
+ *
17
+ * Usage with ts-patch:
18
+ * ```jsonc
19
+ * {
20
+ * "compilerOptions": {
21
+ * "plugins": [
22
+ * {
23
+ * "transform": "@ir-kit/fn-schema-transformer",
24
+ * "bundlePath": "./generated/schemas.json"
25
+ * }
26
+ * ]
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ export default function transformer(program, options) {
32
+ if (!options?.bundlePath) {
33
+ throw new Error('fn-schema-transformer: `bundlePath` is required. Run `fn-schema --bundle <path>` to produce one, then point the plugin at it via { "bundlePath": "..." }.');
34
+ }
35
+ const cwd = path.resolve(options.cwd ?? process.cwd());
36
+ const abs = path.isAbsolute(options.bundlePath)
37
+ ? options.bundlePath
38
+ : path.resolve(cwd, options.bundlePath);
39
+ let bundle = null;
40
+ let nameIndex = null;
41
+ const loadBundle = () => {
42
+ if (bundle && nameIndex)
43
+ return { bundle, byName: nameIndex };
44
+ const raw = readFileSync(abs, "utf-8");
45
+ bundle = JSON.parse(raw);
46
+ nameIndex = new Map();
47
+ for (const [id, sig] of Object.entries(bundle.signatures)) {
48
+ if (sig.name)
49
+ nameIndex.set(sig.name, sig);
50
+ // Always also index by the id itself so id-as-key lookups still work.
51
+ nameIndex.set(id, sig);
52
+ }
53
+ return { bundle, byName: nameIndex };
54
+ };
55
+ const checker = program.getTypeChecker();
56
+ const lookupSig = (arg) => {
57
+ const { byName } = loadBundle();
58
+ // Layer 1 — direct match on the local identifier text.
59
+ const direct = byName.get(arg.text);
60
+ if (direct)
61
+ return direct;
62
+ // Layer 2 — resolve via type checker so `import { createUser as makeUser }`
63
+ // finds the entry under its exported name.
64
+ const sym = checker.getSymbolAtLocation(arg);
65
+ if (!sym)
66
+ return undefined;
67
+ const aliased = (sym.flags & ts.SymbolFlags.Alias) !== 0
68
+ ? checker.getAliasedSymbol(sym)
69
+ : sym;
70
+ const exportedName = aliased.getName();
71
+ return byName.get(exportedName);
72
+ };
73
+ return (context) => (sourceFile) => {
74
+ const visit = (node) => {
75
+ if (ts.isCallExpression(node) &&
76
+ ts.isIdentifier(node.expression) &&
77
+ RUNTIME_FNS.has(node.expression.text)) {
78
+ const arg = node.arguments[0];
79
+ if (arg && ts.isIdentifier(arg)) {
80
+ const sig = lookupSig(arg);
81
+ if (sig) {
82
+ switch (node.expression.text) {
83
+ case "schemaOf":
84
+ return jsonToLiteral({ input: sig.input, output: sig.output });
85
+ case "inputSchemaOf":
86
+ return jsonToLiteral(sig.input);
87
+ case "outputSchemaOf":
88
+ return jsonToLiteral(sig.output);
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return ts.visitEachChild(node, visit, context);
94
+ };
95
+ return ts.visitNode(sourceFile, visit);
96
+ };
97
+ }
98
+ function jsonToLiteral(value) {
99
+ if (value === null)
100
+ return ts.factory.createNull();
101
+ if (value === undefined)
102
+ return ts.factory.createIdentifier("undefined");
103
+ if (typeof value === "string")
104
+ return ts.factory.createStringLiteral(value);
105
+ if (typeof value === "number")
106
+ return value < 0
107
+ ? ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(-value))
108
+ : ts.factory.createNumericLiteral(value);
109
+ if (typeof value === "boolean")
110
+ return value ? ts.factory.createTrue() : ts.factory.createFalse();
111
+ if (Array.isArray(value)) {
112
+ return ts.factory.createArrayLiteralExpression(value.map(jsonToLiteral));
113
+ }
114
+ if (typeof value === "object") {
115
+ return ts.factory.createObjectLiteralExpression(Object.entries(value).map(([k, v]) => ts.factory.createPropertyAssignment(/^[A-Za-z_$][\w$]*$/.test(k)
116
+ ? ts.factory.createIdentifier(k)
117
+ : ts.factory.createStringLiteral(k), jsonToLiteral(v))), true);
118
+ }
119
+ return ts.factory.createIdentifier("undefined");
120
+ }
121
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Marker functions consumers call in their app. The transformer replaces every
3
+ * call site with the literal JSON Schema at compile time. The runtime stubs
4
+ * below exist only so tsc / dev mode resolve the import — they never execute
5
+ * after transformation.
6
+ *
7
+ * If the transformer is NOT applied, `schemaOf` returns `undefined` and
8
+ * `inputSchemaOf` / `outputSchemaOf` likewise — useful for early adopters who
9
+ * want a graceful fallback in environments where the transformer can't run.
10
+ */
11
+ export interface FnSchemaPair<I = unknown, O = unknown> {
12
+ input: I;
13
+ output: O;
14
+ }
15
+ export declare function schemaOf<F extends (...args: never[]) => unknown>(_fn: F): FnSchemaPair | undefined;
16
+ export declare function inputSchemaOf<F extends (...args: never[]) => unknown>(_fn: F): unknown;
17
+ export declare function outputSchemaOf<F extends (...args: never[]) => unknown>(_fn: F): unknown;
18
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACpD,KAAK,EAAE,CAAC,CAAC;IACT,MAAM,EAAE,CAAC,CAAC;CACX;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAC9D,GAAG,EAAE,CAAC,GACL,YAAY,GAAG,SAAS,CAE1B;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EACnE,GAAG,EAAE,CAAC,GACL,OAAO,CAET;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EACpE,GAAG,EAAE,CAAC,GACL,OAAO,CAET"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Marker functions consumers call in their app. The transformer replaces every
3
+ * call site with the literal JSON Schema at compile time. The runtime stubs
4
+ * below exist only so tsc / dev mode resolve the import — they never execute
5
+ * after transformation.
6
+ *
7
+ * If the transformer is NOT applied, `schemaOf` returns `undefined` and
8
+ * `inputSchemaOf` / `outputSchemaOf` likewise — useful for early adopters who
9
+ * want a graceful fallback in environments where the transformer can't run.
10
+ */
11
+ export function schemaOf(_fn) {
12
+ return undefined;
13
+ }
14
+ export function inputSchemaOf(_fn) {
15
+ return undefined;
16
+ }
17
+ export function outputSchemaOf(_fn) {
18
+ return undefined;
19
+ }
20
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,UAAU,QAAQ,CACtB,GAAM;IAEN,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAM;IAEN,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,GAAM;IAEN,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@ir-kit/fn-schema-transformer",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript compiler-API transformer that inlines fn-schema results into emitted code. Replaces `schemaOf(myFunction)` calls with the literal JSON Schema at build time, eliminating runtime extraction cost. Plug into ts-patch, swc, esbuild, or any tool that accepts a custom TS transformer.",
5
+ "keywords": [
6
+ "json-schema",
7
+ "function-signature",
8
+ "typescript-transformer",
9
+ "compile-time"
10
+ ],
11
+ "homepage": "https://github.com/ir-kit/ir-kit/tree/main/packages/fn-schema/transformer",
12
+ "bugs": {
13
+ "url": "https://github.com/ir-kit/ir-kit/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": {
17
+ "name": "Ahmed Rowaihi",
18
+ "email": "ahmedrowaihi@gmail.com"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/ir-kit/ir-kit.git",
23
+ "directory": "packages/fn-schema/transformer"
24
+ },
25
+ "type": "module",
26
+ "sideEffects": false,
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ },
34
+ "./runtime": {
35
+ "types": "./dist/runtime.d.ts",
36
+ "import": "./dist/runtime.js"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "LICENSE.md"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public",
46
+ "provenance": true
47
+ },
48
+ "dependencies": {
49
+ "@ir-kit/fn-schema-core": "0.1.0",
50
+ "@ir-kit/fn-schema-typescript": "0.1.0"
51
+ },
52
+ "peerDependencies": {
53
+ "typescript": ">=5.0.0"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^22",
57
+ "typescript": "5.9.3",
58
+ "vitest": "^4.0.0",
59
+ "@ir-kit/tsconfig": "0.0.0"
60
+ },
61
+ "engines": {
62
+ "node": ">=20.19.0"
63
+ },
64
+ "scripts": {
65
+ "build": "tsc -p tsconfig.build.json",
66
+ "dev": "tsc -p tsconfig.build.json --watch",
67
+ "typecheck": "tsc --noEmit",
68
+ "test": "vitest run --passWithNoTests"
69
+ }
70
+ }