Skip to content

sails-js: published .d.ts files reference private sails-js-types module #1344

@ukint-vs

Description

@ukint-vs

Summary

The published sails-js npm tarball ships .d.ts files containing unresolved external module references to sails-js-types, which is a private: true workspace package not published to npm and not declared as a peerDependency. Consumers cannot resolve these imports directly; they rely on either skipLibCheck: true or the ./types subpath (which IS bundled correctly via the dts rollup step).

Status

File Origin Fixed?
lib/index.d.ts:12 (export type * from 'sails-js-types') added in #1343 ✅ Fixed in #1343 by re-exporting from the bundled ./types.js instead of the workspace package name (commit on feat/js-public-user-type-accessors-1320).
lib/sails-idl-v2.d.ts:128 (get program(): import(\"sails-js-types\").IProgramUnit) pre-existing ❌ Still leaks. Emitted by rollup-plugin-typescript2 from the source import type { IProgramUnit } from './types.js' chain when TS preserves the original module specifier.
lib/util.d.ts:1 (import { ISailsTypeDef } from 'sails-js-types') pre-existing ❌ Still leaks. Built via the dts rollup step from node_modules/sails-js-util/lib/index.d.ts, which itself imports from sails-js-types. The dts plugin didn't inline the cross-package reference.
lib/parser.d.ts:1 (import { IIdlDoc, IInterfaceId, InterfaceIdInput } from 'sails-js-types') pre-existing ❌ Still leaks. Same dts-plugin pass as util.d.ts.

Why this matters

  • Consumers running with skipLibCheck: false (less common, but valid) get type-resolution errors when they import from sails-js, sails-js/util, or sails-js/parser.
  • The ./types subpath works correctly because lib/types.d.ts is built via the dts plugin from node_modules/sails-js-types/lib/index.d.ts and the externals get inlined there. The other paths above don't get the same treatment.
  • sails-js-types being private: true is the right call (it's an internal workspace package), so the fix is on the build side, not the publishing side.

Reproduction

cd js && pnpm install && pnpm build:types && pnpm build:util && pnpm build:parser-idl-v2 && pnpm build:sails
grep -rn "sails-js-types" lib/ | grep -v /cjs/

After the #1343 fix, expect 3 matches: lib/sails-idl-v2.d.ts, lib/util.d.ts, lib/parser.d.ts. None of them should land in the tarball.

Suggested fix

Two parallel changes to the rollup pipeline:

  1. Add a post-typescript dts pass for lib/index.d.ts and lib/sails-idl-v2.d.ts (and any other entry that goes through rollup-plugin-typescript2). The pass takes the typescript-emitted .d.ts as input and runs it through dts() so external 'sails-js-types' imports get inlined the way they already are for lib/types.d.ts.

  2. Fix the existing dts pass for util.d.ts and parser.d.ts so the sails-js-types references they pull in transitively get inlined too. Likely a missing respectExternal: false (or equivalent) option on the dts plugin invocation in js/rollup.config.js. Currently the dts step pulls from node_modules/sails-js-util/lib/index.d.ts, which still imports from sails-js-types — that import isn't getting walked.

Pseudocode for #1:

// rollup.config.js — add after the existing typescript-pass entries
{
  input: 'lib/index.d.ts',
  output: [{ file: 'lib/index.d.ts', format: 'es' }],
  plugins: [nodeResolve({ extensions: ['.d.ts', '.ts'] }), dts()],
}
// And similar for lib/sails-idl-v2.d.ts (or any specific entry whose
// public surface re-exports through sails-js-types).

Alternative for both: drop private: true from sails-js-types and add it as a real published dep / peerDep of sails-js. Larger surface change, exposes a package's release lifecycle that's currently internal — probably not preferred.

Out of scope

  • Publishing sails-js-types as a standalone npm package.
  • Restructuring AST type ownership.

Discovered during

Pre-landing review of #1343 (issue #1320). The PR added a fourth instance of the pattern (export type * from 'sails-js-types' in the index) which was caught by codex review and fixed in-place via Codex's suggestion to re-export from ./types.js. The three remaining leaks predate that PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions