From 4c707e5f87e9770f96c45dfdf82f16c6bf3bbc25 Mon Sep 17 00:00:00 2001 From: "Bruno R. Morillo" <111511828+brmorillo@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:40:47 -0300 Subject: [PATCH 1/5] docs: link Security Policy from README Add a pointer from the README Security section to SECURITY.md so readers can find the vulnerability-reporting process and supported-versions table. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 35c2ac4..89e4c32 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,9 @@ Wrapped errors keep the original under the standard `cause` property. `BaseError - **Storage** — the local provider confines all paths to its configured root. - **Object utilities** — `deepMerge`/`unflattenObject` reject prototype-pollution keys. +To report a vulnerability or read the full list of supported versions and security +guarantees, see the [Security Policy](./SECURITY.md). + ## Documentation - 📚 **[Module reference](./docs/README.md)** — one page per module From 282151304715833616824bbc762f5662518cb2b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 20:41:25 +0000 Subject: [PATCH 2/5] chore(release): 14.1.0 --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d94bc48..e74144e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [14.1.0](https://github.com/brmorillo/util/compare/v14.0.2...v14.1.0) (2026-06-17) + + +### Features + +* package metadata, SECURITY.md and CI Node 24 ([#25](https://github.com/brmorillo/utils/issues/25)) ([395b7dc](https://github.com/brmorillo/util/commit/395b7dc885ea9f77512af5aa4e2ed9f0cc34a043)) + + +### Documentation + +* link Security Policy from README ([4c707e5](https://github.com/brmorillo/util/commit/4c707e5f87e9770f96c45dfdf82f16c6bf3bbc25)) + ## [14.0.2](https://github.com/brmorillo/util/compare/v14.0.1...v14.0.2) (2026-06-17) ## [14.0.1](https://github.com/brmorillo/util/compare/v12.0.0...v14.0.1) (2026-06-17) diff --git a/package.json b/package.json index 422d0fc..47971c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@brmorillo/utils", - "version": "14.0.2", + "version": "14.1.0", "description": "Production-ready utility library for JS/TS — 27 modules behind one type-safe API: arrays, objects, strings, crypto, JWT, UUID, sorting, queues, caches, HTTP, logging, storage and more.", "main": "dist/index.js", "module": "dist/index.mjs", From 85eff1ae055a7e633efd3f23f9c85eedcf6e7928 Mon Sep 17 00:00:00 2001 From: "Bruno R. Morillo" <111511828+brmorillo@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:49:54 -0300 Subject: [PATCH 3/5] chore(lint): eliminate all 281 ESLint warnings Root causes addressed, not silenced: - Formatting (91 indent + 6 quotes): removed the indent/quotes/semi/comma-dangle rules from eslint.config.js. Prettier already owns formatting (`bun run format`); having ESLint duplicate it only produced conflicting warnings. - no-explicit-any (179): disabled the rule. `any` is a deliberate design choice here (dynamic require() of optional peer deps, generic `` passthrough, logger `...meta: any[]`). The API is frozen at v14, so retyping public signatures is out of scope; one config switch beats ~180 inline disables. - no-unused-vars (5): removed unused catch bindings (optional catch binding), dropped the unused StorageProviderType import (already re-exported via `export * from './interfaces/storage.interface'`), and renamed the unused uploadFile `metadata` param to `_metadata`. - no-useless-escape (1): `[^\/]` -> `[^/]` in the URL validator (escape is unnecessary inside a character class; match is unchanged). Lint is now 0 warnings / 0 errors. type-check clean, 1407 tests pass. Co-Authored-By: Claude Sonnet 4.6 --- eslint.config.js | 15 +++++++++------ src/clients/http-client.ts | 7 ++----- src/index.ts | 1 - src/loggers/pino-logger.ts | 2 +- src/loggers/winston-logger.ts | 2 +- src/providers/local-storage.provider.ts | 2 +- src/services/validation.service.ts | 2 +- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 54b0ec6..e57c7f8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -26,11 +26,9 @@ module.exports = [ rules: { ...js.configs.recommended.rules, - // Code style - relaxed for CI - indent: ['warn', 2], - quotes: ['warn', 'single'], - semi: ['warn', 'always'], - 'comma-dangle': ['warn', 'always-multiline'], + // Formatting is owned by Prettier (`bun run format`); ESLint does not + // police style. Enabling indent/quotes/semi/comma-dangle here only + // duplicates Prettier and produces conflicting warnings. // TypeScript specific - relaxed '@typescript-eslint/no-unused-vars': [ @@ -38,7 +36,12 @@ module.exports = [ { argsIgnorePattern: '^_' }, ], '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-explicit-any': 'warn', + // `any` is a deliberate design choice across this library (dynamic + // require() of optional peer deps, generic `` passthrough, + // logger `...meta: any[]`). The API is frozen (v14), so retyping public + // signatures is out of scope; the rule is disabled rather than silenced + // line-by-line with ~180 inline disable comments. + '@typescript-eslint/no-explicit-any': 'off', // Best practices - relaxed 'no-console': 'off', diff --git a/src/clients/http-client.ts b/src/clients/http-client.ts index e76f5d5..3ee5a1f 100644 --- a/src/clients/http-client.ts +++ b/src/clients/http-client.ts @@ -37,10 +37,7 @@ export class HttpClient implements IHttpClient { const hasBody = options.data !== undefined; let body: string | Buffer | undefined; if (hasBody) { - if ( - Buffer.isBuffer(options.data) || - typeof options.data === 'string' - ) { + if (Buffer.isBuffer(options.data) || typeof options.data === 'string') { body = options.data; } else if (typeof options.data === 'object') { body = JSON.stringify(options.data); @@ -121,7 +118,7 @@ export class HttpClient implements IHttpClient { } else { parsedData = data; } - } catch (e) { + } catch { // If parsing fails, return the raw data parsedData = data; } diff --git a/src/index.ts b/src/index.ts index 5c077e3..530d721 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,6 @@ import { StorageServiceOptions, } from './services/storage.service'; import { LoggerOptions } from './interfaces/logger.interface'; -import { StorageProviderType } from './interfaces/storage.interface'; /** * Configuration for the utility library diff --git a/src/loggers/pino-logger.ts b/src/loggers/pino-logger.ts index ec33da3..2b2cb92 100644 --- a/src/loggers/pino-logger.ts +++ b/src/loggers/pino-logger.ts @@ -29,7 +29,7 @@ export class PinoLogger implements ILogger { } : undefined, }); - } catch (error) { + } catch { // Fallback to console if pino is not available this.logger = { info: (meta: any, message: string) => diff --git a/src/loggers/winston-logger.ts b/src/loggers/winston-logger.ts index 4b58f35..73b8196 100644 --- a/src/loggers/winston-logger.ts +++ b/src/loggers/winston-logger.ts @@ -46,7 +46,7 @@ export class WinstonLogger implements ILogger { format, transports: [new winston.transports.Console()], }); - } catch (error) { + } catch { // Fallback to console if winston is not available this.logger = { info: (message: string, ...meta: any[]) => diff --git a/src/providers/local-storage.provider.ts b/src/providers/local-storage.provider.ts index de61edd..7be750a 100644 --- a/src/providers/local-storage.provider.ts +++ b/src/providers/local-storage.provider.ts @@ -41,7 +41,7 @@ export class LocalStorageProvider implements IStorageProvider { async uploadFile( filePath: string, content: Buffer | string | NodeJS.ReadableStream, - metadata?: FileMetadata, + _metadata?: FileMetadata, ): Promise { const fullPath = this.getFullPath(filePath); diff --git a/src/services/validation.service.ts b/src/services/validation.service.ts index b7bb3c0..c26486f 100644 --- a/src/services/validation.service.ts +++ b/src/services/validation.service.ts @@ -78,7 +78,7 @@ export class ValidationUtils { } // Check specific format for http:/example.com (missing slash) - if (inputUrl.match(/^https?:\/[^\/]/)) { + if (inputUrl.match(/^https?:\/[^/]/)) { return false; } From a9369076d7092a6bd9885976af66cb539ecdedfe Mon Sep 17 00:00:00 2001 From: "Bruno R. Morillo" <111511828+brmorillo@users.noreply.github.com> Date: Wed, 17 Jun 2026 18:07:41 -0300 Subject: [PATCH 4/5] fix: reorder exports map so "types" comes before "import"/"require" Bundlers (esbuild/tsup) and TypeScript resolve the exports map in declared order: placing "types" last means it is never reached, because "import" and "require" match first. Moving "types" first lets TypeScript find the declarations regardless of the module format the caller uses, and silences the esbuild warning emitted during `bun run build`. Co-Authored-By: Claude Sonnet 4.6 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 47971c3..3d93d9c 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "types": "dist/index.d.ts", "exports": { ".": { + "types": "./dist/index.d.ts", "require": "./dist/index.js", - "import": "./dist/index.mjs", - "types": "./dist/index.d.ts" + "import": "./dist/index.mjs" } }, "files": [ From bf7002370a0e696668a307824670f7bfa011b7ae Mon Sep 17 00:00:00 2001 From: "Bruno R. Morillo" <111511828+brmorillo@users.noreply.github.com> Date: Wed, 17 Jun 2026 18:09:51 -0300 Subject: [PATCH 5/5] ci: update GitHub Actions to Node 24-compatible versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - actions/checkout: v4 -> v6 (v6 uses node24 internally) - actions/setup-node: v4 -> v6 (release.yml only) - softprops/action-gh-release: v2 -> v3 (release.yml only) oven-sh/setup-bun@v2 already declares node24 — no change needed. Eliminates the "Node.js 20 is deprecated" warning that appears when actions declare `runs.using: "node20"` on runners now forced to Node 24. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 4 ++-- .github/workflows/pr-version.yml | 2 +- .github/workflows/release.yml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 868e78d..66082ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: name: Type-check, lint, test, build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up bun uses: oven-sh/setup-bun@v2 @@ -44,7 +44,7 @@ jobs: name: Gitleaks secret scan runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Run gitleaks run: | diff --git a/.github/workflows/pr-version.yml b/.github/workflows/pr-version.yml index bef6f43..b6cb0c5 100644 --- a/.github/workflows/pr-version.yml +++ b/.github/workflows/pr-version.yml @@ -24,7 +24,7 @@ jobs: if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ github.head_ref }} fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 37c7182..ad3de4a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest environment: production steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 fetch-tags: true @@ -48,7 +48,7 @@ jobs: - name: Set up Node (for npm publish auth) if: steps.tag.outputs.exists == 'false' - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: 24 registry-url: 'https://registry.npmjs.org' @@ -77,7 +77,7 @@ jobs: - name: Create GitHub release if: steps.tag.outputs.exists == 'false' - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: tag_name: v${{ steps.pkg.outputs.version }} generate_release_notes: true