Skip to content

fix(fs): import the hash and sync helpers from the utils subpath - #1484

Merged
allanbowe merged 1 commit into
mainfrom
fix/fs-helpers-from-subpath
Oct 16, 2026
Merged

allanbowe merged 1 commit into
mainfrom
fix/fs-helpers-from-subpath

Conversation

@sasjs-dev

@sasjs-dev sasjs-dev Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Companion to sasjs/utils#283, which stops re-exporting ./fs from the @sasjs/utils barrel.

src/commands/fs/fsCommand.ts imports all seven hash/sync helpers from the barrel, so without this change the next @sasjs/utils bump fails the build with TS2305 for each of them:

compareHashes, extractHashArray, findResourcesNotPresentLocally,
generateCompileProgram, generateProgramToGetRemoteHash,
generateProgramToSyncHashDiff, getHash

They now come from @sasjs/utils/fs. The other imports from the barrel are unchanged.

Why this can land on its own

The subpath has been there for a long time - the helpers are unchanged and already ship under fs/** in the pinned @sasjs/utils 3.7.2 - so this branch typechecks and tests against the current pin and does not wait for the utils release. Whichever lands first, neither repo is broken in between.

Why the helpers moved at all

./fs is the only module in @sasjs/utils that imports crypto, and the barrel re-exported it, so importing anything from the barrel put the crypto chain into a browser bundle: crypto-browserify, browserify-sign, parse-asn1, asn1.js, vm-browserify - roughly 555 KB of AES/RSA/ECDSA polyfills plus a vm shim's dynamic code execution. Measured in sasjs/utils#283: 1971 kB and 21 crypto-suite packages before, 822 kB and none after.

This is the only consumer in the estate

The server, lint, vscode-extension, Data Controller and the adapter either do not use these helpers or already import them from the subpath. vscode-extension's sync-directories command has imported them from @sasjs/utils/fs all along.

Verified

  • npx tsc -p . --noEmit exits 0 against the pinned @sasjs/utils 3.7.2.
  • npm run test:mocked: 86 of 87 suites pass, 670 of 671 tests. The one failure is src/commands/version/spec/version.spec.ts, which needs a globally installed @sasjs/cli (npm list -g @sasjs/cli prints (empty) here); it fails identically on an unmodified checkout of main, so it is not from this change.
  • src/commands/fs/spec/fsCommand.spec.ts: 7 tests pass.
  • npm run lint passes.

@sasjs/utils no longer re-exports './fs' from its barrel (sasjs/utils#283,
closing sasjs/utils#275). './fs' is the only module there that imports crypto,
and re-exporting it put the whole AES/RSA/ECDSA polyfill suite - plus a vm
shim's dynamic code execution - into every browser bundle that imported
anything from the barrel.

The fs commands import all seven helpers from the barrel, so they have to move
to '@sasjs/utils/fs'. Without this, the next @sasjs/utils bump fails the build
with TS2305 for each of them:

  compareHashes, extractHashArray, findResourcesNotPresentLocally,
  generateCompileProgram, generateProgramToGetRemoteHash,
  generateProgramToSyncHashDiff, getHash

The subpath has been there for a long time - the helpers are unchanged and
already ship under 'fs/**' in the pinned 3.7.2 - so this lands on its own,
without waiting for the utils release. The other imports from the barrel stay
where they are.

This is the only consumer in the estate: the server, lint, vscode-extension,
Data Controller and the adapter either do not use these helpers or already
import them from the subpath.

Verified

- npx tsc -p . --noEmit exits 0 against the pinned @sasjs/utils 3.7.2.
- npm run test:mocked: 86 of 87 suites pass, 670 of 671 tests. The one failure
  is src/commands/version/spec/version.spec.ts, which needs a globally
  installed @sasjs/cli ('npm list -g @sasjs/cli' prints "(empty)" on this box);
  it fails identically on an unmodified checkout of main, so it is not from
  this change.
- src/commands/fs/spec/fsCommand.spec.ts: 7 tests pass.
- npm run lint passes.
@github-actions

Copy link
Copy Markdown

Coverage report

Total coverage

Status Category Percentage Covered / Total
🟡 Statements 75.72% 3570/4715
🟡 Branches 63.43% 1464/2308
🟡 Functions 75.53% 716/948
🟢 Lines 84.28% 9089/10784

Status of coverage: 🟢 - ok, 🟡 - slightly more than threshold, 🔴 - under the threshold

Show files with reduced coverage 🔻

Reduced coverage

Status Filename Statements Branches Functions Lines
🟢 src/commands/compile/compileSingleFile.ts 95.83% (-2.08% 🔻) 84% (-4% 🔻) 100% 100%

Status of coverage: 🟢 - ok, 🟡 - slightly more than threshold, 🔴 - under the threshold

Report generated by 🧪jest coverage report action from 8784997

@sasjs-dev sasjs-dev Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the full diff (moves the seven fs hash/sync helper imports in src/commands/fs/fsCommand.ts from the @sasjs/utils barrel to the @sasjs/utils/fs subpath), the pinned @sasjs/utils 3.7.2 tarball (all seven names exist in its fs subpath and the barrel still re-exports them, so this compiles now and stays valid after the upstream barrel change), the import graph (fsCommand.ts is the only consumer of these names), hardening (pinning, .npmrc, lockfile, strict npm audit in CI, gitleaks pre-commit hook) and CI status (both legs green at this head).

No blocking issues.

@allanbowe
allanbowe merged commit 7a74173 into main Oct 16, 2026
2 checks passed
@allanbowe
allanbowe deleted the fix/fs-helpers-from-subpath branch October 16, 2026 10:16
sasjs-dev Bot added a commit that referenced this pull request Oct 16, 2026
| package | from | to |
|---|---|---|
| @sasjs/adapter | 4.19.4 | 5.1.0 |
| @sasjs/utils | 3.7.2 | 4.0.0 |
| @sasjs/lint | 4.1.3 | 4.1.4 |
| @sasjs/core | 5.3.2 | 5.4.0 |

adapter 5.1.0 is the first 5.x to reach the registry - the five before it were
removed by npm's publish scanner - and it changes the package shape: the root is
compiled modules rather than a UMD bundle, the browser build moves to dist/
behind the `browser` field, and `@sasjs/adapter/node` is a re-export of the same
tree rather than a second bundle. Verified in this repo before bumping: the CLI
builds and its mocked suite is unchanged against a packed 5.x.

utils has to move with it. adapter 5.1.0 pins utils 4.0.0 exactly, so leaving
the CLI on 3.7.2 nests a second copy of utils under the adapter - two copies of
the classes and enums that cross the CLI/adapter boundary. utils 4.0.0 is the
release whose barrel stops re-exporting ./fs, which is what #1484 prepared the
fs command for; with both in place the tree carries one copy of utils.

lint 4.1.4 and core 5.4.0 are the current releases of the other two packages
this repo pins.

Verified: npm install, `npm run build` (tsc) exit 0, the mocked suite is
identical to the 4.19.4 baseline (87 suites / 671 tests, 650 passed, and the
same two environment failures - doxygen is not installed here), `npm audit
--omit=dev --audit-level=low` exit 0, `node release/audit.mjs` exit 0, prettier
clean. The lockfile drops 177 lines, which is the nested utils and the packages
utils 4.0.0 no longer carries.
allanbowe pushed a commit that referenced this pull request Oct 16, 2026
…ishes with (#1483)

* fix(ci): publish through OIDC trusted publishing, not npm 10

The v5.0.0 release failed at the publish step: `npm publish --provenance
--access public` answered E404, "'@sasjs/cli@5.0.0' is not in this
registry". Node 22 ships npm 10.x, and OIDC trusted publishing - the
only credential the workflow has; setup-node writes a placeholder
NODE_AUTH_TOKEN - needs npm >= 11.5.1. sasjs/adapter runs
`npm install -g npm@latest` before semantic-release for exactly this
reason, and its publish steps succeed.

Mirror that step here. This is the release blocker: until it lands, no
CLI release can publish, and every downstream pin of @sasjs/utils stays
stranded at the nested 3.6.5 copy.

Verification: the failing run (38581630499) and the last success
(37217927917) show the same placeholder token; the difference is the npm
version the publish runs under. adapter's npmpublish.yml carries the
step, cli's did not.

* fix(ci): pin the npm CLI the release publishes with

`npm install -g npm@latest` put a mutable toolchain in the publish path: a new
npm major would land in the release job with no commit here to review it, which
is the exposure the locked release/ tree exists to avoid. The step's premise is
unchanged - node 22 ships npm 10.x and OIDC trusted publishing needs
>= 11.5.1 - so the fix is to name the version.

Pinned to 12.2.0 rather than a minimum, because it is what `latest` resolved to
when this was written, so the release path is byte-for-byte what it already did;
it is also the version sasjs/lint published 4.1.4 with at 09:29 today through
this same step, which is the evidence that it works on the node 22 matrix.
Verified locally: the pinned version installs and reports 12.2.0 (>= 11.5.1),
and its `npm publish` carries the --provenance/--access surface the trusted
publisher uses.

npm 12 requires node ^22.22.2 || ^24.15.0 || >=26.0.0; setup-node's `22`
currently resolves to 22.23.3, which satisfies it. That floor is named in the
workflow comment so a bump re-checks it.

* fix(deps): bump the @sasjs packages to their released versions

| package | from | to |
|---|---|---|
| @sasjs/adapter | 4.19.4 | 5.1.0 |
| @sasjs/utils | 3.7.2 | 4.0.0 |
| @sasjs/lint | 4.1.3 | 4.1.4 |
| @sasjs/core | 5.3.2 | 5.4.0 |

adapter 5.1.0 is the first 5.x to reach the registry - the five before it were
removed by npm's publish scanner - and it changes the package shape: the root is
compiled modules rather than a UMD bundle, the browser build moves to dist/
behind the `browser` field, and `@sasjs/adapter/node` is a re-export of the same
tree rather than a second bundle. Verified in this repo before bumping: the CLI
builds and its mocked suite is unchanged against a packed 5.x.

utils has to move with it. adapter 5.1.0 pins utils 4.0.0 exactly, so leaving
the CLI on 3.7.2 nests a second copy of utils under the adapter - two copies of
the classes and enums that cross the CLI/adapter boundary. utils 4.0.0 is the
release whose barrel stops re-exporting ./fs, which is what #1484 prepared the
fs command for; with both in place the tree carries one copy of utils.

lint 4.1.4 and core 5.4.0 are the current releases of the other two packages
this repo pins.

Verified: npm install, `npm run build` (tsc) exit 0, the mocked suite is
identical to the 4.19.4 baseline (87 suites / 671 tests, 650 passed, and the
same two environment failures - doxygen is not installed here), `npm audit
--omit=dev --audit-level=low` exit 0, `node release/audit.mjs` exit 0, prettier
clean. The lockfile drops 177 lines, which is the nested utils and the packages
utils 4.0.0 no longer carries.

* ci(release): run the PR workflows under the npm the release publishes with

The release job pins npm 12.2.0 while the PR workflows ran node 22's bundled npm
10.x, so the artifact a pull request validates was packed and installed with a
different npm than the one that publishes it. That divergence is exactly what
turned the sasjs/adapter pack-report change into a release failure instead of a
pull request failure, and pinning the release job here widened it rather than
closing it.

Both PR workflows now install the same pinned npm, at the same point in the job
as npmpublish.yml does, so `Test Package Install` packs with the npm the release
publishes with.

Verified locally under both versions:

- `npm pack` after a build produces the identical 598-file list under npm 11.17.0
  and npm 12.2.0, so the step changes nothing about the artifact today - it is
  latent coverage, not a behaviour change.
- `npm ci` under npm 12.2.0 exits 0 (677 packages) against the committed
  lockfile, so the pin does not disturb the install.
- `npm audit --omit=dev --audit-level=low` and `node release/audit.mjs` both
  exit 0 under npm 12.2.0.

All three workflows now carry the same `npm install -g npm@12.2.0`; bump them
together.

* fix(deps): bump @sasjs/core to 5.5.0

5.5.0 landed after the bump in the previous commit, so the pin in this PR was
already a version behind. Nothing else moves: the other @sasjs packages are
still at their current releases.

Verified: npm install exit 0, `npm run build` (tsc) exit 0, mocked suite
identical to the baseline (87 suites / 671 tests, 650 passed, same two
`doxygen: not found` environment failures).

* fix(deps): bump @sasjs/core to 5.5.2

5.5.1 and 5.5.2 both landed after the previous commit pinned 5.5.0, so the pin
was two patch releases behind within the hour. Nothing else moves - adapter,
utils and lint are still at their current releases.

The delta from 5.5.0 is three commits: a `sasjs lint` declaration fix (#463),
the canonical `_sasjs_webout_headers` variable in the server macros (#464), and
an `mp_getcols` refactor onto `mf_dttmfmts` (#462). No breaking changes.

Verified: npm install exit 0, `npm run build` (tsc) exit 0, mocked suite
identical to the baseline (87 suites / 671 tests, 650 passed, same two
`doxygen: not found` environment failures).

---------

Co-authored-by: sasjs-dev[bot] <sasjs-dev[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant