@zuplo/cli 7.3.2 → 7.4.3
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.
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/cmds/lint.d.ts +9 -0
- package/dist/cmds/lint.d.ts.map +1 -0
- package/dist/cmds/lint.js +67 -0
- package/dist/cmds/lint.js.map +1 -0
- package/dist/lint/handler.d.ts +10 -0
- package/dist/lint/handler.d.ts.map +1 -0
- package/dist/lint/handler.js +60 -0
- package/dist/lint/handler.js.map +1 -0
- package/dist/lint/resolve-binary.d.ts +20 -0
- package/dist/lint/resolve-binary.d.ts.map +1 -0
- package/dist/lint/resolve-binary.js +71 -0
- package/dist/lint/resolve-binary.js.map +1 -0
- package/dist/lint/resolve-binary.test.d.ts +2 -0
- package/dist/lint/resolve-binary.test.d.ts.map +1 -0
- package/dist/lint/resolve-binary.test.js +155 -0
- package/dist/lint/resolve-binary.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@inquirer/checkbox/package.json +5 -4
- package/node_modules/@inquirer/confirm/dist/index.d.ts +1 -1
- package/node_modules/@inquirer/confirm/package.json +4 -3
- package/node_modules/@inquirer/core/README.md +9 -3
- package/node_modules/@inquirer/core/dist/lib/hook-engine.d.ts +2 -8
- package/node_modules/@inquirer/core/dist/lib/use-memo.js +1 -1
- package/node_modules/@inquirer/core/dist/lib/use-state.d.ts +5 -2
- package/node_modules/@inquirer/core/dist/lib/use-state.js +7 -2
- package/node_modules/@inquirer/core/package.json +5 -4
- package/node_modules/@inquirer/editor/dist/index.d.ts +1 -1
- package/node_modules/@inquirer/editor/package.json +5 -4
- package/node_modules/@inquirer/expand/README.md +1 -1
- package/node_modules/@inquirer/expand/package.json +4 -3
- package/node_modules/@inquirer/external-editor/README.md +13 -0
- package/node_modules/@inquirer/external-editor/package.json +4 -3
- package/node_modules/@inquirer/figures/package.json +4 -3
- package/node_modules/@inquirer/input/package.json +4 -3
- package/node_modules/@inquirer/number/dist/index.d.ts +1 -1
- package/node_modules/@inquirer/number/dist/index.js +1 -6
- package/node_modules/@inquirer/number/dist/is-step-of.d.ts +1 -0
- package/node_modules/@inquirer/number/dist/is-step-of.js +22 -0
- package/node_modules/@inquirer/number/package.json +4 -3
- package/node_modules/@inquirer/password/package.json +4 -3
- package/node_modules/@inquirer/rawlist/package.json +4 -3
- package/node_modules/@inquirer/search/README.md +9 -8
- package/node_modules/@inquirer/search/dist/index.d.ts +1 -0
- package/node_modules/@inquirer/search/dist/index.js +6 -1
- package/node_modules/@inquirer/search/package.json +5 -4
- package/node_modules/@inquirer/select/package.json +5 -4
- package/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.js +4 -2
- package/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.mjs +4 -2
- package/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.js +5 -5
- package/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.mjs +5 -5
- package/node_modules/@posthog/core/dist/error-tracking/parsers/base.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/error-tracking/parsers/base.js +2 -1
- package/node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs +2 -1
- package/node_modules/@posthog/core/dist/posthog-core.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/posthog-core.js +1 -0
- package/node_modules/@posthog/core/dist/posthog-core.mjs +1 -0
- package/node_modules/@posthog/core/package.json +1 -1
- package/node_modules/@posthog/core/src/error-tracking/coercers/error-coercer.ts +8 -2
- package/node_modules/@posthog/core/src/error-tracking/coercers/error-event-coercer.spec.ts +33 -0
- package/node_modules/@posthog/core/src/error-tracking/coercers/error-event-coercer.ts +13 -6
- package/node_modules/@posthog/core/src/error-tracking/error-properties-builder.coerce.spec.ts +15 -0
- package/node_modules/@posthog/core/src/error-tracking/parsers/base.spec.ts +34 -0
- package/node_modules/@posthog/core/src/error-tracking/parsers/base.ts +10 -2
- package/node_modules/@posthog/core/src/posthog-core.ts +1 -0
- package/node_modules/@zuplo/core/customer.cli.minified.js +239 -239
- package/node_modules/@zuplo/core/index.minified.js +253 -253
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/chunk-NHSMO7UN.js +409 -0
- package/node_modules/@zuplo/runtime/out/esm/chunk-NHSMO7UN.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/types/index.d.ts +108 -69
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/node_modules/negotiator/lib/accept.js +54 -0
- package/node_modules/negotiator/lib/charset.js +10 -34
- package/node_modules/negotiator/lib/encoding.js +9 -30
- package/node_modules/negotiator/lib/language.js +15 -36
- package/node_modules/negotiator/lib/mediaType.js +16 -134
- package/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
- package/node_modules/negotiator/node_modules/content-type/README.md +71 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/negotiator/node_modules/content-type/package.json +52 -0
- package/node_modules/negotiator/package.json +16 -10
- package/package.json +13 -6
- package/node_modules/@inquirer/external-editor/dist/errors/CreateFileError.d.ts +0 -10
- package/node_modules/@inquirer/external-editor/dist/errors/CreateFileError.js +0 -13
- package/node_modules/@inquirer/external-editor/dist/errors/LaunchEditorError.d.ts +0 -10
- package/node_modules/@inquirer/external-editor/dist/errors/LaunchEditorError.js +0 -13
- package/node_modules/@inquirer/external-editor/dist/errors/ReadFileError.d.ts +0 -10
- package/node_modules/@inquirer/external-editor/dist/errors/ReadFileError.js +0 -13
- package/node_modules/@inquirer/external-editor/dist/errors/RemoveFileError.d.ts +0 -10
- package/node_modules/@inquirer/external-editor/dist/errors/RemoveFileError.js +0 -13
- package/node_modules/@zuplo/runtime/out/esm/chunk-YOMMW6SX.js +0 -409
- package/node_modules/@zuplo/runtime/out/esm/chunk-YOMMW6SX.js.map +0 -1
- package/node_modules/negotiator/HISTORY.md +0 -114
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-YOMMW6SX.js.LEGAL.txt → chunk-NHSMO7UN.js.LEGAL.txt} +0 -0
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import editor from "./cmds/editor.js";
|
|
|
19
19
|
import info from "./cmds/info.js";
|
|
20
20
|
import init from "./cmds/init.js";
|
|
21
21
|
import link from "./cmds/link.js";
|
|
22
|
+
import lint from "./cmds/lint.js";
|
|
22
23
|
import list from "./cmds/list.js";
|
|
23
24
|
import login from "./cmds/login.js";
|
|
24
25
|
import logout from "./cmds/logout.js";
|
|
@@ -88,6 +89,7 @@ if (gte(process.versions.node, MIN_NODE_VERSION)) {
|
|
|
88
89
|
.command(editor)
|
|
89
90
|
.command(info)
|
|
90
91
|
.command(init)
|
|
92
|
+
.command(lint)
|
|
91
93
|
.command(list)
|
|
92
94
|
.command(link)
|
|
93
95
|
.command(login)
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import * as dotenv from \"dotenv\";\n\ndotenv.config();\n\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { gte } from \"semver\";\nimport { hideBin } from \"yargs/helpers\";\nimport yargs from \"yargs/yargs\";\nimport bucket from \"./cmds/bucket/index.js\";\nimport build from \"./cmds/build.js\";\nimport caCertificate from \"./cmds/ca-certificate/index.js\";\nimport compile from \"./cmds/compile.js\";\nimport customDomain from \"./cmds/custom-domain/index.js\";\nimport deleteZup from \"./cmds/delete.js\";\nimport deploy from \"./cmds/deploy.js\";\nimport dev from \"./cmds/dev.js\";\nimport docs from \"./cmds/docs.js\";\nimport editor from \"./cmds/editor.js\";\nimport info from \"./cmds/info.js\";\nimport init from \"./cmds/init.js\";\nimport link from \"./cmds/link.js\";\nimport list from \"./cmds/list.js\";\nimport login from \"./cmds/login.js\";\nimport logout from \"./cmds/logout.js\";\nimport mtlsCertificates from \"./cmds/mtls-certificates/index.js\";\nimport oas from \"./cmds/open-api/index.js\";\nimport project from \"./cmds/project/index.js\";\nimport proxies from \"./cmds/proxies/index.js\";\nimport source from \"./cmds/source/index.js\";\nimport test from \"./cmds/test.js\";\nimport tunnel from \"./cmds/tunnel/index.js\";\nimport variable from \"./cmds/variable/index.js\";\nimport whoami from \"./cmds/whoami.js\";\nimport { captureCliInvocationEvent } from \"./common/analytics/cli-invocation.js\";\nimport { captureError, shutdownAnalytics } from \"./common/analytics/lib.js\";\nimport { ApiError } from \"./common/api/client.js\";\nimport { configureCliDispatcher } from \"./common/cli-dispatcher.js\";\nimport { logger } from \"./common/logger.js\";\nimport { checkPnpmLifecycle } from \"./common/middleware/check-pnpm-lifecycle.js\";\nimport { logLevel } from \"./common/middleware/logging.js\";\nimport { warnIfOutdatedVersion, warnNodeVersion } from \"./common/outdated.js\";\nimport setBlocking, {\n printCriticalFailureToConsole,\n printCriticalFailureToConsoleAndExit,\n} from \"./common/output.js\";\n\n// This allows us to stop the CLI from executing so we can connect the profiler\n\n// biome-ignore lint/style/noProcessEnv: Migrated from ESLint\nif (process.env.ZUPLO_CLI_PROFILING) {\n await confirm({ message: \"Continue executing CLI?\", default: true });\n}\n\n// The CLI requires Node.js 24 or newer, enforced as a hard floor. Our docs\n// tell people to run `npx @zuplo/cli@latest` (including from CI/CD jobs), so\n// anything older stops here with the actionable message below rather than\n// failing later on unsupported syntax.\n// RECOMMENDED matches MIN, so warnNodeVersion() has nothing to warn about today:\n// it only runs once current >= MIN, and warns when current < RECOMMENDED. To add\n// a soft tier later, raise RECOMMENDED ABOVE MIN — versions in between then warn\n// instead of failing.\nconst MIN_NODE_VERSION = \"24.0.0\";\nconst RECOMMENDED_NODE_VERSION = \"24.0.0\";\n\nif (gte(process.versions.node, MIN_NODE_VERSION)) {\n let cliVersion: string;\n try {\n const packageJson = JSON.parse(\n readFileSync(\n fileURLToPath(new URL(\"../package.json\", import.meta.url)),\n \"utf-8\"\n )\n );\n cliVersion = packageJson.version;\n } catch (e) {\n cliVersion = \"0.0.0\";\n logger.error(e);\n await printCriticalFailureToConsoleAndExit(\n `Unable to load @zuplo/cli. The package.json is missing or malformed.`\n );\n }\n\n await warnNodeVersion(RECOMMENDED_NODE_VERSION);\n\n // Install CLI identity headers on undici's global dispatcher before any\n // command handlers run fetch.\n configureCliDispatcher(cliVersion);\n\n const cli = yargs(hideBin(process.argv))\n // This means that all env vars will have to be prefixed with ZUPLO_\n .env(\"ZUPLO\")\n .option(\"prompt\", {\n type: \"boolean\",\n describe: \"Bypass confirmation prompts\",\n default: true,\n hidden: true,\n })\n .option(\"verbose\", {\n alias: \"v\",\n type: \"count\",\n describe: \"Increase verbosity level (-v, -vv, -vvv)\",\n default: 0,\n })\n // setBlocking forces synchronous TTY writes so error messages flush before\n // process.exit. Runs first so subsequent middleware (including the\n // preflight, which can exit) benefit from it.\n .middleware(setBlocking)\n .middleware(logLevel)\n .middleware(checkPnpmLifecycle)\n .middleware((argv) => {\n void captureCliInvocationEvent(argv, cliVersion);\n })\n .command(caCertificate)\n .command(compile)\n .command(customDomain)\n .command(deleteZup) // delete is a reserved keyword in JavaScript, so we call this function deleteZup\n .command(deploy)\n .command(dev)\n .command(docs)\n .command(editor)\n .command(info)\n .command(init)\n .command(list)\n .command(link)\n .command(login)\n .command(logout)\n .command(test)\n .command(oas)\n .command(mtlsCertificates)\n .command(project)\n .command(source)\n .command(tunnel)\n .command(variable)\n .command(build)\n .command(bucket)\n .command(proxies)\n .command(whoami)\n .demandCommand()\n .strictCommands()\n .version(cliVersion)\n .fail(false)\n .help();\n\n let exitCode = 0;\n try {\n await cli.argv;\n\n // Don't block\n void warnIfOutdatedVersion(cliVersion);\n } catch (err) {\n exitCode = 1;\n if (err instanceof Error) {\n await captureError(err);\n }\n if (err instanceof ApiError) {\n // The API client has already logged the structured error and printed\n // a user-facing diagnostic. Nothing more to display here.\n } else {\n printCriticalFailureToConsole(err.message ?? err);\n cli.showHelp();\n }\n } finally {\n await shutdownAnalytics();\n process.exit(exitCode);\n }\n} else {\n await printCriticalFailureToConsoleAndExit(\n `The Zuplo CLI requires at least node.js v${MIN_NODE_VERSION}. You are using v${process.versions.node}. Please update your version of node.js.\n\n Consider using a Node.js version manager such as https://github.com/nvm-sh/nvm.`\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import * as dotenv from \"dotenv\";\n\ndotenv.config();\n\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { gte } from \"semver\";\nimport { hideBin } from \"yargs/helpers\";\nimport yargs from \"yargs/yargs\";\nimport bucket from \"./cmds/bucket/index.js\";\nimport build from \"./cmds/build.js\";\nimport caCertificate from \"./cmds/ca-certificate/index.js\";\nimport compile from \"./cmds/compile.js\";\nimport customDomain from \"./cmds/custom-domain/index.js\";\nimport deleteZup from \"./cmds/delete.js\";\nimport deploy from \"./cmds/deploy.js\";\nimport dev from \"./cmds/dev.js\";\nimport docs from \"./cmds/docs.js\";\nimport editor from \"./cmds/editor.js\";\nimport info from \"./cmds/info.js\";\nimport init from \"./cmds/init.js\";\nimport link from \"./cmds/link.js\";\nimport lint from \"./cmds/lint.js\";\nimport list from \"./cmds/list.js\";\nimport login from \"./cmds/login.js\";\nimport logout from \"./cmds/logout.js\";\nimport mtlsCertificates from \"./cmds/mtls-certificates/index.js\";\nimport oas from \"./cmds/open-api/index.js\";\nimport project from \"./cmds/project/index.js\";\nimport proxies from \"./cmds/proxies/index.js\";\nimport source from \"./cmds/source/index.js\";\nimport test from \"./cmds/test.js\";\nimport tunnel from \"./cmds/tunnel/index.js\";\nimport variable from \"./cmds/variable/index.js\";\nimport whoami from \"./cmds/whoami.js\";\nimport { captureCliInvocationEvent } from \"./common/analytics/cli-invocation.js\";\nimport { captureError, shutdownAnalytics } from \"./common/analytics/lib.js\";\nimport { ApiError } from \"./common/api/client.js\";\nimport { configureCliDispatcher } from \"./common/cli-dispatcher.js\";\nimport { logger } from \"./common/logger.js\";\nimport { checkPnpmLifecycle } from \"./common/middleware/check-pnpm-lifecycle.js\";\nimport { logLevel } from \"./common/middleware/logging.js\";\nimport { warnIfOutdatedVersion, warnNodeVersion } from \"./common/outdated.js\";\nimport setBlocking, {\n printCriticalFailureToConsole,\n printCriticalFailureToConsoleAndExit,\n} from \"./common/output.js\";\n\n// This allows us to stop the CLI from executing so we can connect the profiler\n\n// biome-ignore lint/style/noProcessEnv: Migrated from ESLint\nif (process.env.ZUPLO_CLI_PROFILING) {\n await confirm({ message: \"Continue executing CLI?\", default: true });\n}\n\n// The CLI requires Node.js 24 or newer, enforced as a hard floor. Our docs\n// tell people to run `npx @zuplo/cli@latest` (including from CI/CD jobs), so\n// anything older stops here with the actionable message below rather than\n// failing later on unsupported syntax.\n// RECOMMENDED matches MIN, so warnNodeVersion() has nothing to warn about today:\n// it only runs once current >= MIN, and warns when current < RECOMMENDED. To add\n// a soft tier later, raise RECOMMENDED ABOVE MIN — versions in between then warn\n// instead of failing.\nconst MIN_NODE_VERSION = \"24.0.0\";\nconst RECOMMENDED_NODE_VERSION = \"24.0.0\";\n\nif (gte(process.versions.node, MIN_NODE_VERSION)) {\n let cliVersion: string;\n try {\n const packageJson = JSON.parse(\n readFileSync(\n fileURLToPath(new URL(\"../package.json\", import.meta.url)),\n \"utf-8\"\n )\n );\n cliVersion = packageJson.version;\n } catch (e) {\n cliVersion = \"0.0.0\";\n logger.error(e);\n await printCriticalFailureToConsoleAndExit(\n `Unable to load @zuplo/cli. The package.json is missing or malformed.`\n );\n }\n\n await warnNodeVersion(RECOMMENDED_NODE_VERSION);\n\n // Install CLI identity headers on undici's global dispatcher before any\n // command handlers run fetch.\n configureCliDispatcher(cliVersion);\n\n const cli = yargs(hideBin(process.argv))\n // This means that all env vars will have to be prefixed with ZUPLO_\n .env(\"ZUPLO\")\n .option(\"prompt\", {\n type: \"boolean\",\n describe: \"Bypass confirmation prompts\",\n default: true,\n hidden: true,\n })\n .option(\"verbose\", {\n alias: \"v\",\n type: \"count\",\n describe: \"Increase verbosity level (-v, -vv, -vvv)\",\n default: 0,\n })\n // setBlocking forces synchronous TTY writes so error messages flush before\n // process.exit. Runs first so subsequent middleware (including the\n // preflight, which can exit) benefit from it.\n .middleware(setBlocking)\n .middleware(logLevel)\n .middleware(checkPnpmLifecycle)\n .middleware((argv) => {\n void captureCliInvocationEvent(argv, cliVersion);\n })\n .command(caCertificate)\n .command(compile)\n .command(customDomain)\n .command(deleteZup) // delete is a reserved keyword in JavaScript, so we call this function deleteZup\n .command(deploy)\n .command(dev)\n .command(docs)\n .command(editor)\n .command(info)\n .command(init)\n .command(lint)\n .command(list)\n .command(link)\n .command(login)\n .command(logout)\n .command(test)\n .command(oas)\n .command(mtlsCertificates)\n .command(project)\n .command(source)\n .command(tunnel)\n .command(variable)\n .command(build)\n .command(bucket)\n .command(proxies)\n .command(whoami)\n .demandCommand()\n .strictCommands()\n .version(cliVersion)\n .fail(false)\n .help();\n\n let exitCode = 0;\n try {\n await cli.argv;\n\n // Don't block\n void warnIfOutdatedVersion(cliVersion);\n } catch (err) {\n exitCode = 1;\n if (err instanceof Error) {\n await captureError(err);\n }\n if (err instanceof ApiError) {\n // The API client has already logged the structured error and printed\n // a user-facing diagnostic. Nothing more to display here.\n } else {\n printCriticalFailureToConsole(err.message ?? err);\n cli.showHelp();\n }\n } finally {\n await shutdownAnalytics();\n process.exit(exitCode);\n }\n} else {\n await printCriticalFailureToConsoleAndExit(\n `The Zuplo CLI requires at least node.js v${MIN_NODE_VERSION}. You are using v${process.versions.node}. Please update your version of node.js.\n\n Consider using a Node.js version manager such as https://github.com/nvm-sh/nvm.`\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/cmds/lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAUV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA2Df,OAAO;;AA9D/B,wBAkEE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { captureEvent } from "../common/analytics/lib.js";
|
|
2
|
+
import { identify } from "../common/middleware/user-identification.js";
|
|
3
|
+
import { ZuploProjectValidator } from "../common/validators/file-system-validator.js";
|
|
4
|
+
import { YargsChecker } from "../common/validators/lib.js";
|
|
5
|
+
import { lint } from "../lint/handler.js";
|
|
6
|
+
export default {
|
|
7
|
+
desc: "Lints your OpenAPI specs and policies for errors and Zuplo conventions",
|
|
8
|
+
command: "lint",
|
|
9
|
+
builder: (yargs) => {
|
|
10
|
+
return yargs
|
|
11
|
+
.usage("$0 lint [options]")
|
|
12
|
+
.option("dir", {
|
|
13
|
+
type: "string",
|
|
14
|
+
describe: "The directory containing your Zuplo API",
|
|
15
|
+
default: ".",
|
|
16
|
+
normalize: true,
|
|
17
|
+
})
|
|
18
|
+
.option("config", {
|
|
19
|
+
type: "string",
|
|
20
|
+
describe: "Path to a lint config file. Defaults to zuplo.lint.jsonc or zuplo.lint.json in the project directory.",
|
|
21
|
+
normalize: true,
|
|
22
|
+
})
|
|
23
|
+
.option("format", {
|
|
24
|
+
type: "string",
|
|
25
|
+
describe: "Output format",
|
|
26
|
+
choices: ["text", "json", "sarif"],
|
|
27
|
+
default: "text",
|
|
28
|
+
})
|
|
29
|
+
.option("fail-on", {
|
|
30
|
+
type: "string",
|
|
31
|
+
describe: "Severity threshold that fails the command. Defaults to the failOn value in your lint config, or 'error'.",
|
|
32
|
+
choices: ["error", "warn", "none"],
|
|
33
|
+
})
|
|
34
|
+
.option("fix", {
|
|
35
|
+
type: "boolean",
|
|
36
|
+
describe: "Rewrite your OpenAPI files to fix what can be fixed automatically, then report what is left",
|
|
37
|
+
default: false,
|
|
38
|
+
})
|
|
39
|
+
.option("lint-binary", {
|
|
40
|
+
type: "string",
|
|
41
|
+
describe: "Path to a zuplo-lint executable to use instead of the one installed with the CLI",
|
|
42
|
+
normalize: true,
|
|
43
|
+
hidden: true,
|
|
44
|
+
})
|
|
45
|
+
.example([
|
|
46
|
+
["$0 lint", "Lint the project in the current directory"],
|
|
47
|
+
["$0 lint --fix", "Apply the fixes that can be made automatically"],
|
|
48
|
+
[
|
|
49
|
+
"$0 lint --fail-on warn",
|
|
50
|
+
"Fail the command on warnings as well as errors",
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"$0 lint --format sarif > results.sarif",
|
|
54
|
+
"Emit SARIF for GitHub Code Scanning",
|
|
55
|
+
],
|
|
56
|
+
])
|
|
57
|
+
.check(async (argv) => {
|
|
58
|
+
return await new YargsChecker(new ZuploProjectValidator()).check(argv);
|
|
59
|
+
})
|
|
60
|
+
.middleware([identify]);
|
|
61
|
+
},
|
|
62
|
+
handler: async (argv) => {
|
|
63
|
+
await captureEvent({ argv, event: "zuplo lint" });
|
|
64
|
+
await lint(argv);
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=lint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/cmds/lint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAa,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAErD,eAAe;IACb,IAAI,EAAE,wEAAwE;IAC9E,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,mBAAmB,CAAC;aAC1B,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,yCAAyC;YACnD,OAAO,EAAE,GAAG;YACZ,SAAS,EAAE,IAAI;SAChB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,uGAAuG;YACzG,SAAS,EAAE,IAAI;SAChB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,eAAe;YACzB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC;YAClC,OAAO,EAAE,MAAM;SAChB,CAAC;aACD,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,0GAA0G;YAC5G,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC;SACnC,CAAC;aACD,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,SAAS;YACf,QAAQ,EACN,6FAA6F;YAC/F,OAAO,EAAE,KAAK;SACf,CAAC;aACD,MAAM,CAAC,aAAa,EAAE;YACrB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,kFAAkF;YACpF,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,IAAI;SACb,CAAC;aACD,OAAO,CAAC;YACP,CAAC,SAAS,EAAE,2CAA2C,CAAC;YACxD,CAAC,eAAe,EAAE,gDAAgD,CAAC;YACnE;gBACE,wBAAwB;gBACxB,gDAAgD;aACjD;YACD;gBACE,wCAAwC;gBACxC,qCAAqC;aACtC;SACF,CAAC;aACD,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACpB,OAAO,MAAM,IAAI,YAAY,CAC3B,IAAI,qBAAqB,EAAE,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 { ZuploProjectValidator } from \"../common/validators/file-system-validator.js\";\nimport { YargsChecker } from \"../common/validators/lib.js\";\nimport { Arguments, lint } from \"../lint/handler.js\";\n\nexport default {\n desc: \"Lints your OpenAPI specs and policies for errors and Zuplo conventions\",\n command: \"lint\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 lint [options]\")\n .option(\"dir\", {\n type: \"string\",\n describe: \"The directory containing your Zuplo API\",\n default: \".\",\n normalize: true,\n })\n .option(\"config\", {\n type: \"string\",\n describe:\n \"Path to a lint config file. Defaults to zuplo.lint.jsonc or zuplo.lint.json in the project directory.\",\n normalize: true,\n })\n .option(\"format\", {\n type: \"string\",\n describe: \"Output format\",\n choices: [\"text\", \"json\", \"sarif\"],\n default: \"text\",\n })\n .option(\"fail-on\", {\n type: \"string\",\n describe:\n \"Severity threshold that fails the command. Defaults to the failOn value in your lint config, or 'error'.\",\n choices: [\"error\", \"warn\", \"none\"],\n })\n .option(\"fix\", {\n type: \"boolean\",\n describe:\n \"Rewrite your OpenAPI files to fix what can be fixed automatically, then report what is left\",\n default: false,\n })\n .option(\"lint-binary\", {\n type: \"string\",\n describe:\n \"Path to a zuplo-lint executable to use instead of the one installed with the CLI\",\n normalize: true,\n hidden: true,\n })\n .example([\n [\"$0 lint\", \"Lint the project in the current directory\"],\n [\"$0 lint --fix\", \"Apply the fixes that can be made automatically\"],\n [\n \"$0 lint --fail-on warn\",\n \"Fail the command on warnings as well as errors\",\n ],\n [\n \"$0 lint --format sarif > results.sarif\",\n \"Emit SARIF for GitHub Code Scanning\",\n ],\n ])\n .check(async (argv) => {\n return await new YargsChecker<typeof argv>(\n new ZuploProjectValidator()\n ).check(argv);\n })\n .middleware([identify]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo lint\" });\n await lint(argv as Arguments);\n },\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/lint/handler.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AASD,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,iBAqDzC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import { shutdownAnalytics } from "../common/analytics/lib.js";
|
|
4
|
+
import { printCriticalFailureToConsole } from "../common/output.js";
|
|
5
|
+
import { LintBinaryNotFoundError, resolveLintBinary, } from "./resolve-binary.js";
|
|
6
|
+
const EXIT_VIOLATIONS_FOUND = 1;
|
|
7
|
+
const EXIT_RUN_FAILED = 2;
|
|
8
|
+
export async function lint(argv) {
|
|
9
|
+
let binary;
|
|
10
|
+
try {
|
|
11
|
+
binary = resolveLintBinary({ override: argv.lintBinary });
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err instanceof LintBinaryNotFoundError) {
|
|
15
|
+
printCriticalFailureToConsole(err.message);
|
|
16
|
+
await exit(EXIT_RUN_FAILED);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
const args = ["--dir", path.resolve(argv.dir), "--format", argv.format];
|
|
22
|
+
if (argv.config) {
|
|
23
|
+
args.push("--config", path.resolve(argv.config));
|
|
24
|
+
}
|
|
25
|
+
if (argv.failOn) {
|
|
26
|
+
args.push("--fail-on", argv.failOn);
|
|
27
|
+
}
|
|
28
|
+
if (argv.fix) {
|
|
29
|
+
args.push("--fix");
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await execa(binary, args, { stdio: "inherit" });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
catch (cause) {
|
|
36
|
+
const exitCode = childExitCode(cause);
|
|
37
|
+
if (exitCode === undefined) {
|
|
38
|
+
printCriticalFailureToConsole(`Could not run the linter at ${binary}.\n` +
|
|
39
|
+
`${cause instanceof Error ? cause.message : String(cause)}`);
|
|
40
|
+
await exit(EXIT_RUN_FAILED);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (exitCode !== EXIT_VIOLATIONS_FOUND) {
|
|
44
|
+
printCriticalFailureToConsole(`Lint failed to run (exit code ${exitCode}).`);
|
|
45
|
+
}
|
|
46
|
+
await exit(exitCode);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function exit(code) {
|
|
50
|
+
await shutdownAnalytics();
|
|
51
|
+
process.exit(code);
|
|
52
|
+
}
|
|
53
|
+
function childExitCode(err) {
|
|
54
|
+
if (err instanceof Error && "exitCode" in err) {
|
|
55
|
+
const { exitCode } = err;
|
|
56
|
+
return typeof exitCode === "number" ? exitCode : undefined;
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/lint/handler.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EACL,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAe7B,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAe;IACxC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,iBAAiB,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,uBAAuB,EAAE,CAAC;YAC3C,6BAA6B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACxE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAED,IAAI,CAAC;QAIH,MAAM,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAEtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,6BAA6B,CAC3B,+BAA+B,MAAM,KAAK;gBACxC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9D,CAAC;YACF,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QAKD,IAAI,QAAQ,KAAK,qBAAqB,EAAE,CAAC;YACvC,6BAA6B,CAC3B,iCAAiC,QAAQ,IAAI,CAC9C,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAQD,KAAK,UAAU,IAAI,CAAC,IAAY;IAC9B,MAAM,iBAAiB,EAAE,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAOD,SAAS,aAAa,CAAC,GAAY;IACjC,IAAI,GAAG,YAAY,KAAK,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;QAC9C,MAAM,EAAE,QAAQ,EAAE,GAAG,GAA4B,CAAC;QAClD,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import path from \"node:path\";\nimport { execa } from \"execa\";\nimport { shutdownAnalytics } from \"../common/analytics/lib.js\";\nimport { printCriticalFailureToConsole } from \"../common/output.js\";\nimport {\n LintBinaryNotFoundError,\n resolveLintBinary,\n} from \"./resolve-binary.js\";\n\nexport interface Arguments {\n dir: string;\n config?: string;\n format: string;\n failOn?: string;\n fix: boolean;\n lintBinary?: string;\n}\n\n/**\n * Exit codes, matching the linter's own contract so CI can tell the two apart:\n * 1 means the project has violations, 2 means the linter could not run.\n */\nconst EXIT_VIOLATIONS_FOUND = 1;\nconst EXIT_RUN_FAILED = 2;\n\nexport async function lint(argv: Arguments) {\n let binary: string;\n try {\n binary = resolveLintBinary({ override: argv.lintBinary });\n } catch (err) {\n if (err instanceof LintBinaryNotFoundError) {\n printCriticalFailureToConsole(err.message);\n await exit(EXIT_RUN_FAILED);\n return;\n }\n throw err;\n }\n\n const args = [\"--dir\", path.resolve(argv.dir), \"--format\", argv.format];\n if (argv.config) {\n args.push(\"--config\", path.resolve(argv.config));\n }\n if (argv.failOn) {\n args.push(\"--fail-on\", argv.failOn);\n }\n if (argv.fix) {\n args.push(\"--fix\");\n }\n\n try {\n // The linter writes its own report — results to stdout, diagnostics to\n // stderr — so inherit the streams rather than buffering and re-printing.\n // That also leaves its color and TTY detection intact.\n await execa(binary, args, { stdio: \"inherit\" });\n return;\n } catch (cause) {\n const exitCode = childExitCode(cause);\n\n if (exitCode === undefined) {\n printCriticalFailureToConsole(\n `Could not run the linter at ${binary}.\\n` +\n `${cause instanceof Error ? cause.message : String(cause)}`\n );\n await exit(EXIT_RUN_FAILED);\n return;\n }\n\n // Anything other than \"violations found\" means the linter itself failed.\n // Its diagnostic already went to stderr, but on its own that reads like a\n // lint result rather than a broken invocation.\n if (exitCode !== EXIT_VIOLATIONS_FOUND) {\n printCriticalFailureToConsole(\n `Lint failed to run (exit code ${exitCode}).`\n );\n }\n\n await exit(exitCode);\n }\n}\n\n/**\n * Exit with the linter's own status rather than throwing. Throwing would send\n * this through cli.ts's catch, which prints a redundant error and dumps the\n * help text on top of a report the user has already read. Matches how\n * `zuplo test` propagates a failing run.\n */\nasync function exit(code: number): Promise<never> {\n await shutdownAnalytics();\n process.exit(code);\n}\n\n/**\n * The child's exit status, or undefined when the process never ran. execa types\n * `exitCode` as a number, but a spawn failure — the file is not executable, or\n * is a binary for another architecture — produces an error without one.\n */\nfunction childExitCode(err: unknown): number | undefined {\n if (err instanceof Error && \"exitCode\" in err) {\n const { exitCode } = err as { exitCode: unknown };\n return typeof exitCode === \"number\" ? exitCode : undefined;\n }\n return undefined;\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function lintPackageName(
|
|
2
|
+
platform?: NodeJS.Platform,
|
|
3
|
+
arch?: string
|
|
4
|
+
): string;
|
|
5
|
+
export declare class LintBinaryNotFoundError extends Error {
|
|
6
|
+
readonly packageName: string;
|
|
7
|
+
constructor(message: string, packageName: string);
|
|
8
|
+
}
|
|
9
|
+
export interface ResolveLintBinaryOptions {
|
|
10
|
+
override?: string;
|
|
11
|
+
platform?: NodeJS.Platform;
|
|
12
|
+
arch?: string;
|
|
13
|
+
resolveFrom?: string;
|
|
14
|
+
devBinaryPath?: string;
|
|
15
|
+
fileExists?: (filePath: string) => boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveLintBinary(
|
|
18
|
+
options?: ResolveLintBinaryOptions
|
|
19
|
+
): string;
|
|
20
|
+
//# sourceMappingURL=resolve-binary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-binary.d.ts","sourceRoot":"","sources":["../../src/lint/resolve-binary.ts"],"names":[],"mappings":"AAaA,wBAAgB,eAAe,CAC7B,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,IAAI,GAAE,MAAqB,GAC1B,MAAM,CAER;AAOD,qBAAa,uBAAwB,SAAQ,KAAK;aAG9B,WAAW,EAAE,MAAM;gBADnC,OAAO,EAAE,MAAM,EACC,WAAW,EAAE,MAAM;CAMtC;AAED,MAAM,WAAW,wBAAwB;IAMvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAQd,WAAW,CAAC,EAAE,MAAM,CAAC;IAMrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5C;AAQD,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,wBAA6B,GACrC,MAAM,CA8CR"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
export function lintPackageName(platform = process.platform, arch = process.arch) {
|
|
6
|
+
return `@zuplo/lint-${platform}-${arch}`;
|
|
7
|
+
}
|
|
8
|
+
function binaryFileName(platform = process.platform) {
|
|
9
|
+
return platform === "win32" ? "zuplo-lint.exe" : "zuplo-lint";
|
|
10
|
+
}
|
|
11
|
+
export class LintBinaryNotFoundError extends Error {
|
|
12
|
+
packageName;
|
|
13
|
+
constructor(message, packageName) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.packageName = packageName;
|
|
16
|
+
this.name = "LintBinaryNotFoundError";
|
|
17
|
+
Object.setPrototypeOf(this, LintBinaryNotFoundError.prototype);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function resolveLintBinary(options = {}) {
|
|
21
|
+
const { override, platform = process.platform, arch = process.arch, resolveFrom = fileURLToPath(import.meta.url), devBinaryPath = defaultDevBinaryPath(platform), fileExists = existsSync, } = options;
|
|
22
|
+
if (override) {
|
|
23
|
+
const resolved = path.resolve(override);
|
|
24
|
+
if (!fileExists(resolved)) {
|
|
25
|
+
throw new LintBinaryNotFoundError(`No zuplo-lint binary at ${resolved}.\n` +
|
|
26
|
+
`This path came from --lint-binary (or ZUPLO_LINT_BINARY). Point it at a zuplo-lint executable, or unset it to use the binary installed with the CLI.`, lintPackageName(platform, arch));
|
|
27
|
+
}
|
|
28
|
+
return resolved;
|
|
29
|
+
}
|
|
30
|
+
const packageName = lintPackageName(platform, arch);
|
|
31
|
+
const fileName = binaryFileName(platform);
|
|
32
|
+
const fromPackage = resolveFromPackage(packageName, fileName, resolveFrom, fileExists);
|
|
33
|
+
if (fromPackage) {
|
|
34
|
+
return fromPackage;
|
|
35
|
+
}
|
|
36
|
+
if (devBinaryPath && fileExists(devBinaryPath)) {
|
|
37
|
+
return devBinaryPath;
|
|
38
|
+
}
|
|
39
|
+
throw new LintBinaryNotFoundError(`The zuplo-lint binary for your platform (${platform}-${arch}) is not installed.\n` +
|
|
40
|
+
`It ships as the optional dependency ${packageName}. Reinstall the CLI to pick it up:\n` +
|
|
41
|
+
` npm install --force @zuplo/cli\n` +
|
|
42
|
+
`If your install skips optional dependencies (npm install --no-optional, or a lockfile from another platform), install ${packageName} directly, or point --lint-binary at a zuplo-lint executable you provide.`, packageName);
|
|
43
|
+
}
|
|
44
|
+
function resolveFromPackage(packageName, fileName, resolveFrom, fileExists) {
|
|
45
|
+
let manifest;
|
|
46
|
+
try {
|
|
47
|
+
manifest = createRequire(resolveFrom).resolve(`${packageName}/package.json`);
|
|
48
|
+
}
|
|
49
|
+
catch (cause) {
|
|
50
|
+
if (isModuleNotFound(cause)) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
throw new LintBinaryNotFoundError(`The zuplo-lint package ${packageName} is installed but could not be read:\n` +
|
|
54
|
+
`${cause instanceof Error ? cause.message : String(cause)}\n` +
|
|
55
|
+
`Reinstalling usually fixes this:\n` +
|
|
56
|
+
` npm install --force @zuplo/cli`, packageName);
|
|
57
|
+
}
|
|
58
|
+
const candidate = path.join(path.dirname(manifest), "bin", fileName);
|
|
59
|
+
return fileExists(candidate) ? candidate : undefined;
|
|
60
|
+
}
|
|
61
|
+
function isModuleNotFound(err) {
|
|
62
|
+
if (!(err instanceof Error) || !("code" in err)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const { code } = err;
|
|
66
|
+
return code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND";
|
|
67
|
+
}
|
|
68
|
+
function defaultDevBinaryPath(platform) {
|
|
69
|
+
return fileURLToPath(new URL(`../../../../dist/zuplo-lint/${binaryFileName(platform)}`, import.meta.url));
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=resolve-binary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-binary.js","sourceRoot":"","sources":["../../src/lint/resolve-binary.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * The npm package that carries the zuplo-lint binary for a given platform.\n *\n * @zuplo/cli declares every supported platform as an optional dependency with\n * matching `os`/`cpu` fields, so npm installs only the one that fits the\n * consumer's machine. The naming convention is shared with\n * cmd/zuplo-lint/npm-targets.json, which generates those packages.\n */\nexport function lintPackageName(\n platform: NodeJS.Platform = process.platform,\n arch: string = process.arch\n): string {\n return `@zuplo/lint-${platform}-${arch}`;\n}\n\nfunction binaryFileName(platform: NodeJS.Platform = process.platform): string {\n return platform === \"win32\" ? \"zuplo-lint.exe\" : \"zuplo-lint\";\n}\n\n/** Raised when no zuplo-lint binary can be found for the current platform. */\nexport class LintBinaryNotFoundError extends Error {\n constructor(\n message: string,\n public readonly packageName: string\n ) {\n super(message);\n this.name = \"LintBinaryNotFoundError\";\n Object.setPrototypeOf(this, LintBinaryNotFoundError.prototype);\n }\n}\n\nexport interface ResolveLintBinaryOptions {\n /**\n * An explicit binary path, from `--lint-binary` / `ZUPLO_LINT_BINARY`. Used\n * verbatim when set, which is the escape hatch for air-gapped installs and\n * for testing a locally built linter.\n */\n override?: string;\n platform?: NodeJS.Platform;\n arch?: string;\n /**\n * The file path node resolves the platform package relative to — a file, not\n * a directory, because that is what `createRequire` expects (a directory path\n * would be treated as a file and resolve one level too high). Defaults to\n * this module's own location, which is what makes resolution work from a\n * global install.\n */\n resolveFrom?: string;\n /**\n * Repo-local build output (dist/zuplo-lint/zuplo-lint), used when developing\n * in the monorepo where the platform packages are not installed. Resolution\n * falls back to it only after the platform package is not found.\n */\n devBinaryPath?: string;\n fileExists?: (filePath: string) => boolean;\n}\n\n/**\n * Locate the zuplo-lint executable.\n *\n * Order: explicit override, then the platform's optional dependency, then the\n * monorepo's own build output.\n */\nexport function resolveLintBinary(\n options: ResolveLintBinaryOptions = {}\n): string {\n const {\n override,\n platform = process.platform,\n arch = process.arch,\n resolveFrom = fileURLToPath(import.meta.url),\n devBinaryPath = defaultDevBinaryPath(platform),\n fileExists = existsSync,\n } = options;\n\n if (override) {\n const resolved = path.resolve(override);\n if (!fileExists(resolved)) {\n throw new LintBinaryNotFoundError(\n `No zuplo-lint binary at ${resolved}.\\n` +\n `This path came from --lint-binary (or ZUPLO_LINT_BINARY). Point it at a zuplo-lint executable, or unset it to use the binary installed with the CLI.`,\n lintPackageName(platform, arch)\n );\n }\n return resolved;\n }\n\n const packageName = lintPackageName(platform, arch);\n const fileName = binaryFileName(platform);\n\n const fromPackage = resolveFromPackage(\n packageName,\n fileName,\n resolveFrom,\n fileExists\n );\n if (fromPackage) {\n return fromPackage;\n }\n\n if (devBinaryPath && fileExists(devBinaryPath)) {\n return devBinaryPath;\n }\n\n throw new LintBinaryNotFoundError(\n `The zuplo-lint binary for your platform (${platform}-${arch}) is not installed.\\n` +\n `It ships as the optional dependency ${packageName}. Reinstall the CLI to pick it up:\\n` +\n ` npm install --force @zuplo/cli\\n` +\n `If your install skips optional dependencies (npm install --no-optional, or a lockfile from another platform), install ${packageName} directly, or point --lint-binary at a zuplo-lint executable you provide.`,\n packageName\n );\n}\n\n/**\n * Resolve the binary inside the platform package. `require.resolve` on the\n * package's package.json — rather than on the package name — works even though\n * these packages have no `main`/`exports` entry: they contain only a binary.\n *\n * Returns undefined when the package simply is not installed, which is an\n * ordinary outcome: npm skips optional dependencies whose os/cpu do not match,\n * and a `--no-optional` install skips all of them. Any other resolver failure\n * means the package IS there but is unusable, so it is reported rather than\n * folded into the \"not installed\" path — otherwise a corrupt install sends the\n * user looking for a package that is sitting right there.\n */\nfunction resolveFromPackage(\n packageName: string,\n fileName: string,\n resolveFrom: string,\n fileExists: (filePath: string) => boolean\n): string | undefined {\n let manifest: string;\n try {\n manifest = createRequire(resolveFrom).resolve(\n `${packageName}/package.json`\n );\n } catch (cause) {\n if (isModuleNotFound(cause)) {\n return undefined;\n }\n throw new LintBinaryNotFoundError(\n `The zuplo-lint package ${packageName} is installed but could not be read:\\n` +\n `${cause instanceof Error ? cause.message : String(cause)}\\n` +\n `Reinstalling usually fixes this:\\n` +\n ` npm install --force @zuplo/cli`,\n packageName\n );\n }\n\n const candidate = path.join(path.dirname(manifest), \"bin\", fileName);\n return fileExists(candidate) ? candidate : undefined;\n}\n\n/** Whether an error from `require.resolve` means the package is absent. */\nfunction isModuleNotFound(err: unknown): boolean {\n if (!(err instanceof Error) || !(\"code\" in err)) {\n return false;\n }\n const { code } = err as { code: unknown };\n return code === \"MODULE_NOT_FOUND\" || code === \"ERR_MODULE_NOT_FOUND\";\n}\n\n/**\n * Where `nx run zuplo-lint:build` puts the binary, relative to the compiled\n * CLI at packages/cli/dist/lint/. Only meaningful inside the monorepo.\n */\nfunction defaultDevBinaryPath(platform: NodeJS.Platform): string {\n return fileURLToPath(\n new URL(\n `../../../../dist/zuplo-lint/${binaryFileName(platform)}`,\n import.meta.url\n )\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-binary.test.d.ts","sourceRoot":"","sources":["../../src/lint/resolve-binary.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { after, before, describe, it } from "node:test";
|
|
6
|
+
import { LintBinaryNotFoundError, lintPackageName, resolveLintBinary, } from "./resolve-binary.js";
|
|
7
|
+
describe("lintPackageName", () => {
|
|
8
|
+
it("derives the package name from platform and arch", () => {
|
|
9
|
+
assert.strictEqual(lintPackageName("darwin", "arm64"), "@zuplo/lint-darwin-arm64");
|
|
10
|
+
assert.strictEqual(lintPackageName("linux", "x64"), "@zuplo/lint-linux-x64");
|
|
11
|
+
assert.strictEqual(lintPackageName("win32", "x64"), "@zuplo/lint-win32-x64");
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
describe("resolveLintBinary", () => {
|
|
15
|
+
let tmpRoot;
|
|
16
|
+
let overridePath;
|
|
17
|
+
before(() => {
|
|
18
|
+
tmpRoot = realpathSync(mkdtempSync(path.join(tmpdir(), "lint-binary-")));
|
|
19
|
+
overridePath = path.join(tmpRoot, "custom-zuplo-lint");
|
|
20
|
+
writeFileSync(overridePath, "#!/bin/sh\n");
|
|
21
|
+
});
|
|
22
|
+
after(() => {
|
|
23
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
24
|
+
});
|
|
25
|
+
it("uses an explicit override ahead of everything else", () => {
|
|
26
|
+
const devBinaryPath = path.join(tmpRoot, "dev", "zuplo-lint");
|
|
27
|
+
mkdirSync(path.dirname(devBinaryPath), { recursive: true });
|
|
28
|
+
writeFileSync(devBinaryPath, "");
|
|
29
|
+
assert.strictEqual(resolveLintBinary({ override: overridePath, devBinaryPath }), overridePath);
|
|
30
|
+
});
|
|
31
|
+
it("resolves a relative override against the working directory", () => {
|
|
32
|
+
const relative = path.relative(process.cwd(), overridePath);
|
|
33
|
+
assert.strictEqual(resolveLintBinary({ override: relative }), path.resolve(relative));
|
|
34
|
+
});
|
|
35
|
+
it("reports the bad path when the override does not exist", () => {
|
|
36
|
+
const missing = path.join(tmpRoot, "nope");
|
|
37
|
+
assert.throws(() => resolveLintBinary({ override: missing }), (err) => {
|
|
38
|
+
assert.ok(err instanceof LintBinaryNotFoundError);
|
|
39
|
+
assert.match(err.message, /No zuplo-lint binary at/);
|
|
40
|
+
assert.ok(err.message.includes(missing), "expected the resolved path in the message");
|
|
41
|
+
assert.match(err.message, /--lint-binary/);
|
|
42
|
+
return true;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it("falls back to the repo build output when the platform package is absent", () => {
|
|
46
|
+
const devBinaryPath = path.join(tmpRoot, "dist", "zuplo-lint");
|
|
47
|
+
mkdirSync(path.dirname(devBinaryPath), { recursive: true });
|
|
48
|
+
writeFileSync(devBinaryPath, "");
|
|
49
|
+
assert.strictEqual(resolveLintBinary({
|
|
50
|
+
platform: "linux",
|
|
51
|
+
arch: "mips",
|
|
52
|
+
devBinaryPath,
|
|
53
|
+
}), devBinaryPath);
|
|
54
|
+
});
|
|
55
|
+
it("throws an actionable error when nothing is installed", () => {
|
|
56
|
+
assert.throws(() => resolveLintBinary({
|
|
57
|
+
platform: "linux",
|
|
58
|
+
arch: "mips",
|
|
59
|
+
devBinaryPath: path.join(tmpRoot, "does-not-exist"),
|
|
60
|
+
}), (err) => {
|
|
61
|
+
assert.ok(err instanceof LintBinaryNotFoundError);
|
|
62
|
+
assert.strictEqual(err.packageName, "@zuplo/lint-linux-mips");
|
|
63
|
+
assert.match(err.message, /@zuplo\/lint-linux-mips/);
|
|
64
|
+
assert.match(err.message, /linux-mips/);
|
|
65
|
+
assert.match(err.message, /--lint-binary/);
|
|
66
|
+
return true;
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
it("finds the binary inside an installed platform package", () => {
|
|
70
|
+
const projectDir = path.join(tmpRoot, "consumer");
|
|
71
|
+
const pkgDir = path.join(projectDir, "node_modules", "@zuplo", "lint-linux-x64");
|
|
72
|
+
mkdirSync(path.join(pkgDir, "bin"), { recursive: true });
|
|
73
|
+
writeFileSync(path.join(pkgDir, "package.json"), JSON.stringify({ name: "@zuplo/lint-linux-x64", version: "1.0.0" }));
|
|
74
|
+
const binPath = path.join(pkgDir, "bin", "zuplo-lint");
|
|
75
|
+
writeFileSync(binPath, "");
|
|
76
|
+
const resolved = resolveLintBinary({
|
|
77
|
+
platform: "linux",
|
|
78
|
+
arch: "x64",
|
|
79
|
+
resolveFrom: path.join(projectDir, "index.js"),
|
|
80
|
+
devBinaryPath: path.join(tmpRoot, "does-not-exist"),
|
|
81
|
+
});
|
|
82
|
+
assert.strictEqual(resolved, binPath);
|
|
83
|
+
});
|
|
84
|
+
it("looks for the .exe on Windows", () => {
|
|
85
|
+
const projectDir = path.join(tmpRoot, "consumer-win");
|
|
86
|
+
const pkgDir = path.join(projectDir, "node_modules", "@zuplo", "lint-win32-x64");
|
|
87
|
+
mkdirSync(path.join(pkgDir, "bin"), { recursive: true });
|
|
88
|
+
writeFileSync(path.join(pkgDir, "package.json"), JSON.stringify({ name: "@zuplo/lint-win32-x64", version: "1.0.0" }));
|
|
89
|
+
const binPath = path.join(pkgDir, "bin", "zuplo-lint.exe");
|
|
90
|
+
writeFileSync(binPath, "");
|
|
91
|
+
const resolved = resolveLintBinary({
|
|
92
|
+
platform: "win32",
|
|
93
|
+
arch: "x64",
|
|
94
|
+
resolveFrom: path.join(projectDir, "index.js"),
|
|
95
|
+
devBinaryPath: path.join(tmpRoot, "does-not-exist"),
|
|
96
|
+
});
|
|
97
|
+
assert.strictEqual(resolved, binPath);
|
|
98
|
+
});
|
|
99
|
+
it("reports a package that is present but unreadable, instead of calling it missing", () => {
|
|
100
|
+
const projectDir = path.join(tmpRoot, "consumer-corrupt");
|
|
101
|
+
const pkgDir = path.join(projectDir, "node_modules", "@zuplo", "lint-linux-x64");
|
|
102
|
+
mkdirSync(path.join(pkgDir, "bin"), { recursive: true });
|
|
103
|
+
writeFileSync(path.join(pkgDir, "package.json"), JSON.stringify({
|
|
104
|
+
name: "@zuplo/lint-linux-x64",
|
|
105
|
+
version: "1.0.0",
|
|
106
|
+
exports: { "./bin/*": "./bin/*" },
|
|
107
|
+
}));
|
|
108
|
+
writeFileSync(path.join(pkgDir, "bin", "zuplo-lint"), "");
|
|
109
|
+
const devBinaryPath = path.join(tmpRoot, "dist", "zuplo-lint");
|
|
110
|
+
mkdirSync(path.dirname(devBinaryPath), { recursive: true });
|
|
111
|
+
writeFileSync(devBinaryPath, "");
|
|
112
|
+
assert.throws(() => resolveLintBinary({
|
|
113
|
+
platform: "linux",
|
|
114
|
+
arch: "x64",
|
|
115
|
+
resolveFrom: path.join(projectDir, "index.js"),
|
|
116
|
+
devBinaryPath,
|
|
117
|
+
}), (err) => {
|
|
118
|
+
assert.ok(err instanceof LintBinaryNotFoundError);
|
|
119
|
+
assert.match(err.message, /installed but could not be read/);
|
|
120
|
+
assert.strictEqual(err.packageName, "@zuplo/lint-linux-x64");
|
|
121
|
+
return true;
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
it("treats a genuinely absent package as not installed, not an error to rethrow", () => {
|
|
125
|
+
const projectDir = path.join(tmpRoot, "consumer-absent");
|
|
126
|
+
mkdirSync(projectDir, { recursive: true });
|
|
127
|
+
const devBinaryPath = path.join(tmpRoot, "dist", "zuplo-lint");
|
|
128
|
+
mkdirSync(path.dirname(devBinaryPath), { recursive: true });
|
|
129
|
+
writeFileSync(devBinaryPath, "");
|
|
130
|
+
assert.strictEqual(resolveLintBinary({
|
|
131
|
+
platform: "linux",
|
|
132
|
+
arch: "x64",
|
|
133
|
+
resolveFrom: path.join(projectDir, "index.js"),
|
|
134
|
+
devBinaryPath,
|
|
135
|
+
}), devBinaryPath);
|
|
136
|
+
});
|
|
137
|
+
it("prefers the installed platform package over the repo build output", () => {
|
|
138
|
+
const projectDir = path.join(tmpRoot, "consumer-precedence");
|
|
139
|
+
const pkgDir = path.join(projectDir, "node_modules", "@zuplo", "lint-linux-x64");
|
|
140
|
+
mkdirSync(path.join(pkgDir, "bin"), { recursive: true });
|
|
141
|
+
writeFileSync(path.join(pkgDir, "package.json"), JSON.stringify({ name: "@zuplo/lint-linux-x64", version: "1.0.0" }));
|
|
142
|
+
const binPath = path.join(pkgDir, "bin", "zuplo-lint");
|
|
143
|
+
writeFileSync(binPath, "");
|
|
144
|
+
const devBinaryPath = path.join(tmpRoot, "dist", "zuplo-lint");
|
|
145
|
+
mkdirSync(path.dirname(devBinaryPath), { recursive: true });
|
|
146
|
+
writeFileSync(devBinaryPath, "");
|
|
147
|
+
assert.strictEqual(resolveLintBinary({
|
|
148
|
+
platform: "linux",
|
|
149
|
+
arch: "x64",
|
|
150
|
+
resolveFrom: path.join(projectDir, "index.js"),
|
|
151
|
+
devBinaryPath,
|
|
152
|
+
}), binPath);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=resolve-binary.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-binary.test.js","sourceRoot":"","sources":["../../src/lint/resolve-binary.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport {\n mkdirSync,\n mkdtempSync,\n realpathSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { after, before, describe, it } from \"node:test\";\nimport {\n LintBinaryNotFoundError,\n lintPackageName,\n resolveLintBinary,\n} from \"./resolve-binary.js\";\n\ndescribe(\"lintPackageName\", () => {\n it(\"derives the package name from platform and arch\", () => {\n assert.strictEqual(\n lintPackageName(\"darwin\", \"arm64\"),\n \"@zuplo/lint-darwin-arm64\"\n );\n assert.strictEqual(\n lintPackageName(\"linux\", \"x64\"),\n \"@zuplo/lint-linux-x64\"\n );\n assert.strictEqual(\n lintPackageName(\"win32\", \"x64\"),\n \"@zuplo/lint-win32-x64\"\n );\n });\n});\n\ndescribe(\"resolveLintBinary\", () => {\n let tmpRoot: string;\n let overridePath: string;\n\n before(() => {\n // realpath because require.resolve returns real paths, and on macOS\n // os.tmpdir() is /tmp, a symlink to /private/tmp.\n tmpRoot = realpathSync(mkdtempSync(path.join(tmpdir(), \"lint-binary-\")));\n overridePath = path.join(tmpRoot, \"custom-zuplo-lint\");\n writeFileSync(overridePath, \"#!/bin/sh\\n\");\n });\n\n after(() => {\n rmSync(tmpRoot, { recursive: true, force: true });\n });\n\n it(\"uses an explicit override ahead of everything else\", () => {\n const devBinaryPath = path.join(tmpRoot, \"dev\", \"zuplo-lint\");\n mkdirSync(path.dirname(devBinaryPath), { recursive: true });\n writeFileSync(devBinaryPath, \"\");\n\n assert.strictEqual(\n resolveLintBinary({ override: overridePath, devBinaryPath }),\n overridePath\n );\n });\n\n it(\"resolves a relative override against the working directory\", () => {\n const relative = path.relative(process.cwd(), overridePath);\n\n assert.strictEqual(\n resolveLintBinary({ override: relative }),\n path.resolve(relative)\n );\n });\n\n it(\"reports the bad path when the override does not exist\", () => {\n const missing = path.join(tmpRoot, \"nope\");\n\n assert.throws(\n () => resolveLintBinary({ override: missing }),\n (err: unknown) => {\n assert.ok(err instanceof LintBinaryNotFoundError);\n assert.match(err.message, /No zuplo-lint binary at/);\n assert.ok(\n err.message.includes(missing),\n \"expected the resolved path in the message\"\n );\n // The message has to name the flag, or the user cannot tell where the\n // path came from.\n assert.match(err.message, /--lint-binary/);\n return true;\n }\n );\n });\n\n it(\"falls back to the repo build output when the platform package is absent\", () => {\n const devBinaryPath = path.join(tmpRoot, \"dist\", \"zuplo-lint\");\n mkdirSync(path.dirname(devBinaryPath), { recursive: true });\n writeFileSync(devBinaryPath, \"\");\n\n assert.strictEqual(\n resolveLintBinary({\n platform: \"linux\",\n arch: \"mips\",\n devBinaryPath,\n }),\n devBinaryPath\n );\n });\n\n it(\"throws an actionable error when nothing is installed\", () => {\n assert.throws(\n () =>\n resolveLintBinary({\n platform: \"linux\",\n arch: \"mips\",\n devBinaryPath: path.join(tmpRoot, \"does-not-exist\"),\n }),\n (err: unknown) => {\n assert.ok(err instanceof LintBinaryNotFoundError);\n assert.strictEqual(err.packageName, \"@zuplo/lint-linux-mips\");\n // An unsupported platform must say which package is missing and how to\n // recover, not just that something went wrong.\n assert.match(err.message, /@zuplo\\/lint-linux-mips/);\n assert.match(err.message, /linux-mips/);\n assert.match(err.message, /--lint-binary/);\n return true;\n }\n );\n });\n\n it(\"finds the binary inside an installed platform package\", () => {\n // Lay out a node_modules tree the way npm would, and resolve from a module\n // inside it.\n const projectDir = path.join(tmpRoot, \"consumer\");\n const pkgDir = path.join(\n projectDir,\n \"node_modules\",\n \"@zuplo\",\n \"lint-linux-x64\"\n );\n mkdirSync(path.join(pkgDir, \"bin\"), { recursive: true });\n writeFileSync(\n path.join(pkgDir, \"package.json\"),\n JSON.stringify({ name: \"@zuplo/lint-linux-x64\", version: \"1.0.0\" })\n );\n const binPath = path.join(pkgDir, \"bin\", \"zuplo-lint\");\n writeFileSync(binPath, \"\");\n\n const resolved = resolveLintBinary({\n platform: \"linux\",\n arch: \"x64\",\n resolveFrom: path.join(projectDir, \"index.js\"),\n devBinaryPath: path.join(tmpRoot, \"does-not-exist\"),\n });\n\n assert.strictEqual(resolved, binPath);\n });\n\n it(\"looks for the .exe on Windows\", () => {\n const projectDir = path.join(tmpRoot, \"consumer-win\");\n const pkgDir = path.join(\n projectDir,\n \"node_modules\",\n \"@zuplo\",\n \"lint-win32-x64\"\n );\n mkdirSync(path.join(pkgDir, \"bin\"), { recursive: true });\n writeFileSync(\n path.join(pkgDir, \"package.json\"),\n JSON.stringify({ name: \"@zuplo/lint-win32-x64\", version: \"1.0.0\" })\n );\n const binPath = path.join(pkgDir, \"bin\", \"zuplo-lint.exe\");\n writeFileSync(binPath, \"\");\n\n const resolved = resolveLintBinary({\n platform: \"win32\",\n arch: \"x64\",\n resolveFrom: path.join(projectDir, \"index.js\"),\n devBinaryPath: path.join(tmpRoot, \"does-not-exist\"),\n });\n\n assert.strictEqual(resolved, binPath);\n });\n\n it(\"reports a package that is present but unreadable, instead of calling it missing\", () => {\n // An `exports` map that does not expose ./package.json makes require.resolve\n // fail with ERR_PACKAGE_PATH_NOT_EXPORTED rather than MODULE_NOT_FOUND. The\n // package is right there, so saying \"not installed\" would send the user\n // hunting for something they already have.\n const projectDir = path.join(tmpRoot, \"consumer-corrupt\");\n const pkgDir = path.join(\n projectDir,\n \"node_modules\",\n \"@zuplo\",\n \"lint-linux-x64\"\n );\n mkdirSync(path.join(pkgDir, \"bin\"), { recursive: true });\n writeFileSync(\n path.join(pkgDir, \"package.json\"),\n JSON.stringify({\n name: \"@zuplo/lint-linux-x64\",\n version: \"1.0.0\",\n exports: { \"./bin/*\": \"./bin/*\" },\n })\n );\n writeFileSync(path.join(pkgDir, \"bin\", \"zuplo-lint\"), \"\");\n\n // A dev binary is available, but must NOT be used to paper over this: the\n // consumer's own platform package is broken and they need to know.\n const devBinaryPath = path.join(tmpRoot, \"dist\", \"zuplo-lint\");\n mkdirSync(path.dirname(devBinaryPath), { recursive: true });\n writeFileSync(devBinaryPath, \"\");\n\n assert.throws(\n () =>\n resolveLintBinary({\n platform: \"linux\",\n arch: \"x64\",\n resolveFrom: path.join(projectDir, \"index.js\"),\n devBinaryPath,\n }),\n (err: unknown) => {\n assert.ok(err instanceof LintBinaryNotFoundError);\n assert.match(err.message, /installed but could not be read/);\n assert.strictEqual(err.packageName, \"@zuplo/lint-linux-x64\");\n return true;\n }\n );\n });\n\n it(\"treats a genuinely absent package as not installed, not an error to rethrow\", () => {\n // The counterpart to the test above: MODULE_NOT_FOUND must stay on the\n // ordinary path so the dev fallback still applies.\n const projectDir = path.join(tmpRoot, \"consumer-absent\");\n mkdirSync(projectDir, { recursive: true });\n\n const devBinaryPath = path.join(tmpRoot, \"dist\", \"zuplo-lint\");\n mkdirSync(path.dirname(devBinaryPath), { recursive: true });\n writeFileSync(devBinaryPath, \"\");\n\n assert.strictEqual(\n resolveLintBinary({\n platform: \"linux\",\n arch: \"x64\",\n resolveFrom: path.join(projectDir, \"index.js\"),\n devBinaryPath,\n }),\n devBinaryPath\n );\n });\n\n it(\"prefers the installed platform package over the repo build output\", () => {\n const projectDir = path.join(tmpRoot, \"consumer-precedence\");\n const pkgDir = path.join(\n projectDir,\n \"node_modules\",\n \"@zuplo\",\n \"lint-linux-x64\"\n );\n mkdirSync(path.join(pkgDir, \"bin\"), { recursive: true });\n writeFileSync(\n path.join(pkgDir, \"package.json\"),\n JSON.stringify({ name: \"@zuplo/lint-linux-x64\", version: \"1.0.0\" })\n );\n const binPath = path.join(pkgDir, \"bin\", \"zuplo-lint\");\n writeFileSync(binPath, \"\");\n\n const devBinaryPath = path.join(tmpRoot, \"dist\", \"zuplo-lint\");\n mkdirSync(path.dirname(devBinaryPath), { recursive: true });\n writeFileSync(devBinaryPath, \"\");\n\n assert.strictEqual(\n resolveLintBinary({\n platform: \"linux\",\n arch: \"x64\",\n resolveFrom: path.join(projectDir, \"index.js\"),\n devBinaryPath,\n }),\n binPath\n );\n });\n});\n"]}
|