|
| 1 | +import { spawnSync } from 'child_process' |
| 2 | +import { deepStrictEqual } from 'assert' |
| 3 | +import { dirname, resolve } from 'path' |
| 4 | +import { fileURLToPath } from 'url' |
| 5 | + |
| 6 | +const cwd = dirname(fileURLToPath(import.meta.url)) |
| 7 | +const hook = resolve(cwd, '..', '..', 'hook.mjs') |
| 8 | + |
| 9 | +const mostPopular240NpmModules = [ |
| 10 | + 'ansi-styles', |
| 11 | + 'semver', |
| 12 | + 'supports-color', |
| 13 | + 'chalk', 'has-flag', |
| 14 | + 'debug', |
| 15 | + 'tslib', |
| 16 | + 'color-convert', |
| 17 | + 'ms', |
| 18 | + 'color-name', |
| 19 | + 'lru-cache', |
| 20 | + 'minimatch', |
| 21 | + 'strip-ansi', |
| 22 | + 'source-map', |
| 23 | + 'ansi-regex', |
| 24 | + 'glob', |
| 25 | + 'readable-stream', |
| 26 | + 'commander', |
| 27 | + 'yallist', |
| 28 | + 'string-width', |
| 29 | + 'escape-string-regexp', |
| 30 | + 'brace-expansion', |
| 31 | + 'find-up', |
| 32 | + 'p-locate', |
| 33 | + 'locate-path', |
| 34 | + 'wrap-ansi', |
| 35 | + 'p-limit', |
| 36 | + 'safe-buffer', |
| 37 | + 'kind-of', |
| 38 | + 'minipass', |
| 39 | + 'uuid', |
| 40 | + 'string_decoder', |
| 41 | + 'ajv', |
| 42 | + 'emoji-regex', |
| 43 | + 'isarray', |
| 44 | + 'react-is', |
| 45 | + 'fs-extra', |
| 46 | + 'is-fullwidth-code-point', |
| 47 | + 'get-stream', |
| 48 | + 'json-schema-traverse', |
| 49 | + 'yargs-parser', |
| 50 | + 'glob-parent', |
| 51 | + 'yargs', |
| 52 | + 'rimraf', |
| 53 | + 'acorn', |
| 54 | + 'which', |
| 55 | + 'estraverse', |
| 56 | + 'js-yaml', |
| 57 | + 'path-exists', |
| 58 | + 'argparse', |
| 59 | + 'pretty-format', |
| 60 | + 'resolve-from', |
| 61 | + 'cliui', |
| 62 | + 'schema-utils', |
| 63 | + 'globals', |
| 64 | + 'camelcase', |
| 65 | + 'execa', |
| 66 | + 'punycode', |
| 67 | + 'path-key', |
| 68 | + 'signal-exit', |
| 69 | + 'inherits', |
| 70 | + 'resolve', |
| 71 | + 'mkdirp', |
| 72 | + 'is-stream', |
| 73 | + 'ws', |
| 74 | + 'universalify', |
| 75 | + 'qs', |
| 76 | + 'slash', |
| 77 | + 'json5', |
| 78 | + 'iconv-lite', |
| 79 | + 'form-data', |
| 80 | + 'is-number', |
| 81 | + 'eslint-visitor-keys', |
| 82 | + '@jest/types', |
| 83 | + 'postcss', |
| 84 | + 'make-dir', |
| 85 | + 'pify', |
| 86 | + 'cross-spawn', |
| 87 | + 'braces', |
| 88 | + 'whatwg-url', |
| 89 | + 'fill-range', |
| 90 | + 'eslint-scope', |
| 91 | + 'tr46', |
| 92 | + 'micromatch', |
| 93 | + 'convert-source-map', |
| 94 | + 'define-property', |
| 95 | + 'agent-base', |
| 96 | + 'shebang-regex', |
| 97 | + 'shebang-command', |
| 98 | + 'mimic-fn', |
| 99 | + 'globby', |
| 100 | + 'npm-run-path', |
| 101 | + 'mime', |
| 102 | + '@babel/code-frame', |
| 103 | + 'extend-shallow', |
| 104 | + 'to-regex-range', |
| 105 | + 'onetime', |
| 106 | + 'https-proxy-agent', |
| 107 | + 'y18n', |
| 108 | + 'buffer', |
| 109 | + 'strip-bom', |
| 110 | + 'is-glob', |
| 111 | + 'doctrine', |
| 112 | + 'picocolors', |
| 113 | + 'pkg-dir', |
| 114 | + '@babel/types', |
| 115 | + 'regenerator-runtime', |
| 116 | + 'human-signals', |
| 117 | + '@jridgewell/trace-mapping', |
| 118 | + 'ignore', |
| 119 | + 'jsesc', |
| 120 | + 'parse-json', |
| 121 | + 'jest-worker', |
| 122 | + 'graceful-fs', |
| 123 | + 'jest-util', |
| 124 | + 'jsonfile', |
| 125 | + 'normalize-path', |
| 126 | + 'strip-json-comments', |
| 127 | + 'cosmiconfig', |
| 128 | + 'minimist', |
| 129 | + 'path-type', |
| 130 | + '@babel/parser', |
| 131 | + 'balanced-match', |
| 132 | + 'picomatch', |
| 133 | + 'typescript', |
| 134 | + 'isexe', |
| 135 | + 'statuses', |
| 136 | + 'entities', |
| 137 | + 'bytes', |
| 138 | + 'node-fetch', |
| 139 | + 'http-errors', |
| 140 | + '@babel/highlight', |
| 141 | + '@babel/helper-validator-identifier', |
| 142 | + 'function-bind', |
| 143 | + 'async', |
| 144 | + 'sprintf-js', |
| 145 | + '@babel/generator', |
| 146 | + 'is-extendable', |
| 147 | + 'get-intrinsic', |
| 148 | + 'lodash', |
| 149 | + 'mime-db', |
| 150 | + 'source-map-support', |
| 151 | + 'mime-types', |
| 152 | + 'is-arrayish', |
| 153 | + '@babel/core', |
| 154 | + 'once', |
| 155 | + 'anymatch', |
| 156 | + 'depd', |
| 157 | + 'hosted-git-info', |
| 158 | + 'path-to-regexp', |
| 159 | + 'axios', |
| 160 | + 'is-core-module', |
| 161 | + '@babel/template', |
| 162 | + 'cookie', |
| 163 | + 'write-file-atomic', |
| 164 | + 'js-tokens', |
| 165 | + '@typescript-eslint/typescript-estree', |
| 166 | + '@typescript-eslint/types', |
| 167 | + 'object-inspect', |
| 168 | + 'wrappy', |
| 169 | + 'is-extglob', |
| 170 | + 'chokidar', |
| 171 | + '@typescript-eslint/visitor-keys', |
| 172 | + 'call-bind', |
| 173 | + 'loader-utils', |
| 174 | + 'browserslist', |
| 175 | + 'http-proxy-agent', |
| 176 | + 'fast-glob', |
| 177 | + 'concat-map', |
| 178 | + 'inflight', |
| 179 | + 'ajv-keywords', |
| 180 | + 'ansi-escapes', |
| 181 | + 'ci-info', |
| 182 | + 'fast-deep-equal', |
| 183 | + 'caniuse-lite', |
| 184 | + 'fs.realpath', |
| 185 | + '@jridgewell/gen-mapping', |
| 186 | + 'setprototypeof', |
| 187 | + 'strip-final-newline', |
| 188 | + 'optionator', |
| 189 | + 'path-is-absolute', |
| 190 | + '@babel/traverse', |
| 191 | + 'core-util-is', |
| 192 | + 'has-symbols', |
| 193 | + 'yocto-queue', |
| 194 | + 'p-try', |
| 195 | + 'electron-to-chromium', |
| 196 | + '@smithy/smithy-client', |
| 197 | + 'yaml', |
| 198 | + 'ini', |
| 199 | + '@babel/helper-plugin-utils', |
| 200 | + 'jest-get-type', |
| 201 | + 'type-check', |
| 202 | + 'levn', |
| 203 | + 'is-descriptor', |
| 204 | + 'prelude-ls', |
| 205 | + 'slice-ansi', |
| 206 | + '@typescript-eslint/scope-manager', |
| 207 | + 'isobject', |
| 208 | + 'esprima', |
| 209 | + '@babel/helper-split-export-declaration', |
| 210 | + 'callsites', |
| 211 | + 'readdirp', |
| 212 | + 'escalade', |
| 213 | + 'import-fresh', |
| 214 | + 'get-caller-file', |
| 215 | + '@jridgewell/sourcemap-codec', |
| 216 | + 'acorn-walk', |
| 217 | + 'rxjs', |
| 218 | + 'ieee754', |
| 219 | + 'is-plain-obj', |
| 220 | + 'istanbul-lib-instrument', |
| 221 | + '@babel/helper-module-imports', |
| 222 | + 'side-channel', |
| 223 | + 'normalize-package-data', |
| 224 | + 'is-plain-object', |
| 225 | + '@jridgewell/resolve-uri', |
| 226 | + 'follow-redirects', |
| 227 | + 'array-union', |
| 228 | + 'json-parse-even-better-errors', |
| 229 | + 'path-parse', |
| 230 | + 'has-property-descriptors', |
| 231 | + 'uri-js', |
| 232 | + 'safer-buffer', |
| 233 | + '@babel/helpers', |
| 234 | + 'on-finished', |
| 235 | + '@babel/helper-function-name', |
| 236 | + 'p-map', |
| 237 | + 'postcss-value-parser', |
| 238 | + 'indent-string', |
| 239 | + '@babel/helper-module-transforms', |
| 240 | + 'object-assign', |
| 241 | + 'delayed-stream', |
| 242 | + '@nodelib/fs.stat', |
| 243 | + 'require-directory', |
| 244 | + 'diff', |
| 245 | + 'parse5', |
| 246 | + 'asynckit', |
| 247 | + 'tmp', |
| 248 | + 'combined-stream' |
| 249 | +] |
| 250 | + |
| 251 | +const otherCommonModulesUsedWithInstrumentation = [ |
| 252 | + 'express', |
| 253 | + 'fastify', |
| 254 | + '@hapi/hapi', |
| 255 | + 'connect', |
| 256 | + 'svelte', |
| 257 | + '@sveltejs/kit', |
| 258 | + 'next', |
| 259 | + 'gatsby', |
| 260 | + '@remix-run/node', |
| 261 | + '@remix-run/react' |
| 262 | +] |
| 263 | + |
| 264 | +const modules = [...mostPopular240NpmModules, ...otherCommonModulesUsedWithInstrumentation] |
| 265 | + |
| 266 | +function installLibs (names) { |
| 267 | + spawnSync('npm', ['init', '-y'], { cwd }) |
| 268 | + spawnSync('npm', ['install', ...names], { cwd }) |
| 269 | +} |
| 270 | + |
| 271 | +function getExports (name, loader) { |
| 272 | + const args = ['--input-type=module', '--no-warnings', '-e', `import * as lib from '${name}'; console.log(JSON.stringify(Object.keys(lib)))`] |
| 273 | + if (loader) args.push(loader) |
| 274 | + const out = spawnSync(process.execPath, args, { cwd }) |
| 275 | + if (out.status !== 0) { |
| 276 | + console.error(out.stderr.toString()) |
| 277 | + throw new Error(`Getting exports returned non-zero exit code '${name}'`) |
| 278 | + } |
| 279 | + const stdout = out.stdout.toString() |
| 280 | + return JSON.parse(stdout).sort() |
| 281 | +} |
| 282 | + |
| 283 | +const NPM_LIST_SEMVER_PARSE = /└──.*@((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)/ |
| 284 | + |
| 285 | +function getVersion (name) { |
| 286 | + const result = spawnSync('npm', ['list', name, '--depth', '0'], { cwd }) |
| 287 | + const stdout = result.output.toString() |
| 288 | + const [, version] = stdout.match(NPM_LIST_SEMVER_PARSE) |
| 289 | + return version |
| 290 | +} |
| 291 | + |
| 292 | +function testLib (name) { |
| 293 | + const version = getVersion(name) |
| 294 | + try { |
| 295 | + const expected = getExports(name) |
| 296 | + const actual = getExports(name, `--experimental-loader=${hook}`) |
| 297 | + deepStrictEqual(actual, expected, `Exports for ${name} are different`) |
| 298 | + console.log(`✅ Exports for ${name}@${version} match`) |
| 299 | + return false |
| 300 | + } catch (err) { |
| 301 | + console.error(`❌ Error getting exports for ${name}@${version}:`, err) |
| 302 | + return true |
| 303 | + } |
| 304 | +} |
| 305 | + |
| 306 | +console.log(`📦 Installing ${modules.length} libraries...`) |
| 307 | +installLibs(modules) |
| 308 | + |
| 309 | +let errored = false |
| 310 | +for (const mod of modules) { |
| 311 | + errored += testLib(mod) |
| 312 | +} |
| 313 | + |
| 314 | +if (errored) { |
| 315 | + console.error('❌ Some tests failed') |
| 316 | + process.exit(1) |
| 317 | +} |
0 commit comments