diff --git a/CHANGELOG.md b/CHANGELOG.md index 19fc2be..237ee44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.7.0] - 2026-06-25 +### Added +- Snippet and full file match comments now link to the matched OSS file (and line range, for snippets) for GitHub-hosted components, instead of only referencing the repository +- Match comments display an informational note when the matched component is registry-sourced (e.g. npm, PyPI), where a browsable source link cannot be generated + +### Notes +- The matched file link is only generated for GitHub-hosted components (where the source `url` points to `github.com`). For components sourced from package registries (e.g. npm, PyPI), the registry version and packaged file paths do not map to a GitHub source location, so these comments keep the repository `Source` and show the note instead + ## [1.6.4] - 2026-06-18 ### Fixed - Corrected copyleft documentation in `README.md`: copyleft is determined by `scanoss.py` (`scanoss-py inspect copyleft`) using the OSADL checklist, including `-or-later` licenses, rather than the internal `license.utils.ts` list @@ -219,4 +227,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [1.6.0]: https://github.com/scanoss/gha-code-scan/compare/v1.5.0...v1.6.0 [1.6.1]: https://github.com/scanoss/gha-code-scan/compare/v1.6.0...v1.6.1 [1.6.2]: https://github.com/scanoss/gha-code-scan/compare/v1.6.1...v1.6.2 -[1.6.3]: https://github.com/scanoss/gha-code-scan/compare/v1.6.2...v1.6.3 \ No newline at end of file +[1.6.3]: https://github.com/scanoss/gha-code-scan/compare/v1.6.2...v1.6.3 +[1.7.0]: https://github.com/scanoss/gha-code-scan/compare/v1.6.3...v1.7.0 \ No newline at end of file diff --git a/README.md b/README.md index f9ebb6b..9a480de 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,16 @@ the output into your custom workflow | result-filepath | Scanner results filepath | | stdout-scan-command | Scanner command output | +## Match Comments + +On pull requests, the action posts a commit comment for each snippet and full file match, including the matched **Component**, **License**, and **Source**. + +- For **GitHub-hosted** components, the comment also includes a **File** link pointing directly to the matched source file. For snippets, the matched **OSS Lines** link to the corresponding line range. +- For components sourced from package registries (e.g. npm, PyPI), a browsable source link cannot be generated — the registry version and packaged file paths do not map to a GitHub source location — so the comment shows a note instead: + +> [!NOTE] +> A browsable source link is not available for registry-sourced components. + ## Scan Tuning Parameters The SCANOSS scan engine supports [scan tuning parameters](https://github.com/scanoss/scanoss.py/blob/main/docs/source/scanoss_settings_schema.rst#scan-tuning-parameters) for snippet matching. diff --git a/__tests__/oss-file-contents.test.ts b/__tests__/oss-file-contents.test.ts new file mode 100644 index 0000000..656bfa7 --- /dev/null +++ b/__tests__/oss-file-contents.test.ts @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +/* + Copyright (c) 2025, SCANOSS + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +jest.mock('@actions/core', () => ({ + debug: jest.fn(), + info: jest.fn(), + warning: jest.fn(), + error: jest.fn() +})); + +const mockInputs = { + API_KEY: 'test-key', + API_URL: 'https://api.osskb.org/scan/direct' +}; + +jest.mock('../src/app.input', () => mockInputs); + +import { fetchOssSnippetBlock, getFileContentsUrl } from '../src/utils/oss-file-contents'; +import { SnippetMatch } from '../src/types/annotations'; + +const baseSnippet: SnippetMatch = { + file: 'src/Folder.ts', + component: 'scanoss', + version: '0.4.4-beta', + matched: '91%', + lines: '5-62', + oss_lines: '2-4', + url: 'https://www.npmjs.com/package/scanoss', + file_hash: 'abcdef123456' +}; + +const FILE_BODY = 'line1\nline2\nline3\nline4\nline5\n'; + +describe('getFileContentsUrl', () => { + it('derives the file_contents endpoint from the configured api.url origin', () => { + expect(getFileContentsUrl('hash123')).toBe('https://api.osskb.org/file_contents/hash123'); + }); +}); + +describe('fetchOssSnippetBlock', () => { + const originalFetch = global.fetch; + + beforeEach(() => { + mockInputs.API_KEY = 'test-key'; + mockInputs.API_URL = 'https://api.osskb.org/scan/direct'; + // Safety net: any test that hits fetch without setting its own mock fails + // loudly instead of reaching the real SCANOSS endpoint. + global.fetch = jest.fn(() => { + throw new Error('Unexpected real fetch call - mock the response in the test'); + }) as unknown as typeof fetch; + }); + + afterEach(() => { + global.fetch = originalFetch; + jest.clearAllMocks(); + }); + + it('returns null when no api.key is configured (premium feature)', async () => { + mockInputs.API_KEY = ''; + const fetchSpy = jest.fn(); + global.fetch = fetchSpy as unknown as typeof fetch; + + const result = await fetchOssSnippetBlock(baseSnippet); + + expect(result).toBeNull(); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('returns null when the match has no file_hash', async () => { + const fetchSpy = jest.fn(); + global.fetch = fetchSpy as unknown as typeof fetch; + + const result = await fetchOssSnippetBlock({ ...baseSnippet, file_hash: undefined }); + + expect(result).toBeNull(); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('returns null and does not throw when the request fails (e.g. 403)', async () => { + global.fetch = jest.fn().mockResolvedValue({ ok: false, status: 403 }) as unknown as typeof fetch; + + const result = await fetchOssSnippetBlock(baseSnippet); + + expect(result).toBeNull(); + }); + + it('returns null when fetch throws', async () => { + global.fetch = jest.fn().mockRejectedValue(new Error('network')) as unknown as typeof fetch; + + const result = await fetchOssSnippetBlock(baseSnippet); + + expect(result).toBeNull(); + }); + + it('inlines the oss_lines slice as a fenced code block with language hint', async () => { + const fetchSpy = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + text: async () => FILE_BODY + }); + global.fetch = fetchSpy as unknown as typeof fetch; + + const result = await fetchOssSnippetBlock(baseSnippet); + + // oss_lines '2-4' -> lines 2,3,4 + expect(result).toBe('\n\n```ts\nline2\nline3\nline4\n```'); + expect(fetchSpy).toHaveBeenCalledWith('https://api.osskb.org/file_contents/abcdef123456', { + headers: { 'X-Session': 'test-key' } + }); + }); + + it('truncates output exceeding the character budget and notes the truncation', async () => { + // 500 lines of 50 chars each (~25 KB) far exceeds the 10 KB budget. + const body = Array.from({ length: 500 }, () => 'x'.repeat(50)).join('\n'); + global.fetch = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + text: async () => body + }) as unknown as typeof fetch; + + const result = await fetchOssSnippetBlock({ ...baseSnippet, oss_lines: 'all' }); + + expect(result).toContain('Output truncated to 10000 characters'); + // The fenced code body stays within the budget... + const fenced = (result ?? '').split('```')[1].replace(/^ts\n/, '').trimEnd(); + expect(fenced.length).toBeLessThanOrEqual(10000); + // ...and is clipped at a line boundary (the last full line is intact) + expect(fenced.endsWith('x')).toBe(true); + expect(fenced.split('\n').every(line => line === 'x'.repeat(50))).toBe(true); + }); +}); diff --git a/dist/index.js b/dist/index.js index 19c688d..5417072 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,4 +1,4 @@ -/*! scanoss-code-scan-action v1.6.4 | MIT */ +/*! scanoss-code-scan-action v1.7.0 | MIT */ "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; @@ -49,8 +49,8 @@ var require_context = __commonJS({ if ((0, fs_1.existsSync)(process.env.GITHUB_EVENT_PATH)) { this.payload = JSON.parse((0, fs_1.readFileSync)(process.env.GITHUB_EVENT_PATH, { encoding: "utf8" })); } else { - const path10 = process.env.GITHUB_EVENT_PATH; - process.stdout.write(`GITHUB_EVENT_PATH ${path10} does not exist${os_1.EOL}`); + const path11 = process.env.GITHUB_EVENT_PATH; + process.stdout.write(`GITHUB_EVENT_PATH ${path11} does not exist${os_1.EOL}`); } } this.eventName = process.env.GITHUB_EVENT_NAME; @@ -872,14 +872,14 @@ var require_util = __commonJS({ } const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80; let origin = url2.origin != null ? url2.origin : `${url2.protocol}//${url2.hostname}:${port}`; - let path10 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`; + let path11 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`; if (origin.endsWith("/")) { origin = origin.substring(0, origin.length - 1); } - if (path10 && !path10.startsWith("/")) { - path10 = `/${path10}`; + if (path11 && !path11.startsWith("/")) { + path11 = `/${path11}`; } - url2 = new URL(origin + path10); + url2 = new URL(origin + path11); } return url2; } @@ -2493,20 +2493,20 @@ var require_parseParams = __commonJS({ var require_basename = __commonJS({ "node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) { "use strict"; - module2.exports = function basename5(path10) { - if (typeof path10 !== "string") { + module2.exports = function basename5(path11) { + if (typeof path11 !== "string") { return ""; } - for (var i = path10.length - 1; i >= 0; --i) { - switch (path10.charCodeAt(i)) { + for (var i = path11.length - 1; i >= 0; --i) { + switch (path11.charCodeAt(i)) { case 47: // '/' case 92: - path10 = path10.slice(i + 1); - return path10 === ".." || path10 === "." ? "" : path10; + path11 = path11.slice(i + 1); + return path11 === ".." || path11 === "." ? "" : path11; } } - return path10 === ".." || path10 === "." ? "" : path10; + return path11 === ".." || path11 === "." ? "" : path11; }; } }); @@ -5536,7 +5536,7 @@ var require_request = __commonJS({ } var Request = class _Request { constructor(origin, { - path: path10, + path: path11, method, body: body2, headers, @@ -5550,11 +5550,11 @@ var require_request = __commonJS({ throwOnError, expectContinue }, handler2) { - if (typeof path10 !== "string") { + if (typeof path11 !== "string") { throw new InvalidArgumentError("path must be a string"); - } else if (path10[0] !== "/" && !(path10.startsWith("http://") || path10.startsWith("https://")) && method !== "CONNECT") { + } else if (path11[0] !== "/" && !(path11.startsWith("http://") || path11.startsWith("https://")) && method !== "CONNECT") { throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.exec(path10) !== null) { + } else if (invalidPathRegex.exec(path11) !== null) { throw new InvalidArgumentError("invalid request path"); } if (typeof method !== "string") { @@ -5617,7 +5617,7 @@ var require_request = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? util3.buildURL(path10, query) : path10; + this.path = query ? util3.buildURL(path11, query) : path11; this.origin = origin; this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; this.blocking = blocking == null ? false : blocking; @@ -6625,9 +6625,9 @@ var require_RedirectHandler = __commonJS({ return this.handler.onHeaders(statusCode, headers, resume, statusText); } const { origin, pathname, search } = util3.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path10 = search ? `${pathname}${search}` : pathname; + const path11 = search ? `${pathname}${search}` : pathname; this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path10; + this.opts.path = path11; this.opts.origin = origin; this.opts.maxRedirections = 0; this.opts.query = null; @@ -7867,7 +7867,7 @@ var require_client = __commonJS({ writeH2(client2, client2[kHTTP2Session], request2); return; } - const { body: body2, method, path: path10, host, upgrade, headers, blocking, reset } = request2; + const { body: body2, method, path: path11, host, upgrade, headers, blocking, reset } = request2; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body2 && typeof body2.read === "function") { body2.read(0); @@ -7917,7 +7917,7 @@ var require_client = __commonJS({ if (blocking) { socket[kBlocking] = true; } - let header = `${method} ${path10} HTTP/1.1\r + let header = `${method} ${path11} HTTP/1.1\r `; if (typeof host === "string") { header += `host: ${host}\r @@ -7980,7 +7980,7 @@ upgrade: ${upgrade}\r return true; } function writeH2(client2, session, request2) { - const { body: body2, method, path: path10, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; + const { body: body2, method, path: path11, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; let headers; if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()); else headers = reqHeaders; @@ -8023,7 +8023,7 @@ upgrade: ${upgrade}\r }); return true; } - headers[HTTP2_HEADER_PATH] = path10; + headers[HTTP2_HEADER_PATH] = path11; headers[HTTP2_HEADER_SCHEME] = "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body2 && typeof body2.read === "function") { @@ -10263,20 +10263,20 @@ var require_mock_utils = __commonJS({ } return true; } - function safeUrl(path10) { - if (typeof path10 !== "string") { - return path10; + function safeUrl(path11) { + if (typeof path11 !== "string") { + return path11; } - const pathSegments = path10.split("?"); + const pathSegments = path11.split("?"); if (pathSegments.length !== 2) { - return path10; + return path11; } const qp = new URLSearchParams(pathSegments.pop()); qp.sort(); return [...pathSegments, qp.toString()].join("?"); } - function matchKey(mockDispatch2, { path: path10, method, body: body2, headers }) { - const pathMatch = matchValue(mockDispatch2.path, path10); + function matchKey(mockDispatch2, { path: path11, method, body: body2, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path11); const methodMatch = matchValue(mockDispatch2.method, method); const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body2) : true; const headersMatch = matchHeaders(mockDispatch2, headers); @@ -10294,7 +10294,7 @@ var require_mock_utils = __commonJS({ function getMockDispatch(mockDispatches, key) { const basePath = key.query ? buildURL(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path10 }) => matchValue(safeUrl(path10), resolvedPath)); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path11 }) => matchValue(safeUrl(path11), resolvedPath)); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -10331,9 +10331,9 @@ var require_mock_utils = __commonJS({ } } function buildKey(opts) { - const { path: path10, method, body: body2, headers, query } = opts; + const { path: path11, method, body: body2, headers, query } = opts; return { - path: path10, + path: path11, method, body: body2, headers, @@ -10782,10 +10782,10 @@ var require_pending_interceptors_formatter = __commonJS({ } format(pendingInterceptors) { const withPrettyHeaders = pendingInterceptors.map( - ({ method, path: path10, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + ({ method, path: path11, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ Method: method, Origin: origin, - Path: path10, + Path: path11, "Status code": statusCode, Persistent: persist ? "\u2705" : "\u274C", Invocations: timesInvoked, @@ -12927,7 +12927,7 @@ var require_fetch = __commonJS({ this.emit("terminated", error2); } }; - function fetch2(input, init = {}) { + function fetch3(input, init = {}) { webidl.argumentLengthCheck(arguments, 1, { header: "globalThis.fetch" }); const p = createDeferredPromise(); let requestObject; @@ -13857,7 +13857,7 @@ var require_fetch = __commonJS({ } } module2.exports = { - fetch: fetch2, + fetch: fetch3, Fetch, fetching, finalizeAndReportTiming @@ -15405,8 +15405,8 @@ var require_util6 = __commonJS({ } } } - function validateCookiePath(path10) { - for (const char of path10) { + function validateCookiePath(path11) { + for (const char of path11) { const code = char.charCodeAt(0); if (code < 33 || char === ";") { throw new Error("Invalid cookie path"); @@ -17086,11 +17086,11 @@ var require_undici = __commonJS({ if (typeof opts.path !== "string") { throw new InvalidArgumentError("invalid opts.path"); } - let path10 = opts.path; + let path11 = opts.path; if (!opts.path.startsWith("/")) { - path10 = `/${path10}`; + path11 = `/${path11}`; } - url2 = new URL(util3.parseOrigin(url2).origin + path10); + url2 = new URL(util3.parseOrigin(url2).origin + path11); } else { if (!opts) { opts = typeof url2 === "object" ? url2 : {}; @@ -17113,7 +17113,7 @@ var require_undici = __commonJS({ module2.exports.getGlobalDispatcher = getGlobalDispatcher; if (util3.nodeMajor > 16 || util3.nodeMajor === 16 && util3.nodeMinor >= 8) { let fetchImpl = null; - module2.exports.fetch = async function fetch2(resource) { + module2.exports.fetch = async function fetch3(resource) { if (!fetchImpl) { fetchImpl = require_fetch().fetch; } @@ -18625,16 +18625,16 @@ var require_dist_node5 = __commonJS({ let headers = {}; let status; let url2; - let { fetch: fetch2 } = globalThis; + let { fetch: fetch3 } = globalThis; if ((_b = requestOptions.request) == null ? void 0 : _b.fetch) { - fetch2 = requestOptions.request.fetch; + fetch3 = requestOptions.request.fetch; } - if (!fetch2) { + if (!fetch3) { throw new Error( "fetch is not set. Please pass a fetch implementation as new Octokit({ request: { fetch }}). Learn more at https://github.com/octokit/octokit.js/#fetch-missing" ); } - return fetch2(requestOptions.url, { + return fetch3(requestOptions.url, { method: requestOptions.method, body: requestOptions.body, redirect: (_c = requestOptions.request) == null ? void 0 : _c.redirect, @@ -22580,14 +22580,14 @@ var require_util8 = __commonJS({ } const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80; let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`; - let path10 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`; + let path11 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`; if (origin[origin.length - 1] === "/") { origin = origin.slice(0, origin.length - 1); } - if (path10 && path10[0] !== "/") { - path10 = `/${path10}`; + if (path11 && path11[0] !== "/") { + path11 = `/${path11}`; } - return new URL(`${origin}${path10}`); + return new URL(`${origin}${path11}`); } if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) { throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); @@ -23038,39 +23038,39 @@ var require_diagnostics = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path10, origin } + request: { method, path: path11, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path10); + debuglog("sending request to %s %s/%s", method, origin, path11); }); diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { const { - request: { method, path: path10, origin }, + request: { method, path: path11, origin }, response: { statusCode } } = evt; debuglog( "received response to %s %s/%s - HTTP %d", method, origin, - path10, + path11, statusCode ); }); diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { const { - request: { method, path: path10, origin } + request: { method, path: path11, origin } } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path10); + debuglog("trailers received from %s %s/%s", method, origin, path11); }); diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { const { - request: { method, path: path10, origin }, + request: { method, path: path11, origin }, error: error2 } = evt; debuglog( "request to %s %s/%s errored - %s", method, origin, - path10, + path11, error2.message ); }); @@ -23119,9 +23119,9 @@ var require_diagnostics = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path10, origin } + request: { method, path: path11, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path10); + debuglog("sending request to %s %s/%s", method, origin, path11); }); } diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { @@ -23184,7 +23184,7 @@ var require_request3 = __commonJS({ var kHandler = /* @__PURE__ */ Symbol("handler"); var Request = class { constructor(origin, { - path: path10, + path: path11, method, body: body2, headers, @@ -23199,11 +23199,11 @@ var require_request3 = __commonJS({ expectContinue, servername }, handler2) { - if (typeof path10 !== "string") { + if (typeof path11 !== "string") { throw new InvalidArgumentError("path must be a string"); - } else if (path10[0] !== "/" && !(path10.startsWith("http://") || path10.startsWith("https://")) && method !== "CONNECT") { + } else if (path11[0] !== "/" && !(path11.startsWith("http://") || path11.startsWith("https://")) && method !== "CONNECT") { throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.test(path10)) { + } else if (invalidPathRegex.test(path11)) { throw new InvalidArgumentError("invalid request path"); } if (typeof method !== "string") { @@ -23266,7 +23266,7 @@ var require_request3 = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? buildURL(path10, query) : path10; + this.path = query ? buildURL(path11, query) : path11; this.origin = origin; this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; this.blocking = blocking == null ? false : blocking; @@ -27779,7 +27779,7 @@ var require_client_h1 = __commonJS({ return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } function writeH1(client2, request2) { - const { method, path: path10, host, upgrade, blocking, reset } = request2; + const { method, path: path11, host, upgrade, blocking, reset } = request2; let { body: body2, headers, contentLength: contentLength2 } = request2; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH"; if (util3.isFormDataLike(body2)) { @@ -27845,7 +27845,7 @@ var require_client_h1 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - let header = `${method} ${path10} HTTP/1.1\r + let header = `${method} ${path11} HTTP/1.1\r `; if (typeof host === "string") { header += `host: ${host}\r @@ -28371,7 +28371,7 @@ var require_client_h2 = __commonJS({ } function writeH2(client2, request2) { const session = client2[kHTTP2Session]; - const { method, path: path10, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; + const { method, path: path11, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; let { body: body2 } = request2; if (upgrade) { util3.errorRequest(client2, request2, new Error("Upgrade not supported for H2")); @@ -28438,7 +28438,7 @@ var require_client_h2 = __commonJS({ }); return true; } - headers[HTTP2_HEADER_PATH] = path10; + headers[HTTP2_HEADER_PATH] = path11; headers[HTTP2_HEADER_SCHEME] = "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body2 && typeof body2.read === "function") { @@ -28791,9 +28791,9 @@ var require_redirect_handler = __commonJS({ return this.handler.onHeaders(statusCode, headers, resume, statusText); } const { origin, pathname, search } = util3.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path10 = search ? `${pathname}${search}` : pathname; + const path11 = search ? `${pathname}${search}` : pathname; this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path10; + this.opts.path = path11; this.opts.origin = origin; this.opts.maxRedirections = 0; this.opts.query = null; @@ -30027,10 +30027,10 @@ var require_proxy_agent2 = __commonJS({ }; const { origin, - path: path10 = "/", + path: path11 = "/", headers = {} } = opts; - opts.path = origin + path10; + opts.path = origin + path11; if (!("host" in headers) && !("Host" in headers)) { const { host } = new URL2(origin); headers.host = host; @@ -31951,20 +31951,20 @@ var require_mock_utils2 = __commonJS({ } return true; } - function safeUrl(path10) { - if (typeof path10 !== "string") { - return path10; + function safeUrl(path11) { + if (typeof path11 !== "string") { + return path11; } - const pathSegments = path10.split("?"); + const pathSegments = path11.split("?"); if (pathSegments.length !== 2) { - return path10; + return path11; } const qp = new URLSearchParams(pathSegments.pop()); qp.sort(); return [...pathSegments, qp.toString()].join("?"); } - function matchKey(mockDispatch2, { path: path10, method, body: body2, headers }) { - const pathMatch = matchValue(mockDispatch2.path, path10); + function matchKey(mockDispatch2, { path: path11, method, body: body2, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path11); const methodMatch = matchValue(mockDispatch2.method, method); const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body2) : true; const headersMatch = matchHeaders(mockDispatch2, headers); @@ -31986,7 +31986,7 @@ var require_mock_utils2 = __commonJS({ function getMockDispatch(mockDispatches, key) { const basePath = key.query ? buildURL(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path10 }) => matchValue(safeUrl(path10), resolvedPath)); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path11 }) => matchValue(safeUrl(path11), resolvedPath)); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -32024,9 +32024,9 @@ var require_mock_utils2 = __commonJS({ } } function buildKey(opts) { - const { path: path10, method, body: body2, headers, query } = opts; + const { path: path11, method, body: body2, headers, query } = opts; return { - path: path10, + path: path11, method, body: body2, headers, @@ -32489,10 +32489,10 @@ var require_pending_interceptors_formatter2 = __commonJS({ } format(pendingInterceptors) { const withPrettyHeaders = pendingInterceptors.map( - ({ method, path: path10, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + ({ method, path: path11, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ Method: method, Origin: origin, - Path: path10, + Path: path11, "Status code": statusCode, Persistent: persist ? PERSISTENT : NOT_PERSISTENT, Invocations: timesInvoked, @@ -34826,7 +34826,7 @@ var require_fetch2 = __commonJS({ function handleFetchDone(response) { finalizeAndReportTiming(response, "fetch"); } - function fetch2(input, init = void 0) { + function fetch3(input, init = void 0) { webidl.argumentLengthCheck(arguments, 1, "globalThis.fetch"); let p = createDeferredPromise(); let requestObject; @@ -35783,7 +35783,7 @@ var require_fetch2 = __commonJS({ } } module2.exports = { - fetch: fetch2, + fetch: fetch3, Fetch, fetching, finalizeAndReportTiming @@ -37373,9 +37373,9 @@ var require_util13 = __commonJS({ } } } - function validateCookiePath(path10) { - for (let i = 0; i < path10.length; ++i) { - const code = path10.charCodeAt(i); + function validateCookiePath(path11) { + for (let i = 0; i < path11.length; ++i) { + const code = path11.charCodeAt(i); if (code < 32 || // exclude CTLs (0-31) code === 127 || // DEL code === 59) { @@ -39969,11 +39969,11 @@ var require_undici2 = __commonJS({ if (typeof opts.path !== "string") { throw new InvalidArgumentError("invalid opts.path"); } - let path10 = opts.path; + let path11 = opts.path; if (!opts.path.startsWith("/")) { - path10 = `/${path10}`; + path11 = `/${path11}`; } - url2 = new URL(util3.parseOrigin(url2).origin + path10); + url2 = new URL(util3.parseOrigin(url2).origin + path11); } else { if (!opts) { opts = typeof url2 === "object" ? url2 : {}; @@ -39995,7 +39995,7 @@ var require_undici2 = __commonJS({ module2.exports.setGlobalDispatcher = setGlobalDispatcher; module2.exports.getGlobalDispatcher = getGlobalDispatcher; var fetchImpl = require_fetch2().fetch; - module2.exports.fetch = async function fetch2(init, options = void 0) { + module2.exports.fetch = async function fetch3(init, options = void 0) { try { return await fetchImpl(init, options); } catch (err) { @@ -45976,8 +45976,8 @@ var require_minimatch = __commonJS({ return new Minimatch(pattern, options).match(p); }; module2.exports = minimatch; - var path10 = require_path(); - minimatch.sep = path10.sep; + var path11 = require_path(); + minimatch.sep = path11.sep; var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **"); minimatch.GLOBSTAR = GLOBSTAR; var expand2 = require_brace_expansion(); @@ -46583,8 +46583,8 @@ var require_minimatch = __commonJS({ if (this.empty) return f === ""; if (f === "/" && partial) return true; const options = this.options; - if (path10.sep !== "/") { - f = f.split(path10.sep).join("/"); + if (path11.sep !== "/") { + f = f.split(path11.sep).join("/"); } f = f.split(slashSplit); this.debug(this.pattern, "split", f); @@ -46622,13 +46622,13 @@ var require_minimatch = __commonJS({ var require_readdir_glob = __commonJS({ "node_modules/readdir-glob/index.js"(exports2, module2) { module2.exports = readdirGlob; - var fs14 = require("fs"); + var fs15 = require("fs"); var { EventEmitter: EventEmitter3 } = require("events"); var { Minimatch } = require_minimatch(); var { resolve: resolve2 } = require("path"); function readdir2(dir, strict) { return new Promise((resolve3, reject) => { - fs14.readdir(dir, { withFileTypes: true }, (err, files) => { + fs15.readdir(dir, { withFileTypes: true }, (err, files) => { if (err) { switch (err.code) { case "ENOTDIR": @@ -46661,7 +46661,7 @@ var require_readdir_glob = __commonJS({ } function stat2(file, followSymlinks) { return new Promise((resolve3, reject) => { - const statFunc = followSymlinks ? fs14.stat : fs14.lstat; + const statFunc = followSymlinks ? fs15.stat : fs15.lstat; statFunc(file, (err, stats) => { if (err) { switch (err.code) { @@ -46682,8 +46682,8 @@ var require_readdir_glob = __commonJS({ }); }); } - async function* exploreWalkAsync(dir, path10, followSymlinks, useStat, shouldSkip, strict) { - let files = await readdir2(path10 + dir, strict); + async function* exploreWalkAsync(dir, path11, followSymlinks, useStat, shouldSkip, strict) { + let files = await readdir2(path11 + dir, strict); for (const file of files) { let name = file.name; if (name === void 0) { @@ -46692,7 +46692,7 @@ var require_readdir_glob = __commonJS({ } const filename = dir + "/" + name; const relative2 = filename.slice(1); - const absolute = path10 + "/" + relative2; + const absolute = path11 + "/" + relative2; let stats = null; if (useStat || followSymlinks) { stats = await stat2(absolute, followSymlinks); @@ -46706,15 +46706,15 @@ var require_readdir_glob = __commonJS({ if (stats.isDirectory()) { if (!shouldSkip(relative2)) { yield { relative: relative2, absolute, stats }; - yield* exploreWalkAsync(filename, path10, followSymlinks, useStat, shouldSkip, false); + yield* exploreWalkAsync(filename, path11, followSymlinks, useStat, shouldSkip, false); } } else { yield { relative: relative2, absolute, stats }; } } } - async function* explore(path10, followSymlinks, useStat, shouldSkip) { - yield* exploreWalkAsync("", path10, followSymlinks, useStat, shouldSkip, true); + async function* explore(path11, followSymlinks, useStat, shouldSkip) { + yield* exploreWalkAsync("", path11, followSymlinks, useStat, shouldSkip, true); } function readOptions(options) { return { @@ -48726,54 +48726,54 @@ var require_polyfills = __commonJS({ } var chdir; module2.exports = patch; - function patch(fs14) { + function patch(fs15) { if (constants3.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { - patchLchmod(fs14); - } - if (!fs14.lutimes) { - patchLutimes(fs14); - } - fs14.chown = chownFix(fs14.chown); - fs14.fchown = chownFix(fs14.fchown); - fs14.lchown = chownFix(fs14.lchown); - fs14.chmod = chmodFix(fs14.chmod); - fs14.fchmod = chmodFix(fs14.fchmod); - fs14.lchmod = chmodFix(fs14.lchmod); - fs14.chownSync = chownFixSync(fs14.chownSync); - fs14.fchownSync = chownFixSync(fs14.fchownSync); - fs14.lchownSync = chownFixSync(fs14.lchownSync); - fs14.chmodSync = chmodFixSync(fs14.chmodSync); - fs14.fchmodSync = chmodFixSync(fs14.fchmodSync); - fs14.lchmodSync = chmodFixSync(fs14.lchmodSync); - fs14.stat = statFix(fs14.stat); - fs14.fstat = statFix(fs14.fstat); - fs14.lstat = statFix(fs14.lstat); - fs14.statSync = statFixSync(fs14.statSync); - fs14.fstatSync = statFixSync(fs14.fstatSync); - fs14.lstatSync = statFixSync(fs14.lstatSync); - if (fs14.chmod && !fs14.lchmod) { - fs14.lchmod = function(path10, mode, cb) { + patchLchmod(fs15); + } + if (!fs15.lutimes) { + patchLutimes(fs15); + } + fs15.chown = chownFix(fs15.chown); + fs15.fchown = chownFix(fs15.fchown); + fs15.lchown = chownFix(fs15.lchown); + fs15.chmod = chmodFix(fs15.chmod); + fs15.fchmod = chmodFix(fs15.fchmod); + fs15.lchmod = chmodFix(fs15.lchmod); + fs15.chownSync = chownFixSync(fs15.chownSync); + fs15.fchownSync = chownFixSync(fs15.fchownSync); + fs15.lchownSync = chownFixSync(fs15.lchownSync); + fs15.chmodSync = chmodFixSync(fs15.chmodSync); + fs15.fchmodSync = chmodFixSync(fs15.fchmodSync); + fs15.lchmodSync = chmodFixSync(fs15.lchmodSync); + fs15.stat = statFix(fs15.stat); + fs15.fstat = statFix(fs15.fstat); + fs15.lstat = statFix(fs15.lstat); + fs15.statSync = statFixSync(fs15.statSync); + fs15.fstatSync = statFixSync(fs15.fstatSync); + fs15.lstatSync = statFixSync(fs15.lstatSync); + if (fs15.chmod && !fs15.lchmod) { + fs15.lchmod = function(path11, mode, cb) { if (cb) process.nextTick(cb); }; - fs14.lchmodSync = function() { + fs15.lchmodSync = function() { }; } - if (fs14.chown && !fs14.lchown) { - fs14.lchown = function(path10, uid, gid, cb) { + if (fs15.chown && !fs15.lchown) { + fs15.lchown = function(path11, uid, gid, cb) { if (cb) process.nextTick(cb); }; - fs14.lchownSync = function() { + fs15.lchownSync = function() { }; } if (platform2 === "win32") { - fs14.rename = typeof fs14.rename !== "function" ? fs14.rename : (function(fs$rename) { + fs15.rename = typeof fs15.rename !== "function" ? fs15.rename : (function(fs$rename) { function rename2(from, to, cb) { var start = Date.now(); var backoff = 0; fs$rename(from, to, function CB(er) { if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) { setTimeout(function() { - fs14.stat(to, function(stater, st) { + fs15.stat(to, function(stater, st) { if (stater && stater.code === "ENOENT") fs$rename(from, to, CB); else @@ -48789,9 +48789,9 @@ var require_polyfills = __commonJS({ } if (Object.setPrototypeOf) Object.setPrototypeOf(rename2, fs$rename); return rename2; - })(fs14.rename); + })(fs15.rename); } - fs14.read = typeof fs14.read !== "function" ? fs14.read : (function(fs$read) { + fs15.read = typeof fs15.read !== "function" ? fs15.read : (function(fs$read) { function read(fd, buffer2, offset, length, position, callback_) { var callback; if (callback_ && typeof callback_ === "function") { @@ -48799,22 +48799,22 @@ var require_polyfills = __commonJS({ callback = function(er, _2, __) { if (er && er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; - return fs$read.call(fs14, fd, buffer2, offset, length, position, callback); + return fs$read.call(fs15, fd, buffer2, offset, length, position, callback); } callback_.apply(this, arguments); }; } - return fs$read.call(fs14, fd, buffer2, offset, length, position, callback); + return fs$read.call(fs15, fd, buffer2, offset, length, position, callback); } if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read); return read; - })(fs14.read); - fs14.readSync = typeof fs14.readSync !== "function" ? fs14.readSync : /* @__PURE__ */ (function(fs$readSync) { + })(fs15.read); + fs15.readSync = typeof fs15.readSync !== "function" ? fs15.readSync : /* @__PURE__ */ (function(fs$readSync) { return function(fd, buffer2, offset, length, position) { var eagCounter = 0; while (true) { try { - return fs$readSync.call(fs14, fd, buffer2, offset, length, position); + return fs$readSync.call(fs15, fd, buffer2, offset, length, position); } catch (er) { if (er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; @@ -48824,11 +48824,11 @@ var require_polyfills = __commonJS({ } } }; - })(fs14.readSync); - function patchLchmod(fs15) { - fs15.lchmod = function(path10, mode, callback) { - fs15.open( - path10, + })(fs15.readSync); + function patchLchmod(fs16) { + fs16.lchmod = function(path11, mode, callback) { + fs16.open( + path11, constants3.O_WRONLY | constants3.O_SYMLINK, mode, function(err, fd) { @@ -48836,80 +48836,80 @@ var require_polyfills = __commonJS({ if (callback) callback(err); return; } - fs15.fchmod(fd, mode, function(err2) { - fs15.close(fd, function(err22) { + fs16.fchmod(fd, mode, function(err2) { + fs16.close(fd, function(err22) { if (callback) callback(err2 || err22); }); }); } ); }; - fs15.lchmodSync = function(path10, mode) { - var fd = fs15.openSync(path10, constants3.O_WRONLY | constants3.O_SYMLINK, mode); + fs16.lchmodSync = function(path11, mode) { + var fd = fs16.openSync(path11, constants3.O_WRONLY | constants3.O_SYMLINK, mode); var threw = true; var ret; try { - ret = fs15.fchmodSync(fd, mode); + ret = fs16.fchmodSync(fd, mode); threw = false; } finally { if (threw) { try { - fs15.closeSync(fd); + fs16.closeSync(fd); } catch (er) { } } else { - fs15.closeSync(fd); + fs16.closeSync(fd); } } return ret; }; } - function patchLutimes(fs15) { - if (constants3.hasOwnProperty("O_SYMLINK") && fs15.futimes) { - fs15.lutimes = function(path10, at, mt, cb) { - fs15.open(path10, constants3.O_SYMLINK, function(er, fd) { + function patchLutimes(fs16) { + if (constants3.hasOwnProperty("O_SYMLINK") && fs16.futimes) { + fs16.lutimes = function(path11, at, mt, cb) { + fs16.open(path11, constants3.O_SYMLINK, function(er, fd) { if (er) { if (cb) cb(er); return; } - fs15.futimes(fd, at, mt, function(er2) { - fs15.close(fd, function(er22) { + fs16.futimes(fd, at, mt, function(er2) { + fs16.close(fd, function(er22) { if (cb) cb(er2 || er22); }); }); }); }; - fs15.lutimesSync = function(path10, at, mt) { - var fd = fs15.openSync(path10, constants3.O_SYMLINK); + fs16.lutimesSync = function(path11, at, mt) { + var fd = fs16.openSync(path11, constants3.O_SYMLINK); var ret; var threw = true; try { - ret = fs15.futimesSync(fd, at, mt); + ret = fs16.futimesSync(fd, at, mt); threw = false; } finally { if (threw) { try { - fs15.closeSync(fd); + fs16.closeSync(fd); } catch (er) { } } else { - fs15.closeSync(fd); + fs16.closeSync(fd); } } return ret; }; - } else if (fs15.futimes) { - fs15.lutimes = function(_a, _b, _c, cb) { + } else if (fs16.futimes) { + fs16.lutimes = function(_a, _b, _c, cb) { if (cb) process.nextTick(cb); }; - fs15.lutimesSync = function() { + fs16.lutimesSync = function() { }; } } function chmodFix(orig) { if (!orig) return orig; return function(target, mode, cb) { - return orig.call(fs14, target, mode, function(er) { + return orig.call(fs15, target, mode, function(er) { if (chownErOk(er)) er = null; if (cb) cb.apply(this, arguments); }); @@ -48919,7 +48919,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, mode) { try { - return orig.call(fs14, target, mode); + return orig.call(fs15, target, mode); } catch (er) { if (!chownErOk(er)) throw er; } @@ -48928,7 +48928,7 @@ var require_polyfills = __commonJS({ function chownFix(orig) { if (!orig) return orig; return function(target, uid, gid, cb) { - return orig.call(fs14, target, uid, gid, function(er) { + return orig.call(fs15, target, uid, gid, function(er) { if (chownErOk(er)) er = null; if (cb) cb.apply(this, arguments); }); @@ -48938,7 +48938,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, uid, gid) { try { - return orig.call(fs14, target, uid, gid); + return orig.call(fs15, target, uid, gid); } catch (er) { if (!chownErOk(er)) throw er; } @@ -48958,13 +48958,13 @@ var require_polyfills = __commonJS({ } if (cb) cb.apply(this, arguments); } - return options ? orig.call(fs14, target, options, callback) : orig.call(fs14, target, callback); + return options ? orig.call(fs15, target, options, callback) : orig.call(fs15, target, callback); }; } function statFixSync(orig) { if (!orig) return orig; return function(target, options) { - var stats = options ? orig.call(fs14, target, options) : orig.call(fs14, target); + var stats = options ? orig.call(fs15, target, options) : orig.call(fs15, target); if (stats) { if (stats.uid < 0) stats.uid += 4294967296; if (stats.gid < 0) stats.gid += 4294967296; @@ -48993,16 +48993,16 @@ var require_legacy_streams = __commonJS({ "node_modules/graceful-fs/legacy-streams.js"(exports2, module2) { var Stream = require("stream").Stream; module2.exports = legacy; - function legacy(fs14) { + function legacy(fs15) { return { ReadStream, WriteStream }; - function ReadStream(path10, options) { - if (!(this instanceof ReadStream)) return new ReadStream(path10, options); + function ReadStream(path11, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path11, options); Stream.call(this); var self2 = this; - this.path = path10; + this.path = path11; this.fd = null; this.readable = true; this.paused = false; @@ -49036,7 +49036,7 @@ var require_legacy_streams = __commonJS({ }); return; } - fs14.open(this.path, this.flags, this.mode, function(err, fd) { + fs15.open(this.path, this.flags, this.mode, function(err, fd) { if (err) { self2.emit("error", err); self2.readable = false; @@ -49047,10 +49047,10 @@ var require_legacy_streams = __commonJS({ self2._read(); }); } - function WriteStream(path10, options) { - if (!(this instanceof WriteStream)) return new WriteStream(path10, options); + function WriteStream(path11, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path11, options); Stream.call(this); - this.path = path10; + this.path = path11; this.fd = null; this.writable = true; this.flags = "w"; @@ -49075,7 +49075,7 @@ var require_legacy_streams = __commonJS({ this.busy = false; this._queue = []; if (this.fd === null) { - this._open = fs14.open; + this._open = fs15.open; this._queue.push([this._open, this.path, this.flags, this.mode, void 0]); this.flush(); } @@ -49110,7 +49110,7 @@ var require_clone = __commonJS({ // node_modules/graceful-fs/graceful-fs.js var require_graceful_fs = __commonJS({ "node_modules/graceful-fs/graceful-fs.js"(exports2, module2) { - var fs14 = require("fs"); + var fs15 = require("fs"); var polyfills = require_polyfills(); var legacy = require_legacy_streams(); var clone = require_clone(); @@ -49142,12 +49142,12 @@ var require_graceful_fs = __commonJS({ m = "GFS4: " + m.split(/\n/).join("\nGFS4: "); console.error(m); }; - if (!fs14[gracefulQueue]) { + if (!fs15[gracefulQueue]) { queue = global[gracefulQueue] || []; - publishQueue(fs14, queue); - fs14.close = (function(fs$close) { + publishQueue(fs15, queue); + fs15.close = (function(fs$close) { function close(fd, cb) { - return fs$close.call(fs14, fd, function(err) { + return fs$close.call(fs15, fd, function(err) { if (!err) { resetQueue(); } @@ -49159,48 +49159,48 @@ var require_graceful_fs = __commonJS({ value: fs$close }); return close; - })(fs14.close); - fs14.closeSync = (function(fs$closeSync) { + })(fs15.close); + fs15.closeSync = (function(fs$closeSync) { function closeSync(fd) { - fs$closeSync.apply(fs14, arguments); + fs$closeSync.apply(fs15, arguments); resetQueue(); } Object.defineProperty(closeSync, previousSymbol, { value: fs$closeSync }); return closeSync; - })(fs14.closeSync); + })(fs15.closeSync); if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) { process.on("exit", function() { - debug2(fs14[gracefulQueue]); - require("assert").equal(fs14[gracefulQueue].length, 0); + debug2(fs15[gracefulQueue]); + require("assert").equal(fs15[gracefulQueue].length, 0); }); } } var queue; if (!global[gracefulQueue]) { - publishQueue(global, fs14[gracefulQueue]); - } - module2.exports = patch(clone(fs14)); - if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs14.__patched) { - module2.exports = patch(fs14); - fs14.__patched = true; - } - function patch(fs15) { - polyfills(fs15); - fs15.gracefulify = patch; - fs15.createReadStream = createReadStream2; - fs15.createWriteStream = createWriteStream2; - var fs$readFile = fs15.readFile; - fs15.readFile = readFile; - function readFile(path10, options, cb) { + publishQueue(global, fs15[gracefulQueue]); + } + module2.exports = patch(clone(fs15)); + if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs15.__patched) { + module2.exports = patch(fs15); + fs15.__patched = true; + } + function patch(fs16) { + polyfills(fs16); + fs16.gracefulify = patch; + fs16.createReadStream = createReadStream2; + fs16.createWriteStream = createWriteStream2; + var fs$readFile = fs16.readFile; + fs16.readFile = readFile; + function readFile(path11, options, cb) { if (typeof options === "function") cb = options, options = null; - return go$readFile(path10, options, cb); - function go$readFile(path11, options2, cb2, startTime) { - return fs$readFile(path11, options2, function(err) { + return go$readFile(path11, options, cb); + function go$readFile(path12, options2, cb2, startTime) { + return fs$readFile(path12, options2, function(err) { if (err && (err.code === "EMFILE" || err.code === "ENFILE")) - enqueue([go$readFile, [path11, options2, cb2], err, startTime || Date.now(), Date.now()]); + enqueue([go$readFile, [path12, options2, cb2], err, startTime || Date.now(), Date.now()]); else { if (typeof cb2 === "function") cb2.apply(this, arguments); @@ -49208,16 +49208,16 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$writeFile = fs15.writeFile; - fs15.writeFile = writeFile2; - function writeFile2(path10, data, options, cb) { + var fs$writeFile = fs16.writeFile; + fs16.writeFile = writeFile2; + function writeFile2(path11, data, options, cb) { if (typeof options === "function") cb = options, options = null; - return go$writeFile(path10, data, options, cb); - function go$writeFile(path11, data2, options2, cb2, startTime) { - return fs$writeFile(path11, data2, options2, function(err) { + return go$writeFile(path11, data, options, cb); + function go$writeFile(path12, data2, options2, cb2, startTime) { + return fs$writeFile(path12, data2, options2, function(err) { if (err && (err.code === "EMFILE" || err.code === "ENFILE")) - enqueue([go$writeFile, [path11, data2, options2, cb2], err, startTime || Date.now(), Date.now()]); + enqueue([go$writeFile, [path12, data2, options2, cb2], err, startTime || Date.now(), Date.now()]); else { if (typeof cb2 === "function") cb2.apply(this, arguments); @@ -49225,17 +49225,17 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$appendFile = fs15.appendFile; + var fs$appendFile = fs16.appendFile; if (fs$appendFile) - fs15.appendFile = appendFile2; - function appendFile2(path10, data, options, cb) { + fs16.appendFile = appendFile2; + function appendFile2(path11, data, options, cb) { if (typeof options === "function") cb = options, options = null; - return go$appendFile(path10, data, options, cb); - function go$appendFile(path11, data2, options2, cb2, startTime) { - return fs$appendFile(path11, data2, options2, function(err) { + return go$appendFile(path11, data, options, cb); + function go$appendFile(path12, data2, options2, cb2, startTime) { + return fs$appendFile(path12, data2, options2, function(err) { if (err && (err.code === "EMFILE" || err.code === "ENFILE")) - enqueue([go$appendFile, [path11, data2, options2, cb2], err, startTime || Date.now(), Date.now()]); + enqueue([go$appendFile, [path12, data2, options2, cb2], err, startTime || Date.now(), Date.now()]); else { if (typeof cb2 === "function") cb2.apply(this, arguments); @@ -49243,9 +49243,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$copyFile = fs15.copyFile; + var fs$copyFile = fs16.copyFile; if (fs$copyFile) - fs15.copyFile = copyFile2; + fs16.copyFile = copyFile2; function copyFile2(src, dest, flags, cb) { if (typeof flags === "function") { cb = flags; @@ -49263,34 +49263,34 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$readdir = fs15.readdir; - fs15.readdir = readdir2; + var fs$readdir = fs16.readdir; + fs16.readdir = readdir2; var noReaddirOptionVersions = /^v[0-5]\./; - function readdir2(path10, options, cb) { + function readdir2(path11, options, cb) { if (typeof options === "function") cb = options, options = null; - var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path11, options2, cb2, startTime) { - return fs$readdir(path11, fs$readdirCallback( - path11, + var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path12, options2, cb2, startTime) { + return fs$readdir(path12, fs$readdirCallback( + path12, options2, cb2, startTime )); - } : function go$readdir2(path11, options2, cb2, startTime) { - return fs$readdir(path11, options2, fs$readdirCallback( - path11, + } : function go$readdir2(path12, options2, cb2, startTime) { + return fs$readdir(path12, options2, fs$readdirCallback( + path12, options2, cb2, startTime )); }; - return go$readdir(path10, options, cb); - function fs$readdirCallback(path11, options2, cb2, startTime) { + return go$readdir(path11, options, cb); + function fs$readdirCallback(path12, options2, cb2, startTime) { return function(err, files) { if (err && (err.code === "EMFILE" || err.code === "ENFILE")) enqueue([ go$readdir, - [path11, options2, cb2], + [path12, options2, cb2], err, startTime || Date.now(), Date.now() @@ -49305,21 +49305,21 @@ var require_graceful_fs = __commonJS({ } } if (process.version.substr(0, 4) === "v0.8") { - var legStreams = legacy(fs15); + var legStreams = legacy(fs16); ReadStream = legStreams.ReadStream; WriteStream = legStreams.WriteStream; } - var fs$ReadStream = fs15.ReadStream; + var fs$ReadStream = fs16.ReadStream; if (fs$ReadStream) { ReadStream.prototype = Object.create(fs$ReadStream.prototype); ReadStream.prototype.open = ReadStream$open; } - var fs$WriteStream = fs15.WriteStream; + var fs$WriteStream = fs16.WriteStream; if (fs$WriteStream) { WriteStream.prototype = Object.create(fs$WriteStream.prototype); WriteStream.prototype.open = WriteStream$open; } - Object.defineProperty(fs15, "ReadStream", { + Object.defineProperty(fs16, "ReadStream", { get: function() { return ReadStream; }, @@ -49329,7 +49329,7 @@ var require_graceful_fs = __commonJS({ enumerable: true, configurable: true }); - Object.defineProperty(fs15, "WriteStream", { + Object.defineProperty(fs16, "WriteStream", { get: function() { return WriteStream; }, @@ -49340,7 +49340,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileReadStream = ReadStream; - Object.defineProperty(fs15, "FileReadStream", { + Object.defineProperty(fs16, "FileReadStream", { get: function() { return FileReadStream; }, @@ -49351,7 +49351,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileWriteStream = WriteStream; - Object.defineProperty(fs15, "FileWriteStream", { + Object.defineProperty(fs16, "FileWriteStream", { get: function() { return FileWriteStream; }, @@ -49361,7 +49361,7 @@ var require_graceful_fs = __commonJS({ enumerable: true, configurable: true }); - function ReadStream(path10, options) { + function ReadStream(path11, options) { if (this instanceof ReadStream) return fs$ReadStream.apply(this, arguments), this; else @@ -49381,7 +49381,7 @@ var require_graceful_fs = __commonJS({ } }); } - function WriteStream(path10, options) { + function WriteStream(path11, options) { if (this instanceof WriteStream) return fs$WriteStream.apply(this, arguments), this; else @@ -49399,22 +49399,22 @@ var require_graceful_fs = __commonJS({ } }); } - function createReadStream2(path10, options) { - return new fs15.ReadStream(path10, options); + function createReadStream2(path11, options) { + return new fs16.ReadStream(path11, options); } - function createWriteStream2(path10, options) { - return new fs15.WriteStream(path10, options); + function createWriteStream2(path11, options) { + return new fs16.WriteStream(path11, options); } - var fs$open = fs15.open; - fs15.open = open2; - function open2(path10, flags, mode, cb) { + var fs$open = fs16.open; + fs16.open = open2; + function open2(path11, flags, mode, cb) { if (typeof mode === "function") cb = mode, mode = null; - return go$open(path10, flags, mode, cb); - function go$open(path11, flags2, mode2, cb2, startTime) { - return fs$open(path11, flags2, mode2, function(err, fd) { + return go$open(path11, flags, mode, cb); + function go$open(path12, flags2, mode2, cb2, startTime) { + return fs$open(path12, flags2, mode2, function(err, fd) { if (err && (err.code === "EMFILE" || err.code === "ENFILE")) - enqueue([go$open, [path11, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]); + enqueue([go$open, [path12, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]); else { if (typeof cb2 === "function") cb2.apply(this, arguments); @@ -49422,20 +49422,20 @@ var require_graceful_fs = __commonJS({ }); } } - return fs15; + return fs16; } function enqueue(elem) { debug2("ENQUEUE", elem[0].name, elem[1]); - fs14[gracefulQueue].push(elem); + fs15[gracefulQueue].push(elem); retry2(); } var retryTimer; function resetQueue() { var now = Date.now(); - for (var i = 0; i < fs14[gracefulQueue].length; ++i) { - if (fs14[gracefulQueue][i].length > 2) { - fs14[gracefulQueue][i][3] = now; - fs14[gracefulQueue][i][4] = now; + for (var i = 0; i < fs15[gracefulQueue].length; ++i) { + if (fs15[gracefulQueue][i].length > 2) { + fs15[gracefulQueue][i][3] = now; + fs15[gracefulQueue][i][4] = now; } } retry2(); @@ -49443,9 +49443,9 @@ var require_graceful_fs = __commonJS({ function retry2() { clearTimeout(retryTimer); retryTimer = void 0; - if (fs14[gracefulQueue].length === 0) + if (fs15[gracefulQueue].length === 0) return; - var elem = fs14[gracefulQueue].shift(); + var elem = fs15[gracefulQueue].shift(); var fn = elem[0]; var args = elem[1]; var err = elem[2]; @@ -49467,7 +49467,7 @@ var require_graceful_fs = __commonJS({ debug2("RETRY", fn.name, args); fn.apply(null, args.concat([startTime])); } else { - fs14[gracefulQueue].push(elem); + fs15[gracefulQueue].push(elem); } } if (retryTimer === void 0) { @@ -49771,7 +49771,7 @@ var require_BufferList = __commonJS({ this.head = this.tail = null; this.length = 0; }; - BufferList.prototype.join = function join3(s) { + BufferList.prototype.join = function join4(s) { if (this.length === 0) return ""; var p = this.head; var ret = "" + p.data; @@ -51519,22 +51519,22 @@ var require_lazystream = __commonJS({ // node_modules/normalize-path/index.js var require_normalize_path = __commonJS({ "node_modules/normalize-path/index.js"(exports2, module2) { - module2.exports = function(path10, stripTrailing) { - if (typeof path10 !== "string") { + module2.exports = function(path11, stripTrailing) { + if (typeof path11 !== "string") { throw new TypeError("expected path to be a string"); } - if (path10 === "\\" || path10 === "/") return "/"; - var len = path10.length; - if (len <= 1) return path10; + if (path11 === "\\" || path11 === "/") return "/"; + var len = path11.length; + if (len <= 1) return path11; var prefix2 = ""; - if (len > 4 && path10[3] === "\\") { - var ch = path10[2]; - if ((ch === "?" || ch === ".") && path10.slice(0, 2) === "\\\\") { - path10 = path10.slice(2); + if (len > 4 && path11[3] === "\\") { + var ch = path11[2]; + if ((ch === "?" || ch === ".") && path11.slice(0, 2) === "\\\\") { + path11 = path11.slice(2); prefix2 = "//"; } } - var segs = path10.split(/[/\\]+/); + var segs = path11.split(/[/\\]+/); if (stripTrailing !== false && segs[segs.length - 1] === "") { segs.pop(); } @@ -60576,11 +60576,11 @@ var require_commonjs3 = __commonJS({ return (f) => f.length === len && f !== "." && f !== ".."; }; var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix"; - var path10 = { + var path11 = { win32: { sep: "\\" }, posix: { sep: "/" } }; - exports2.sep = defaultPlatform === "win32" ? path10.win32.sep : path10.posix.sep; + exports2.sep = defaultPlatform === "win32" ? path11.win32.sep : path11.posix.sep; exports2.minimatch.sep = exports2.sep; exports2.GLOBSTAR = /* @__PURE__ */ Symbol("globstar **"); exports2.minimatch.GLOBSTAR = exports2.GLOBSTAR; @@ -63901,12 +63901,12 @@ var require_commonjs6 = __commonJS({ /** * Get the Path object referenced by the string path, resolved from this Path */ - resolve(path10) { - if (!path10) { + resolve(path11) { + if (!path11) { return this; } - const rootPath = this.getRootString(path10); - const dir = path10.substring(rootPath.length); + const rootPath = this.getRootString(path11); + const dir = path11.substring(rootPath.length); const dirParts = dir.split(this.splitSep); const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts); return result; @@ -64659,8 +64659,8 @@ var require_commonjs6 = __commonJS({ /** * @internal */ - getRootString(path10) { - return node_path_1.win32.parse(path10).root; + getRootString(path11) { + return node_path_1.win32.parse(path11).root; } /** * @internal @@ -64707,8 +64707,8 @@ var require_commonjs6 = __commonJS({ /** * @internal */ - getRootString(path10) { - return path10.startsWith("/") ? "/" : ""; + getRootString(path11) { + return path11.startsWith("/") ? "/" : ""; } /** * @internal @@ -64758,8 +64758,8 @@ var require_commonjs6 = __commonJS({ * * @internal */ - constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs14 = defaultFS } = {}) { - this.#fs = fsFromOption(fs14); + constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs15 = defaultFS } = {}) { + this.#fs = fsFromOption(fs15); if (cwd instanceof URL || cwd.startsWith("file://")) { cwd = (0, node_url_1.fileURLToPath)(cwd); } @@ -64798,11 +64798,11 @@ var require_commonjs6 = __commonJS({ /** * Get the depth of a provided path, string, or the cwd */ - depth(path10 = this.cwd) { - if (typeof path10 === "string") { - path10 = this.cwd.resolve(path10); + depth(path11 = this.cwd) { + if (typeof path11 === "string") { + path11 = this.cwd.resolve(path11); } - return path10.depth(); + return path11.depth(); } /** * Return the cache of child entries. Exposed so subclasses can create @@ -65289,9 +65289,9 @@ var require_commonjs6 = __commonJS({ process4(); return results; } - chdir(path10 = this.cwd) { + chdir(path11 = this.cwd) { const oldCwd = this.cwd; - this.cwd = typeof path10 === "string" ? this.cwd.resolve(path10) : path10; + this.cwd = typeof path11 === "string" ? this.cwd.resolve(path11) : path11; this.cwd[setAsCwd](oldCwd); } }; @@ -65318,8 +65318,8 @@ var require_commonjs6 = __commonJS({ /** * @internal */ - newRoot(fs14) { - return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs14 }); + newRoot(fs15) { + return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs15 }); } /** * Return true if the provided path string is an absolute path @@ -65348,8 +65348,8 @@ var require_commonjs6 = __commonJS({ /** * @internal */ - newRoot(fs14) { - return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs14 }); + newRoot(fs15) { + return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs15 }); } /** * Return true if the provided path string is an absolute path @@ -65679,8 +65679,8 @@ var require_processor = __commonJS({ } // match, absolute, ifdir entries() { - return [...this.store.entries()].map(([path10, n]) => [ - path10, + return [...this.store.entries()].map(([path11, n]) => [ + path11, !!(n & 2), !!(n & 1) ]); @@ -65898,9 +65898,9 @@ var require_walker = __commonJS({ signal; maxDepth; includeChildMatches; - constructor(patterns, path10, opts) { + constructor(patterns, path11, opts) { this.patterns = patterns; - this.path = path10; + this.path = path11; this.opts = opts; this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/"; this.includeChildMatches = opts.includeChildMatches !== false; @@ -65919,11 +65919,11 @@ var require_walker = __commonJS({ }); } } - #ignored(path10) { - return this.seen.has(path10) || !!this.#ignore?.ignored?.(path10); + #ignored(path11) { + return this.seen.has(path11) || !!this.#ignore?.ignored?.(path11); } - #childrenIgnored(path10) { - return !!this.#ignore?.childrenIgnored?.(path10); + #childrenIgnored(path11) { + return !!this.#ignore?.childrenIgnored?.(path11); } // backpressure mechanism pause() { @@ -66139,8 +66139,8 @@ var require_walker = __commonJS({ exports2.GlobUtil = GlobUtil; var GlobWalker = class extends GlobUtil { matches = /* @__PURE__ */ new Set(); - constructor(patterns, path10, opts) { - super(patterns, path10, opts); + constructor(patterns, path11, opts) { + super(patterns, path11, opts); } matchEmit(e) { this.matches.add(e); @@ -66178,8 +66178,8 @@ var require_walker = __commonJS({ exports2.GlobWalker = GlobWalker; var GlobStream = class extends GlobUtil { results; - constructor(patterns, path10, opts) { - super(patterns, path10, opts); + constructor(patterns, path11, opts) { + super(patterns, path11, opts); this.results = new minipass_1.Minipass({ signal: this.signal, objectMode: true @@ -66534,8 +66534,8 @@ var require_commonjs7 = __commonJS({ // node_modules/archiver-utils/file.js var require_file3 = __commonJS({ "node_modules/archiver-utils/file.js"(exports2, module2) { - var fs14 = require_graceful_fs(); - var path10 = require("path"); + var fs15 = require_graceful_fs(); + var path11 = require("path"); var flatten = require_flatten(); var difference = require_difference(); var union = require_union(); @@ -66560,8 +66560,8 @@ var require_file3 = __commonJS({ return result; }; file.exists = function() { - var filepath = path10.join.apply(path10, arguments); - return fs14.existsSync(filepath); + var filepath = path11.join.apply(path11, arguments); + return fs15.existsSync(filepath); }; file.expand = function(...args) { var options = isPlainObject3(args[0]) ? args.shift() : {}; @@ -66574,12 +66574,12 @@ var require_file3 = __commonJS({ }); if (options.filter) { matches = matches.filter(function(filepath) { - filepath = path10.join(options.cwd || "", filepath); + filepath = path11.join(options.cwd || "", filepath); try { if (typeof options.filter === "function") { return options.filter(filepath); } else { - return fs14.statSync(filepath)[options.filter](); + return fs15.statSync(filepath)[options.filter](); } } catch (e) { return false; @@ -66591,7 +66591,7 @@ var require_file3 = __commonJS({ file.expandMapping = function(patterns, destBase, options) { options = Object.assign({ rename: function(destBase2, destPath) { - return path10.join(destBase2 || "", destPath); + return path11.join(destBase2 || "", destPath); } }, options); var files = []; @@ -66599,14 +66599,14 @@ var require_file3 = __commonJS({ file.expand(options, patterns).forEach(function(src) { var destPath = src; if (options.flatten) { - destPath = path10.basename(destPath); + destPath = path11.basename(destPath); } if (options.ext) { destPath = destPath.replace(/(\.[^\/]*)?$/, options.ext); } var dest = options.rename(destBase, destPath, options); if (options.cwd) { - src = path10.join(options.cwd, src); + src = path11.join(options.cwd, src); } dest = dest.replace(pathSeparatorRe, "/"); src = src.replace(pathSeparatorRe, "/"); @@ -66687,8 +66687,8 @@ var require_file3 = __commonJS({ // node_modules/archiver-utils/index.js var require_archiver_utils = __commonJS({ "node_modules/archiver-utils/index.js"(exports2, module2) { - var fs14 = require_graceful_fs(); - var path10 = require("path"); + var fs15 = require_graceful_fs(); + var path11 = require("path"); var isStream = require_is_stream(); var lazystream = require_lazystream(); var normalizePath = require_normalize_path(); @@ -66736,7 +66736,7 @@ var require_archiver_utils = __commonJS({ }; utils.lazyReadStream = function(filepath) { return new lazystream.Readable(function() { - return fs14.createReadStream(filepath); + return fs15.createReadStream(filepath); }); }; utils.normalizeInputSource = function(source) { @@ -66764,7 +66764,7 @@ var require_archiver_utils = __commonJS({ callback = base; base = dirpath; } - fs14.readdir(dirpath, function(err, list) { + fs15.readdir(dirpath, function(err, list) { var i = 0; var file; var filepath; @@ -66776,11 +66776,11 @@ var require_archiver_utils = __commonJS({ if (!file) { return callback(null, results); } - filepath = path10.join(dirpath, file); - fs14.stat(filepath, function(err2, stats) { + filepath = path11.join(dirpath, file); + fs15.stat(filepath, function(err2, stats) { results.push({ path: filepath, - relative: path10.relative(base, filepath).replace(/\\/g, "/"), + relative: path11.relative(base, filepath).replace(/\\/g, "/"), stats }); if (stats && stats.isDirectory()) { @@ -66839,10 +66839,10 @@ var require_error = __commonJS({ // node_modules/archiver/lib/core.js var require_core = __commonJS({ "node_modules/archiver/lib/core.js"(exports2, module2) { - var fs14 = require("fs"); + var fs15 = require("fs"); var glob = require_readdir_glob(); var async = require_async(); - var path10 = require("path"); + var path11 = require("path"); var util3 = require_archiver_utils(); var inherits = require("util").inherits; var ArchiverError = require_error(); @@ -66903,7 +66903,7 @@ var require_core = __commonJS({ data.sourcePath = filepath; task.data = data; this._entriesCount++; - if (data.stats && data.stats instanceof fs14.Stats) { + if (data.stats && data.stats instanceof fs15.Stats) { task = this._updateQueueTaskWithStats(task, data.stats); if (task) { if (data.stats.size) { @@ -67074,7 +67074,7 @@ var require_core = __commonJS({ callback(); return; } - fs14.lstat(task.filepath, function(err, stats) { + fs15.lstat(task.filepath, function(err, stats) { if (this._state.aborted) { setImmediate(callback); return; @@ -67117,10 +67117,10 @@ var require_core = __commonJS({ task.data.sourceType = "buffer"; task.source = Buffer.concat([]); } else if (stats.isSymbolicLink() && this._moduleSupports("symlink")) { - var linkPath = fs14.readlinkSync(task.filepath); - var dirName = path10.dirname(task.filepath); + var linkPath = fs15.readlinkSync(task.filepath); + var dirName = path11.dirname(task.filepath); task.data.type = "symlink"; - task.data.linkname = path10.relative(dirName, path10.resolve(dirName, linkPath)); + task.data.linkname = path11.relative(dirName, path11.resolve(dirName, linkPath)); task.data.sourceType = "buffer"; task.source = Buffer.concat([]); } else { @@ -72213,14 +72213,14 @@ var require_util20 = __commonJS({ } const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80; let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`; - let path10 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`; + let path11 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`; if (origin[origin.length - 1] === "/") { origin = origin.slice(0, origin.length - 1); } - if (path10 && path10[0] !== "/") { - path10 = `/${path10}`; + if (path11 && path11[0] !== "/") { + path11 = `/${path11}`; } - return new URL(`${origin}${path10}`); + return new URL(`${origin}${path11}`); } if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) { throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); @@ -72671,39 +72671,39 @@ var require_diagnostics2 = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path10, origin } + request: { method, path: path11, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path10); + debuglog("sending request to %s %s/%s", method, origin, path11); }); diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { const { - request: { method, path: path10, origin }, + request: { method, path: path11, origin }, response: { statusCode } } = evt; debuglog( "received response to %s %s/%s - HTTP %d", method, origin, - path10, + path11, statusCode ); }); diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { const { - request: { method, path: path10, origin } + request: { method, path: path11, origin } } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path10); + debuglog("trailers received from %s %s/%s", method, origin, path11); }); diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { const { - request: { method, path: path10, origin }, + request: { method, path: path11, origin }, error: error2 } = evt; debuglog( "request to %s %s/%s errored - %s", method, origin, - path10, + path11, error2.message ); }); @@ -72752,9 +72752,9 @@ var require_diagnostics2 = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path10, origin } + request: { method, path: path11, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path10); + debuglog("sending request to %s %s/%s", method, origin, path11); }); } diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { @@ -72817,7 +72817,7 @@ var require_request5 = __commonJS({ var kHandler = /* @__PURE__ */ Symbol("handler"); var Request = class { constructor(origin, { - path: path10, + path: path11, method, body: body2, headers, @@ -72832,11 +72832,11 @@ var require_request5 = __commonJS({ expectContinue, servername }, handler2) { - if (typeof path10 !== "string") { + if (typeof path11 !== "string") { throw new InvalidArgumentError("path must be a string"); - } else if (path10[0] !== "/" && !(path10.startsWith("http://") || path10.startsWith("https://")) && method !== "CONNECT") { + } else if (path11[0] !== "/" && !(path11.startsWith("http://") || path11.startsWith("https://")) && method !== "CONNECT") { throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.test(path10)) { + } else if (invalidPathRegex.test(path11)) { throw new InvalidArgumentError("invalid request path"); } if (typeof method !== "string") { @@ -72899,7 +72899,7 @@ var require_request5 = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? buildURL(path10, query) : path10; + this.path = query ? buildURL(path11, query) : path11; this.origin = origin; this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; this.blocking = blocking == null ? false : blocking; @@ -77412,7 +77412,7 @@ var require_client_h12 = __commonJS({ return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } function writeH1(client2, request2) { - const { method, path: path10, host, upgrade, blocking, reset } = request2; + const { method, path: path11, host, upgrade, blocking, reset } = request2; let { body: body2, headers, contentLength: contentLength2 } = request2; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH"; if (util3.isFormDataLike(body2)) { @@ -77478,7 +77478,7 @@ var require_client_h12 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - let header = `${method} ${path10} HTTP/1.1\r + let header = `${method} ${path11} HTTP/1.1\r `; if (typeof host === "string") { header += `host: ${host}\r @@ -78004,7 +78004,7 @@ var require_client_h22 = __commonJS({ } function writeH2(client2, request2) { const session = client2[kHTTP2Session]; - const { method, path: path10, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; + const { method, path: path11, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; let { body: body2 } = request2; if (upgrade) { util3.errorRequest(client2, request2, new Error("Upgrade not supported for H2")); @@ -78071,7 +78071,7 @@ var require_client_h22 = __commonJS({ }); return true; } - headers[HTTP2_HEADER_PATH] = path10; + headers[HTTP2_HEADER_PATH] = path11; headers[HTTP2_HEADER_SCHEME] = "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body2 && typeof body2.read === "function") { @@ -78424,9 +78424,9 @@ var require_redirect_handler2 = __commonJS({ return this.handler.onHeaders(statusCode, headers, resume, statusText); } const { origin, pathname, search } = util3.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path10 = search ? `${pathname}${search}` : pathname; + const path11 = search ? `${pathname}${search}` : pathname; this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path10; + this.opts.path = path11; this.opts.origin = origin; this.opts.maxRedirections = 0; this.opts.query = null; @@ -79660,10 +79660,10 @@ var require_proxy_agent3 = __commonJS({ }; const { origin, - path: path10 = "/", + path: path11 = "/", headers = {} } = opts; - opts.path = origin + path10; + opts.path = origin + path11; if (!("host" in headers) && !("Host" in headers)) { const { host } = new URL2(origin); headers.host = host; @@ -81584,20 +81584,20 @@ var require_mock_utils3 = __commonJS({ } return true; } - function safeUrl(path10) { - if (typeof path10 !== "string") { - return path10; + function safeUrl(path11) { + if (typeof path11 !== "string") { + return path11; } - const pathSegments = path10.split("?"); + const pathSegments = path11.split("?"); if (pathSegments.length !== 2) { - return path10; + return path11; } const qp = new URLSearchParams(pathSegments.pop()); qp.sort(); return [...pathSegments, qp.toString()].join("?"); } - function matchKey(mockDispatch2, { path: path10, method, body: body2, headers }) { - const pathMatch = matchValue(mockDispatch2.path, path10); + function matchKey(mockDispatch2, { path: path11, method, body: body2, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path11); const methodMatch = matchValue(mockDispatch2.method, method); const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body2) : true; const headersMatch = matchHeaders(mockDispatch2, headers); @@ -81619,7 +81619,7 @@ var require_mock_utils3 = __commonJS({ function getMockDispatch(mockDispatches, key) { const basePath = key.query ? buildURL(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path10 }) => matchValue(safeUrl(path10), resolvedPath)); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path11 }) => matchValue(safeUrl(path11), resolvedPath)); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -81657,9 +81657,9 @@ var require_mock_utils3 = __commonJS({ } } function buildKey(opts) { - const { path: path10, method, body: body2, headers, query } = opts; + const { path: path11, method, body: body2, headers, query } = opts; return { - path: path10, + path: path11, method, body: body2, headers, @@ -82122,10 +82122,10 @@ var require_pending_interceptors_formatter3 = __commonJS({ } format(pendingInterceptors) { const withPrettyHeaders = pendingInterceptors.map( - ({ method, path: path10, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + ({ method, path: path11, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ Method: method, Origin: origin, - Path: path10, + Path: path11, "Status code": statusCode, Persistent: persist ? PERSISTENT : NOT_PERSISTENT, Invocations: timesInvoked, @@ -84459,7 +84459,7 @@ var require_fetch3 = __commonJS({ function handleFetchDone(response) { finalizeAndReportTiming(response, "fetch"); } - function fetch2(input, init = void 0) { + function fetch3(input, init = void 0) { webidl.argumentLengthCheck(arguments, 1, "globalThis.fetch"); let p = createDeferredPromise(); let requestObject; @@ -85416,7 +85416,7 @@ var require_fetch3 = __commonJS({ } } module2.exports = { - fetch: fetch2, + fetch: fetch3, Fetch, fetching, finalizeAndReportTiming @@ -87006,9 +87006,9 @@ var require_util25 = __commonJS({ } } } - function validateCookiePath(path10) { - for (let i = 0; i < path10.length; ++i) { - const code = path10.charCodeAt(i); + function validateCookiePath(path11) { + for (let i = 0; i < path11.length; ++i) { + const code = path11.charCodeAt(i); if (code < 32 || // exclude CTLs (0-31) code === 127 || // DEL code === 59) { @@ -89602,11 +89602,11 @@ var require_undici3 = __commonJS({ if (typeof opts.path !== "string") { throw new InvalidArgumentError("invalid opts.path"); } - let path10 = opts.path; + let path11 = opts.path; if (!opts.path.startsWith("/")) { - path10 = `/${path10}`; + path11 = `/${path11}`; } - url2 = new URL(util3.parseOrigin(url2).origin + path10); + url2 = new URL(util3.parseOrigin(url2).origin + path11); } else { if (!opts) { opts = typeof url2 === "object" ? url2 : {}; @@ -89628,7 +89628,7 @@ var require_undici3 = __commonJS({ module2.exports.setGlobalDispatcher = setGlobalDispatcher; module2.exports.getGlobalDispatcher = getGlobalDispatcher; var fetchImpl = require_fetch3().fetch; - module2.exports.fetch = async function fetch2(init, options = void 0) { + module2.exports.fetch = async function fetch3(init, options = void 0) { try { return await fetchImpl(init, options); } catch (err) { @@ -90610,7 +90610,7 @@ var require_traverse = __commonJS({ })(this.value); }; function walk(root, cb, immutable) { - var path10 = []; + var path11 = []; var parents = []; var alive = true; return (function walker(node_) { @@ -90619,11 +90619,11 @@ var require_traverse = __commonJS({ var state3 = { node, node_, - path: [].concat(path10), + path: [].concat(path11), parent: parents.slice(-1)[0], - key: path10.slice(-1)[0], - isRoot: path10.length === 0, - level: path10.length, + key: path11.slice(-1)[0], + isRoot: path11.length === 0, + level: path11.length, circular: null, update: function(x) { if (!state3.isRoot) { @@ -90678,7 +90678,7 @@ var require_traverse = __commonJS({ parents.push(state3); var keys = Object.keys(state3.node); keys.forEach(function(key, i2) { - path10.push(key); + path11.push(key); if (modifiers.pre) modifiers.pre.call(state3, state3.node[key], key); var child = walker(state3.node[key]); if (immutable && Object.hasOwnProperty.call(state3.node, key)) { @@ -90687,7 +90687,7 @@ var require_traverse = __commonJS({ child.isLast = i2 == keys.length - 1; child.isFirst = i2 == 0; if (modifiers.post) modifiers.post.call(state3, child); - path10.pop(); + path11.pop(); }); parents.pop(); } @@ -91708,11 +91708,11 @@ var require_unzip_stream = __commonJS({ return requiredLength; case states.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX: var isUtf8 = (this.parsedEntity.flags & 2048) !== 0; - var path10 = this._decodeString(chunk.slice(0, this.parsedEntity.fileNameLength), isUtf8); + var path11 = this._decodeString(chunk.slice(0, this.parsedEntity.fileNameLength), isUtf8); var extraDataBuffer = chunk.slice(this.parsedEntity.fileNameLength, this.parsedEntity.fileNameLength + this.parsedEntity.extraFieldLength); var extra = this._readExtraFields(extraDataBuffer); if (extra && extra.parsed && extra.parsed.path && !isUtf8) { - path10 = extra.parsed.path; + path11 = extra.parsed.path; } this.parsedEntity.extra = extra.parsed; var isUnix = (this.parsedEntity.versionMadeBy & 65280) >> 8 === 3; @@ -91724,7 +91724,7 @@ var require_unzip_stream = __commonJS({ } if (this.options.debug) { const debugObj2 = Object.assign({}, this.parsedEntity, { - path: path10, + path: path11, flags: "0x" + this.parsedEntity.flags.toString(16), unixAttrs: unixAttrs && "0" + unixAttrs.toString(8), isSymlink, @@ -92161,8 +92161,8 @@ var require_parser_stream = __commonJS({ // node_modules/mkdirp/index.js var require_mkdirp = __commonJS({ "node_modules/mkdirp/index.js"(exports2, module2) { - var path10 = require("path"); - var fs14 = require("fs"); + var path11 = require("path"); + var fs15 = require("fs"); var _0777 = parseInt("0777", 8); module2.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; function mkdirP(p, opts, f, made) { @@ -92173,7 +92173,7 @@ var require_mkdirp = __commonJS({ opts = { mode: opts }; } var mode = opts.mode; - var xfs = opts.fs || fs14; + var xfs = opts.fs || fs15; if (mode === void 0) { mode = _0777; } @@ -92181,7 +92181,7 @@ var require_mkdirp = __commonJS({ var cb = f || /* istanbul ignore next */ function() { }; - p = path10.resolve(p); + p = path11.resolve(p); xfs.mkdir(p, mode, function(er) { if (!er) { made = made || p; @@ -92189,8 +92189,8 @@ var require_mkdirp = __commonJS({ } switch (er.code) { case "ENOENT": - if (path10.dirname(p) === p) return cb(er); - mkdirP(path10.dirname(p), opts, function(er2, made2) { + if (path11.dirname(p) === p) return cb(er); + mkdirP(path11.dirname(p), opts, function(er2, made2) { if (er2) cb(er2, made2); else mkdirP(p, opts, cb, made2); }); @@ -92212,19 +92212,19 @@ var require_mkdirp = __commonJS({ opts = { mode: opts }; } var mode = opts.mode; - var xfs = opts.fs || fs14; + var xfs = opts.fs || fs15; if (mode === void 0) { mode = _0777; } if (!made) made = null; - p = path10.resolve(p); + p = path11.resolve(p); try { xfs.mkdirSync(p, mode); made = made || p; } catch (err0) { switch (err0.code) { case "ENOENT": - made = sync(path10.dirname(p), opts, made); + made = sync(path11.dirname(p), opts, made); sync(p, opts, made); break; // In the case of any other error, just see if there's a dir @@ -92249,8 +92249,8 @@ var require_mkdirp = __commonJS({ // node_modules/unzip-stream/lib/extract.js var require_extract2 = __commonJS({ "node_modules/unzip-stream/lib/extract.js"(exports2, module2) { - var fs14 = require("fs"); - var path10 = require("path"); + var fs15 = require("fs"); + var path11 = require("path"); var util3 = require("util"); var mkdirp = require_mkdirp(); var Transform3 = require("stream").Transform; @@ -92292,11 +92292,11 @@ var require_extract2 = __commonJS({ }; Extract.prototype._processEntry = function(entry) { var self2 = this; - var destPath = path10.join(this.opts.path, entry.path); - var directory = entry.isDirectory ? destPath : path10.dirname(destPath); + var destPath = path11.join(this.opts.path, entry.path); + var directory = entry.isDirectory ? destPath : path11.dirname(destPath); this.unfinishedEntries++; var writeFileFn = function() { - var pipedStream = fs14.createWriteStream(destPath); + var pipedStream = fs15.createWriteStream(destPath); pipedStream.on("close", function() { self2.unfinishedEntries--; self2._notifyAwaiter(); @@ -93715,12 +93715,12 @@ var require_io_util = __commonJS({ var _a; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getCmdPath = exports2.tryGetExecutablePath = exports2.isRooted = exports2.isDirectory = exports2.exists = exports2.READONLY = exports2.UV_FS_O_EXLOCK = exports2.IS_WINDOWS = exports2.unlink = exports2.symlink = exports2.stat = exports2.rmdir = exports2.rm = exports2.rename = exports2.readlink = exports2.readdir = exports2.open = exports2.mkdir = exports2.lstat = exports2.copyFile = exports2.chmod = void 0; - var fs14 = __importStar(require("fs")); - var path10 = __importStar(require("path")); - _a = fs14.promises, exports2.chmod = _a.chmod, exports2.copyFile = _a.copyFile, exports2.lstat = _a.lstat, exports2.mkdir = _a.mkdir, exports2.open = _a.open, exports2.readdir = _a.readdir, exports2.readlink = _a.readlink, exports2.rename = _a.rename, exports2.rm = _a.rm, exports2.rmdir = _a.rmdir, exports2.stat = _a.stat, exports2.symlink = _a.symlink, exports2.unlink = _a.unlink; + var fs15 = __importStar(require("fs")); + var path11 = __importStar(require("path")); + _a = fs15.promises, exports2.chmod = _a.chmod, exports2.copyFile = _a.copyFile, exports2.lstat = _a.lstat, exports2.mkdir = _a.mkdir, exports2.open = _a.open, exports2.readdir = _a.readdir, exports2.readlink = _a.readlink, exports2.rename = _a.rename, exports2.rm = _a.rm, exports2.rmdir = _a.rmdir, exports2.stat = _a.stat, exports2.symlink = _a.symlink, exports2.unlink = _a.unlink; exports2.IS_WINDOWS = process.platform === "win32"; exports2.UV_FS_O_EXLOCK = 268435456; - exports2.READONLY = fs14.constants.O_RDONLY; + exports2.READONLY = fs15.constants.O_RDONLY; function exists3(fsPath) { return __awaiter15(this, void 0, void 0, function* () { try { @@ -93765,7 +93765,7 @@ var require_io_util = __commonJS({ } if (stats && stats.isFile()) { if (exports2.IS_WINDOWS) { - const upperExt = path10.extname(filePath).toUpperCase(); + const upperExt = path11.extname(filePath).toUpperCase(); if (extensions.some((validExt) => validExt.toUpperCase() === upperExt)) { return filePath; } @@ -93789,11 +93789,11 @@ var require_io_util = __commonJS({ if (stats && stats.isFile()) { if (exports2.IS_WINDOWS) { try { - const directory = path10.dirname(filePath); - const upperName = path10.basename(filePath).toUpperCase(); + const directory = path11.dirname(filePath); + const upperName = path11.basename(filePath).toUpperCase(); for (const actualName of yield exports2.readdir(directory)) { if (upperName === actualName.toUpperCase()) { - filePath = path10.join(directory, actualName); + filePath = path11.join(directory, actualName); break; } } @@ -93888,7 +93888,7 @@ var require_io = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.findInPath = exports2.which = exports2.mkdirP = exports2.rmRF = exports2.mv = exports2.cp = void 0; var assert_1 = require("assert"); - var path10 = __importStar(require("path")); + var path11 = __importStar(require("path")); var ioUtil = __importStar(require_io_util()); function cp(source, dest, options = {}) { return __awaiter15(this, void 0, void 0, function* () { @@ -93897,7 +93897,7 @@ var require_io = __commonJS({ if (destStat && destStat.isFile() && !force) { return; } - const newDest = destStat && destStat.isDirectory() && copySourceDirectory ? path10.join(dest, path10.basename(source)) : dest; + const newDest = destStat && destStat.isDirectory() && copySourceDirectory ? path11.join(dest, path11.basename(source)) : dest; if (!(yield ioUtil.exists(source))) { throw new Error(`no such file or directory: ${source}`); } @@ -93909,7 +93909,7 @@ var require_io = __commonJS({ yield cpDirRecursive(source, newDest, 0, force); } } else { - if (path10.relative(source, newDest) === "") { + if (path11.relative(source, newDest) === "") { throw new Error(`'${newDest}' and '${source}' are the same file`); } yield copyFile2(source, newDest, force); @@ -93922,7 +93922,7 @@ var require_io = __commonJS({ if (yield ioUtil.exists(dest)) { let destExists = true; if (yield ioUtil.isDirectory(dest)) { - dest = path10.join(dest, path10.basename(source)); + dest = path11.join(dest, path11.basename(source)); destExists = yield ioUtil.exists(dest); } if (destExists) { @@ -93933,7 +93933,7 @@ var require_io = __commonJS({ } } } - yield mkdirP(path10.dirname(dest)); + yield mkdirP(path11.dirname(dest)); yield ioUtil.rename(source, dest); }); } @@ -93996,7 +93996,7 @@ var require_io = __commonJS({ } const extensions = []; if (ioUtil.IS_WINDOWS && process.env["PATHEXT"]) { - for (const extension of process.env["PATHEXT"].split(path10.delimiter)) { + for (const extension of process.env["PATHEXT"].split(path11.delimiter)) { if (extension) { extensions.push(extension); } @@ -94009,12 +94009,12 @@ var require_io = __commonJS({ } return []; } - if (tool.includes(path10.sep)) { + if (tool.includes(path11.sep)) { return []; } const directories = []; if (process.env.PATH) { - for (const p of process.env.PATH.split(path10.delimiter)) { + for (const p of process.env.PATH.split(path11.delimiter)) { if (p) { directories.push(p); } @@ -94022,7 +94022,7 @@ var require_io = __commonJS({ } const matches = []; for (const directory of directories) { - const filePath = yield ioUtil.tryGetExecutablePath(path10.join(directory, tool), extensions); + const filePath = yield ioUtil.tryGetExecutablePath(path11.join(directory, tool), extensions); if (filePath) { matches.push(filePath); } @@ -94138,7 +94138,7 @@ var require_toolrunner = __commonJS({ var os7 = __importStar(require("os")); var events = __importStar(require("events")); var child = __importStar(require("child_process")); - var path10 = __importStar(require("path")); + var path11 = __importStar(require("path")); var io = __importStar(require_io()); var ioUtil = __importStar(require_io_util()); var timers_1 = require("timers"); @@ -94353,7 +94353,7 @@ var require_toolrunner = __commonJS({ exec() { return __awaiter15(this, void 0, void 0, function* () { if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS3 && this.toolPath.includes("\\"))) { - this.toolPath = path10.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + this.toolPath = path11.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); } this.toolPath = yield io.which(this.toolPath, true); return new Promise((resolve2, reject) => __awaiter15(this, void 0, void 0, function* () { @@ -97813,13 +97813,13 @@ These characters are not allowed in the artifact name due to limitations with ce } info(`Artifact name is valid!`); } -function validateFilePath(path10) { - if (!path10) { +function validateFilePath(path11) { + if (!path11) { throw new Error(`Provided file path input during validation is empty`); } for (const [invalidCharacterKey, errorMessageForCharacter] of invalidArtifactFilePathCharacters) { - if (path10.includes(invalidCharacterKey)) { - throw new Error(`The path for one of the files in artifact is not valid: ${path10}. Contains the following character: ${errorMessageForCharacter} + if (path11.includes(invalidCharacterKey)) { + throw new Error(`The path for one of the files in artifact is not valid: ${path11}. Contains the following character: ${errorMessageForCharacter} Invalid characters include: ${Array.from(invalidArtifactFilePathCharacters.values()).toString()} @@ -102221,15 +102221,15 @@ function getRequestUrl(baseUri, operationSpec, operationArguments, fallbackObjec let isAbsolutePath = false; let requestUrl = replaceAll(baseUri, urlReplacements); if (operationSpec.path) { - let path10 = replaceAll(operationSpec.path, urlReplacements); - if (operationSpec.path === "/{nextLink}" && path10.startsWith("/")) { - path10 = path10.substring(1); + let path11 = replaceAll(operationSpec.path, urlReplacements); + if (operationSpec.path === "/{nextLink}" && path11.startsWith("/")) { + path11 = path11.substring(1); } - if (isAbsoluteUrl(path10)) { - requestUrl = path10; + if (isAbsoluteUrl(path11)) { + requestUrl = path11; isAbsolutePath = true; } else { - requestUrl = appendPath(requestUrl, path10); + requestUrl = appendPath(requestUrl, path11); } } const { queryParams, sequenceParams } = calculateQueryParameters(operationSpec, operationArguments, fallbackObject); @@ -102275,9 +102275,9 @@ function appendPath(url2, pathToAppend) { } const searchStart = pathToAppend.indexOf("?"); if (searchStart !== -1) { - const path10 = pathToAppend.substring(0, searchStart); + const path11 = pathToAppend.substring(0, searchStart); const search = pathToAppend.substring(searchStart + 1); - newPath = newPath + path10; + newPath = newPath + path11; if (search) { parsedUrl.search = parsedUrl.search ? `${parsedUrl.search}&${search}` : search; } @@ -106237,9 +106237,9 @@ var StorageSharedKeyCredentialPolicy = class extends CredentialPolicy { * @param request - */ getCanonicalizedResourceString(request2) { - const path10 = getURLPath(request2.url) || "/"; + const path11 = getURLPath(request2.url) || "/"; let canonicalizedResourceString = ""; - canonicalizedResourceString += `/${this.factory.accountName}${path10}`; + canonicalizedResourceString += `/${this.factory.accountName}${path11}`; const queries = getURLQueries(request2.url); const lowercaseQueries = {}; if (queries) { @@ -106729,9 +106729,9 @@ function storageSharedKeyCredentialPolicy(options) { return canonicalizedHeadersStringToSign; } function getCanonicalizedResourceString(request2) { - const path10 = getURLPath(request2.url) || "/"; + const path11 = getURLPath(request2.url) || "/"; let canonicalizedResourceString = ""; - canonicalizedResourceString += `/${options.accountName}${path10}`; + canonicalizedResourceString += `/${options.accountName}${path11}`; const queries = getURLQueries(request2.url); const lowercaseQueries = {}; if (queries) { @@ -120672,10 +120672,10 @@ var StorageContextClient = class extends StorageClient { // node_modules/@azure/storage-blob/dist/esm/utils/utils.common.js function escapeURLPath(url2) { const urlParsed = new URL(url2); - let path10 = urlParsed.pathname; - path10 = path10 || "/"; - path10 = escape(path10); - urlParsed.pathname = path10; + let path11 = urlParsed.pathname; + path11 = path11 || "/"; + path11 = escape(path11); + urlParsed.pathname = path11; return urlParsed.toString(); } function getProxyUriFromDevConnString(connectionString) { @@ -120760,9 +120760,9 @@ function escape(text) { } function appendToURLPath(url2, name) { const urlParsed = new URL(url2); - let path10 = urlParsed.pathname; - path10 = path10 ? path10.endsWith("/") ? `${path10}${name}` : `${path10}/${name}` : name; - urlParsed.pathname = path10; + let path11 = urlParsed.pathname; + path11 = path11 ? path11.endsWith("/") ? `${path11}${name}` : `${path11}/${name}` : name; + urlParsed.pathname = path11; return urlParsed.toString(); } function setURLParameter2(url2, name, value) { @@ -127759,8 +127759,8 @@ var Context = class { if ((0, import_fs2.existsSync)(process.env.GITHUB_EVENT_PATH)) { this.payload = JSON.parse((0, import_fs2.readFileSync)(process.env.GITHUB_EVENT_PATH, { encoding: "utf8" })); } else { - const path10 = process.env.GITHUB_EVENT_PATH; - process.stdout.write(`GITHUB_EVENT_PATH ${path10} does not exist${import_os4.EOL}`); + const path11 = process.env.GITHUB_EVENT_PATH; + process.stdout.write(`GITHUB_EVENT_PATH ${path11} does not exist${import_os4.EOL}`); } } this.eventName = process.env.GITHUB_EVENT_NAME; @@ -128428,8 +128428,8 @@ function isPlainObject2(value) { } var noop = () => ""; async function fetchWrapper(requestOptions) { - const fetch2 = requestOptions.request?.fetch || globalThis.fetch; - if (!fetch2) { + const fetch3 = requestOptions.request?.fetch || globalThis.fetch; + if (!fetch3) { throw new Error( "fetch is not set. Please pass a fetch implementation as new Octokit({ request: { fetch }}). Learn more at https://github.com/octokit/octokit.js/#fetch-missing" ); @@ -128445,7 +128445,7 @@ async function fetchWrapper(requestOptions) { ); let fetchResponse; try { - fetchResponse = await fetch2(requestOptions.url, { + fetchResponse = await fetch3(requestOptions.url, { method: requestOptions.method, body: body2, redirect: requestOptions.request?.redirect, @@ -131490,10 +131490,10 @@ var scrubQueryParameters = (url2) => { parsed.search = ""; return parsed.toString(); }; -function exists2(path10) { +function exists2(path11) { return __awaiter10(this, void 0, void 0, function* () { try { - yield import_promises3.default.access(path10); + yield import_promises3.default.access(path11); return true; } catch (error2) { if (error2.code === "ENOENT") { @@ -131702,17 +131702,17 @@ function requestLog(octokit) { octokit.log.debug("request", options); const start = Date.now(); const requestOptions = octokit.request.endpoint.parse(options); - const path10 = requestOptions.url.replace(options.baseUrl, ""); + const path11 = requestOptions.url.replace(options.baseUrl, ""); return request2(options).then((response) => { const requestId2 = response.headers["x-github-request-id"]; octokit.log.info( - `${requestOptions.method} ${path10} - ${response.status} with id ${requestId2} in ${Date.now() - start}ms` + `${requestOptions.method} ${path11} - ${response.status} with id ${requestId2} in ${Date.now() - start}ms` ); return response; }).catch((error2) => { const requestId2 = error2.response?.headers["x-github-request-id"] || "UNKNOWN"; octokit.log.error( - `${requestOptions.method} ${path10} - ${error2.status} with id ${requestId2} in ${Date.now() - start}ms` + `${requestOptions.method} ${path11} - ${error2.status} with id ${requestId2} in ${Date.now() - start}ms` ); throw error2; }); @@ -134242,8 +134242,8 @@ var ScanOssService = class { return new Error(`Error converting scan results into ${format} format`); } try { - const fs14 = await import("fs"); - await fs14.promises.access(filename, fs14.constants.F_OK); + const fs15 = await import("fs"); + await fs15.promises.access(filename, fs15.constants.F_OK); await uploadToArtifacts(filename); info(`Successfully converted results into ${format} format`); } catch (fileError) { @@ -134258,7 +134258,7 @@ var ScanOssService = class { var scanossService = new ScanOssService(); // src/utils/snippet-annotations.utils.ts -var fs13 = __toESM(require("fs")); +var fs14 = __toESM(require("fs")); var import_github24 = __toESM(require_github()); // src/utils/line-parsers.ts @@ -134377,6 +134377,8 @@ function createFileMatchSummaryAnnotation(fileMatches) { } // src/utils/github-comment-api.ts +var fs13 = __toESM(require("fs")); +var path10 = __toESM(require("path")); var import_github22 = __toESM(require_github()); // src/utils/api-cache.ts @@ -134470,6 +134472,117 @@ var RequestDeduplicator = class { }; var requestDeduplicator = new RequestDeduplicator(); +// src/utils/oss-file-contents.ts +var MAX_INLINE_CHARS = 1e4; +var DEFAULT_API_ORIGIN = "https://api.osskb.org"; +var EXTENSION_TO_LANGUAGE = { + ts: "ts", + tsx: "tsx", + js: "js", + jsx: "jsx", + mjs: "js", + cjs: "js", + py: "python", + java: "java", + c: "c", + h: "c", + cpp: "cpp", + cc: "cpp", + hpp: "cpp", + cs: "csharp", + go: "go", + rs: "rust", + rb: "ruby", + php: "php", + swift: "swift", + kt: "kotlin", + scala: "scala", + sh: "bash", + bash: "bash", + json: "json", + yaml: "yaml", + yml: "yaml", + xml: "xml", + html: "html", + css: "css", + scss: "scss", + sql: "sql", + md: "markdown" +}; +function getFileContentsUrl(fileHash) { + let origin = DEFAULT_API_ORIGIN; + if (API_URL) { + try { + origin = new URL(API_URL).origin; + } catch { + origin = DEFAULT_API_ORIGIN; + } + } + return `${origin}/file_contents/${fileHash}`; +} +function languageFromPath(filePath) { + const ext = filePath.split(".").pop()?.toLowerCase() ?? ""; + return EXTENSION_TO_LANGUAGE[ext] ?? ""; +} +async function fetchOssSnippetBlock(snippet) { + if (!snippet.file_hash) { + debug("OSS file contents skipped: match has no file_hash"); + return null; + } + if (!API_KEY) { + debug("OSS file contents skipped: no api.key configured (premium feature)"); + return null; + } + const url2 = getFileContentsUrl(snippet.file_hash); + let content; + try { + const response = await fetch(url2, { + headers: { "X-Session": API_KEY } + }); + if (!response.ok) { + debug(`OSS file contents request failed for ${snippet.file_hash}: HTTP ${response.status}`); + return null; + } + content = await response.text(); + } catch (error2) { + debug(`OSS file contents request errored for ${snippet.file_hash}: ${error2}`); + return null; + } + if (!content) return null; + const lines = content.split("\n"); + const range2 = parseLineRange(snippet.oss_lines); + const isWholeFile = !range2 || snippet.oss_lines === "all"; + let start = 1; + let end = lines.length; + if (!isWholeFile && range2) { + start = Math.max(1, range2.start); + end = Math.min(lines.length, range2.end); + } + const selectedLines = lines.slice(start - 1, end); + if (selectedLines.length === 0) return null; + let selected = selectedLines.join("\n"); + let truncated = false; + if (selected.length > MAX_INLINE_CHARS) { + let clipped = selected.slice(0, MAX_INLINE_CHARS); + const lastNewline = clipped.lastIndexOf("\n"); + if (lastNewline > 0) clipped = clipped.slice(0, lastNewline); + selected = clipped; + truncated = true; + } + if (!selected) return null; + const language = languageFromPath(snippet.file); + let block = ` + +\`\`\`${language} +${selected} +\`\`\``; + if (truncated) { + block += ` +_Output truncated to ${MAX_INLINE_CHARS} characters._`; + } + return block; +} + // src/utils/github-comment-api.ts function getFileUrl2(filePath) { const { owner, repo, sha } = resolveRepoAndSha(); @@ -134484,33 +134597,86 @@ function getFileUrlWithLineHighlight2(filePath, lineRange) { return `${baseUrl2}#L${lineRange.start}-L${lineRange.end}`; } } -function formatSnippetAnnotationMessage(filePath, snippet, localLines) { +function getLocalFileLineCount(filePath) { + try { + const content = fs13.readFileSync(path10.join(REPO_DIR, filePath), "utf8"); + if (!content) return null; + const normalized = content.endsWith("\n") ? content.slice(0, -1) : content; + return normalized.split("\n").length; + } catch { + return null; + } +} +function getOssFileGithubUrl(match, lineAnchor) { + if (!match.version || !match.file || !match.url) return null; + if (!match.url.startsWith("https://github.com/")) return null; + let filePath = match.file; + if (filePath.includes("/") && match.component && filePath.startsWith(`${match.component}-`)) { + filePath = filePath.substring(filePath.indexOf("/") + 1); + } + const base = `${match.url}/blob/${match.version}/${filePath}`; + return lineAnchor ? `${base}${lineAnchor}` : base; +} +function buildLineAnchor(oss_lines) { + const range2 = parseLineRange(oss_lines); + if (!range2) return ""; + return range2.start === range2.end ? `#L${range2.start}` : `#L${range2.start}-L${range2.end}`; +} +async function formatSnippetAnnotationMessage(filePath, snippet, localLines) { let message = `Code snippet matches ${snippet.component}`; if (snippet.version) { - message += ` v${snippet.version}`; + message += ` v${snippet.version.replace(/^v/, "")}`; } - message += ` (${snippet.matched}% similarity)`; + message += ` (${snippet.matched} similarity)`; if (snippet.licenses && snippet.licenses.length > 0) { - const license = snippet.licenses[0]; message += ` -License: ${license.name}`; +License: ${snippet.licenses[0].name}`; } if (snippet.url) { message += ` Source: ${snippet.url}`; } - if (snippet.oss_lines) { + const ossFileUrl = getOssFileGithubUrl(snippet); + let note = ""; + if (ossFileUrl) { + let ossRelativePath = snippet.file; + if (ossRelativePath.includes("/") && snippet.component && ossRelativePath.startsWith(`${snippet.component}-`)) { + ossRelativePath = ossRelativePath.substring(ossRelativePath.indexOf("/") + 1); + } message += ` +**OSS source file:** [${ossRelativePath}](${ossFileUrl})`; + if (snippet.oss_lines) { + const ossLinesUrl = getOssFileGithubUrl(snippet, buildLineAnchor(snippet.oss_lines)); + message += ` +OSS Lines: [${snippet.oss_lines}](${ossLinesUrl})`; + } + } else { + if (snippet.oss_lines) { + message += ` OSS Lines: ${snippet.oss_lines}`; + } + note = ` + +> [!NOTE] +> A browsable source link is not available for registry-sourced components.`; + } + const ossSnippetBlock = await fetchOssSnippetBlock(snippet); + if (ossSnippetBlock) { + message += ossSnippetBlock; } const viewUrl = snippet.lines === "all" ? getFileUrl2(filePath) : getFileUrlWithLineHighlight2(filePath, localLines); message += ` -View: ${viewUrl}`; + +**\u{1F4CD} Your file:** + +${viewUrl}`; + message += note; return message; } function formatFileAnnotationMessage(filePath, fileMatch) { const fileUrl = getFileUrl2(filePath); - const component = `${fileMatch.component}${fileMatch.version ? ` v${fileMatch.version}` : ""}`; + const version3 = fileMatch.version ? `v${fileMatch.version.replace(/^v/, "")}` : ""; + const component = `${fileMatch.component}${version3 ? ` ${version3}` : ""}`; let message = `**Full file match detected in [${filePath}](${fileUrl})** `; @@ -134525,6 +134691,25 @@ function formatFileAnnotationMessage(filePath, fileMatch) { message += `- **Source**: [${fileMatch.url}](${fileMatch.url}) `; } + const ossFileUrl = getOssFileGithubUrl(fileMatch); + let note = ""; + if (ossFileUrl) { + const ossRelativePath = fileMatch.file.includes("/") && fileMatch.file.startsWith(`${fileMatch.component}-`) ? fileMatch.file.substring(fileMatch.file.indexOf("/") + 1) : fileMatch.file; + message += `- **OSS source file**: [${ossRelativePath}](${ossFileUrl}) +`; + } else { + note = ` + +> [!NOTE] +> A browsable source link is not available for registry-sourced components.`; + } + const lineCount = getLocalFileLineCount(filePath); + const viewUrl = lineCount && lineCount > 0 ? getFileUrlWithLineHighlight2(filePath, { start: 1, end: lineCount }) : fileUrl; + message += ` +**\u{1F4CD} Your file:** + +${viewUrl}`; + message += note; return message; } async function createSnippetCommitComment(filePath, snippetMatch) { @@ -134533,8 +134718,9 @@ async function createSnippetCommitComment(filePath, snippetMatch) { warning(`Could not parse line range: ${snippetMatch.lines} for file: ${filePath}`); return false; } - const message = formatSnippetAnnotationMessage(filePath, snippetMatch, localLines); - const commentBody = `\u{1F50D} **Code Similarity Found** + const message = await formatSnippetAnnotationMessage(filePath, snippetMatch, localLines); + const commentBody = `> [!WARNING] +> \u{1F50D} **Code Similarity Found** \u2014 open-source code detected in this file. ${message}`; try { @@ -134569,7 +134755,8 @@ ${message}`; } async function createFileCommitComment(filePath, fileMatch) { const message = formatFileAnnotationMessage(filePath, fileMatch); - const commentBody = `\u{1F4C4} **Full File Match Found** + const commentBody = `> [!CAUTION] +> \u{1F4C4} **Full File Match Found** \u2014 this file matches an open-source component. ${message}`; try { @@ -134583,7 +134770,7 @@ ${message}`; body: commentBody }; info(`Creating file commit comment for ${filePath}`); - const deduplicationKey = `file-comment:${sha}:${filePath}:${fileMatch.component}${fileMatch.version ? `:v${fileMatch.version}` : ""}`; + const deduplicationKey = `file-comment:${sha}:${filePath}:${fileMatch.component}${fileMatch.version ? `:${fileMatch.version}` : ""}`; await requestDeduplicator.deduplicate(deduplicationKey, async () => { return await octokit.rest.repos.createCommitComment(params); }); @@ -134653,12 +134840,12 @@ async function createMainConversationComment(snippetMatches, fileMatches) { // src/utils/snippet-annotations.utils.ts async function createSnippetAnnotations(resultsPath) { - if (!fs13.existsSync(resultsPath)) { + if (!fs14.existsSync(resultsPath)) { warning(`Results file not found: ${resultsPath}`); return; } try { - const resultsContent = fs13.readFileSync(resultsPath, "utf8"); + const resultsContent = fs14.readFileSync(resultsPath, "utf8"); const results = JSON.parse(resultsContent); const snippetMatches = []; const fileMatches = []; diff --git a/package.json b/package.json index 4adac31..f508de8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "scanoss-code-scan-action", "description": "SCANOSS Code Scan Action", - "version": "1.6.4", + "version": "1.7.0", "author": "SCANOSS", "private": true, "homepage": "https://github.com/scanoss/code-scan-action/", diff --git a/src/types/annotations.ts b/src/types/annotations.ts index 6c0c6ab..a0e16f8 100644 --- a/src/types/annotations.ts +++ b/src/types/annotations.ts @@ -43,6 +43,8 @@ export interface SnippetMatch { url?: string; purl?: string[]; licenses?: LicenseInfo[]; + /** MD5 of the matched OSS file, used to retrieve its contents via the SCANOSS file_contents API */ + file_hash?: string; } /** diff --git a/src/utils/github-comment-api.ts b/src/utils/github-comment-api.ts index 4058123..8f949ef 100644 --- a/src/utils/github-comment-api.ts +++ b/src/utils/github-comment-api.ts @@ -22,12 +22,15 @@ */ import * as core from '@actions/core'; +import * as fs from 'fs'; +import * as path from 'path'; import { context, getOctokit } from '@actions/github'; import * as inputs from '../app.input'; import { isPullRequest, resolveRepoAndSha } from './github.utils'; import { SnippetMatch, FileMatch, LineRange, SnippetMatchWithPath, FileMatchWithPath } from '../types/annotations'; import { parseLineRange } from './line-parsers'; import { requestDeduplicator } from './api-cache'; +import { fetchOssSnippetBlock } from './oss-file-contents'; /** * Creates a GitHub URL for the file @@ -53,34 +56,119 @@ function getFileUrlWithLineHighlight(filePath: string, lineRange: LineRange): st } } -function formatSnippetAnnotationMessage(filePath: string, snippet: SnippetMatch, localLines: LineRange): string { +/** + * Best-effort count of the lines in a repository file checked out in the workspace. + * + * Used to build a whole-file line anchor (`#L1-L{n}`) for full-file matches: GitHub + * only renders the embedded code preview for permalinks that carry a line range, so a + * bare blob URL stays a plain link. Returns null when the file cannot be read, in which + * case the caller falls back to the plain (non-embedding) link. + */ +function getLocalFileLineCount(filePath: string): number | null { + try { + const content = fs.readFileSync(path.join(inputs.REPO_DIR, filePath), 'utf8'); + if (!content) return null; + // Ignore a single trailing newline so it doesn't add a phantom empty line. + const normalized = content.endsWith('\n') ? content.slice(0, -1) : content; + return normalized.split('\n').length; + } catch { + return null; + } +} + +/** + * Builds a GitHub permalink to a specific OSS file. + * + * Only applies to GitHub-native components, detected via the `url` field pointing to + * github.com. We intentionally do NOT use the PURL: a registry component (e.g. an npm + * package) can carry a `pkg:github` PURL, but its `version` (registry version) and `file` + * (tarball path) do not map to the GitHub repository and would produce broken links. + * + * The `file` field may include a "{component}-{ref}/" prefix that is stripped. + */ +function getOssFileGithubUrl( + match: { url?: string; version?: string; file: string; component: string }, + lineAnchor?: string +): string | null { + if (!match.version || !match.file || !match.url) return null; + if (!match.url.startsWith('https://github.com/')) return null; + + // Strip the "{component}-{ref}/" prefix when present + let filePath = match.file; + if (filePath.includes('/') && match.component && filePath.startsWith(`${match.component}-`)) { + filePath = filePath.substring(filePath.indexOf('/') + 1); + } + + const base = `${match.url}/blob/${match.version}/${filePath}`; + return lineAnchor ? `${base}${lineAnchor}` : base; +} + +function buildLineAnchor(oss_lines: string): string { + const range = parseLineRange(oss_lines); + if (!range) return ''; + return range.start === range.end ? `#L${range.start}` : `#L${range.start}-L${range.end}`; +} + +async function formatSnippetAnnotationMessage( + filePath: string, + snippet: SnippetMatch, + localLines: LineRange +): Promise { let message = `Code snippet matches ${snippet.component}`; if (snippet.version) { - message += ` v${snippet.version}`; + message += ` v${snippet.version.replace(/^v/, '')}`; } - message += ` (${snippet.matched}% similarity)`; + message += ` (${snippet.matched} similarity)`; - // Add license information if (snippet.licenses && snippet.licenses.length > 0) { - const license = snippet.licenses[0]; - message += `\nLicense: ${license.name}`; + message += `\nLicense: ${snippet.licenses[0].name}`; } - // Add source URL if (snippet.url) { message += `\nSource: ${snippet.url}`; } - // Add OSS line range - if (snippet.oss_lines) { - message += `\nOSS Lines: ${snippet.oss_lines}`; + const ossFileUrl = getOssFileGithubUrl(snippet); + let note = ''; + + if (ossFileUrl) { + // GitHub-native component: link to the matched file and line range + let ossRelativePath = snippet.file; + if (ossRelativePath.includes('/') && snippet.component && ossRelativePath.startsWith(`${snippet.component}-`)) { + ossRelativePath = ossRelativePath.substring(ossRelativePath.indexOf('/') + 1); + } + message += `\n**OSS source file:** [${ossRelativePath}](${ossFileUrl})`; + + if (snippet.oss_lines) { + const ossLinesUrl = getOssFileGithubUrl(snippet, buildLineAnchor(snippet.oss_lines)); + message += `\nOSS Lines: [${snippet.oss_lines}](${ossLinesUrl})`; + } + } else { + // Non-GitHub component: no browsable source link can be built + if (snippet.oss_lines) { + message += `\nOSS Lines: ${snippet.oss_lines}`; + } + note = `\n\n> [!NOTE]\n> A browsable source link is not available for registry-sourced components.`; } - // Add view link + // Inline the matched OSS source (fetched by file hash from the SCANOSS file_contents + // API). Works for any component regardless of source registry, but requires a premium + // api.key; returns null otherwise and the message degrades gracefully. + const ossSnippetBlock = await fetchOssSnippetBlock(snippet); + if (ossSnippetBlock) { + message += ossSnippetBlock; + } + + // Link to the matching code in the user's own repository, clearly labelled to + // distinguish it from the OSS source above. The bare permalink in its own paragraph + // lets GitHub render it as an embedded snippet preview. const viewUrl = snippet.lines === 'all' ? getFileUrl(filePath) : getFileUrlWithLineHighlight(filePath, localLines); - message += `\nView: ${viewUrl}`; + message += `\n\n**📍 Your file:**\n\n${viewUrl}`; + + // Append the note (if any) at the very end of the comment + message += note; return message; } @@ -93,7 +181,8 @@ function formatSnippetAnnotationMessage(filePath: string, snippet: SnippetMatch, */ function formatFileAnnotationMessage(filePath: string, fileMatch: FileMatch): string { const fileUrl = getFileUrl(filePath); - const component = `${fileMatch.component}${fileMatch.version ? ` v${fileMatch.version}` : ''}`; + const version = fileMatch.version ? `v${fileMatch.version.replace(/^v/, '')}` : ''; + const component = `${fileMatch.component}${version ? ` ${version}` : ''}`; let message = `**Full file match detected in [${filePath}](${fileUrl})**\n\n`; message += `- **Component**: ${component}\n`; @@ -107,6 +196,33 @@ function formatFileAnnotationMessage(filePath: string, fileMatch: FileMatch): st message += `- **Source**: [${fileMatch.url}](${fileMatch.url})\n`; } + const ossFileUrl = getOssFileGithubUrl(fileMatch); + let note = ''; + if (ossFileUrl) { + // GitHub-native component: link to the matched source file + const ossRelativePath = + fileMatch.file.includes('/') && fileMatch.file.startsWith(`${fileMatch.component}-`) + ? fileMatch.file.substring(fileMatch.file.indexOf('/') + 1) + : fileMatch.file; + message += `- **OSS source file**: [${ossRelativePath}](${ossFileUrl})\n`; + } else { + // Non-GitHub component: no browsable source link can be built + note = `\n\n> [!NOTE]\n> A browsable source link is not available for registry-sourced components.`; + } + + // Link to the matched file in the user's own repo, clearly labelled to distinguish it + // from the OSS source above. GitHub only renders the embedded snippet preview when the + // permalink carries a line range, so anchor the whole file (#L1-L{n}) when we can read + // it; otherwise fall back to the plain blob link. The bare permalink in its own + // paragraph lets GitHub render the embedded preview. + const lineCount = getLocalFileLineCount(filePath); + const viewUrl = + lineCount && lineCount > 0 ? getFileUrlWithLineHighlight(filePath, { start: 1, end: lineCount }) : fileUrl; + message += `\n**📍 Your file:**\n\n${viewUrl}`; + + // Append the note (if any) at the very end of the comment + message += note; + return message; } @@ -142,8 +258,8 @@ export async function createSnippetCommitComment(filePath: string, snippetMatch: return false; } - const message = formatSnippetAnnotationMessage(filePath, snippetMatch, localLines); - const commentBody = `🔍 **Code Similarity Found**\n\n${message}`; + const message = await formatSnippetAnnotationMessage(filePath, snippetMatch, localLines); + const commentBody = `> [!WARNING]\n> 🔍 **Code Similarity Found** — open-source code detected in this file.\n\n${message}`; try { const octokit = getOctokit(inputs.GITHUB_TOKEN); @@ -190,7 +306,7 @@ export async function createSnippetCommitComment(filePath: string, snippetMatch: */ export async function createFileCommitComment(filePath: string, fileMatch: FileMatch): Promise { const message = formatFileAnnotationMessage(filePath, fileMatch); - const commentBody = `📄 **Full File Match Found**\n\n${message}`; + const commentBody = `> [!CAUTION]\n> 📄 **Full File Match Found** — this file matches an open-source component.\n\n${message}`; try { const octokit = getOctokit(inputs.GITHUB_TOKEN); @@ -207,7 +323,7 @@ export async function createFileCommitComment(filePath: string, fileMatch: FileM core.info(`Creating file commit comment for ${filePath}`); // Use request deduplication to prevent duplicate comments for the same file - const deduplicationKey = `file-comment:${sha}:${filePath}:${fileMatch.component}${fileMatch.version ? `:v${fileMatch.version}` : ''}`; + const deduplicationKey = `file-comment:${sha}:${filePath}:${fileMatch.component}${fileMatch.version ? `:${fileMatch.version}` : ''}`; await requestDeduplicator.deduplicate(deduplicationKey, async () => { return await octokit.rest.repos.createCommitComment(params); }); diff --git a/src/utils/oss-file-contents.ts b/src/utils/oss-file-contents.ts new file mode 100644 index 0000000..4acc5c9 --- /dev/null +++ b/src/utils/oss-file-contents.ts @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +/* + Copyright (c) 2025, SCANOSS + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +import * as core from '@actions/core'; +import * as inputs from '../app.input'; +import { SnippetMatch, LineRange } from '../types/annotations'; +import { parseLineRange } from './line-parsers'; + +/** + * Maximum number of characters of OSS source to inline into a comment. GitHub caps + * comment bodies at 65,536 characters; ~10 KB leaves ample headroom for the rest of + * the message while still showing a substantial portion of the matched code. + */ +const MAX_INLINE_CHARS = 10000; + +/** Default SCANOSS host used when no custom api.url is supplied. */ +const DEFAULT_API_ORIGIN = 'https://api.osskb.org'; + +/** + * Maps common file extensions to a Markdown code-fence language hint for syntax highlighting. + */ +const EXTENSION_TO_LANGUAGE: Record = { + ts: 'ts', + tsx: 'tsx', + js: 'js', + jsx: 'jsx', + mjs: 'js', + cjs: 'js', + py: 'python', + java: 'java', + c: 'c', + h: 'c', + cpp: 'cpp', + cc: 'cpp', + hpp: 'cpp', + cs: 'csharp', + go: 'go', + rs: 'rust', + rb: 'ruby', + php: 'php', + swift: 'swift', + kt: 'kotlin', + scala: 'scala', + sh: 'bash', + bash: 'bash', + json: 'json', + yaml: 'yaml', + yml: 'yaml', + xml: 'xml', + html: 'html', + css: 'css', + scss: 'scss', + sql: 'sql', + md: 'markdown' +}; + +/** + * Derives the SCANOSS file_contents endpoint URL for a given file hash. + * + * The configured `api.url` points at the scan endpoint (e.g. + * `https://api.osskb.org/scan/direct`); the file_contents endpoint lives at the + * same origin under `/file_contents/{md5}`. + */ +export function getFileContentsUrl(fileHash: string): string { + let origin = DEFAULT_API_ORIGIN; + if (inputs.API_URL) { + try { + origin = new URL(inputs.API_URL).origin; + } catch { + origin = DEFAULT_API_ORIGIN; + } + } + return `${origin}/file_contents/${fileHash}`; +} + +/** + * Resolves a Markdown code-fence language hint from a file path. + */ +function languageFromPath(filePath: string): string { + const ext = filePath.split('.').pop()?.toLowerCase() ?? ''; + return EXTENSION_TO_LANGUAGE[ext] ?? ''; +} + +/** + * Fetches the matched OSS file from the SCANOSS file_contents API and returns the + * portion covered by `oss_lines` as a Markdown fenced code block. + * + * The file_contents endpoint is a premium SCANOSS feature: it requires a valid + * `api.key` (sent as the `X-Session` header). When no key is configured, when the + * match lacks a file hash, or when the request fails, this returns `null` and the + * caller should fall back to the existing link/plain-text behavior. + * + * @param snippet - The snippet match containing `file_hash` and `oss_lines` + * @returns A fenced code block string, or `null` when contents cannot be inlined + */ +export async function fetchOssSnippetBlock(snippet: SnippetMatch): Promise { + if (!snippet.file_hash) { + core.debug('OSS file contents skipped: match has no file_hash'); + return null; + } + + // file_contents is premium-gated; without an API key the request returns 403. + if (!inputs.API_KEY) { + core.debug('OSS file contents skipped: no api.key configured (premium feature)'); + return null; + } + + const url = getFileContentsUrl(snippet.file_hash); + + let content: string; + try { + const response = await fetch(url, { + headers: { 'X-Session': inputs.API_KEY } + }); + + if (!response.ok) { + core.debug(`OSS file contents request failed for ${snippet.file_hash}: HTTP ${response.status}`); + return null; + } + + content = await response.text(); + } catch (error) { + core.debug(`OSS file contents request errored for ${snippet.file_hash}: ${error}`); + return null; + } + + if (!content) return null; + + const lines = content.split('\n'); + + // Determine the slice covered by oss_lines (1-based, inclusive). "all" yields {1,1}. + const range: LineRange | null = parseLineRange(snippet.oss_lines); + const isWholeFile = !range || snippet.oss_lines === 'all'; + + let start = 1; + let end = lines.length; + if (!isWholeFile && range) { + start = Math.max(1, range.start); + end = Math.min(lines.length, range.end); + } + + const selectedLines = lines.slice(start - 1, end); + if (selectedLines.length === 0) return null; + + let selected = selectedLines.join('\n'); + let truncated = false; + if (selected.length > MAX_INLINE_CHARS) { + // Clip to the character budget, then back off to the last complete line so we + // never emit a half-line of code. + let clipped = selected.slice(0, MAX_INLINE_CHARS); + const lastNewline = clipped.lastIndexOf('\n'); + if (lastNewline > 0) clipped = clipped.slice(0, lastNewline); + selected = clipped; + truncated = true; + } + + if (!selected) return null; + + const language = languageFromPath(snippet.file); + let block = `\n\n\`\`\`${language}\n${selected}\n\`\`\``; + if (truncated) { + block += `\n_Output truncated to ${MAX_INLINE_CHARS} characters._`; + } + + return block; +}