From 41749ce1a0fd379fff99ab3a689174aee8293c9c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 May 2026 17:08:28 +0000 Subject: [PATCH 1/6] Initial plan From 34b97229cd1a7b280cf2c37914e3cf57cfad0955 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 May 2026 17:13:21 +0000 Subject: [PATCH 2/6] feat: add funding metadata to package manifests Agent-Logs-Url: https://github.com/nevware21/ts-utils/sessions/2e7013fa-24b9-4872-b36e-5334a452fffa Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com> --- lib/package.json | 10 +++++ lib/test/src/node/funding.details.test.ts | 51 +++++++++++++++++++++++ package.json | 10 +++++ 3 files changed, 71 insertions(+) create mode 100644 lib/test/src/node/funding.details.test.ts diff --git a/lib/package.json b/lib/package.json index 731a9841..c0bed294 100644 --- a/lib/package.json +++ b/lib/package.json @@ -164,6 +164,16 @@ "bugs": { "url": "https://github.com/nevware21/ts-utils/issues" }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nevware21" + }, + { + "type": "other", + "url": "https://buymeacoffee.com/nevware21" + } + ], "licenses": [ { "type": "MIT", diff --git a/lib/test/src/node/funding.details.test.ts b/lib/test/src/node/funding.details.test.ts new file mode 100644 index 00000000..29b55e17 --- /dev/null +++ b/lib/test/src/node/funding.details.test.ts @@ -0,0 +1,51 @@ +/* + * @nevware21/ts-utils + * https://github.com/nevware21/ts-utils + * + * Copyright (c) 2026 NevWare21 Solutions LLC + * Licensed under the MIT license. + */ + +import * as fs from "fs"; + +import { assert } from "@nevware21/tripwire-chai"; + +describe("funding metadata references", () => { + function _getFundingUrls(packageJson: any): string[] { + let funding = packageJson && packageJson.funding; + if (!funding) { + return []; + } + + let fundingEntries = Array.isArray(funding) ? funding : [funding]; + return fundingEntries.map((entry) => { + return typeof entry === "string" ? entry : entry && entry.url; + }).filter((entry) => !!entry); + } + + it("includes funding metadata in root and published package files", () => { + let rootPackage = JSON.parse(fs.readFileSync("package.json", "utf8")); + let publishPackage = JSON.parse(fs.readFileSync("lib/package.json", "utf8")); + + let expectedUrls = [ + "https://github.com/sponsors/nevware21", + "https://buymeacoffee.com/nevware21" + ]; + + expectedUrls.forEach((expectedUrl) => { + assert.equal(_getFundingUrls(rootPackage).indexOf(expectedUrl) !== -1, true, "Expected root package.json funding to contain " + expectedUrl); + assert.equal(_getFundingUrls(publishPackage).indexOf(expectedUrl) !== -1, true, "Expected lib/package.json funding to contain " + expectedUrl); + }); + }); + + it("keeps sponsor references in documentation and github funding config", () => { + let readme = fs.readFileSync("README.md", "utf8"); + let docsReadme = fs.readFileSync("docs/README.md", "utf8"); + let githubFunding = fs.readFileSync(".github/FUNDING.yml", "utf8"); + + assert.equal(readme.indexOf("https://github.com/sponsors/nevware21") !== -1, true, "Expected README.md sponsor link to exist"); + assert.equal(docsReadme.indexOf("https://github.com/sponsors/nevware21") !== -1, true, "Expected docs/README.md sponsor link to exist"); + assert.equal(githubFunding.indexOf("github: [nevware21]") !== -1, true, "Expected .github/FUNDING.yml GitHub Sponsors entry to exist"); + assert.equal(githubFunding.indexOf("buy_me_a_coffee: nevware21") !== -1, true, "Expected .github/FUNDING.yml Buy Me a Coffee entry to exist"); + }); +}); diff --git a/package.json b/package.json index 0a97ce78..c9c440d3 100644 --- a/package.json +++ b/package.json @@ -199,6 +199,16 @@ "bugs": { "url": "https://github.com/nevware21/ts-utils/issues" }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nevware21" + }, + { + "type": "other", + "url": "https://buymeacoffee.com/nevware21" + } + ], "licenses": [ { "type": "MIT", From 6a23d99d0c210d9a70218662b1beb76ccc44231b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 May 2026 17:16:31 +0000 Subject: [PATCH 3/6] test: harden sponsor link validation logic Agent-Logs-Url: https://github.com/nevware21/ts-utils/sessions/2e7013fa-24b9-4872-b36e-5334a452fffa Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com> --- lib/test/src/node/funding.details.test.ts | 30 ++++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/test/src/node/funding.details.test.ts b/lib/test/src/node/funding.details.test.ts index 29b55e17..25d6c96b 100644 --- a/lib/test/src/node/funding.details.test.ts +++ b/lib/test/src/node/funding.details.test.ts @@ -11,6 +11,24 @@ import * as fs from "fs"; import { assert } from "@nevware21/tripwire-chai"; describe("funding metadata references", () => { + function _hasGitHubSponsorLink(content: string): boolean { + let markdownLinkRegex = /\[[^\]]+\]\((https?:\/\/[^)]+)\)/g; + let match: RegExpExecArray | null; + while ((match = markdownLinkRegex.exec(content))) { + let linkUrl = match[1]; + try { + let parsed = new URL(linkUrl); + if (parsed.hostname === "github.com" && parsed.pathname === "/sponsors/nevware21") { + return true; + } + } catch (e) { + // Ignore invalid URLs while scanning links + } + } + + return false; + } + function _getFundingUrls(packageJson: any): string[] { let funding = packageJson && packageJson.funding; if (!funding) { @@ -33,8 +51,8 @@ describe("funding metadata references", () => { ]; expectedUrls.forEach((expectedUrl) => { - assert.equal(_getFundingUrls(rootPackage).indexOf(expectedUrl) !== -1, true, "Expected root package.json funding to contain " + expectedUrl); - assert.equal(_getFundingUrls(publishPackage).indexOf(expectedUrl) !== -1, true, "Expected lib/package.json funding to contain " + expectedUrl); + assert.equal(_getFundingUrls(rootPackage).includes(expectedUrl), true, "Expected root package.json funding to contain " + expectedUrl); + assert.equal(_getFundingUrls(publishPackage).includes(expectedUrl), true, "Expected lib/package.json funding to contain " + expectedUrl); }); }); @@ -43,9 +61,9 @@ describe("funding metadata references", () => { let docsReadme = fs.readFileSync("docs/README.md", "utf8"); let githubFunding = fs.readFileSync(".github/FUNDING.yml", "utf8"); - assert.equal(readme.indexOf("https://github.com/sponsors/nevware21") !== -1, true, "Expected README.md sponsor link to exist"); - assert.equal(docsReadme.indexOf("https://github.com/sponsors/nevware21") !== -1, true, "Expected docs/README.md sponsor link to exist"); - assert.equal(githubFunding.indexOf("github: [nevware21]") !== -1, true, "Expected .github/FUNDING.yml GitHub Sponsors entry to exist"); - assert.equal(githubFunding.indexOf("buy_me_a_coffee: nevware21") !== -1, true, "Expected .github/FUNDING.yml Buy Me a Coffee entry to exist"); + assert.equal(_hasGitHubSponsorLink(readme), true, "Expected README.md sponsor link to exist"); + assert.equal(_hasGitHubSponsorLink(docsReadme), true, "Expected docs/README.md sponsor link to exist"); + assert.equal(githubFunding.includes("github: [nevware21]"), true, "Expected .github/FUNDING.yml GitHub Sponsors entry to exist"); + assert.equal(githubFunding.includes("buy_me_a_coffee: nevware21"), true, "Expected .github/FUNDING.yml Buy Me a Coffee entry to exist"); }); }); From 3c1b03963ed5866a6b01e9e87648973ebff11e5e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 May 2026 17:18:16 +0000 Subject: [PATCH 4/6] style: use const for immutable funding test values Agent-Logs-Url: https://github.com/nevware21/ts-utils/sessions/2e7013fa-24b9-4872-b36e-5334a452fffa Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com> --- lib/test/src/node/funding.details.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/test/src/node/funding.details.test.ts b/lib/test/src/node/funding.details.test.ts index 25d6c96b..6c934bfe 100644 --- a/lib/test/src/node/funding.details.test.ts +++ b/lib/test/src/node/funding.details.test.ts @@ -12,10 +12,10 @@ import { assert } from "@nevware21/tripwire-chai"; describe("funding metadata references", () => { function _hasGitHubSponsorLink(content: string): boolean { - let markdownLinkRegex = /\[[^\]]+\]\((https?:\/\/[^)]+)\)/g; + const markdownLinkRegex = /\[[^\]]+\]\((https?:\/\/[^)]+)\)/g; let match: RegExpExecArray | null; while ((match = markdownLinkRegex.exec(content))) { - let linkUrl = match[1]; + const linkUrl = match[1]; try { let parsed = new URL(linkUrl); if (parsed.hostname === "github.com" && parsed.pathname === "/sponsors/nevware21") { @@ -35,7 +35,7 @@ describe("funding metadata references", () => { return []; } - let fundingEntries = Array.isArray(funding) ? funding : [funding]; + const fundingEntries = Array.isArray(funding) ? funding : [funding]; return fundingEntries.map((entry) => { return typeof entry === "string" ? entry : entry && entry.url; }).filter((entry) => !!entry); From e2bd24dbcd42bb01c2ec5587b220337c01fbca3e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 04:53:16 +0000 Subject: [PATCH 5/6] revert: drop unnecessary const-only churn in funding details test Agent-Logs-Url: https://github.com/nevware21/ts-utils/sessions/c1512a10-2595-4043-8a39-8524dd74135a Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com> --- lib/test/src/node/funding.details.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/test/src/node/funding.details.test.ts b/lib/test/src/node/funding.details.test.ts index 6c934bfe..25d6c96b 100644 --- a/lib/test/src/node/funding.details.test.ts +++ b/lib/test/src/node/funding.details.test.ts @@ -12,10 +12,10 @@ import { assert } from "@nevware21/tripwire-chai"; describe("funding metadata references", () => { function _hasGitHubSponsorLink(content: string): boolean { - const markdownLinkRegex = /\[[^\]]+\]\((https?:\/\/[^)]+)\)/g; + let markdownLinkRegex = /\[[^\]]+\]\((https?:\/\/[^)]+)\)/g; let match: RegExpExecArray | null; while ((match = markdownLinkRegex.exec(content))) { - const linkUrl = match[1]; + let linkUrl = match[1]; try { let parsed = new URL(linkUrl); if (parsed.hostname === "github.com" && parsed.pathname === "/sponsors/nevware21") { @@ -35,7 +35,7 @@ describe("funding metadata references", () => { return []; } - const fundingEntries = Array.isArray(funding) ? funding : [funding]; + let fundingEntries = Array.isArray(funding) ? funding : [funding]; return fundingEntries.map((entry) => { return typeof entry === "string" ? entry : entry && entry.url; }).filter((entry) => !!entry); From 6604187c50dbd11561f0b981e2f5588dd5b05536 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 05:01:06 +0000 Subject: [PATCH 6/6] test: remove unneeded funding details test Agent-Logs-Url: https://github.com/nevware21/ts-utils/sessions/78d2a5a6-56db-47dc-8f8b-803e0d9704ba Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com> --- lib/test/src/node/funding.details.test.ts | 69 ----------------------- 1 file changed, 69 deletions(-) delete mode 100644 lib/test/src/node/funding.details.test.ts diff --git a/lib/test/src/node/funding.details.test.ts b/lib/test/src/node/funding.details.test.ts deleted file mode 100644 index 25d6c96b..00000000 --- a/lib/test/src/node/funding.details.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * @nevware21/ts-utils - * https://github.com/nevware21/ts-utils - * - * Copyright (c) 2026 NevWare21 Solutions LLC - * Licensed under the MIT license. - */ - -import * as fs from "fs"; - -import { assert } from "@nevware21/tripwire-chai"; - -describe("funding metadata references", () => { - function _hasGitHubSponsorLink(content: string): boolean { - let markdownLinkRegex = /\[[^\]]+\]\((https?:\/\/[^)]+)\)/g; - let match: RegExpExecArray | null; - while ((match = markdownLinkRegex.exec(content))) { - let linkUrl = match[1]; - try { - let parsed = new URL(linkUrl); - if (parsed.hostname === "github.com" && parsed.pathname === "/sponsors/nevware21") { - return true; - } - } catch (e) { - // Ignore invalid URLs while scanning links - } - } - - return false; - } - - function _getFundingUrls(packageJson: any): string[] { - let funding = packageJson && packageJson.funding; - if (!funding) { - return []; - } - - let fundingEntries = Array.isArray(funding) ? funding : [funding]; - return fundingEntries.map((entry) => { - return typeof entry === "string" ? entry : entry && entry.url; - }).filter((entry) => !!entry); - } - - it("includes funding metadata in root and published package files", () => { - let rootPackage = JSON.parse(fs.readFileSync("package.json", "utf8")); - let publishPackage = JSON.parse(fs.readFileSync("lib/package.json", "utf8")); - - let expectedUrls = [ - "https://github.com/sponsors/nevware21", - "https://buymeacoffee.com/nevware21" - ]; - - expectedUrls.forEach((expectedUrl) => { - assert.equal(_getFundingUrls(rootPackage).includes(expectedUrl), true, "Expected root package.json funding to contain " + expectedUrl); - assert.equal(_getFundingUrls(publishPackage).includes(expectedUrl), true, "Expected lib/package.json funding to contain " + expectedUrl); - }); - }); - - it("keeps sponsor references in documentation and github funding config", () => { - let readme = fs.readFileSync("README.md", "utf8"); - let docsReadme = fs.readFileSync("docs/README.md", "utf8"); - let githubFunding = fs.readFileSync(".github/FUNDING.yml", "utf8"); - - assert.equal(_hasGitHubSponsorLink(readme), true, "Expected README.md sponsor link to exist"); - assert.equal(_hasGitHubSponsorLink(docsReadme), true, "Expected docs/README.md sponsor link to exist"); - assert.equal(githubFunding.includes("github: [nevware21]"), true, "Expected .github/FUNDING.yml GitHub Sponsors entry to exist"); - assert.equal(githubFunding.includes("buy_me_a_coffee: nevware21"), true, "Expected .github/FUNDING.yml Buy Me a Coffee entry to exist"); - }); -});