@dunx/transform 3.8.2 → 3.8.3

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.
@@ -84,6 +84,35 @@ var collectTypeOnlyNames = (program) => {
84
84
  names.delete(name);
85
85
  return names;
86
86
  };
87
+ var boundNames = (program) => {
88
+ const names = new Set;
89
+ const bind = (node) => {
90
+ const name = nameOf(node);
91
+ if (name !== undefined)
92
+ names.add(name);
93
+ };
94
+ for (const statement of program.body ?? []) {
95
+ if (isImportDeclaration(statement)) {
96
+ for (const specifier of statement.specifiers) {
97
+ bind(specifier.local);
98
+ }
99
+ continue;
100
+ }
101
+ const declaration = statement.declaration ?? statement;
102
+ if (declaration.declare === true)
103
+ continue;
104
+ if (declaration.type === "VariableDeclaration") {
105
+ for (const declarator of declaration.declarations ?? []) {
106
+ bind(declarator.id);
107
+ }
108
+ continue;
109
+ }
110
+ if (isClassDeclaration(declaration) || declaration.type === "FunctionDeclaration" || declaration.type === "TSEnumDeclaration" || declaration.type === "TSModuleDeclaration") {
111
+ bind(declaration.id);
112
+ }
113
+ }
114
+ return names;
115
+ };
87
116
  var collectTypeParameters = (klass) => {
88
117
  const names = new Set;
89
118
  if (klass.typeParameters === null)
@@ -120,7 +149,7 @@ var annotationOf = (param) => {
120
149
  return inner.typeAnnotation?.typeAnnotation;
121
150
  };
122
151
  var hasDefault = (param) => isAssignmentPattern(isParameterProperty(param) ? param.parameter : param);
123
- var entryFor = (source, param, erased) => {
152
+ var entryFor = (source, param, erased, bound) => {
124
153
  const text = JSON.stringify(slice(source, param));
125
154
  const optional = hasDefault(param) ? ", optional: true" : "";
126
155
  const unresolved = `{ unresolved: ${text}${optional} }`;
@@ -129,8 +158,13 @@ var entryFor = (source, param, erased) => {
129
158
  return unresolved;
130
159
  const root = nameOf(rootOfTypeName(annotation.typeName));
131
160
  const cause = root === undefined ? undefined : erased.get(root);
132
- if (cause === undefined)
133
- return slice(source, annotation.typeName);
161
+ if (cause === undefined) {
162
+ const named = slice(source, annotation.typeName);
163
+ if (root === undefined || bound.has(root))
164
+ return named;
165
+ const missing = named === root ? `typeof ${root} === 'undefined'` : `typeof ${root} === 'undefined' || ${named} === undefined`;
166
+ return `${missing} ? ${unresolved} : ${named}`;
167
+ }
134
168
  return cause === "import-type" ? `{ unresolved: ${text}${optional}, typeOnly: ${JSON.stringify(root)} }` : unresolved;
135
169
  };
136
170
  var transform2 = (source, filename = "input.ts") => {
@@ -141,6 +175,7 @@ var transform2 = (source, filename = "input.ts") => {
141
175
  }
142
176
  const program = parsed.program;
143
177
  const typeOnly = collectTypeOnlyNames(program);
178
+ const bound = boundNames(program);
144
179
  const edits = [];
145
180
  const annotated = [];
146
181
  walk(program, (node) => {
@@ -152,7 +187,7 @@ var transform2 = (source, filename = "input.ts") => {
152
187
  const erased = erasedNames(typeOnly, node);
153
188
  const params = constructorParams(node);
154
189
  if (params.length > 0) {
155
- const entries = params.map((param) => entryFor(source, param, erased));
190
+ const entries = params.map((param) => entryFor(source, param, erased, bound));
156
191
  annotated.push(name);
157
192
  edits.push({
158
193
  start: node.end,
package/dist/erased.d.ts CHANGED
@@ -13,5 +13,16 @@ export type ErasureCause = 'import-type' | 'declared-type';
13
13
  * inline `type` specifiers, local interfaces and type aliases.
14
14
  */
15
15
  export declare const collectTypeOnlyNames: (program: Node) => ReadonlyMap<string, ErasureCause>;
16
+ /**
17
+ * Every name this file binds **at runtime**: imported, or declared at the top
18
+ * level. Anything else a constructor annotation names is ambient.
19
+ *
20
+ * Two ways a name looks bound and is not, each of which would suppress
21
+ * `entryFor`'s guard and bring the `ReferenceError` back: a `declare`, which
22
+ * promises a runtime value this file does not create, and a binding nested in a
23
+ * function, which is not in scope at a constructor signature. Top-level
24
+ * statements only, for the second - a `walk` would collect it.
25
+ */
26
+ export declare const boundNames: (program: Node) => ReadonlySet<string>;
16
27
  /** Every name in this file that a value position cannot use. */
17
28
  export declare const erasedNames: (typeOnly: ReadonlyMap<string, ErasureCause>, klass: ClassNode) => ReadonlyMap<string, ErasureCause>;
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  applyEdits2,
4
4
  transform2,
5
5
  depsPlugin2
6
- } from "./chunk-x4mcmdwj.js";
6
+ } from "./chunk-9qq1p8f7.js";
7
7
  export {
8
8
  applyEdits2 as applyEdits,
9
9
  depsPlugin2 as depsPlugin,
package/dist/preload.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  depsPlugin2
4
- } from "./chunk-x4mcmdwj.js";
4
+ } from "./chunk-9qq1p8f7.js";
5
5
 
6
6
  // src/preload.ts
7
7
  var {plugin } = globalThis.Bun;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunx/transform",
3
- "version": "3.8.2",
3
+ "version": "3.8.3",
4
4
  "description": "Load-time transform that records constructor dependencies for the dunx container",
5
5
  "keywords": [
6
6
  "bun",