@zuplo/cli 6.74.2 → 6.74.6

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 (64) hide show
  1. package/dist/cmds/test.d.ts.map +1 -1
  2. package/dist/cmds/test.js +8 -0
  3. package/dist/cmds/test.js.map +1 -1
  4. package/dist/common/utils/pnpm-lifecycle.d.ts.map +1 -1
  5. package/dist/common/utils/pnpm-lifecycle.js +1 -4
  6. package/dist/common/utils/pnpm-lifecycle.js.map +1 -1
  7. package/dist/common/utils/pnpm-lifecycle.test.js +23 -4
  8. package/dist/common/utils/pnpm-lifecycle.test.js.map +1 -1
  9. package/dist/test/handler.d.ts +2 -1
  10. package/dist/test/handler.d.ts.map +1 -1
  11. package/dist/test/handler.js.map +1 -1
  12. package/dist/test/invoke-test.d.ts +3 -2
  13. package/dist/test/invoke-test.d.ts.map +1 -1
  14. package/dist/test/invoke-test.js +26 -0
  15. package/dist/test/invoke-test.js.map +1 -1
  16. package/dist/test/invoke-test.test.js +16 -0
  17. package/dist/test/invoke-test.test.js.map +1 -1
  18. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +2 -2
  19. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +12 -12
  20. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/general/encrypt.js +50 -51
  21. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/local.js +10 -31
  22. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +17 -26
  23. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/compact/verify.js +2 -2
  24. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/flattened/sign.js +1 -9
  25. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/general/sign.js +12 -21
  26. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/general/verify.js +13 -11
  27. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/decrypt.js +3 -3
  28. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/verify.js +4 -4
  29. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/export.js +3 -3
  30. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/generate_key_pair.js +7 -6
  31. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/asn1.js +29 -62
  32. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/content_encryption.js +16 -34
  33. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/crypto_key.js +6 -0
  34. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/invalid_key_input.js +0 -1
  35. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_algorithms.js +44 -71
  36. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +46 -41
  37. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +14 -13
  38. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwk_to_key.js +5 -10
  39. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_algorithms.js +20 -18
  40. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_sign.js +12 -6
  41. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_verify.js +26 -27
  42. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +60 -102
  43. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key.js +61 -99
  44. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_algorithm.js +2 -8
  45. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_descriptor.js +1 -1
  46. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_management.js +74 -161
  47. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/options.js +11 -14
  48. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/signing.js +6 -16
  49. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/type_checks.js +13 -18
  50. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/util/base64url.js +4 -3
  51. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
  52. package/node_modules/@zuplo/core/package.json +1 -1
  53. package/node_modules/@zuplo/graphql/package.json +1 -1
  54. package/node_modules/@zuplo/openapi-tools/package.json +3 -3
  55. package/node_modules/@zuplo/otel/package.json +1 -1
  56. package/node_modules/@zuplo/runtime/out/esm/{chunk-B5LJC45G.js → chunk-CKGECOOJ.js} +88 -88
  57. package/node_modules/@zuplo/runtime/out/esm/chunk-CKGECOOJ.js.map +1 -0
  58. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  59. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  60. package/node_modules/@zuplo/runtime/out/types/index.d.ts +5 -1
  61. package/node_modules/@zuplo/runtime/package.json +1 -1
  62. package/package.json +6 -6
  63. package/node_modules/@zuplo/runtime/out/esm/chunk-B5LJC45G.js.map +0 -1
  64. /package/node_modules/@zuplo/runtime/out/esm/{chunk-B5LJC45G.js.LEGAL.txt → chunk-CKGECOOJ.js.LEGAL.txt} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/cmds/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAWV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAoDf,OAAO;;AAvD/B,wBA2DE"}
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/cmds/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAWV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA6Df,OAAO;;AAhE/B,wBAoEE"}
package/dist/cmds/test.js CHANGED
@@ -18,6 +18,10 @@ export default {
18
18
  .option("filter", {
19
19
  type: "string",
20
20
  describe: "A filter to run a subset of tests (e.g., --filter 'test name' or --filter '/test-name-regex/')",
21
+ })
22
+ .option("skip-filter", {
23
+ type: "string",
24
+ describe: "Skip tests whose name matches this pattern (e.g., --skip-filter '\\[deep\\]'). Applied after --filter.",
21
25
  })
22
26
  .option("test-concurrency", {
23
27
  type: "number",
@@ -43,6 +47,10 @@ export default {
43
47
  "$0 test --endpoint https://your-api-123abc.zuplo.app --filter '/api\\/v1/'",
44
48
  "Run tests matching a regex pattern",
45
49
  ],
50
+ [
51
+ "$0 test --endpoint https://your-api-123abc.zuplo.app --skip-filter '\\[slow\\]'",
52
+ "Run everything except tests tagged [slow] in their name",
53
+ ],
46
54
  [
47
55
  "MY_VAR=example $0 test --endpoint https://your-api-123abc.zuplo.app",
48
56
  "Run tests with environment variables",
@@ -1 +1 @@
1
- {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/cmds/test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAa,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAErD,eAAe;IACb,IAAI,EAAE,iDAAiD;IACvD,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,oCAAoC,CAAC;aAC3C,MAAM,CAAC,UAAU,EAAE;YAClB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,0CAA0C;YACpD,YAAY,EAAE,IAAI;SACnB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,gGAAgG;SACnG,CAAC;aACD,MAAM,CAAC,kBAAkB,EAAE;YAC1B,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAI;SACb,CAAC;aACD,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,yCAAyC;YACnD,OAAO,EAAE,GAAG;YACZ,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,IAAI;SACb,CAAC;aACD,OAAO,CAAC;YACP;gBACE,sDAAsD;gBACtD,yCAAyC;aAC1C;YACD;gBACE,sEAAsE;gBACtE,8CAA8C;aAC/C;YACD;gBACE,4EAA4E;gBAC5E,oCAAoC;aACrC;YACD;gBACE,qEAAqE;gBACrE,sCAAsC;aACvC;SACF,CAAC;aACD,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAEpB,WAAW,CAAC,IAAI,CAAC,QAAkB,EAAE,YAAY,CAAC,CAAC;YAEnD,OAAO,MAAM,IAAI,YAAY,CAC3B,2BAA2B,CAC5B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC;aACD,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,CAAC,IAAiB,CAAC,CAAC;IAChC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../common/analytics/lib.js\";\nimport { identify } from \"../common/middleware/user-identification.js\";\nimport { validateUrl } from \"../common/validators/argument-validators.js\";\nimport { validTestDirectoryValidator } from \"../common/validators/file-system-validator.js\";\nimport { YargsChecker } from \"../common/validators/lib.js\";\nimport { Arguments, test } from \"../test/handler.js\";\n\nexport default {\n desc: \"Runs the tests under /tests against an endpoint\",\n command: \"test\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 test --endpoint <url> [options]\")\n .option(\"endpoint\", {\n type: \"string\",\n describe: \"The URL of the Zuplo API to test against\",\n demandOption: true,\n })\n .option(\"filter\", {\n type: \"string\",\n describe:\n \"A filter to run a subset of tests (e.g., --filter 'test name' or --filter '/test-name-regex/')\",\n })\n .option(\"test-concurrency\", {\n type: \"number\",\n hidden: true,\n })\n .option(\"dir\", {\n type: \"string\",\n describe: \"The directory containing your Zuplo API\",\n default: \".\",\n normalize: true,\n hidden: true,\n })\n .example([\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app\",\n \"Run all tests against your deployed API\",\n ],\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app --filter 'auth'\",\n \"Run only tests matching 'auth' in their name\",\n ],\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app --filter '/api\\\\/v1/'\",\n \"Run tests matching a regex pattern\",\n ],\n [\n \"MY_VAR=example $0 test --endpoint https://your-api-123abc.zuplo.app\",\n \"Run tests with environment variables\",\n ],\n ])\n .check(async (argv) => {\n // Validate endpoint is a valid URL\n validateUrl(argv.endpoint as string, \"--endpoint\");\n\n return await new YargsChecker<typeof argv>(\n validTestDirectoryValidator\n ).check(argv);\n })\n .middleware([identify]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo test\" });\n await test(argv as Arguments);\n },\n};\n"]}
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/cmds/test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAa,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAErD,eAAe;IACb,IAAI,EAAE,iDAAiD;IACvD,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,oCAAoC,CAAC;aAC3C,MAAM,CAAC,UAAU,EAAE;YAClB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,0CAA0C;YACpD,YAAY,EAAE,IAAI;SACnB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,gGAAgG;SACnG,CAAC;aACD,MAAM,CAAC,aAAa,EAAE;YACrB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,wGAAwG;SAC3G,CAAC;aACD,MAAM,CAAC,kBAAkB,EAAE;YAC1B,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAI;SACb,CAAC;aACD,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,yCAAyC;YACnD,OAAO,EAAE,GAAG;YACZ,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,IAAI;SACb,CAAC;aACD,OAAO,CAAC;YACP;gBACE,sDAAsD;gBACtD,yCAAyC;aAC1C;YACD;gBACE,sEAAsE;gBACtE,8CAA8C;aAC/C;YACD;gBACE,4EAA4E;gBAC5E,oCAAoC;aACrC;YACD;gBACE,iFAAiF;gBACjF,yDAAyD;aAC1D;YACD;gBACE,qEAAqE;gBACrE,sCAAsC;aACvC;SACF,CAAC;aACD,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAEpB,WAAW,CAAC,IAAI,CAAC,QAAkB,EAAE,YAAY,CAAC,CAAC;YAEnD,OAAO,MAAM,IAAI,YAAY,CAC3B,2BAA2B,CAC5B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC;aACD,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,CAAC,IAAiB,CAAC,CAAC;IAChC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../common/analytics/lib.js\";\nimport { identify } from \"../common/middleware/user-identification.js\";\nimport { validateUrl } from \"../common/validators/argument-validators.js\";\nimport { validTestDirectoryValidator } from \"../common/validators/file-system-validator.js\";\nimport { YargsChecker } from \"../common/validators/lib.js\";\nimport { Arguments, test } from \"../test/handler.js\";\n\nexport default {\n desc: \"Runs the tests under /tests against an endpoint\",\n command: \"test\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 test --endpoint <url> [options]\")\n .option(\"endpoint\", {\n type: \"string\",\n describe: \"The URL of the Zuplo API to test against\",\n demandOption: true,\n })\n .option(\"filter\", {\n type: \"string\",\n describe:\n \"A filter to run a subset of tests (e.g., --filter 'test name' or --filter '/test-name-regex/')\",\n })\n .option(\"skip-filter\", {\n type: \"string\",\n describe:\n \"Skip tests whose name matches this pattern (e.g., --skip-filter '\\\\[deep\\\\]'). Applied after --filter.\",\n })\n .option(\"test-concurrency\", {\n type: \"number\",\n hidden: true,\n })\n .option(\"dir\", {\n type: \"string\",\n describe: \"The directory containing your Zuplo API\",\n default: \".\",\n normalize: true,\n hidden: true,\n })\n .example([\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app\",\n \"Run all tests against your deployed API\",\n ],\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app --filter 'auth'\",\n \"Run only tests matching 'auth' in their name\",\n ],\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app --filter '/api\\\\/v1/'\",\n \"Run tests matching a regex pattern\",\n ],\n [\n \"$0 test --endpoint https://your-api-123abc.zuplo.app --skip-filter '\\\\[slow\\\\]'\",\n \"Run everything except tests tagged [slow] in their name\",\n ],\n [\n \"MY_VAR=example $0 test --endpoint https://your-api-123abc.zuplo.app\",\n \"Run tests with environment variables\",\n ],\n ])\n .check(async (argv) => {\n // Validate endpoint is a valid URL\n validateUrl(argv.endpoint as string, \"--endpoint\");\n\n return await new YargsChecker<typeof argv>(\n validTestDirectoryValidator\n ).check(argv);\n })\n .middleware([identify]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo test\" });\n await test(argv as Arguments);\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"pnpm-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/common/utils/pnpm-lifecycle.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,oEAMtB,CAAC;AAIX,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,MAAM,CAK7D;AAkBD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAalE;AAED,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAqCnE;AAED,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAYrE"}
1
+ {"version":3,"file":"pnpm-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/common/utils/pnpm-lifecycle.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,oEAMtB,CAAC;AAIX,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,MAAM,CAK7D;AAkBD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAalE;AAED,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAsDnE;AAED,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAYrE"}
@@ -64,11 +64,8 @@ export function readBlockedBuilds(modulesYamlPath) {
64
64
  const ignored = Array.isArray(record.ignoredBuilds)
65
65
  ? record.ignoredBuilds
66
66
  : [];
67
- const pending = Array.isArray(record.pendingBuilds)
68
- ? record.pendingBuilds
69
- : [];
70
67
  const names = new Set();
71
- for (const entry of [...ignored, ...pending]) {
68
+ for (const entry of ignored) {
72
69
  if (typeof entry !== "string") {
73
70
  continue;
74
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pnpm-lifecycle.js","sourceRoot":"","sources":["../../../src/common/utils/pnpm-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport { logger } from \"../logger.js\";\n\nexport const CRITICAL_BUILD_DEPS = [\n \"deno\",\n \"workerd\",\n \"esbuild\",\n \"@swc/core\",\n \"protobufjs\",\n] as const;\n\nconst MODULES_YAML = path.join(\"node_modules\", \".modules.yaml\");\n\nexport function isPnpmDlx(somePath: string): boolean {\n const normalized = somePath.replace(/\\\\/g, \"/\");\n return (\n normalized.includes(\"/pnpm/dlx/\") || normalized.includes(\"/pnpm-cache/dlx/\")\n );\n}\n\nexport function formatCommand(argv: { _?: unknown[] }): string {\n if (!Array.isArray(argv._) || argv._.length === 0) {\n return \"<cmd>\";\n }\n return argv._.map(String).map(shellQuote).join(\" \");\n}\n\n// Cross-platform quoting: leaves safe-character tokens untouched and wraps\n// anything else in JSON-style double quotes. JSON.stringify handles embedded\n// quotes and control chars consistently. Round-trips in bash/zsh; on\n// cmd.exe / PowerShell the doubled backslashes JSON emits pass through\n// verbatim (their escape chars are caret/backtick, not backslash), but\n// Windows path APIs and path.resolve collapse consecutive separators, so\n// any path positional the CLI accepts still lands at the right directory.\n// POSIX-only edge case: $VAR / backticks inside double quotes would expand\n// on paste — rare in CLI positionals, accepted trade-off.\nfunction shellQuote(arg: string): string {\n if (/^[a-zA-Z0-9_./@:=+-]+$/.test(arg)) {\n return arg;\n }\n return JSON.stringify(arg);\n}\n\nexport function findCliModulesYaml(startDir: string): string | null {\n let current = path.resolve(startDir);\n while (true) {\n const candidate = path.join(current, MODULES_YAML);\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n\nexport function readBlockedBuilds(modulesYamlPath: string): string[] {\n let raw: string;\n try {\n raw = readFileSync(modulesYamlPath, \"utf-8\");\n } catch (cause) {\n logger.debug({ cause, modulesYamlPath }, \"Could not read .modules.yaml\");\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = yaml.load(raw);\n } catch (cause) {\n logger.debug({ cause, modulesYamlPath }, \"Could not parse .modules.yaml\");\n return [];\n }\n\n if (!parsed || typeof parsed !== \"object\") {\n return [];\n }\n\n const record = parsed as Record<string, unknown>;\n const ignored = Array.isArray(record.ignoredBuilds)\n ? record.ignoredBuilds\n : [];\n const pending = Array.isArray(record.pendingBuilds)\n ? record.pendingBuilds\n : [];\n\n const names = new Set<string>();\n for (const entry of [...ignored, ...pending]) {\n if (typeof entry !== \"string\") {\n continue;\n }\n names.add(stripVersion(entry));\n }\n return [...names];\n}\n\nexport function getBlockedCriticalDeps(cliModuleDir: string): string[] {\n try {\n const modulesYaml = findCliModulesYaml(cliModuleDir);\n if (!modulesYaml) {\n return [];\n }\n const blocked = new Set(readBlockedBuilds(modulesYaml));\n return CRITICAL_BUILD_DEPS.filter((name) => blocked.has(name));\n } catch (cause) {\n logger.debug({ cause, cliModuleDir }, \"pnpm lifecycle detection failed\");\n return [];\n }\n}\n\nfunction stripVersion(entry: string): string {\n // Scoped packages keep their leading \"@\", so split on the LAST \"@\".\n const at = entry.lastIndexOf(\"@\");\n if (at <= 0) {\n return entry;\n }\n return entry.slice(0, at);\n}\n"]}
1
+ {"version":3,"file":"pnpm-lifecycle.js","sourceRoot":"","sources":["../../../src/common/utils/pnpm-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport { logger } from \"../logger.js\";\n\nexport const CRITICAL_BUILD_DEPS = [\n \"deno\",\n \"workerd\",\n \"esbuild\",\n \"@swc/core\",\n \"protobufjs\",\n] as const;\n\nconst MODULES_YAML = path.join(\"node_modules\", \".modules.yaml\");\n\nexport function isPnpmDlx(somePath: string): boolean {\n const normalized = somePath.replace(/\\\\/g, \"/\");\n return (\n normalized.includes(\"/pnpm/dlx/\") || normalized.includes(\"/pnpm-cache/dlx/\")\n );\n}\n\nexport function formatCommand(argv: { _?: unknown[] }): string {\n if (!Array.isArray(argv._) || argv._.length === 0) {\n return \"<cmd>\";\n }\n return argv._.map(String).map(shellQuote).join(\" \");\n}\n\n// Cross-platform quoting: leaves safe-character tokens untouched and wraps\n// anything else in JSON-style double quotes. JSON.stringify handles embedded\n// quotes and control chars consistently. Round-trips in bash/zsh; on\n// cmd.exe / PowerShell the doubled backslashes JSON emits pass through\n// verbatim (their escape chars are caret/backtick, not backslash), but\n// Windows path APIs and path.resolve collapse consecutive separators, so\n// any path positional the CLI accepts still lands at the right directory.\n// POSIX-only edge case: $VAR / backticks inside double quotes would expand\n// on paste — rare in CLI positionals, accepted trade-off.\nfunction shellQuote(arg: string): string {\n if (/^[a-zA-Z0-9_./@:=+-]+$/.test(arg)) {\n return arg;\n }\n return JSON.stringify(arg);\n}\n\nexport function findCliModulesYaml(startDir: string): string | null {\n let current = path.resolve(startDir);\n while (true) {\n const candidate = path.join(current, MODULES_YAML);\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n\nexport function readBlockedBuilds(modulesYamlPath: string): string[] {\n let raw: string;\n try {\n raw = readFileSync(modulesYamlPath, \"utf-8\");\n } catch (cause) {\n logger.debug({ cause, modulesYamlPath }, \"Could not read .modules.yaml\");\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = yaml.load(raw);\n } catch (cause) {\n logger.debug({ cause, modulesYamlPath }, \"Could not parse .modules.yaml\");\n return [];\n }\n\n if (!parsed || typeof parsed !== \"object\") {\n return [];\n }\n\n const record = parsed as Record<string, unknown>;\n const ignored = Array.isArray(record.ignoredBuilds)\n ? record.ignoredBuilds\n : [];\n // `ignoredBuilds` only — `pendingBuilds` is deliberately NOT read.\n //\n // The two fields mean different things. `ignoredBuilds` is pnpm's record\n // that the user never approved a build script, which is precisely the\n // situation this preflight exists to explain. `pendingBuilds` is pnpm's\n // internal work queue: packages it intended to build during some past\n // install. Nothing clears that queue when the build later happens by another\n // route, so it goes stale and stops describing the world.\n //\n // Reading it caused a false hard-failure. A tree installed with pnpm at some\n // point and with npm afterwards keeps the old `.modules.yaml`; npm builds the\n // binaries, they work, and the CLI still refused to start because\n // `pendingBuilds` named one of them. zuplo/core's own node_modules was in\n // exactly that state — `pendingBuilds: [\"@swc/core@1.15.40\"]` left over from\n // a month-old pnpm run, with a working @swc/core on disk.\n //\n // The asymmetry matters: this path ends in\n // printCriticalFailureToConsoleAndExit, so a false positive blocks a working\n // install outright, while a false negative only costs the user this nicer\n // message and leaves the original crash they would have got anyway.\n\n const names = new Set<string>();\n for (const entry of ignored) {\n if (typeof entry !== \"string\") {\n continue;\n }\n names.add(stripVersion(entry));\n }\n return [...names];\n}\n\nexport function getBlockedCriticalDeps(cliModuleDir: string): string[] {\n try {\n const modulesYaml = findCliModulesYaml(cliModuleDir);\n if (!modulesYaml) {\n return [];\n }\n const blocked = new Set(readBlockedBuilds(modulesYaml));\n return CRITICAL_BUILD_DEPS.filter((name) => blocked.has(name));\n } catch (cause) {\n logger.debug({ cause, cliModuleDir }, \"pnpm lifecycle detection failed\");\n return [];\n }\n}\n\nfunction stripVersion(entry: string): string {\n // Scoped packages keep their leading \"@\", so split on the LAST \"@\".\n const at = entry.lastIndexOf(\"@\");\n if (at <= 0) {\n return entry;\n }\n return entry.slice(0, at);\n}\n"]}
@@ -54,18 +54,37 @@ describe("pnpm-lifecycle", () => {
54
54
  const file = writeModulesYaml("ignoredBuilds:\n - '@swc/core@1.10.18'\n");
55
55
  assert.deepStrictEqual(readBlockedBuilds(file), ["@swc/core"]);
56
56
  });
57
- it("merges and dedupes ignoredBuilds and pendingBuilds", () => {
57
+ it("dedupes repeated ignoredBuilds entries", () => {
58
58
  const file = writeModulesYaml([
59
59
  "ignoredBuilds:",
60
60
  " - deno@2.3.1",
61
61
  " - esbuild@0.25.2",
62
- "pendingBuilds:",
63
62
  " - deno@2.3.1",
64
- " - workerd@1.20241230.0",
65
63
  "",
66
64
  ].join("\n"));
67
65
  const result = readBlockedBuilds(file).sort();
68
- assert.deepStrictEqual(result, ["deno", "esbuild", "workerd"]);
66
+ assert.deepStrictEqual(result, ["deno", "esbuild"]);
67
+ });
68
+ it("ignores pendingBuilds, which goes stale and blocked a working install", () => {
69
+ const file = writeModulesYaml([
70
+ "ignoredBuilds: []",
71
+ "pendingBuilds:",
72
+ " - '@swc/core@1.15.40'",
73
+ " - workerd@1.20241230.0",
74
+ "",
75
+ ].join("\n"));
76
+ assert.deepStrictEqual(readBlockedBuilds(file), [], "pendingBuilds must not mark a dependency blocked — it is a queue of " +
77
+ "intended builds, not evidence that any of them failed");
78
+ });
79
+ it("still reports a dependency the user declined to build", () => {
80
+ const file = writeModulesYaml([
81
+ "ignoredBuilds:",
82
+ " - '@swc/core@1.15.40'",
83
+ "pendingBuilds:",
84
+ " - workerd@1.20241230.0",
85
+ "",
86
+ ].join("\n"));
87
+ assert.deepStrictEqual(readBlockedBuilds(file), ["@swc/core"]);
69
88
  });
70
89
  it("returns [] when both lists are empty", () => {
71
90
  const file = writeModulesYaml("ignoredBuilds: []\npendingBuilds: []\n");
@@ -1 +1 @@
1
- {"version":3,"file":"pnpm-lifecycle.test.js","sourceRoot":"","sources":["../../../src/common/utils/pnpm-lifecycle.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport { mkdirSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport {\n findCliModulesYaml,\n formatCommand,\n getBlockedCriticalDeps,\n isPnpmDlx,\n readBlockedBuilds,\n} from \"./pnpm-lifecycle.js\";\n\ndescribe(\"pnpm-lifecycle\", () => {\n let tmp: string;\n\n beforeEach(() => {\n tmp = mkdtempSync(path.join(os.tmpdir(), \"zup-pnpm-\"));\n });\n\n afterEach(() => {\n rmSync(tmp, { recursive: true, force: true });\n });\n\n function writeModulesYaml(contents: string, dir = tmp): string {\n const nm = path.join(dir, \"node_modules\");\n mkdirSync(nm, { recursive: true });\n const file = path.join(nm, \".modules.yaml\");\n writeFileSync(file, contents);\n return file;\n }\n\n describe(\"findCliModulesYaml\", () => {\n it(\"finds .modules.yaml in the start directory\", () => {\n const file = writeModulesYaml(\"ignoredBuilds: []\\n\");\n assert.strictEqual(findCliModulesYaml(tmp), file);\n });\n\n it(\"walks up to find .modules.yaml in an ancestor\", () => {\n const file = writeModulesYaml(\"ignoredBuilds: []\\n\");\n const nested = path.join(tmp, \"a\", \"b\", \"c\");\n mkdirSync(nested, { recursive: true });\n assert.strictEqual(findCliModulesYaml(nested), file);\n });\n\n it(\"returns null when no .modules.yaml exists in tree\", () => {\n const nested = path.join(tmp, \"a\", \"b\");\n mkdirSync(nested, { recursive: true });\n assert.strictEqual(findCliModulesYaml(nested), null);\n });\n });\n\n describe(\"readBlockedBuilds\", () => {\n it(\"returns [] when file is missing\", () => {\n const missing = path.join(tmp, \"does-not-exist.yaml\");\n assert.deepStrictEqual(readBlockedBuilds(missing), []);\n });\n\n it(\"returns [] for malformed YAML\", () => {\n const file = writeModulesYaml(\"not: valid: yaml: [\\n\");\n assert.deepStrictEqual(readBlockedBuilds(file), []);\n });\n\n it(\"strips @version suffix from package names\", () => {\n const file = writeModulesYaml(\n \"ignoredBuilds:\\n - deno@2.3.1\\n - workerd@1.20241230.0\\n\"\n );\n const result = readBlockedBuilds(file).sort();\n assert.deepStrictEqual(result, [\"deno\", \"workerd\"]);\n });\n\n it(\"preserves leading @ on scoped packages\", () => {\n const file = writeModulesYaml(\n \"ignoredBuilds:\\n - '@swc/core@1.10.18'\\n\"\n );\n assert.deepStrictEqual(readBlockedBuilds(file), [\"@swc/core\"]);\n });\n\n it(\"merges and dedupes ignoredBuilds and pendingBuilds\", () => {\n const file = writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - deno@2.3.1\",\n \" - esbuild@0.25.2\",\n \"pendingBuilds:\",\n \" - deno@2.3.1\",\n \" - workerd@1.20241230.0\",\n \"\",\n ].join(\"\\n\")\n );\n const result = readBlockedBuilds(file).sort();\n assert.deepStrictEqual(result, [\"deno\", \"esbuild\", \"workerd\"]);\n });\n\n it(\"returns [] when both lists are empty\", () => {\n const file = writeModulesYaml(\"ignoredBuilds: []\\npendingBuilds: []\\n\");\n assert.deepStrictEqual(readBlockedBuilds(file), []);\n });\n });\n\n describe(\"isPnpmDlx\", () => {\n it(\"detects macOS pnpm dlx cache paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/Users/me/Library/Caches/pnpm/dlx/abc/node_modules/foo\"),\n true\n );\n });\n\n it(\"detects Linux pnpm dlx cache paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/home/me/.local/share/pnpm/dlx/abc/node_modules/foo\"),\n true\n );\n });\n\n it(\"detects Windows pnpm-cache dlx paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\n \"C:\\\\Users\\\\me\\\\AppData\\\\Local\\\\pnpm-cache\\\\dlx\\\\abc\\\\node_modules\\\\foo\"\n ),\n true\n );\n });\n\n it(\"returns false for ordinary project paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/Users/me/projects/foo/node_modules/.pnpm/bar\"),\n false\n );\n });\n\n it(\"returns false for paths that contain dlx without pnpm\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/Users/me/dlx/something/node_modules\"),\n false\n );\n });\n });\n\n describe(\"getBlockedCriticalDeps\", () => {\n it(\"returns [] when no .modules.yaml is found\", () => {\n assert.deepStrictEqual(getBlockedCriticalDeps(tmp), []);\n });\n\n it(\"returns all matching critical deps\", () => {\n writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - deno@2.3.1\",\n \" - protobufjs@7.5.6\",\n \" - workerd@1.20241230.0\",\n \" - esbuild@0.25.2\",\n \" - '@swc/core@1.10.18'\",\n \" - esbuild@0.25.12\",\n \"pendingBuilds: []\",\n \"\",\n ].join(\"\\n\")\n );\n const result = getBlockedCriticalDeps(tmp);\n assert.deepStrictEqual(result, [\n \"deno\",\n \"workerd\",\n \"esbuild\",\n \"@swc/core\",\n \"protobufjs\",\n ]);\n });\n\n it(\"returns subset when only some criticals are blocked\", () => {\n writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - '@swc/core@1.10.18'\",\n \" - protobufjs@7.5.6\",\n \"pendingBuilds: []\",\n \"\",\n ].join(\"\\n\")\n );\n assert.deepStrictEqual(getBlockedCriticalDeps(tmp), [\n \"@swc/core\",\n \"protobufjs\",\n ]);\n });\n\n it(\"ignores unrelated packages\", () => {\n writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - some-other-pkg@1.0.0\",\n \"pendingBuilds: []\",\n \"\",\n ].join(\"\\n\")\n );\n assert.deepStrictEqual(getBlockedCriticalDeps(tmp), []);\n });\n });\n\n describe(\"formatCommand\", () => {\n it(\"returns <cmd> for empty positionals\", () => {\n assert.strictEqual(formatCommand({ _: [] }), \"<cmd>\");\n });\n\n it(\"returns <cmd> when _ is missing entirely\", () => {\n assert.strictEqual(formatCommand({}), \"<cmd>\");\n });\n\n it(\"returns the single command unchanged\", () => {\n assert.strictEqual(formatCommand({ _: [\"deploy\"] }), \"deploy\");\n });\n\n it(\"preserves the full subcommand path\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"project\", \"create\", \"my-app\"] }),\n \"project create my-app\"\n );\n });\n\n it(\"stringifies non-string entries\", () => {\n assert.strictEqual(formatCommand({ _: [123, \"create\"] }), \"123 create\");\n });\n\n it(\"double-quotes positionals containing whitespace\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"init\", \"my project\"] }),\n 'init \"my project\"'\n );\n });\n\n it(\"double-quotes positionals with shell metacharacters\", () => {\n assert.strictEqual(\n formatCommand({\n _: [\"delete\", \"https://api.example.com/foo?bar=1&baz=2\"],\n }),\n 'delete \"https://api.example.com/foo?bar=1&baz=2\"'\n );\n });\n\n it(\"escapes embedded double quotes via JSON encoding\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"init\", 'say \"hi\"'] }),\n 'init \"say \\\\\"hi\\\\\"\"'\n );\n });\n\n it(\"leaves embedded single quotes alone (JSON doesn't need to escape them)\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"init\", \"don't\"] }),\n `init \"don't\"`\n );\n });\n\n it(\"leaves dotted/URL-safe tokens unquoted\", () => {\n assert.strictEqual(\n formatCommand({\n _: [\"init\", \"./my-dir\", \"v1.2.3\", \"user@example.com\"],\n }),\n \"init ./my-dir v1.2.3 user@example.com\"\n );\n });\n });\n});\n"]}
1
+ {"version":3,"file":"pnpm-lifecycle.test.js","sourceRoot":"","sources":["../../../src/common/utils/pnpm-lifecycle.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport { mkdirSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport {\n findCliModulesYaml,\n formatCommand,\n getBlockedCriticalDeps,\n isPnpmDlx,\n readBlockedBuilds,\n} from \"./pnpm-lifecycle.js\";\n\ndescribe(\"pnpm-lifecycle\", () => {\n let tmp: string;\n\n beforeEach(() => {\n tmp = mkdtempSync(path.join(os.tmpdir(), \"zup-pnpm-\"));\n });\n\n afterEach(() => {\n rmSync(tmp, { recursive: true, force: true });\n });\n\n function writeModulesYaml(contents: string, dir = tmp): string {\n const nm = path.join(dir, \"node_modules\");\n mkdirSync(nm, { recursive: true });\n const file = path.join(nm, \".modules.yaml\");\n writeFileSync(file, contents);\n return file;\n }\n\n describe(\"findCliModulesYaml\", () => {\n it(\"finds .modules.yaml in the start directory\", () => {\n const file = writeModulesYaml(\"ignoredBuilds: []\\n\");\n assert.strictEqual(findCliModulesYaml(tmp), file);\n });\n\n it(\"walks up to find .modules.yaml in an ancestor\", () => {\n const file = writeModulesYaml(\"ignoredBuilds: []\\n\");\n const nested = path.join(tmp, \"a\", \"b\", \"c\");\n mkdirSync(nested, { recursive: true });\n assert.strictEqual(findCliModulesYaml(nested), file);\n });\n\n it(\"returns null when no .modules.yaml exists in tree\", () => {\n const nested = path.join(tmp, \"a\", \"b\");\n mkdirSync(nested, { recursive: true });\n assert.strictEqual(findCliModulesYaml(nested), null);\n });\n });\n\n describe(\"readBlockedBuilds\", () => {\n it(\"returns [] when file is missing\", () => {\n const missing = path.join(tmp, \"does-not-exist.yaml\");\n assert.deepStrictEqual(readBlockedBuilds(missing), []);\n });\n\n it(\"returns [] for malformed YAML\", () => {\n const file = writeModulesYaml(\"not: valid: yaml: [\\n\");\n assert.deepStrictEqual(readBlockedBuilds(file), []);\n });\n\n it(\"strips @version suffix from package names\", () => {\n const file = writeModulesYaml(\n \"ignoredBuilds:\\n - deno@2.3.1\\n - workerd@1.20241230.0\\n\"\n );\n const result = readBlockedBuilds(file).sort();\n assert.deepStrictEqual(result, [\"deno\", \"workerd\"]);\n });\n\n it(\"preserves leading @ on scoped packages\", () => {\n const file = writeModulesYaml(\n \"ignoredBuilds:\\n - '@swc/core@1.10.18'\\n\"\n );\n assert.deepStrictEqual(readBlockedBuilds(file), [\"@swc/core\"]);\n });\n\n it(\"dedupes repeated ignoredBuilds entries\", () => {\n const file = writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - deno@2.3.1\",\n \" - esbuild@0.25.2\",\n \" - deno@2.3.1\",\n \"\",\n ].join(\"\\n\")\n );\n const result = readBlockedBuilds(file).sort();\n assert.deepStrictEqual(result, [\"deno\", \"esbuild\"]);\n });\n\n // The regression this file exists to prevent. `pendingBuilds` is pnpm's\n // work queue, not a record that anything is broken, and nothing clears it\n // when the build later happens some other way — so a tree that used pnpm\n // once and npm since keeps a stale entry for a package that works fine.\n // Counting it made the CLI refuse to start on a healthy install.\n it(\"ignores pendingBuilds, which goes stale and blocked a working install\", () => {\n const file = writeModulesYaml(\n [\n \"ignoredBuilds: []\",\n \"pendingBuilds:\",\n \" - '@swc/core@1.15.40'\",\n \" - workerd@1.20241230.0\",\n \"\",\n ].join(\"\\n\")\n );\n assert.deepStrictEqual(\n readBlockedBuilds(file),\n [],\n \"pendingBuilds must not mark a dependency blocked — it is a queue of \" +\n \"intended builds, not evidence that any of them failed\"\n );\n });\n\n it(\"still reports a dependency the user declined to build\", () => {\n const file = writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - '@swc/core@1.15.40'\",\n \"pendingBuilds:\",\n \" - workerd@1.20241230.0\",\n \"\",\n ].join(\"\\n\")\n );\n assert.deepStrictEqual(readBlockedBuilds(file), [\"@swc/core\"]);\n });\n\n it(\"returns [] when both lists are empty\", () => {\n const file = writeModulesYaml(\"ignoredBuilds: []\\npendingBuilds: []\\n\");\n assert.deepStrictEqual(readBlockedBuilds(file), []);\n });\n });\n\n describe(\"isPnpmDlx\", () => {\n it(\"detects macOS pnpm dlx cache paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/Users/me/Library/Caches/pnpm/dlx/abc/node_modules/foo\"),\n true\n );\n });\n\n it(\"detects Linux pnpm dlx cache paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/home/me/.local/share/pnpm/dlx/abc/node_modules/foo\"),\n true\n );\n });\n\n it(\"detects Windows pnpm-cache dlx paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\n \"C:\\\\Users\\\\me\\\\AppData\\\\Local\\\\pnpm-cache\\\\dlx\\\\abc\\\\node_modules\\\\foo\"\n ),\n true\n );\n });\n\n it(\"returns false for ordinary project paths\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/Users/me/projects/foo/node_modules/.pnpm/bar\"),\n false\n );\n });\n\n it(\"returns false for paths that contain dlx without pnpm\", () => {\n assert.strictEqual(\n isPnpmDlx(\"/Users/me/dlx/something/node_modules\"),\n false\n );\n });\n });\n\n describe(\"getBlockedCriticalDeps\", () => {\n it(\"returns [] when no .modules.yaml is found\", () => {\n assert.deepStrictEqual(getBlockedCriticalDeps(tmp), []);\n });\n\n it(\"returns all matching critical deps\", () => {\n writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - deno@2.3.1\",\n \" - protobufjs@7.5.6\",\n \" - workerd@1.20241230.0\",\n \" - esbuild@0.25.2\",\n \" - '@swc/core@1.10.18'\",\n \" - esbuild@0.25.12\",\n \"pendingBuilds: []\",\n \"\",\n ].join(\"\\n\")\n );\n const result = getBlockedCriticalDeps(tmp);\n assert.deepStrictEqual(result, [\n \"deno\",\n \"workerd\",\n \"esbuild\",\n \"@swc/core\",\n \"protobufjs\",\n ]);\n });\n\n it(\"returns subset when only some criticals are blocked\", () => {\n writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - '@swc/core@1.10.18'\",\n \" - protobufjs@7.5.6\",\n \"pendingBuilds: []\",\n \"\",\n ].join(\"\\n\")\n );\n assert.deepStrictEqual(getBlockedCriticalDeps(tmp), [\n \"@swc/core\",\n \"protobufjs\",\n ]);\n });\n\n it(\"ignores unrelated packages\", () => {\n writeModulesYaml(\n [\n \"ignoredBuilds:\",\n \" - some-other-pkg@1.0.0\",\n \"pendingBuilds: []\",\n \"\",\n ].join(\"\\n\")\n );\n assert.deepStrictEqual(getBlockedCriticalDeps(tmp), []);\n });\n });\n\n describe(\"formatCommand\", () => {\n it(\"returns <cmd> for empty positionals\", () => {\n assert.strictEqual(formatCommand({ _: [] }), \"<cmd>\");\n });\n\n it(\"returns <cmd> when _ is missing entirely\", () => {\n assert.strictEqual(formatCommand({}), \"<cmd>\");\n });\n\n it(\"returns the single command unchanged\", () => {\n assert.strictEqual(formatCommand({ _: [\"deploy\"] }), \"deploy\");\n });\n\n it(\"preserves the full subcommand path\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"project\", \"create\", \"my-app\"] }),\n \"project create my-app\"\n );\n });\n\n it(\"stringifies non-string entries\", () => {\n assert.strictEqual(formatCommand({ _: [123, \"create\"] }), \"123 create\");\n });\n\n it(\"double-quotes positionals containing whitespace\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"init\", \"my project\"] }),\n 'init \"my project\"'\n );\n });\n\n it(\"double-quotes positionals with shell metacharacters\", () => {\n assert.strictEqual(\n formatCommand({\n _: [\"delete\", \"https://api.example.com/foo?bar=1&baz=2\"],\n }),\n 'delete \"https://api.example.com/foo?bar=1&baz=2\"'\n );\n });\n\n it(\"escapes embedded double quotes via JSON encoding\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"init\", 'say \"hi\"'] }),\n 'init \"say \\\\\"hi\\\\\"\"'\n );\n });\n\n it(\"leaves embedded single quotes alone (JSON doesn't need to escape them)\", () => {\n assert.strictEqual(\n formatCommand({ _: [\"init\", \"don't\"] }),\n `init \"don't\"`\n );\n });\n\n it(\"leaves dotted/URL-safe tokens unquoted\", () => {\n assert.strictEqual(\n formatCommand({\n _: [\"init\", \"./my-dir\", \"v1.2.3\", \"user@example.com\"],\n }),\n \"init ./my-dir v1.2.3 user@example.com\"\n );\n });\n });\n});\n"]}
@@ -1,7 +1,8 @@
1
1
  export interface Arguments {
2
2
  dir: string;
3
3
  endpoint: string;
4
- filter: string;
4
+ filter?: string;
5
+ skipFilter?: string;
5
6
  testConcurrency?: number;
6
7
  }
7
8
  export declare function test(argv: Arguments): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/test/handler.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,iBA0BzC"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/test/handler.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IAOjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,iBA0BzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/test/handler.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAwB,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAShD,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAe;IAExC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAC1D,UAAU,CAAC,OAAO,CAAC,CAAC;IAGpB,MAAM,MAAM,GAAgB,MAAM,OAAO,CAAC,KAAK,CAAC;QAC9C,GAAG,2BAA2B,CAAC,IAAI,CAAC;QACpC,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,MAAM,EACb,qCAAqC,IAAI,CAAC,GAAG,IAAI,cAAc,EAAE,CAClE,CAAC;IACJ,CAAC;SAAM,CAAC;QAEN,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;AACH,CAAC","sourcesContent":["import path from \"node:path\";\nimport esbuild, { BuildResult } from \"esbuild\";\nimport { rimrafSync } from \"rimraf\";\nimport { TEST_IN_FOLDER, TEST_OUT_FOLDER } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport { generateBuildOptionsForTest } from \"./esbuild-config.js\";\nimport { runTests } from \"./invoke-test.js\";\nimport { findTestFiles } from \"./test-files.js\";\n\nexport interface Arguments {\n dir: string;\n endpoint: string;\n filter: string;\n testConcurrency?: number;\n}\n\nexport async function test(argv: Arguments) {\n // 1. Clean out the folder\n const normalizedDir = path.resolve(argv.dir);\n const testDir = path.join(normalizedDir, TEST_OUT_FOLDER);\n rimrafSync(testDir);\n\n // 2. Build the test files\n const result: BuildResult = await esbuild.build({\n ...generateBuildOptionsForTest(argv),\n entryPoints: findTestFiles(argv.dir),\n });\n\n if (result.warnings.length > 0) {\n logger.debug(result.warnings);\n }\n\n if (result.errors.length > 0) {\n logger.error(\n result.errors,\n `Failed to build the test files in ${argv.dir}/${TEST_IN_FOLDER}`\n );\n } else {\n // 3. Run `node test`\n const { exitCode } = await runTests(argv);\n process.exit(exitCode);\n }\n}\n"]}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/test/handler.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAwB,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAgBhD,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAe;IAExC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAC1D,UAAU,CAAC,OAAO,CAAC,CAAC;IAGpB,MAAM,MAAM,GAAgB,MAAM,OAAO,CAAC,KAAK,CAAC;QAC9C,GAAG,2BAA2B,CAAC,IAAI,CAAC;QACpC,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,MAAM,EACb,qCAAqC,IAAI,CAAC,GAAG,IAAI,cAAc,EAAE,CAClE,CAAC;IACJ,CAAC;SAAM,CAAC;QAEN,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;AACH,CAAC","sourcesContent":["import path from \"node:path\";\nimport esbuild, { BuildResult } from \"esbuild\";\nimport { rimrafSync } from \"rimraf\";\nimport { TEST_IN_FOLDER, TEST_OUT_FOLDER } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport { generateBuildOptionsForTest } from \"./esbuild-config.js\";\nimport { runTests } from \"./invoke-test.js\";\nimport { findTestFiles } from \"./test-files.js\";\n\nexport interface Arguments {\n dir: string;\n endpoint: string;\n /**\n * Optional: only `--endpoint` is `demandOption` on the yargs command, and\n * `cmds/test.ts` reaches `test()` through an unchecked `argv as Arguments`\n * cast, so a missing `--filter` arrives as `undefined` at runtime regardless\n * of what this type claims. `buildNodeTestArgs` already guards for it.\n */\n filter?: string;\n skipFilter?: string;\n testConcurrency?: number;\n}\n\nexport async function test(argv: Arguments) {\n // 1. Clean out the folder\n const normalizedDir = path.resolve(argv.dir);\n const testDir = path.join(normalizedDir, TEST_OUT_FOLDER);\n rimrafSync(testDir);\n\n // 2. Build the test files\n const result: BuildResult = await esbuild.build({\n ...generateBuildOptionsForTest(argv),\n entryPoints: findTestFiles(argv.dir),\n });\n\n if (result.warnings.length > 0) {\n logger.debug(result.warnings);\n }\n\n if (result.errors.length > 0) {\n logger.error(\n result.errors,\n `Failed to build the test files in ${argv.dir}/${TEST_IN_FOLDER}`\n );\n } else {\n // 3. Run `node test`\n const { exitCode } = await runTests(argv);\n process.exit(exitCode);\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
- import { ExecaReturnBase } from "execa";
2
- import { Arguments } from "./handler.js";
1
+ import { type ExecaReturnBase } from "execa";
2
+ import type { Arguments } from "./handler.js";
3
+ export declare function supportsTestSkipPattern(nodeVersion?: string): boolean;
3
4
  export declare function runTests(
4
5
  argv: Arguments
5
6
  ): Promise<Pick<ExecaReturnBase<string>, "exitCode">>;
@@ -1 +1 @@
1
- {"version":3,"file":"invoke-test.d.ts","sourceRoot":"","sources":["../../src/test/invoke-test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAS,MAAM,OAAO,CAAC;AAI/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AASzC,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAwBpD"}
1
+ {"version":3,"file":"invoke-test.d.ts","sourceRoot":"","sources":["../../src/test/invoke-test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAS,MAAM,OAAO,CAAC;AAIpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAkB9C,wBAAgB,uBAAuB,CACrC,WAAW,GAAE,MAA8B,GAC1C,OAAO,CAcT;AAaD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAwBpD"}
@@ -9,6 +9,26 @@ class MissingNodeExecutableError extends Error {
9
9
  Object.setPrototypeOf(this, MissingNodeExecutableError.prototype);
10
10
  }
11
11
  }
12
+ const MIN_NODE_FOR_SKIP_PATTERN = { major: 22, minor: 1 };
13
+ export function supportsTestSkipPattern(nodeVersion = process.versions.node) {
14
+ const [major, minor] = nodeVersion
15
+ .split(".")
16
+ .map((part) => Number.parseInt(part, 10));
17
+ if (Number.isNaN(major) || Number.isNaN(minor)) {
18
+ return true;
19
+ }
20
+ return (major > MIN_NODE_FOR_SKIP_PATTERN.major ||
21
+ (major === MIN_NODE_FOR_SKIP_PATTERN.major &&
22
+ minor >= MIN_NODE_FOR_SKIP_PATTERN.minor));
23
+ }
24
+ class UnsupportedSkipFilterError extends Error {
25
+ constructor(nodeVersion) {
26
+ super(`--skip-filter requires Node >= ${MIN_NODE_FOR_SKIP_PATTERN.major}.${MIN_NODE_FOR_SKIP_PATTERN.minor}.0 ` +
27
+ `(it maps to Node's --test-skip-pattern, added in v22.1.0), but this is Node ${nodeVersion}. ` +
28
+ `Upgrade Node, or drop --skip-filter and use --filter to select tests instead.`);
29
+ Object.setPrototypeOf(this, UnsupportedSkipFilterError.prototype);
30
+ }
31
+ }
12
32
  export async function runTests(argv) {
13
33
  const nodeExecutable = process.platform === "win32" ? "node.exe" : "node";
14
34
  if (nodeExecutable) {
@@ -38,6 +58,12 @@ function buildNodeTestArgs(argv) {
38
58
  if (argv.filter) {
39
59
  args.push("--test-name-pattern", argv.filter);
40
60
  }
61
+ if (argv.skipFilter) {
62
+ if (!supportsTestSkipPattern()) {
63
+ throw new UnsupportedSkipFilterError(process.versions.node);
64
+ }
65
+ args.push("--test-skip-pattern", argv.skipFilter);
66
+ }
41
67
  return args;
42
68
  }
43
69
  function compiledTestGlob(dir) {
@@ -1 +1 @@
1
- {"version":3,"file":"invoke-test.js","sourceRoot":"","sources":["../../src/test/invoke-test.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { ExecaReturnBase, execa } from \"execa\";\nimport fg from \"fast-glob\";\nimport { TEST_OUT_FOLDER } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport { Arguments } from \"./handler.js\";\n\nclass MissingNodeExecutableError extends Error {\n constructor() {\n super(\"Missing executable: Cannot locate node executable\");\n Object.setPrototypeOf(this, MissingNodeExecutableError.prototype);\n }\n}\n\nexport async function runTests(\n argv: Arguments\n): Promise<Pick<ExecaReturnBase<string>, \"exitCode\">> {\n // Assume that \"node\" is in the path\n const nodeExecutable = process.platform === \"win32\" ? \"node.exe\" : \"node\";\n if (nodeExecutable) {\n const args = buildNodeTestArgs(argv);\n const serialTestTargets =\n argv.testConcurrency === 1 ? findCompiledTestFiles(argv.dir) : [];\n const testTargets =\n serialTestTargets.length > 0\n ? serialTestTargets\n : [compiledTestGlob(argv.dir)];\n let failedResult: Pick<ExecaReturnBase<string>, \"exitCode\"> | undefined;\n\n for (const testTarget of testTargets) {\n const result = await runNodeTest(nodeExecutable, [...args, testTarget]);\n if (result.exitCode !== 0 && failedResult === undefined) {\n failedResult = result;\n }\n }\n\n return failedResult ?? { exitCode: 0 };\n } else {\n throw new MissingNodeExecutableError();\n }\n}\n\nfunction buildNodeTestArgs(argv: Arguments): string[] {\n const args = [\"--test\", \"--test-reporter=spec\", \"--enable-source-maps\"];\n if (argv.testConcurrency !== undefined && argv.testConcurrency !== 1) {\n args.push(`--test-concurrency=${argv.testConcurrency}`);\n }\n if (argv.filter) {\n args.push(\"--test-name-pattern\", argv.filter);\n }\n return args;\n}\n\nfunction compiledTestGlob(dir: string): string {\n const nodeVersion = parseInt(process.versions.node.split(\".\")[0], 10);\n return nodeVersion >= 21\n ? path.join(dir, TEST_OUT_FOLDER, \"**\", \"*.test.mjs\")\n : path.join(dir, TEST_OUT_FOLDER);\n}\n\nfunction findCompiledTestFiles(dir: string): string[] {\n const normalizedDir = path.normalize(dir);\n const testOutDir = fg.convertPathToPattern(\n path.join(normalizedDir, TEST_OUT_FOLDER)\n );\n return fg.sync(path.posix.join(testOutDir, \"**\", \"*.test.mjs\")).sort();\n}\n\nasync function runNodeTest(\n nodeExecutable: string,\n args: string[]\n): Promise<Pick<ExecaReturnBase<string>, \"exitCode\">> {\n const nodeProcess = execa(nodeExecutable, args);\n nodeProcess.stdout?.pipe(process.stdout);\n nodeProcess.stderr?.pipe(process.stderr);\n try {\n const result = await nodeProcess;\n return result;\n } catch (err) {\n // We do not want to output the err by default since it could be a test\n // failure. Test failures are already reported by piping stdout and stderr\n // above.\n logger.debug(err);\n return { exitCode: err.exitCode };\n }\n}\n"]}
1
+ {"version":3,"file":"invoke-test.js","sourceRoot":"","sources":["../../src/test/invoke-test.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { type ExecaReturnBase, execa } from \"execa\";\nimport fg from \"fast-glob\";\nimport { TEST_OUT_FOLDER } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport type { Arguments } from \"./handler.js\";\n\nclass MissingNodeExecutableError extends Error {\n constructor() {\n super(\"Missing executable: Cannot locate node executable\");\n Object.setPrototypeOf(this, MissingNodeExecutableError.prototype);\n }\n}\n\n/**\n * Node added `--test-skip-pattern` in v22.1.0. It exists on NO earlier release\n * line — it was never backported to v20.x or v21.x — while this package's\n * `engines.node` is `>=20.17.0`. Without this guard, `--skip-filter` on a\n * supported-but-older Node dies inside the spawned child with a bare\n * `bad option: --test-skip-pattern`, which reads like a broken CLI install.\n */\nconst MIN_NODE_FOR_SKIP_PATTERN = { major: 22, minor: 1 };\n\nexport function supportsTestSkipPattern(\n nodeVersion: string = process.versions.node\n): boolean {\n const [major, minor] = nodeVersion\n .split(\".\")\n .map((part) => Number.parseInt(part, 10));\n if (Number.isNaN(major) || Number.isNaN(minor)) {\n // Unparseable version: assume support and let Node speak for itself rather\n // than blocking a valid run on a version string we failed to read.\n return true;\n }\n return (\n major > MIN_NODE_FOR_SKIP_PATTERN.major ||\n (major === MIN_NODE_FOR_SKIP_PATTERN.major &&\n minor >= MIN_NODE_FOR_SKIP_PATTERN.minor)\n );\n}\n\nclass UnsupportedSkipFilterError extends Error {\n constructor(nodeVersion: string) {\n super(\n `--skip-filter requires Node >= ${MIN_NODE_FOR_SKIP_PATTERN.major}.${MIN_NODE_FOR_SKIP_PATTERN.minor}.0 ` +\n `(it maps to Node's --test-skip-pattern, added in v22.1.0), but this is Node ${nodeVersion}. ` +\n `Upgrade Node, or drop --skip-filter and use --filter to select tests instead.`\n );\n Object.setPrototypeOf(this, UnsupportedSkipFilterError.prototype);\n }\n}\n\nexport async function runTests(\n argv: Arguments\n): Promise<Pick<ExecaReturnBase<string>, \"exitCode\">> {\n // Assume that \"node\" is in the path\n const nodeExecutable = process.platform === \"win32\" ? \"node.exe\" : \"node\";\n if (nodeExecutable) {\n const args = buildNodeTestArgs(argv);\n const serialTestTargets =\n argv.testConcurrency === 1 ? findCompiledTestFiles(argv.dir) : [];\n const testTargets =\n serialTestTargets.length > 0\n ? serialTestTargets\n : [compiledTestGlob(argv.dir)];\n let failedResult: Pick<ExecaReturnBase<string>, \"exitCode\"> | undefined;\n\n for (const testTarget of testTargets) {\n const result = await runNodeTest(nodeExecutable, [...args, testTarget]);\n if (result.exitCode !== 0 && failedResult === undefined) {\n failedResult = result;\n }\n }\n\n return failedResult ?? { exitCode: 0 };\n } else {\n throw new MissingNodeExecutableError();\n }\n}\n\nfunction buildNodeTestArgs(argv: Arguments): string[] {\n const args = [\"--test\", \"--test-reporter=spec\", \"--enable-source-maps\"];\n if (argv.testConcurrency !== undefined && argv.testConcurrency !== 1) {\n args.push(`--test-concurrency=${argv.testConcurrency}`);\n }\n if (argv.filter) {\n args.push(\"--test-name-pattern\", argv.filter);\n }\n if (argv.skipFilter) {\n if (!supportsTestSkipPattern()) {\n throw new UnsupportedSkipFilterError(process.versions.node);\n }\n args.push(\"--test-skip-pattern\", argv.skipFilter);\n }\n return args;\n}\n\nfunction compiledTestGlob(dir: string): string {\n const nodeVersion = parseInt(process.versions.node.split(\".\")[0], 10);\n return nodeVersion >= 21\n ? path.join(dir, TEST_OUT_FOLDER, \"**\", \"*.test.mjs\")\n : path.join(dir, TEST_OUT_FOLDER);\n}\n\nfunction findCompiledTestFiles(dir: string): string[] {\n const normalizedDir = path.normalize(dir);\n const testOutDir = fg.convertPathToPattern(\n path.join(normalizedDir, TEST_OUT_FOLDER)\n );\n return fg.sync(path.posix.join(testOutDir, \"**\", \"*.test.mjs\")).sort();\n}\n\nasync function runNodeTest(\n nodeExecutable: string,\n args: string[]\n): Promise<Pick<ExecaReturnBase<string>, \"exitCode\">> {\n const nodeProcess = execa(nodeExecutable, args);\n nodeProcess.stdout?.pipe(process.stdout);\n nodeProcess.stderr?.pipe(process.stderr);\n try {\n const result = await nodeProcess;\n return result;\n } catch (err) {\n // We do not want to output the err by default since it could be a test\n // failure. Test failures are already reported by piping stdout and stderr\n // above.\n logger.debug(err);\n return { exitCode: err.exitCode };\n }\n}\n"]}
@@ -5,6 +5,7 @@ import path from "node:path";
5
5
  import { describe, it } from "node:test";
6
6
  import { expect } from "chai";
7
7
  import { TEST_OUT_FOLDER } from "../common/constants.js";
8
+ import { supportsTestSkipPattern } from "./invoke-test.js";
8
9
  describe("runTests", () => {
9
10
  it("runs every compiled test file serially after a failure", async () => {
10
11
  const testDir = await mkdtemp(path.join(os.tmpdir(), "zuplo-run-tests-serial-"));
@@ -54,4 +55,19 @@ describe("runTests", () => {
54
55
  }
55
56
  });
56
57
  });
58
+ describe("supportsTestSkipPattern", () => {
59
+ it("rejects release lines that never shipped the flag", () => {
60
+ for (const version of ["20.17.0", "20.20.2", "21.7.3", "22.0.0"]) {
61
+ expect(supportsTestSkipPattern(version), version).to.equal(false);
62
+ }
63
+ });
64
+ it("accepts v22.1.0 and later", () => {
65
+ for (const version of ["22.1.0", "22.22.1", "23.0.0", "24.1.0"]) {
66
+ expect(supportsTestSkipPattern(version), version).to.equal(true);
67
+ }
68
+ });
69
+ it("assumes support when the version string is unparseable", () => {
70
+ expect(supportsTestSkipPattern("not-a-version")).to.equal(true);
71
+ });
72
+ });
57
73
  //# sourceMappingURL=invoke-test.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"invoke-test.test.js","sourceRoot":"","sources":["../../src/test/invoke-test.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { access, mkdir, mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, it } from \"node:test\";\nimport { expect } from \"chai\";\nimport { TEST_OUT_FOLDER } from \"../common/constants.js\";\n\ndescribe(\"runTests\", () => {\n it(\"runs every compiled test file serially after a failure\", async () => {\n const testDir = await mkdtemp(\n path.join(os.tmpdir(), \"zuplo-run-tests-serial-\")\n );\n\n try {\n const compiledTestDir = path.join(testDir, TEST_OUT_FOLDER);\n const secondTestMarker = path.join(testDir, \"second-test-ran\");\n await mkdir(compiledTestDir, { recursive: true });\n await writeFile(\n path.join(compiledTestDir, \"a-first.test.mjs\"),\n [\n 'import test from \"node:test\";',\n 'test(\"Moonshot first\", () => {',\n ' throw new Error(\"expected failure\");',\n \"});\",\n ].join(\"\\n\")\n );\n await writeFile(\n path.join(compiledTestDir, \"b-second.test.mjs\"),\n [\n 'import { writeFileSync } from \"node:fs\";',\n 'import test from \"node:test\";',\n 'test(\"Moonshot second\", () => {',\n ` writeFileSync(${JSON.stringify(secondTestMarker)}, \"ran\");`,\n \"});\",\n ].join(\"\\n\")\n );\n\n const environment = { ...process.env };\n delete environment.NODE_TEST_CONTEXT;\n const invokeTestUrl = new URL(\"./invoke-test.js\", import.meta.url).href;\n const script = [\n `import { runTests } from ${JSON.stringify(invokeTestUrl)};`,\n `const result = await runTests(${JSON.stringify({\n dir: testDir,\n endpoint: \"http://localhost\",\n filter: \"Moonshot\",\n testConcurrency: 1,\n })});`,\n \"process.exitCode = result.exitCode;\",\n ].join(\"\\n\");\n const exitCode = await new Promise<number | null>((resolve, reject) => {\n const child = spawn(\n process.execPath,\n [\"--input-type=module\", \"--eval\", script],\n {\n env: environment,\n stdio: \"ignore\",\n }\n );\n child.once(\"error\", reject);\n child.once(\"exit\", resolve);\n });\n\n expect(exitCode).not.to.equal(0);\n await access(secondTestMarker);\n } finally {\n await rm(testDir, { recursive: true, force: true });\n }\n });\n});\n"]}
1
+ {"version":3,"file":"invoke-test.test.js","sourceRoot":"","sources":["../../src/test/invoke-test.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { access, mkdir, mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, it } from \"node:test\";\nimport { expect } from \"chai\";\nimport { TEST_OUT_FOLDER } from \"../common/constants.js\";\nimport { supportsTestSkipPattern } from \"./invoke-test.js\";\n\ndescribe(\"runTests\", () => {\n it(\"runs every compiled test file serially after a failure\", async () => {\n const testDir = await mkdtemp(\n path.join(os.tmpdir(), \"zuplo-run-tests-serial-\")\n );\n\n try {\n const compiledTestDir = path.join(testDir, TEST_OUT_FOLDER);\n const secondTestMarker = path.join(testDir, \"second-test-ran\");\n await mkdir(compiledTestDir, { recursive: true });\n await writeFile(\n path.join(compiledTestDir, \"a-first.test.mjs\"),\n [\n 'import test from \"node:test\";',\n 'test(\"Moonshot first\", () => {',\n ' throw new Error(\"expected failure\");',\n \"});\",\n ].join(\"\\n\")\n );\n await writeFile(\n path.join(compiledTestDir, \"b-second.test.mjs\"),\n [\n 'import { writeFileSync } from \"node:fs\";',\n 'import test from \"node:test\";',\n 'test(\"Moonshot second\", () => {',\n ` writeFileSync(${JSON.stringify(secondTestMarker)}, \"ran\");`,\n \"});\",\n ].join(\"\\n\")\n );\n\n const environment = { ...process.env };\n delete environment.NODE_TEST_CONTEXT;\n const invokeTestUrl = new URL(\"./invoke-test.js\", import.meta.url).href;\n const script = [\n `import { runTests } from ${JSON.stringify(invokeTestUrl)};`,\n `const result = await runTests(${JSON.stringify({\n dir: testDir,\n endpoint: \"http://localhost\",\n filter: \"Moonshot\",\n testConcurrency: 1,\n })});`,\n \"process.exitCode = result.exitCode;\",\n ].join(\"\\n\");\n const exitCode = await new Promise<number | null>((resolve, reject) => {\n const child = spawn(\n process.execPath,\n [\"--input-type=module\", \"--eval\", script],\n {\n env: environment,\n stdio: \"ignore\",\n }\n );\n child.once(\"error\", reject);\n child.once(\"exit\", resolve);\n });\n\n expect(exitCode).not.to.equal(0);\n await access(secondTestMarker);\n } finally {\n await rm(testDir, { recursive: true, force: true });\n }\n });\n});\n\ndescribe(\"supportsTestSkipPattern\", () => {\n // `--skip-filter` maps to Node's `--test-skip-pattern`, which landed in\n // v22.1.0 and was never backported. This package's engines.node is\n // \">=20.17.0\", so the gap is reachable by a real user: without the guard the\n // spawned child dies with a bare `bad option: --test-skip-pattern`.\n it(\"rejects release lines that never shipped the flag\", () => {\n for (const version of [\"20.17.0\", \"20.20.2\", \"21.7.3\", \"22.0.0\"]) {\n expect(supportsTestSkipPattern(version), version).to.equal(false);\n }\n });\n\n it(\"accepts v22.1.0 and later\", () => {\n for (const version of [\"22.1.0\", \"22.22.1\", \"23.0.0\", \"24.1.0\"]) {\n expect(supportsTestSkipPattern(version), version).to.equal(true);\n }\n });\n\n it(\"assumes support when the version string is unparseable\", () => {\n // Better to let Node itself reject an unknown flag than to block a valid\n // run because we could not read a version string.\n expect(supportsTestSkipPattern(\"not-a-version\")).to.equal(true);\n });\n});\n"]}
@@ -1,9 +1,9 @@
1
1
  import { prepareDecrypt, decryptCompact } from '../../lib/jwe_decrypt.js';
2
2
  export async function compactDecrypt(jwe, key, options) {
3
3
  const decrypted = await decryptCompact(jwe, prepareDecrypt(options), key);
4
- const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.parsedProt };
4
+ const result = { plaintext: decrypted[0], protectedHeader: decrypted[1] };
5
5
  if (typeof key === 'function') {
6
- return { ...result, key: decrypted.key };
6
+ return { ...result, key: decrypted[2] };
7
7
  }
8
8
  return result;
9
9
  }
@@ -56,17 +56,17 @@ export class FlattenedEncrypt {
56
56
  throw new JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()');
57
57
  }
58
58
  validateCritDuplicates(JWEInvalid, this.#protectedHeader);
59
- return createJWE({
60
- plaintext: this.#plaintext,
61
- protectedHeader: this.#protectedHeader,
62
- unprotectedHeader: this.#unprotectedHeader,
63
- sharedUnprotectedHeader: this.#sharedUnprotectedHeader,
64
- aad: this.#aad,
65
- cek: this.#cek,
66
- iv: this.#iv,
67
- keyManagementParameters: this.#keyManagementParameters,
68
- crit: options?.crit,
69
- unprotectedParameters: options ? unprotected in options : false,
70
- }, key);
59
+ return createJWE([
60
+ this.#plaintext,
61
+ this.#protectedHeader,
62
+ this.#unprotectedHeader,
63
+ this.#sharedUnprotectedHeader,
64
+ this.#aad,
65
+ this.#cek,
66
+ this.#iv,
67
+ this.#keyManagementParameters,
68
+ options?.crit,
69
+ options ? unprotected in options : false,
70
+ ], key);
71
71
  }
72
72
  }