@zmdb/compiler 1.0.0-beta.1
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 +674 -0
- package/README.md +40 -0
- package/dist/codegen/index.d.ts +50 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +364 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/scan.d.ts +105 -0
- package/dist/codegen/scan.d.ts.map +1 -0
- package/dist/codegen/scan.js +450 -0
- package/dist/codegen/scan.js.map +1 -0
- package/dist/codegen/witness.d.ts +76 -0
- package/dist/codegen/witness.d.ts.map +1 -0
- package/dist/codegen/witness.js +690 -0
- package/dist/codegen/witness.js.map +1 -0
- package/dist/config/contract.d.ts +41 -0
- package/dist/config/contract.d.ts.map +1 -0
- package/dist/config/contract.js +5 -0
- package/dist/config/contract.js.map +1 -0
- package/dist/config/index.d.ts +53 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +277 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.zmdb.generated.d.ts +12 -0
- package/dist/config/index.zmdb.generated.js +28 -0
- package/dist/config/index.zmdb.witness.d.ts +3 -0
- package/dist/config/index.zmdb.witness.d.ts.map +1 -0
- package/dist/config/index.zmdb.witness.js +20 -0
- package/dist/config/index.zmdb.witness.js.map +1 -0
- package/dist/configured-plugin.d.ts +11 -0
- package/dist/configured-plugin.d.ts.map +1 -0
- package/dist/configured-plugin.js +27 -0
- package/dist/configured-plugin.js.map +1 -0
- package/dist/emit/index.d.ts +103 -0
- package/dist/emit/index.d.ts.map +1 -0
- package/dist/emit/index.js +1356 -0
- package/dist/emit/index.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +254 -0
- package/dist/index.js.map +1 -0
- package/dist/lint/ast.d.ts +17 -0
- package/dist/lint/ast.d.ts.map +1 -0
- package/dist/lint/ast.js +77 -0
- package/dist/lint/ast.js.map +1 -0
- package/dist/lint/host-types.d.ts +9 -0
- package/dist/lint/host-types.d.ts.map +1 -0
- package/dist/lint/host-types.js +2 -0
- package/dist/lint/host-types.js.map +1 -0
- package/dist/lint/index.d.ts +23 -0
- package/dist/lint/index.d.ts.map +1 -0
- package/dist/lint/index.js +53 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/rules/no-distributed-nullable-tags.d.ts +3 -0
- package/dist/lint/rules/no-distributed-nullable-tags.d.ts.map +1 -0
- package/dist/lint/rules/no-distributed-nullable-tags.js +71 -0
- package/dist/lint/rules/no-distributed-nullable-tags.js.map +1 -0
- package/dist/lint/rules/no-empty-patch.d.ts +3 -0
- package/dist/lint/rules/no-empty-patch.d.ts.map +1 -0
- package/dist/lint/rules/no-empty-patch.js +26 -0
- package/dist/lint/rules/no-empty-patch.js.map +1 -0
- package/dist/lint/rules/no-interpolated-sql.d.ts +3 -0
- package/dist/lint/rules/no-interpolated-sql.d.ts.map +1 -0
- package/dist/lint/rules/no-interpolated-sql.js +35 -0
- package/dist/lint/rules/no-interpolated-sql.js.map +1 -0
- package/dist/lint/rules/no-unbounded-find.d.ts +3 -0
- package/dist/lint/rules/no-unbounded-find.d.ts.map +1 -0
- package/dist/lint/rules/no-unbounded-find.js +26 -0
- package/dist/lint/rules/no-unbounded-find.js.map +1 -0
- package/dist/lint/rules/no-unknown-json-column.d.ts +3 -0
- package/dist/lint/rules/no-unknown-json-column.d.ts.map +1 -0
- package/dist/lint/rules/no-unknown-json-column.js +35 -0
- package/dist/lint/rules/no-unknown-json-column.js.map +1 -0
- package/dist/lint/rules/require-sql-on-number.d.ts +3 -0
- package/dist/lint/rules/require-sql-on-number.d.ts.map +1 -0
- package/dist/lint/rules/require-sql-on-number.js +34 -0
- package/dist/lint/rules/require-sql-on-number.js.map +1 -0
- package/dist/lint/types.d.ts +12 -0
- package/dist/lint/types.d.ts.map +1 -0
- package/dist/lint/types.js +2 -0
- package/dist/lint/types.js.map +1 -0
- package/dist/metro/metro.d.ts +22 -0
- package/dist/metro/metro.d.ts.map +1 -0
- package/dist/metro/metro.js +242 -0
- package/dist/metro/metro.js.map +1 -0
- package/dist/protobuf/decode.d.ts +20 -0
- package/dist/protobuf/decode.d.ts.map +1 -0
- package/dist/protobuf/decode.js +289 -0
- package/dist/protobuf/decode.js.map +1 -0
- package/dist/protobuf/descriptor.d.ts +16 -0
- package/dist/protobuf/descriptor.d.ts.map +1 -0
- package/dist/protobuf/descriptor.js +303 -0
- package/dist/protobuf/descriptor.js.map +1 -0
- package/dist/protobuf/encode.d.ts +20 -0
- package/dist/protobuf/encode.d.ts.map +1 -0
- package/dist/protobuf/encode.js +203 -0
- package/dist/protobuf/encode.js.map +1 -0
- package/dist/protobuf/grpc-ir.d.ts +16 -0
- package/dist/protobuf/grpc-ir.d.ts.map +1 -0
- package/dist/protobuf/grpc-ir.js +2 -0
- package/dist/protobuf/grpc-ir.js.map +1 -0
- package/dist/protobuf/plan.d.ts +42 -0
- package/dist/protobuf/plan.d.ts.map +1 -0
- package/dist/protobuf/plan.js +158 -0
- package/dist/protobuf/plan.js.map +1 -0
- package/dist/reflect/callsites.d.ts +40 -0
- package/dist/reflect/callsites.d.ts.map +1 -0
- package/dist/reflect/callsites.js +153 -0
- package/dist/reflect/callsites.js.map +1 -0
- package/dist/reflect/index.d.ts +106 -0
- package/dist/reflect/index.d.ts.map +1 -0
- package/dist/reflect/index.js +1421 -0
- package/dist/reflect/index.js.map +1 -0
- package/dist/reflect/session.d.ts +118 -0
- package/dist/reflect/session.d.ts.map +1 -0
- package/dist/reflect/session.js +228 -0
- package/dist/reflect/session.js.map +1 -0
- package/dist/testing/index.d.ts +69 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +210 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/transform/index.d.ts +74 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +572 -0
- package/dist/transform/index.js.map +1 -0
- package/dist/unplugin/index.d.ts +53 -0
- package/dist/unplugin/index.d.ts.map +1 -0
- package/dist/unplugin/index.js +130 -0
- package/dist/unplugin/index.js.map +1 -0
- package/dist/unplugin/inline-bench.d.ts +29 -0
- package/dist/unplugin/inline-bench.d.ts.map +1 -0
- package/dist/unplugin/inline-bench.js +82 -0
- package/dist/unplugin/inline-bench.js.map +1 -0
- package/package.json +110 -0
- package/src/codegen/index.ts +451 -0
- package/src/codegen/scan.ts +574 -0
- package/src/codegen/witness.ts +819 -0
- package/src/config/contract.ts +48 -0
- package/src/config/index.ts +384 -0
- package/src/config/index.zmdb.generated.d.ts +12 -0
- package/src/config/index.zmdb.generated.js +28 -0
- package/src/config/index.zmdb.witness.ts +22 -0
- package/src/configured-plugin.ts +35 -0
- package/src/emit/index.ts +1496 -0
- package/src/errors.ts +6 -0
- package/src/index.ts +336 -0
- package/src/lint/ast.ts +96 -0
- package/src/lint/host-types.ts +9 -0
- package/src/lint/index.ts +80 -0
- package/src/lint/rules/no-distributed-nullable-tags.ts +76 -0
- package/src/lint/rules/no-empty-patch.ts +26 -0
- package/src/lint/rules/no-interpolated-sql.ts +45 -0
- package/src/lint/rules/no-unbounded-find.ts +26 -0
- package/src/lint/rules/no-unknown-json-column.ts +36 -0
- package/src/lint/rules/require-sql-on-number.ts +34 -0
- package/src/lint/types.ts +11 -0
- package/src/metro/metro.ts +313 -0
- package/src/protobuf/decode.ts +375 -0
- package/src/protobuf/descriptor.ts +353 -0
- package/src/protobuf/encode.ts +277 -0
- package/src/protobuf/grpc-ir.ts +17 -0
- package/src/protobuf/plan.ts +244 -0
- package/src/reflect/callsites.ts +198 -0
- package/src/reflect/index.ts +1723 -0
- package/src/reflect/session.ts +276 -0
- package/src/testing/index.ts +298 -0
- package/src/transform/index.ts +690 -0
- package/src/unplugin/index.ts +182 -0
- package/src/unplugin/inline-bench.ts +92 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// `@zmdb/compiler/testing` — tagged schema values, without a transform step.
|
|
2
|
+
//
|
|
3
|
+
// `schemaOf<User>()` is compiled away by the transform, and it has no runtime: a type
|
|
4
|
+
// argument does not survive to runtime, so a build that skipped the transform gets a thrown
|
|
5
|
+
// error rather than a plausible-looking empty schema. That is the right behaviour in an
|
|
6
|
+
// application and an awkward one in a test, because a unit test usually runs off the
|
|
7
|
+
// TypeScript source with no bundler in the way — `vitest`, `node --strip-types`, `tsx`. Ask
|
|
8
|
+
// for the schema there and you get the error, correctly, and no way forward.
|
|
9
|
+
//
|
|
10
|
+
// So this does through the compiler API what the transform does during a build: open the
|
|
11
|
+
// project, read exported tagged interfaces, and turn their IR into schema values. Tests can
|
|
12
|
+
// name individual exports with `schemasFrom`; build tools whose config already resolved a
|
|
13
|
+
// concrete file set use `schemasFromFiles`. Both return what the transform would have inlined
|
|
14
|
+
// — literally the same `schemaFromIR(schemaIrFromType(...))` expression — rather than a
|
|
15
|
+
// stand-in for the shipped path.
|
|
16
|
+
//
|
|
17
|
+
// ```ts
|
|
18
|
+
// import { schemasFrom } from '@zmdb/compiler/testing';
|
|
19
|
+
//
|
|
20
|
+
// export interface User extends Table<'users'> {
|
|
21
|
+
// id: number & Sql<'integer'> & Serial & PrimaryKey;
|
|
22
|
+
// email: string & Sql<'varchar'> & Length<255> & Unique;
|
|
23
|
+
// }
|
|
24
|
+
//
|
|
25
|
+
// const { User: users } = schemasFrom(import.meta.url, ['User']);
|
|
26
|
+
// ```
|
|
27
|
+
//
|
|
28
|
+
// The interfaces can live in the test file itself, which is the point: a fixture two
|
|
29
|
+
// directories away is a fixture nobody reads. They do have to be `export`ed, because the
|
|
30
|
+
// module's export table is how a name is resolved to a symbol.
|
|
31
|
+
//
|
|
32
|
+
// ## What it costs
|
|
33
|
+
//
|
|
34
|
+
// One compiler session per call — about 80ms to load a package-sized project, and about 3ms
|
|
35
|
+
// to resolve a type out of it. So a test should call once at module scope with every name it
|
|
36
|
+
// needs, while a command should pass its whole configured file set once. The session is
|
|
37
|
+
// closed before the call returns, because an open one holds a child process and a process
|
|
38
|
+
// that leaks those hangs on exit.
|
|
39
|
+
//
|
|
40
|
+
// It does check the module's own diagnostics first, which costs about 6ms and earns it back
|
|
41
|
+
// the first time somebody mistypes an import. A type read out of a file that does not compile
|
|
42
|
+
// comes back as an error type, and the reflection reports an error type as "the checker could
|
|
43
|
+
// not resolve this type" — true, unhelpful, and repeated once per column. The compile error is
|
|
44
|
+
// the thing that happened, so that is what gets raised.
|
|
45
|
+
import { existsSync } from 'node:fs';
|
|
46
|
+
import { dirname, join, resolve } from 'node:path';
|
|
47
|
+
import { fileURLToPath } from 'node:url';
|
|
48
|
+
import {} from '@zmdb/schema';
|
|
49
|
+
import { schemaFromIR } from '@zmdb/schema/ir';
|
|
50
|
+
import {} from '@zmdb/schema/naming';
|
|
51
|
+
import { schemaIrFromType } from '../reflect/index.js';
|
|
52
|
+
import { ReflectSession } from '../reflect/session.js';
|
|
53
|
+
function reflectOptions(options) {
|
|
54
|
+
return options.naming === undefined ? undefined : { naming: options.naming };
|
|
55
|
+
}
|
|
56
|
+
export function schemasFrom(module, names, options = {}) {
|
|
57
|
+
const irs = schemaIrsFrom(module, names, options);
|
|
58
|
+
const schemas = {};
|
|
59
|
+
for (const [name, ir] of Object.entries(irs))
|
|
60
|
+
schemas[name] = schemaFromIR(ir);
|
|
61
|
+
return schemas;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Every exported tagged table declaration in a concrete file set.
|
|
65
|
+
*
|
|
66
|
+
* Config loading has already expanded and project-checked these files. This
|
|
67
|
+
* bridge keeps the remaining compiler work in the reflection library: one
|
|
68
|
+
* session for the project, one pass over each module's exports, and the same
|
|
69
|
+
* `schemaFromIR` conversion used by `schemaOf<T>()` and `schemasFrom()`.
|
|
70
|
+
*/
|
|
71
|
+
export function schemasFromFiles(files, options) {
|
|
72
|
+
if (files.length === 0)
|
|
73
|
+
throw new Error('the configured schema file set is empty');
|
|
74
|
+
using session = ReflectSession.open({ project: options.project });
|
|
75
|
+
const schemas = new Map();
|
|
76
|
+
const diagnostics = [];
|
|
77
|
+
for (const file of files.toSorted()) {
|
|
78
|
+
const sourceFile = session.sourceFile(file);
|
|
79
|
+
if (!sourceFile) {
|
|
80
|
+
throw new Error(`${file} is not part of ${options.project}; the configured schema files must belong to the project`);
|
|
81
|
+
}
|
|
82
|
+
const broken = session.diagnostics(file);
|
|
83
|
+
if (broken.length > 0) {
|
|
84
|
+
throw new Error(`${file} does not compile, so its table declarations cannot be read (${broken.length} diagnostic(s)):\n` +
|
|
85
|
+
broken
|
|
86
|
+
.slice(0, 5)
|
|
87
|
+
.map(one => ` TS${String(one.code)}: ${one.text}`)
|
|
88
|
+
.join('\n'));
|
|
89
|
+
}
|
|
90
|
+
const moduleSymbol = session.checker.getSymbolAtLocation(sourceFile);
|
|
91
|
+
if (!moduleSymbol)
|
|
92
|
+
throw new Error(`${file} has no module symbol, so it exports nothing to read`);
|
|
93
|
+
const exported = session.checker
|
|
94
|
+
.getExportsOfModule(moduleSymbol)
|
|
95
|
+
.toSorted((left, right) => left.name.localeCompare(right.name));
|
|
96
|
+
for (const symbol of exported) {
|
|
97
|
+
const type = session.checker.getDeclaredTypeOfSymbol(symbol);
|
|
98
|
+
const reflected = schemaIrFromType(session.checker, type, sourceFile, reflectOptions(options));
|
|
99
|
+
const isTable = reflected.diagnostics.every(diagnostic => !diagnostic.reason.includes("no Table<'name'> tag"));
|
|
100
|
+
if (!isTable)
|
|
101
|
+
continue;
|
|
102
|
+
diagnostics.push(...reflected.diagnostics);
|
|
103
|
+
const schema = schemaFromIR(reflected.ir);
|
|
104
|
+
const previous = schemas.get(schema.ir.table);
|
|
105
|
+
if (previous !== undefined) {
|
|
106
|
+
if (JSON.stringify(previous.ir) !== JSON.stringify(schema.ir)) {
|
|
107
|
+
throw new Error(`configured schema files export conflicting declarations for table ${schema.ir.table}`);
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
schemas.set(schema.ir.table, schema);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (diagnostics.length > 0) {
|
|
115
|
+
if (options.onDiagnostics)
|
|
116
|
+
options.onDiagnostics(diagnostics);
|
|
117
|
+
else {
|
|
118
|
+
throw new Error(`the reflection refused ${diagnostics.length} thing(s) in the configured schema files:\n` +
|
|
119
|
+
diagnostics.map(one => ` ${one.path ? `${one.path}: ` : ''}${one.reason}`).join('\n'));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (schemas.size === 0) {
|
|
123
|
+
throw new Error(`the configured schema files export no tagged table declarations: ${files.toSorted().join(', ')}`);
|
|
124
|
+
}
|
|
125
|
+
return [...schemas.values()].toSorted((left, right) => left.ir.table.localeCompare(right.ir.table));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The same, stopping at the IR.
|
|
129
|
+
*
|
|
130
|
+
* Separate because the IR is the spine and a test about the front-end wants to see it
|
|
131
|
+
* directly — the schema value is one conversion further on, and `schemaFromIR` is not the
|
|
132
|
+
* thing under test.
|
|
133
|
+
*/
|
|
134
|
+
export function schemaIrsFrom(module, names, options = {}) {
|
|
135
|
+
const file = module.startsWith('file:') ? fileURLToPath(module) : resolve(module);
|
|
136
|
+
const project = options.project ?? nearestProject(file);
|
|
137
|
+
using session = ReflectSession.open({ project });
|
|
138
|
+
const sourceFile = session.sourceFile(file);
|
|
139
|
+
if (!sourceFile) {
|
|
140
|
+
throw new Error(`${file} is not part of ${project}. The tagged interfaces have to be in the program for ` +
|
|
141
|
+
'the checker to have a declared type for them.');
|
|
142
|
+
}
|
|
143
|
+
// Before anything is read off the type: a file that does not compile has error types in it,
|
|
144
|
+
// and an error type reflects as a refusal per column rather than as the one problem it is.
|
|
145
|
+
const broken = session.diagnostics(file);
|
|
146
|
+
if (broken.length > 0) {
|
|
147
|
+
throw new Error(`${file} does not compile, so its types cannot be read (${broken.length} diagnostic(s)):\n` +
|
|
148
|
+
broken
|
|
149
|
+
.slice(0, 5)
|
|
150
|
+
.map(one => ` TS${String(one.code)}: ${one.text}`)
|
|
151
|
+
.join('\n'));
|
|
152
|
+
}
|
|
153
|
+
const { checker } = session;
|
|
154
|
+
const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
|
|
155
|
+
if (!moduleSymbol)
|
|
156
|
+
throw new Error(`${file} has no module symbol, so it exports nothing to read`);
|
|
157
|
+
const exported = new Map(checker.getExportsOfModule(moduleSymbol).map(symbol => [symbol.name, symbol]));
|
|
158
|
+
const irs = {};
|
|
159
|
+
const diagnostics = [];
|
|
160
|
+
for (const name of names) {
|
|
161
|
+
const symbol = exported.get(name);
|
|
162
|
+
if (!symbol) {
|
|
163
|
+
// Naming the exports is worth the line: the usual cause is a missing `export`, and the
|
|
164
|
+
// message "User is not exported" is not obviously that when the interface is right there.
|
|
165
|
+
throw new Error(`${file} exports no \`${name}\`. It has to be \`export interface ${name}\` — the module's ` +
|
|
166
|
+
`export table is how the name is resolved. Exports found: ${[...exported.keys()].join(', ') || 'none'}.`);
|
|
167
|
+
}
|
|
168
|
+
const type = checker.getDeclaredTypeOfSymbol(symbol);
|
|
169
|
+
// One reflector per name, which `schemaIrFromType` gives us: the node budget and the
|
|
170
|
+
// helper-name table are per-reflection state, and sharing them across unrelated tables
|
|
171
|
+
// would make one table's refusals show up against another's.
|
|
172
|
+
const result = schemaIrFromType(checker, type, sourceFile, reflectOptions(options));
|
|
173
|
+
irs[name] = result.ir;
|
|
174
|
+
diagnostics.push(...result.diagnostics);
|
|
175
|
+
}
|
|
176
|
+
if (diagnostics.length > 0) {
|
|
177
|
+
if (options.onDiagnostics)
|
|
178
|
+
options.onDiagnostics(diagnostics);
|
|
179
|
+
else {
|
|
180
|
+
throw new Error(`the reflection refused ${diagnostics.length} thing(s) in ${file}:\n` +
|
|
181
|
+
diagnostics.map(one => ` ${one.path ? `${one.path}: ` : ''}${one.reason}`).join('\n'));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// boundary: `irs` is filled in by the loop above, one key per member of `names`, and the
|
|
185
|
+
// loop throws rather than skipping when a name is not exported — so every key the return
|
|
186
|
+
// type promises is present by the time this runs. What the assertion buys is the *literal*
|
|
187
|
+
// keys: built from a `Record<string, SchemaIR>` because the names arrive as values, and no
|
|
188
|
+
// amount of building it differently makes the compiler read them back off the array.
|
|
189
|
+
return irs;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The nearest `tsconfig.json` at or above a file.
|
|
193
|
+
*
|
|
194
|
+
* The same rule `tsc` uses for a bare invocation, and the same one the codegen CLI documents,
|
|
195
|
+
* so a caller who has not thought about it gets the project they would have guessed.
|
|
196
|
+
*/
|
|
197
|
+
function nearestProject(file) {
|
|
198
|
+
let directory = dirname(file);
|
|
199
|
+
for (;;) {
|
|
200
|
+
const candidate = join(directory, 'tsconfig.json');
|
|
201
|
+
if (existsSync(candidate))
|
|
202
|
+
return candidate;
|
|
203
|
+
const parent = dirname(directory);
|
|
204
|
+
if (parent === directory) {
|
|
205
|
+
throw new Error(`no tsconfig.json at or above ${file}; pass \`project\` explicitly`);
|
|
206
|
+
}
|
|
207
|
+
directory = parent;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type EmitOptions } from '../emit/index.js';
|
|
2
|
+
import { type ReflectOptions } from '../reflect/index.js';
|
|
3
|
+
import type { ReflectSession } from '../reflect/session.js';
|
|
4
|
+
/**
|
|
5
|
+
* The calls `transformFile` rewrites. Matched by identifier text — see `callsites.ts`.
|
|
6
|
+
*
|
|
7
|
+
* Exported because no-bundler project compilation asks the same question about the same names, and
|
|
8
|
+
* two lists would drift: a callee added here and not there is a call the bundler inlines
|
|
9
|
+
* and the CLI leaves as a runtime walk, which is a silent performance cliff between two
|
|
10
|
+
* paths that are supposed to be equivalent.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CALLEES: ReadonlySet<string>;
|
|
13
|
+
/** A call site left alone, and why. Plan D4: the build reports these as errors. */
|
|
14
|
+
export interface TransformDiagnostic {
|
|
15
|
+
readonly fileName: string;
|
|
16
|
+
/** Offset of the call this came from, when it came from one. */
|
|
17
|
+
readonly position?: number;
|
|
18
|
+
readonly callee?: string;
|
|
19
|
+
/** The property chain within the type that reached the refusal. */
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly reason: string;
|
|
22
|
+
/** The type as the checker prints it, when that is more use than the path. */
|
|
23
|
+
readonly source?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface TransformResult {
|
|
26
|
+
readonly code: string;
|
|
27
|
+
readonly changed: boolean;
|
|
28
|
+
readonly diagnostics: readonly TransformDiagnostic[];
|
|
29
|
+
}
|
|
30
|
+
export interface TransformContext {
|
|
31
|
+
/** One session per build, held open by the caller. See `session.ts`. */
|
|
32
|
+
readonly session: ReflectSession;
|
|
33
|
+
readonly emit?: EmitOptions;
|
|
34
|
+
readonly reflect?: ReflectOptions;
|
|
35
|
+
/** Synthetic test projects can opt into their ambient global call declarations. */
|
|
36
|
+
readonly allowUnboundCallees?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Rewrite every reachable validation call in one file.
|
|
40
|
+
*
|
|
41
|
+
* The file must be part of the session's project and its text must be what the compiler
|
|
42
|
+
* parsed. When either does not hold the offsets are meaningless, so this degrades to
|
|
43
|
+
* `transformCode` and says so, rather than rewriting at a position it guessed.
|
|
44
|
+
*/
|
|
45
|
+
export declare function transformFile(fileName: string, code: string, context: TransformContext): TransformResult;
|
|
46
|
+
/**
|
|
47
|
+
* Text edits in original coordinates, applied back to front, with one twist: `slice`
|
|
48
|
+
* reads the *current* text, so an outer call sees an inner one already rewritten.
|
|
49
|
+
*
|
|
50
|
+
* The bookkeeping is a list of applied edits and their length deltas. Because AST spans
|
|
51
|
+
* nest and never partially overlap, and because callers work backwards, every applied
|
|
52
|
+
* edit is either inside the span being asked about or entirely after it — which is what
|
|
53
|
+
* makes a single sum the right answer.
|
|
54
|
+
*/
|
|
55
|
+
export declare class Rewriter {
|
|
56
|
+
#private;
|
|
57
|
+
constructor(text: string);
|
|
58
|
+
get text(): string;
|
|
59
|
+
/** A span of the original text, as it reads now. */
|
|
60
|
+
slice(start: number, end: number): string;
|
|
61
|
+
/** Replace a span of the original text. Call in descending order of `start`. */
|
|
62
|
+
replace(start: number, end: number, text: string): void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Inline `validate(tags.X(…), expr)`, and nothing else.
|
|
66
|
+
*
|
|
67
|
+
* A rule spelled at the call site needs no type information, which is why this survives
|
|
68
|
+
* without a compiler: the scanner is here only to avoid rewriting the inside of a string
|
|
69
|
+
* literal or a comment. `validate<T>(expr)` and every other type-argument form are left
|
|
70
|
+
* for `transformFile`; this function does not look at type arguments at all beyond
|
|
71
|
+
* skipping past them.
|
|
72
|
+
*/
|
|
73
|
+
export declare function transformCode(code: string): string;
|
|
74
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transform/index.ts"],"names":[],"mappings":"AAkCA,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG5E,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,WAAW,CAAC,MAAM,CAAiB,CAAC;AA+B1D,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,mFAAmF;IACnF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CACxC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAqIxG;AAqOD;;;;;;;;GAQG;AACH,qBAAa,QAAQ;;IAKnB,YAAY,IAAI,EAAE,MAAM,EAEvB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,oDAAoD;IACpD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAExC;IAED,gFAAgF;IAChF,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQtD;CASF;AA6ED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkFlD"}
|