@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.
Files changed (172) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +40 -0
  3. package/dist/codegen/index.d.ts +50 -0
  4. package/dist/codegen/index.d.ts.map +1 -0
  5. package/dist/codegen/index.js +364 -0
  6. package/dist/codegen/index.js.map +1 -0
  7. package/dist/codegen/scan.d.ts +105 -0
  8. package/dist/codegen/scan.d.ts.map +1 -0
  9. package/dist/codegen/scan.js +450 -0
  10. package/dist/codegen/scan.js.map +1 -0
  11. package/dist/codegen/witness.d.ts +76 -0
  12. package/dist/codegen/witness.d.ts.map +1 -0
  13. package/dist/codegen/witness.js +690 -0
  14. package/dist/codegen/witness.js.map +1 -0
  15. package/dist/config/contract.d.ts +41 -0
  16. package/dist/config/contract.d.ts.map +1 -0
  17. package/dist/config/contract.js +5 -0
  18. package/dist/config/contract.js.map +1 -0
  19. package/dist/config/index.d.ts +53 -0
  20. package/dist/config/index.d.ts.map +1 -0
  21. package/dist/config/index.js +277 -0
  22. package/dist/config/index.js.map +1 -0
  23. package/dist/config/index.zmdb.generated.d.ts +12 -0
  24. package/dist/config/index.zmdb.generated.js +28 -0
  25. package/dist/config/index.zmdb.witness.d.ts +3 -0
  26. package/dist/config/index.zmdb.witness.d.ts.map +1 -0
  27. package/dist/config/index.zmdb.witness.js +20 -0
  28. package/dist/config/index.zmdb.witness.js.map +1 -0
  29. package/dist/configured-plugin.d.ts +11 -0
  30. package/dist/configured-plugin.d.ts.map +1 -0
  31. package/dist/configured-plugin.js +27 -0
  32. package/dist/configured-plugin.js.map +1 -0
  33. package/dist/emit/index.d.ts +103 -0
  34. package/dist/emit/index.d.ts.map +1 -0
  35. package/dist/emit/index.js +1356 -0
  36. package/dist/emit/index.js.map +1 -0
  37. package/dist/errors.d.ts +7 -0
  38. package/dist/errors.d.ts.map +1 -0
  39. package/dist/errors.js +2 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/index.d.ts +46 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +254 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/lint/ast.d.ts +17 -0
  46. package/dist/lint/ast.d.ts.map +1 -0
  47. package/dist/lint/ast.js +77 -0
  48. package/dist/lint/ast.js.map +1 -0
  49. package/dist/lint/host-types.d.ts +9 -0
  50. package/dist/lint/host-types.d.ts.map +1 -0
  51. package/dist/lint/host-types.js +2 -0
  52. package/dist/lint/host-types.js.map +1 -0
  53. package/dist/lint/index.d.ts +23 -0
  54. package/dist/lint/index.d.ts.map +1 -0
  55. package/dist/lint/index.js +53 -0
  56. package/dist/lint/index.js.map +1 -0
  57. package/dist/lint/rules/no-distributed-nullable-tags.d.ts +3 -0
  58. package/dist/lint/rules/no-distributed-nullable-tags.d.ts.map +1 -0
  59. package/dist/lint/rules/no-distributed-nullable-tags.js +71 -0
  60. package/dist/lint/rules/no-distributed-nullable-tags.js.map +1 -0
  61. package/dist/lint/rules/no-empty-patch.d.ts +3 -0
  62. package/dist/lint/rules/no-empty-patch.d.ts.map +1 -0
  63. package/dist/lint/rules/no-empty-patch.js +26 -0
  64. package/dist/lint/rules/no-empty-patch.js.map +1 -0
  65. package/dist/lint/rules/no-interpolated-sql.d.ts +3 -0
  66. package/dist/lint/rules/no-interpolated-sql.d.ts.map +1 -0
  67. package/dist/lint/rules/no-interpolated-sql.js +35 -0
  68. package/dist/lint/rules/no-interpolated-sql.js.map +1 -0
  69. package/dist/lint/rules/no-unbounded-find.d.ts +3 -0
  70. package/dist/lint/rules/no-unbounded-find.d.ts.map +1 -0
  71. package/dist/lint/rules/no-unbounded-find.js +26 -0
  72. package/dist/lint/rules/no-unbounded-find.js.map +1 -0
  73. package/dist/lint/rules/no-unknown-json-column.d.ts +3 -0
  74. package/dist/lint/rules/no-unknown-json-column.d.ts.map +1 -0
  75. package/dist/lint/rules/no-unknown-json-column.js +35 -0
  76. package/dist/lint/rules/no-unknown-json-column.js.map +1 -0
  77. package/dist/lint/rules/require-sql-on-number.d.ts +3 -0
  78. package/dist/lint/rules/require-sql-on-number.d.ts.map +1 -0
  79. package/dist/lint/rules/require-sql-on-number.js +34 -0
  80. package/dist/lint/rules/require-sql-on-number.js.map +1 -0
  81. package/dist/lint/types.d.ts +12 -0
  82. package/dist/lint/types.d.ts.map +1 -0
  83. package/dist/lint/types.js +2 -0
  84. package/dist/lint/types.js.map +1 -0
  85. package/dist/metro/metro.d.ts +22 -0
  86. package/dist/metro/metro.d.ts.map +1 -0
  87. package/dist/metro/metro.js +242 -0
  88. package/dist/metro/metro.js.map +1 -0
  89. package/dist/protobuf/decode.d.ts +20 -0
  90. package/dist/protobuf/decode.d.ts.map +1 -0
  91. package/dist/protobuf/decode.js +289 -0
  92. package/dist/protobuf/decode.js.map +1 -0
  93. package/dist/protobuf/descriptor.d.ts +16 -0
  94. package/dist/protobuf/descriptor.d.ts.map +1 -0
  95. package/dist/protobuf/descriptor.js +303 -0
  96. package/dist/protobuf/descriptor.js.map +1 -0
  97. package/dist/protobuf/encode.d.ts +20 -0
  98. package/dist/protobuf/encode.d.ts.map +1 -0
  99. package/dist/protobuf/encode.js +203 -0
  100. package/dist/protobuf/encode.js.map +1 -0
  101. package/dist/protobuf/grpc-ir.d.ts +16 -0
  102. package/dist/protobuf/grpc-ir.d.ts.map +1 -0
  103. package/dist/protobuf/grpc-ir.js +2 -0
  104. package/dist/protobuf/grpc-ir.js.map +1 -0
  105. package/dist/protobuf/plan.d.ts +42 -0
  106. package/dist/protobuf/plan.d.ts.map +1 -0
  107. package/dist/protobuf/plan.js +158 -0
  108. package/dist/protobuf/plan.js.map +1 -0
  109. package/dist/reflect/callsites.d.ts +40 -0
  110. package/dist/reflect/callsites.d.ts.map +1 -0
  111. package/dist/reflect/callsites.js +153 -0
  112. package/dist/reflect/callsites.js.map +1 -0
  113. package/dist/reflect/index.d.ts +106 -0
  114. package/dist/reflect/index.d.ts.map +1 -0
  115. package/dist/reflect/index.js +1421 -0
  116. package/dist/reflect/index.js.map +1 -0
  117. package/dist/reflect/session.d.ts +118 -0
  118. package/dist/reflect/session.d.ts.map +1 -0
  119. package/dist/reflect/session.js +228 -0
  120. package/dist/reflect/session.js.map +1 -0
  121. package/dist/testing/index.d.ts +69 -0
  122. package/dist/testing/index.d.ts.map +1 -0
  123. package/dist/testing/index.js +210 -0
  124. package/dist/testing/index.js.map +1 -0
  125. package/dist/transform/index.d.ts +74 -0
  126. package/dist/transform/index.d.ts.map +1 -0
  127. package/dist/transform/index.js +572 -0
  128. package/dist/transform/index.js.map +1 -0
  129. package/dist/unplugin/index.d.ts +53 -0
  130. package/dist/unplugin/index.d.ts.map +1 -0
  131. package/dist/unplugin/index.js +130 -0
  132. package/dist/unplugin/index.js.map +1 -0
  133. package/dist/unplugin/inline-bench.d.ts +29 -0
  134. package/dist/unplugin/inline-bench.d.ts.map +1 -0
  135. package/dist/unplugin/inline-bench.js +82 -0
  136. package/dist/unplugin/inline-bench.js.map +1 -0
  137. package/package.json +110 -0
  138. package/src/codegen/index.ts +451 -0
  139. package/src/codegen/scan.ts +574 -0
  140. package/src/codegen/witness.ts +819 -0
  141. package/src/config/contract.ts +48 -0
  142. package/src/config/index.ts +384 -0
  143. package/src/config/index.zmdb.generated.d.ts +12 -0
  144. package/src/config/index.zmdb.generated.js +28 -0
  145. package/src/config/index.zmdb.witness.ts +22 -0
  146. package/src/configured-plugin.ts +35 -0
  147. package/src/emit/index.ts +1496 -0
  148. package/src/errors.ts +6 -0
  149. package/src/index.ts +336 -0
  150. package/src/lint/ast.ts +96 -0
  151. package/src/lint/host-types.ts +9 -0
  152. package/src/lint/index.ts +80 -0
  153. package/src/lint/rules/no-distributed-nullable-tags.ts +76 -0
  154. package/src/lint/rules/no-empty-patch.ts +26 -0
  155. package/src/lint/rules/no-interpolated-sql.ts +45 -0
  156. package/src/lint/rules/no-unbounded-find.ts +26 -0
  157. package/src/lint/rules/no-unknown-json-column.ts +36 -0
  158. package/src/lint/rules/require-sql-on-number.ts +34 -0
  159. package/src/lint/types.ts +11 -0
  160. package/src/metro/metro.ts +313 -0
  161. package/src/protobuf/decode.ts +375 -0
  162. package/src/protobuf/descriptor.ts +353 -0
  163. package/src/protobuf/encode.ts +277 -0
  164. package/src/protobuf/grpc-ir.ts +17 -0
  165. package/src/protobuf/plan.ts +244 -0
  166. package/src/reflect/callsites.ts +198 -0
  167. package/src/reflect/index.ts +1723 -0
  168. package/src/reflect/session.ts +276 -0
  169. package/src/testing/index.ts +298 -0
  170. package/src/transform/index.ts +690 -0
  171. package/src/unplugin/index.ts +182 -0
  172. package/src/unplugin/inline-bench.ts +92 -0
