OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-repo / scripts / bare-deps.mjs

54 lines · javascript ref:
// Bare dep compat: add a "bare" export condition to @noble/hashes' ./crypto so it resolves
// to the bare-safe crypto.js (globalThis.crypto ?? undefined) instead of cryptoNode.js
// (`import 'node:crypto'`, which Bare can't load). @noble/curves + @scure/* import
// @noble/hashes, so this one condition unblocks the whole crypto tree. We sign
// deterministically (RFC6979), so the shim degrading to undefined is never called.
//
// node_modules is reinstall-wiped, so this runs on `postinstall` (see the package.json of
// each package that depends on @noble). Idempotent. Run manually with explicit roots
// (`node scripts/bare-deps.mjs identity repo pds`) to patch the whole dev tree at once;
// with no args it patches the CURRENT package (process.cwd()) — the postinstall case.

import { readdirSync, readFileSync, writeFileSync, statSync } from 'node:fs'
import { join } from 'node:path'

function patch (pjPath) {
  let j
  try { j = JSON.parse(readFileSync(pjPath, 'utf8')) } catch { return false }
  const exp = j.exports && j.exports['./crypto']
  if (exp && typeof exp === 'object' && !exp.bare) {
    j.exports['./crypto'] = { bare: './esm/crypto.js', ...exp } // "bare" first → matched before "node"
    writeFileSync(pjPath, JSON.stringify(j, null, 2) + '\n')
    return true
  }
  return false
}

const isDir = (p) => { try { return statSync(p).isDirectory() } catch { return false } }

// Walk a node_modules dir: patch any @noble/hashes found, recurse into nested node_modules.
function walk (nm, found) {
  let entries
  try { entries = readdirSync(nm, { withFileTypes: true }) } catch { return }
  for (const e of entries) {
    if (!e.isDirectory()) continue
    const dir = join(nm, e.name)
    if (e.name === '@noble') {
      const pj = join(dir, 'hashes', 'package.json')
      if (patch(pj)) found.push(pj)
      // scoped pkgs may carry their own nested node_modules
      for (const p of readdirSync(dir)) { const nn = join(dir, p, 'node_modules'); if (isDir(nn)) walk(nn, found) }
    } else if (e.name.startsWith('@')) {
      for (const p of readdirSync(dir)) { const nn = join(dir, p, 'node_modules'); if (isDir(nn)) walk(nn, found) }
    } else {
      const nn = join(dir, 'node_modules'); if (isDir(nn)) walk(nn, found)
    }
  }
}

const roots = process.argv.slice(2)
if (roots.length === 0) roots.push(process.cwd())
const found = []
for (const r of roots) { const nm = join(r, 'node_modules'); if (isDir(nm)) walk(nm, found) }
console.log(found.length ? `bare-deps: patched ${found.length} @noble/hashes` : 'bare-deps: nothing to patch')