ts-node-pack 0.1.1 → 0.1.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +55 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-node-pack",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Pack a TypeScript package into a Node-compatible npm tarball without modifying the source tree",
5
5
  "keywords": [
6
6
  "cli",
package/src/index.js CHANGED
@@ -83,21 +83,20 @@ export async function tsNodePack(
83
83
  log(`Copied ${packFiles.length} file(s) into staging`);
84
84
 
85
85
  // ── Phase 4: Decide whether to run tsc, generate config if so ────────
86
- // Three conditions trigger declaration emit:
87
- // 1. user passed --tsconfig (explicit opt-in)
88
- // 2. tsconfig.build.json exists (agoric convention for opt-in)
89
- // 3. any source contains .ts/.tsx/.mts (we'd be stripping them
90
- // anyway, and probably want their declarations)
91
- // For pure JS+JSDoc packages with only `tsconfig.json` and no .ts
92
- // sources, this skips tsc entirely matching what `npm pack` would
93
- // have done before ts-node-pack: ship .js files, no .d.ts.
86
+ // Trigger declaration emit only when there's something to derive:
87
+ // 1. user passed --tsconfig (explicit opt-in), OR
88
+ // 2. any source contains .ts/.tsx/.mts (we'd be stripping them
89
+ // anyway, and probably want their declarations).
90
+ // The mere presence of tsconfig.build.json is NOT enough — monorepos
91
+ // commonly keep one per package for a root project-references build
92
+ // (`tsc --build`) without intending each package to be independently
93
+ // emit-able. Pure JS+JSDoc packages with no .ts sources skip tsc and
94
+ // ship whatever .js files are already in the packlist, matching plain
95
+ // `npm pack` semantics.
94
96
  const hasTsSources = packFiles.some(
95
97
  (f) => /\.(ts|tsx|mts)$/.test(f) && !/\.d\.(ts|mts)$/.test(f),
96
98
  );
97
- const isExplicitOptIn =
98
- tsconfigPath !== null &&
99
- (tsconfig !== undefined || basename(tsconfigPath) === "tsconfig.build.json");
100
- const shouldRunTsc = tsconfigPath !== null && (isExplicitOptIn || hasTsSources);
99
+ const shouldRunTsc = tsconfigPath !== null && (tsconfig !== undefined || hasTsSources);
101
100
 
102
101
  if (shouldRunTsc) {
103
102
  log("Phase 4: Generating derived tsconfig...");
@@ -107,8 +106,21 @@ export async function tsNodePack(
107
106
  // location. Pin typeRoots when that directory exists. (TS 6.0
108
107
  // surfaces the missing resolution as TS2688 instead of the silent
109
108
  // "Cannot find module 'node:util'" cascade of earlier versions.)
110
- const atTypesDir = join(packageDir, "node_modules", "@types");
111
- const hasAtTypes = existsSync(atTypesDir);
109
+ // Walk upward to find the nearest ancestor that actually has
110
+ // node_modules/@types. Yarn 4's pnpm linker keeps `@types` only at
111
+ // the workspace root, so the package's own node_modules is empty.
112
+ const findAtTypes = (start ) => {
113
+ let dir = start;
114
+ while (true) {
115
+ const candidate = join(dir, "node_modules", "@types");
116
+ if (existsSync(candidate)) return candidate;
117
+ const parent = dirname(dir);
118
+ if (parent === dir) return null;
119
+ dir = parent;
120
+ }
121
+ };
122
+ const atTypesDir = findAtTypes(packageDir);
123
+ const hasAtTypes = atTypesDir !== null;
112
124
  const emitConfig = {
113
125
  extends: tsconfigPath,
114
126
  compilerOptions: {
@@ -236,14 +248,33 @@ function findLocalBin(startDir, name) {
236
248
  }
237
249
  }
238
250
 
239
- async function runTsc(emitConfigPath, cwd, log) {
251
+ async function findLocalTsc(cwd) {
240
252
  // Prefer a local tsc so users control the compiler version (and to avoid
241
253
  // npx resolving to macOS's /usr/bin/tsc — the TeX/Smalltalk compiler —
242
254
  // when no local install exists). In a monorepo, the package's own
243
255
  // node_modules/.bin may be empty while the workspace root has the
244
256
  // binary, so walk upward the same way npm's `$PATH` composition does.
245
257
  const binName = process.platform === "win32" ? "tsc.cmd" : "tsc";
246
- const localTsc = findLocalBin(cwd, binName);
258
+ const fromBin = findLocalBin(cwd, binName);
259
+ if (fromBin !== null) return fromBin;
260
+ // Yarn 4's pnpm/PnP linkers do not populate node_modules/.bin/. Fall back
261
+ // to `yarn bin tsc`, which resolves through the active linker and prints
262
+ // the absolute path of the tsc binary when the workspace depends on it.
263
+ try {
264
+ const { stdout } = await execFileAsync("yarn", ["bin", "tsc"], {
265
+ cwd,
266
+ maxBuffer: 1024 * 1024,
267
+ });
268
+ const candidate = stdout.trim().split("\n").pop();
269
+ if (candidate && existsSync(candidate)) return candidate;
270
+ } catch {
271
+ // `yarn` not on PATH or not a yarn project — fall through to npx.
272
+ }
273
+ return null;
274
+ }
275
+
276
+ async function runTsc(emitConfigPath, cwd, log) {
277
+ const localTsc = await findLocalTsc(cwd);
247
278
  const useLocal = localTsc !== null;
248
279
  const [cmd, argv] = useLocal
249
280
  ? [localTsc, ["-p", emitConfigPath]]
@@ -503,15 +534,21 @@ export function rewritePackageJson(pkg) {
503
534
  delete result.scripts;
504
535
 
505
536
  // Rewrite entry points
537
+ const originalMain = result.main;
506
538
  if (result.main) result.main = rewriteTsToJs(result.main);
507
539
  if (result.module) result.module = rewriteTsToJs(result.module);
540
+ const mainWasTs = result.main !== originalMain;
508
541
 
509
- // Rewrite or derive types
542
+ // Only synthesize a `types` field from `main` when `main` was a .ts
543
+ // source (a .d.ts will be emitted alongside the .js). For pure JS+JSDoc
544
+ // packages, inventing `"./index.d.ts"` would point at a file that
545
+ // ts-node-pack never creates — see @endo/ses-ava in agoric/endo, where
546
+ // this produced a dangling types pointer in published tarballs.
510
547
  if (result.types) {
511
548
  result.types = rewriteTsToDts(result.types);
512
549
  } else if (result.typings) {
513
550
  result.typings = rewriteTsToDts(result.typings);
514
- } else if (result.main) {
551
+ } else if (mainWasTs) {
515
552
  result.types = result.main.replace(/\.js$/, ".d.ts");
516
553
  }
517
554