@@ -0,0 +1,450 @@
1
+ // The source-analysis half of no-bundler project compilation: what to generate, which canonical
2
+ // package export each call resolves to, and what the generated module has to import.
3
+ //
4
+ // Nothing here asks the checker anything. That is deliberate — every question this file
5
+ // answers is about *text*: which calls carry a type argument, which names that type
6
+ // argument mentions, and where those names came from. Answering them syntactically keeps
7
+ // the expensive half (one `tsgo` session, one reflection per type) to exactly the call
8
+ // sites that survive this pass.
9
+ //
10
+ // The one non-obvious job is the import block of the witness module. `is<Omit<User, 'id'>>`
11
+ // is written in a file where `Omit` is global and `User` is imported from `./models.ts`;
12
+ // the same type argument in a *different* file resolves to nothing. So the witness is
13
+ // written next to the source it came from and re-states the source's own imports, filtered
14
+ // to the names the type arguments actually mention. A name the witness could not import is
15
+ // a refusal with the name in it, not a guess (plan D4).
16
+ import { isClassDeclaration, isEnumDeclaration, isExportDeclaration, isExportKeyword, isIdentifier, isImportDeclaration, isInterfaceDeclaration, isModuleDeclaration, isNamedExports, isNamedImports, isNamespaceImport, isPropertyAccessExpression, isQualifiedName, isStringLiteral, isTypeAliasDeclaration, isTypeQueryNode, isTypeReferenceNode, isVariableStatement, } from 'typescript/unstable/ast/is';
17
+ import { CALL_OWNERS, findOwnedCallSites } from '../reflect/callsites.js';
18
+ import { CALLEES } from '../transform/index.js';
19
+ // -----------------------------------------------------------------------------
20
+ // Reading a module
21
+ // -----------------------------------------------------------------------------
22
+ /**
23
+ * Whether a declaration carries `export`.
24
+ *
25
+ * boundary: `modifiers` is declared on each of the dozen node types that can have one, and
26
+ * not on `Node`. Asking for it as an optional property is how a walk that accepts any node
27
+ * reads it without a `switch` over those dozen types — and the `Array.isArray` on the next
28
+ * line is what makes the read sound rather than the cast.
29
+ */
30
+ function exported(node) {
31
+ const modifiers = node.modifiers;
32
+ return Array.isArray(modifiers) && modifiers.some(modifier => isExportKeyword(modifier));
33
+ }
34
+ /** Import bindings, local declarations and exports of one module. */
35
+ export function moduleFacts(sourceFile) {
36
+ const imports = new Map();
37
+ const locals = new Set();
38
+ const exports = new Set();
39
+ for (const statement of sourceFile.statements) {
40
+ if (isImportDeclaration(statement)) {
41
+ const specifierNode = statement.moduleSpecifier;
42
+ if (!isStringLiteral(specifierNode))
43
+ continue;
44
+ const specifier = specifierNode.text;
45
+ const clause = statement.importClause;
46
+ if (!clause)
47
+ continue;
48
+ if (clause.name) {
49
+ imports.set(clause.name.text, { specifier, kind: 'default', original: 'default' });
50
+ }
51
+ const bindings = clause.namedBindings;
52
+ if (bindings === undefined)
53
+ continue;
54
+ if (isNamespaceImport(bindings)) {
55
+ imports.set(bindings.name.text, { specifier, kind: 'namespace', original: '*' });
56
+ }
57
+ else if (isNamedImports(bindings)) {
58
+ for (const element of bindings.elements) {
59
+ if (!isIdentifier(element.name))
60
+ continue;
61
+ const original = element.propertyName && isIdentifier(element.propertyName) ? element.propertyName.text : element.name.text;
62
+ imports.set(element.name.text, { specifier, kind: 'named', original });
63
+ }
64
+ }
65
+ continue;
66
+ }
67
+ if (isInterfaceDeclaration(statement) ||
68
+ isTypeAliasDeclaration(statement) ||
69
+ isClassDeclaration(statement) ||
70
+ isEnumDeclaration(statement) ||
71
+ isModuleDeclaration(statement)) {
72
+ const name = statement.name;
73
+ if (name && isIdentifier(name)) {
74
+ locals.add(name.text);
75
+ if (exported(statement))
76
+ exports.add(name.text);
77
+ }
78
+ continue;
79
+ }
80
+ if (isVariableStatement(statement)) {
81
+ // Only for `typeof x` in a type argument. The declaration list can destructure, and
82
+ // a destructured binding is not something a type query can name, so plain
83
+ // identifiers are the whole of what is useful here.
84
+ for (const declaration of statement.declarationList.declarations) {
85
+ if (!isIdentifier(declaration.name))
86
+ continue;
87
+ locals.add(declaration.name.text);
88
+ if (exported(statement))
89
+ exports.add(declaration.name.text);
90
+ }
91
+ continue;
92
+ }
93
+ if (isExportDeclaration(statement)) {
94
+ const bindings = statement.exportClause;
95
+ if (bindings && isNamedExports(bindings)) {
96
+ for (const element of bindings.elements) {
97
+ if (isIdentifier(element.name))
98
+ exports.add(element.name.text);
99
+ }
100
+ }
101
+ continue;
102
+ }
103
+ if (exported(statement)) {
104
+ // boundary: same shape as `exported` above — `name` belongs to the declaration types,
105
+ // not to `Node`, and this branch is the fall-through for the statement kinds the cases
106
+ // above did not name. `isIdentifier` is what proves the read, so a node with no `name`
107
+ // and a node whose name is a computed property both fall out here.
108
+ const name = statement.name;
109
+ if (name && isIdentifier(name))
110
+ exports.add(name.text);
111
+ }
112
+ }
113
+ return { imports, locals, exported: exports };
114
+ }
115
+ /**
116
+ * The names a type argument depends on, as written.
117
+ *
118
+ * Only the *head* of a reference counts: `ns.T` needs `ns`, `Omit<User, 'id'>` needs
119
+ * `Omit` and `User`, and the `'id'` needs nothing. Collecting every identifier instead
120
+ * would drag in the property names of an inline object type and then refuse the call site
121
+ * because `email` is not importable.
122
+ */
123
+ export function referencedNames(node) {
124
+ const names = new Set();
125
+ const head = (name) => {
126
+ if (isIdentifier(name))
127
+ names.add(name.text);
128
+ else if (isQualifiedName(name))
129
+ head(name.left);
130
+ };
131
+ const walk = (current) => {
132
+ if (isTypeReferenceNode(current))
133
+ head(current.typeName);
134
+ else if (isTypeQueryNode(current))
135
+ head(current.exprName);
136
+ current.forEachChild(walk);
137
+ };
138
+ walk(node);
139
+ return names;
140
+ }
141
+ // -----------------------------------------------------------------------------
142
+ // Naming
143
+ // -----------------------------------------------------------------------------
144
+ /** `is` → `Is`, so the export reads as a sentence: `zmdbIsUser`. */
145
+ function capitalise(text) {
146
+ return text.charAt(0).toUpperCase() + text.slice(1);
147
+ }
148
+ const PREFIXES = {
149
+ is: 'Is',
150
+ isShallow: 'IsShallow',
151
+ equals: 'Equals',
152
+ assert: 'Assert',
153
+ assertShallow: 'AssertShallow',
154
+ assertEquals: 'AssertEquals',
155
+ validate: 'Validate',
156
+ validateShallow: 'ValidateShallow',
157
+ random: 'Random',
158
+ toJsonSchema: 'JsonSchema',
159
+ schemaOf: 'Schema',
160
+ toolFor: 'Tool',
161
+ grpcDescriptor: 'GrpcDescriptor',
162
+ loadGrpcService: 'LoadGrpcService',
163
+ protoDescriptor: 'ProtoDescriptor',
164
+ protoDecode: 'ProtoDecode',
165
+ protoEncode: 'ProtoEncode',
166
+ };
167
+ /** How long a slug may get before it stops being a name and starts being the type. */
168
+ const MAX_SLUG = 48;
169
+ /**
170
+ * A stable export name for one entry.
171
+ *
172
+ * Stability is the requirement, not beauty: the name is written into the user's source, so
173
+ * it has to come out the same on every run or the codegen produces a diff per invocation.
174
+ * It is derived only from the callee and the type text, both of which are in the source.
175
+ */
176
+ export function exportName(callee, typeText, taken, depthText, identityText) {
177
+ const slug = `${typeText} ${identityText ?? ''}`
178
+ .replaceAll(/[^A-Za-z0-9]+/g, ' ')
179
+ .trim()
180
+ .split(/\s+/)
181
+ .map(capitalise)
182
+ .join('')
183
+ .slice(0, MAX_SLUG);
184
+ const depth = depthText === undefined
185
+ ? ''
186
+ : `Depth${depthText
187
+ .replaceAll(/[^A-Za-z0-9]+/g, ' ')
188
+ .trim()
189
+ .split(/\s+/)
190
+ .map(capitalise)
191
+ .join('')}`;
192
+ const base = `zmdb${PREFIXES[callee] ?? capitalise(callee)}${slug}${depth}`;
193
+ if (!taken.has(base))
194
+ return base;
195
+ // Two different types with the same slug — `Pick<User, 'id'>` and `Pick<User, "id">`,
196
+ // say. Numbering is ugly and deterministic, which is the right trade for a generated
197
+ // name; guessing that they are the same type would be neither.
198
+ for (let n = 2;; n += 1) {
199
+ const candidate = `${base}_${String(n)}`;
200
+ if (!taken.has(candidate))
201
+ return candidate;
202
+ }
203
+ }
204
+ // -----------------------------------------------------------------------------
205
+ // Where the callee came from
206
+ // -----------------------------------------------------------------------------
207
+ /**
208
+ * The package a callee lives in, for a call that did not import it by name.
209
+ *
210
+ * Only reached by `zmdb.is<User>(x)` where `zmdb` turns out not to be an import either —
211
+ * an unusual file. The subpaths are the truth about where each function is declared, and a
212
+ * project that installed only the product package has them all re-exported from `zmdb`, so the
213
+ * import the witness writes resolves in both layouts as long as the source's own import
214
+ * could be read. When it could not, this is the better guess than nothing.
215
+ */
216
+ const DEFAULT_MODULES = {
217
+ is: '@zmdb/validator',
218
+ equals: '@zmdb/validator',
219
+ assert: '@zmdb/validator',
220
+ assertShallow: '@zmdb/validator',
221
+ assertEquals: '@zmdb/validator',
222
+ validate: '@zmdb/validator',
223
+ validateShallow: '@zmdb/validator',
224
+ isShallow: '@zmdb/validator',
225
+ random: '@zmdb/validator',
226
+ toJsonSchema: '@zmdb/schema/openapi',
227
+ schemaOf: '@zmdb/schema',
228
+ toolFor: '@zmdb/ai',
229
+ grpcDescriptor: '@zmdb/protobuf',
230
+ loadGrpcService: '@zmdb/protobuf',
231
+ protoDescriptor: '@zmdb/protobuf',
232
+ protoDecode: '@zmdb/protobuf',
233
+ protoEncode: '@zmdb/protobuf',
234
+ };
235
+ /**
236
+ * Which module the witness should import a callee from.
237
+ *
238
+ * The source's own import, whenever there is one, and not a fixed table: a project that
239
+ * installed `zmdb` can import `is` from the product root, and a witness that reached past
240
+ * it to `@zmdb/validator` would import a package that is not in the
241
+ * consumer's dependencies. `zmdb.is<User>(x)` resolves through the namespace's own import
242
+ * for the same reason.
243
+ */
244
+ function calleeSpecifier(facts, site) {
245
+ if (site.specifier !== undefined)
246
+ return site.specifier;
247
+ const direct = facts.imports.get(site.callee);
248
+ if (direct)
249
+ return direct.specifier;
250
+ const target = site.node.expression;
251
+ if (isPropertyAccessExpression(target) && isIdentifier(target.expression)) {
252
+ const namespace = facts.imports.get(target.expression.text);
253
+ if (namespace)
254
+ return namespace.specifier;
255
+ }
256
+ return DEFAULT_MODULES[site.callee] ?? '@zmdb/validator';
257
+ }
258
+ /**
259
+ * How to spell a relative import of a sibling `.ts` file, as this module spells it.
260
+ *
261
+ * There is no universally right answer — `./models.ts` needs
262
+ * `allowImportingTsExtensions`, and `./models.js` names a file that does not exist until
263
+ * something compiles it — so the witness copies whatever the source does. Only when the
264
+ * source has no relative import at all does the project's own setting decide.
265
+ */
266
+ function relativeExtension(facts, tsExtensions) {
267
+ let sawJs = false;
268
+ for (const binding of facts.imports.values()) {
269
+ if (!binding.specifier.startsWith('.'))
270
+ continue;
271
+ if (/\.[cm]?tsx?$/.test(binding.specifier))
272
+ return '.ts';
273
+ if (/\.[cm]?jsx?$/.test(binding.specifier))
274
+ sawJs = true;
275
+ }
276
+ if (sawJs)
277
+ return '.js';
278
+ return tsExtensions === false ? '.js' : '.ts';
279
+ }
280
+ /** `/a/b/models.ts` → `./models.ts` or `./models.js`, per `relativeExtension`. */
281
+ function siblingSpecifier(fileName, extension) {
282
+ const name = basename(fileName);
283
+ const stem = name.replace(/\.[cm]?tsx?$/, '');
284
+ return `./${stem}${extension}`;
285
+ }
286
+ /**
287
+ * Everything the generator needs for one source file.
288
+ *
289
+ * Two inputs rather than one, because the rewrite is destructive: after a run the source
290
+ * says `zmdbIsUser(data)` and the `is<User>` that produced it is gone. The witness keeps
291
+ * it — and keeps it in a form the compiler checks, so a renamed or deleted `User` is a
292
+ * build error in a generated file rather than a validator that quietly describes a type
293
+ * nobody declares any more. So the entry set is the union of the two, and an entry the
294
+ * source has stopped referencing is dropped, which is what stops the witness accumulating
295
+ * validators for code that no longer exists.
296
+ */
297
+ export function scan(input) {
298
+ const { checker, sourceFile, witnessFile } = input;
299
+ const sourceText = sourceFile.text;
300
+ const entries = [];
301
+ const sites = [];
302
+ const refusals = [];
303
+ const calleeSources = new Map();
304
+ const taken = new Set();
305
+ /** Callee, type, depth and captured literals → one shared generated export. */
306
+ const byKey = new Map();
307
+ /** Heads still to resolve, and the file each was written in. */
308
+ const pending = [];
309
+ const add = (callee, typeText, file, node, depthText, depthNode, argumentsText) => {
310
+ const identity = argumentsText?.join('\u0000') ?? '';
311
+ const key = `${callee}\u0000${typeText}\u0000${depthText ?? ''}\u0000${identity}`;
312
+ const existing = byKey.get(key);
313
+ if (existing)
314
+ return existing;
315
+ const entry = {
316
+ callee,
317
+ typeText,
318
+ ...(depthText === undefined ? {} : { depthText }),
319
+ ...(argumentsText === undefined ? {} : { argumentsText }),
320
+ name: exportName(callee, typeText, taken, depthText, identity),
321
+ };
322
+ taken.add(entry.name);
323
+ byKey.set(key, entry);
324
+ entries.push(entry);
325
+ const names = new Set(referencedNames(node));
326
+ if (depthNode !== undefined) {
327
+ for (const name of referencedNames(depthNode))
328
+ names.add(name);
329
+ }
330
+ pending.push({ names, file, typeText });
331
+ return entry;
332
+ };
333
+ const depthOf = (site, file) => {
334
+ if (!site.callee.endsWith('Shallow'))
335
+ return {};
336
+ const node = site.node.typeArguments?.[1];
337
+ if (node === undefined)
338
+ return {};
339
+ const text = file.text.slice(node.getStart(), node.end).trim();
340
+ return text === '1' ? {} : { text, node };
341
+ };
342
+ const capturedArguments = (site, file) => {
343
+ if (site.callee !== 'grpcDescriptor' && site.callee !== 'loadGrpcService')
344
+ return undefined;
345
+ const args = site.node.arguments;
346
+ if (args.length !== 2 || !args.every(argument => isStringLiteral(argument))) {
347
+ refusals.push({
348
+ typeText: file.text.slice(site.typeArgument.getStart(), site.typeArgument.end),
349
+ reason: `\`${site.callee}<S>()\` needs exactly two string literals: service and package`,
350
+ });
351
+ return [];
352
+ }
353
+ return args.map(argument => file.text.slice(argument.getStart(), argument.end));
354
+ };
355
+ // The witness is written next to the source, so the source's own relative specifiers
356
+ // resolve unchanged from it. `facts` is therefore consulted per originating file: a
357
+ // carried entry's names were written in the witness and resolve against the witness.
358
+ const factsFor = new Map();
359
+ const facts = (file) => {
360
+ const cached = factsFor.get(file);
361
+ if (cached)
362
+ return cached;
363
+ const fresh = moduleFacts(file);
364
+ factsFor.set(file, fresh);
365
+ return fresh;
366
+ };
367
+ // Carried entries first, so an export name never moves because a new call site was added
368
+ // above an old one — the source references these names, and a rename would be a diff in
369
+ // hand-written code for no reason.
370
+ if (witnessFile) {
371
+ for (const site of findOwnedCallSites(witnessFile, checker, CALLEES, CALL_OWNERS)) {
372
+ const typeText = witnessFile.text.slice(site.typeArgument.getStart(), site.typeArgument.end);
373
+ const depth = depthOf(site, witnessFile);
374
+ const argumentsText = capturedArguments(site, witnessFile);
375
+ const name = exportName(site.callee, typeText, new Set(), depth.text, argumentsText?.join('\u0000'));
376
+ // Referenced by identifier, not by import: the source may have been edited by hand
377
+ // since, and what matters is whether the name is still used anywhere in it.
378
+ if (!referencesName(sourceText, name))
379
+ continue;
380
+ add(site.callee, typeText, witnessFile, site.typeArgument, depth.text, depth.node, argumentsText);
381
+ calleeSources.set(site.callee, calleeSpecifier(facts(witnessFile), site));
382
+ }
383
+ }
384
+ for (const site of findOwnedCallSites(sourceFile, checker, CALLEES, CALL_OWNERS)) {
385
+ const typeText = sourceText.slice(site.typeArgument.getStart(), site.typeArgument.end);
386
+ const depth = depthOf(site, sourceFile);
387
+ const argumentsText = capturedArguments(site, sourceFile);
388
+ sites.push({
389
+ site,
390
+ entry: add(site.callee, typeText, sourceFile, site.typeArgument, depth.text, depth.node, argumentsText),
391
+ });
392
+ // The source's answer overrides the witness's: the witness only ever says what a
393
+ // previous run wrote, and the user may since have changed where they import from.
394
+ calleeSources.set(site.callee, calleeSpecifier(facts(sourceFile), site));
395
+ }
396
+ const typeImports = new Map();
397
+ const extension = relativeExtension(facts(sourceFile), input.tsExtensions);
398
+ for (const { names, file, typeText } of pending) {
399
+ for (const name of names) {
400
+ if (typeImports.has(name))
401
+ continue;
402
+ const binding = facts(file).imports.get(name);
403
+ if (binding) {
404
+ typeImports.set(name, {
405
+ specifier: binding.specifier,
406
+ kind: binding.kind,
407
+ local: name,
408
+ original: binding.original,
409
+ });
410
+ continue;
411
+ }
412
+ // Declared where the call was written. Importable only if that module exports it —
413
+ // and the generated module is a different module, so "it is right there" is not
414
+ // enough.
415
+ const own = facts(file);
416
+ if (own.locals.has(name)) {
417
+ if (own.exported.has(name)) {
418
+ typeImports.set(name, {
419
+ specifier: siblingSpecifier(file.fileName, extension),
420
+ kind: 'named',
421
+ local: name,
422
+ original: name,
423
+ });
424
+ }
425
+ else {
426
+ refusals.push({
427
+ typeText,
428
+ reason: `\`${name}\` is declared in ${basename(file.fileName)} but not exported, so the generated ` +
429
+ 'module cannot name it. Export it, or move it to a module that does.',
430
+ });
431
+ }
432
+ continue;
433
+ }
434
+ // Not imported and not declared here: global (`Date`, `Omit`, `Record`), which needs
435
+ // no import at all. A name that is neither global nor importable is already a
436
+ // compile error in the source, so there is nothing for this pass to add.
437
+ }
438
+ }
439
+ return { entries, sites, refusals, typeImports: [...typeImports.values()], calleeSources };
440
+ }
441
+ /** Whether `text` uses `name` as an identifier, rather than as part of a longer one. */
442
+ export function referencesName(text, name) {
443
+ const pattern = new RegExp(`(?<![\\w$])${name}(?![\\w$])`);
444
+ return pattern.test(text);
445
+ }
446
+ export function basename(path) {
447
+ const cut = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
448
+ return cut === -1 ? path : path.slice(cut + 1);
449
+ }
450
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/codegen/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { SourceFile } from 'typescript/unstable/ast';
2
+ import type { Entry, SiteEntry, TypeImport } from './scan.js';
3
+ export interface ArtifactPaths {
4
+ readonly witness: string;
5
+ readonly js: string;
6
+ readonly dts: string;
7
+ /** What the rewritten source imports. Always the `.js`; TypeScript finds the `.d.ts`. */
8
+ readonly specifier: string;
9
+ }
10
+ /**
11
+ * Where the three files go for one source file.
12
+ *
13
+ * Beside the source, one set per source file, which is a deliberate departure from a single
14
+ * per-project module. Two things fall out of it and both are worth more than the tidiness:
15
+ * the witness's relative imports are the source's own relative imports unchanged (no path
16
+ * arithmetic, and none of the ways that gets it wrong), and two files that both write
17
+ * `is<Row>` cannot collide over the export name `zmdbIsRow`.
18
+ *
19
+ * The runtime extension follows the source's, so a `.mts` file gets a `.mjs` — the module
20
+ * kind of the generated file has to match the module kind of the file importing it.
21
+ */
22
+ export declare function artifactPaths(sourcePath: string): ArtifactPaths;
23
+ /** Whether a path is something a previous run wrote. The scan must not recurse into these. */
24
+ export declare function isGeneratedPath(path: string): boolean;
25
+ /**
26
+ * Which quote the source file uses for its own imports. Single unless it says otherwise —
27
+ * the majority style, and the one a file with no imports at all is most likely to want.
28
+ */
29
+ export declare function quoteStyle(sourceFile: SourceFile): string;
30
+ export interface WitnessInput {
31
+ /** Base name of the source this witness belongs to, for the header. */
32
+ readonly sourceName: string;
33
+ readonly entries: readonly Entry[];
34
+ readonly typeImports: readonly TypeImport[];
35
+ readonly calleeSources: ReadonlyMap<string, string>;
36
+ /** The quote character the source uses. See `quoteStyle`. */
37
+ readonly style: string;
38
+ }
39
+ export declare function witnessSource(input: WitnessInput): string;
40
+ export interface GeneratedModules {
41
+ readonly js: string;
42
+ readonly dts: string;
43
+ }
44
+ export interface GenerateInput extends WitnessInput {
45
+ /** `transformFile`'s output for the witness. */
46
+ readonly transformed: string;
47
+ }
48
+ /**
49
+ * The `.js` and the `.d.ts`, assembled from the transformed witness.
50
+ *
51
+ * Only the wrapper bodies come from the transform; every other line is regenerated here from
52
+ * the same `Entry` list the witness was built from. So the two files cannot disagree about a
53
+ * signature, and neither can drift from the witness.
54
+ */
55
+ export declare function generatedModules(input: GenerateInput): GeneratedModules;
56
+ export interface RewriteInput {
57
+ readonly sourceFile: SourceFile;
58
+ readonly code: string;
59
+ readonly sites: readonly SiteEntry[];
60
+ /** What to import the generated module as. See `artifactPaths`. */
61
+ readonly specifier: string;
62
+ readonly entries: readonly Entry[];
63
+ readonly calleeSources: ReadonlyMap<string, string>;
64
+ /** The quote character the source uses. See `quoteStyle`. */
65
+ readonly style: string;
66
+ }
67
+ /**
68
+ * `is<User>(data)` → `zmdbIsUser(data)`, plus the import that makes it resolve.
69
+ *
70
+ * The whole call is replaced rather than just its callee, because the type argument has to
71
+ * go with it and `is<User>` is one span in the middle of another. Arguments are read through
72
+ * the `Rewriter`, so `assert<A>(is<B>(x))` picks up the inner rewrite instead of carrying a
73
+ * stale copy of it.
74
+ */
75
+ export declare function rewriteSource(input: RewriteInput): string;
76
+ //# sourceMappingURL=witness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"witness.d.ts","sourceRoot":"","sources":["../../src/codegen/witness.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAA6B,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAYrF,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AA4B9D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAUD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAiB/D;AAOD,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAgND;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CASzD;AAMD,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CA0BzD;AAMD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,CAwDvE;AA0CD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAmCzD"}