From 5f2d37f165e9d204f9e58c1c025b7cae20fbb700 Mon Sep 17 00:00:00 2001 From: Leonardo Trevizo Date: Wed, 5 Nov 2025 22:30:21 -0600 Subject: [PATCH 01/12] feat(createSecurePair-deprecation): handle Node.js DEP0064 migration --- .../tls-createsecurepair-to-socket/README.md | 120 ++++++++++++ .../codemod.yaml | 24 +++ .../package.json | 24 +++ .../src/workflow.ts | 172 ++++++++++++++++++ .../tests/expected/cjs-destructured-basic.js | 2 + .../tests/expected/cjs-destructured-flags.js | 2 + .../tests/expected/cjs-namespace-basic.js | 2 + .../tests/expected/esm-named-basic.js | 2 + .../tests/expected/esm-namespace-basic.js | 2 + .../expected/mixed-with-other-symbols.js | 3 + .../tests/input/cjs-destructured-basic.js | 2 + .../tests/input/cjs-destructured-flags.js | 2 + .../tests/input/cjs-namespace-basic.js | 2 + .../tests/input/esm-named-basic.js | 2 + .../tests/input/esm-namespace-basic.js | 2 + .../tests/input/mixed-with-other-symbols.js | 3 + .../workflow.yaml | 25 +++ 17 files changed, 391 insertions(+) create mode 100644 recipes/tls-createsecurepair-to-socket/README.md create mode 100644 recipes/tls-createsecurepair-to-socket/codemod.yaml create mode 100644 recipes/tls-createsecurepair-to-socket/package.json create mode 100644 recipes/tls-createsecurepair-to-socket/src/workflow.ts create mode 100644 recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-flags.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/expected/cjs-namespace-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/expected/esm-named-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/expected/esm-namespace-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/expected/mixed-with-other-symbols.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-flags.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/input/cjs-namespace-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/input/esm-named-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/input/esm-namespace-basic.js create mode 100644 recipes/tls-createsecurepair-to-socket/tests/input/mixed-with-other-symbols.js create mode 100644 recipes/tls-createsecurepair-to-socket/workflow.yaml diff --git a/recipes/tls-createsecurepair-to-socket/README.md b/recipes/tls-createsecurepair-to-socket/README.md new file mode 100644 index 00000000..2b34cd3d --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/README.md @@ -0,0 +1,120 @@ +# `tls.createSecurePair` deprecation DEP0064 + +This recipe transforms the usage from the deprecated `createSecurePair()` to `TLSSocket()`. + +See [DEP0064](https://nodejs.org/api/deprecations.html#dep0064-tlscreatesecurepair). + +## Examples + +### Case 1: Basic `createSecurePair` usage + +**Before:** +```js +const { createSecurePair } = require('node:tls'); + +const pair = createSecurePair(credentials); +``` + +**After:** +```js +const { TLSSocket } = require('node:tls'); + +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +``` + +--- + +### Case 2: Namespace import + +**Before:** +```js +const tls = require('node:tls'); + +const pair = tls.createSecurePair(credentials); +``` + +**After:** +```js +const tls = require('node:tls'); + +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); +``` + +--- + +### Case 3: With server context + +**Before:** +```js +const { createSecurePair } = require('node:tls'); + +const pair = createSecurePair(credentials, true, true, false); +``` + +**After:** +```js +const { TLSSocket } = require('node:tls'); + +const socket = new TLSSocket(underlyingSocket, { + secureContext: credentials, + isServer: true, + requestCert: true, + rejectUnauthorized: false +}); +``` + +--- + +### Case 4: ESM import + +**Before:** +```js +import { createSecurePair } from 'node:tls'; + +const pair = createSecurePair(credentials); +``` + +**After:** +```js +import { TLSSocket } from 'node:tls'; + +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +``` + +--- + +### Case 5: ESM namespace import + +**Before:** +```js +import * as tls from 'node:tls'; + +const pair = tls.createSecurePair(credentials); +``` + +**After:** +```js +import * as tls from 'node:tls'; + +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); +``` + +--- + +### Case 6: Mixed usage with other TLS functions + +**Before:** +```js +const { createSecurePair, createServer } = require('node:tls'); + +const pair = createSecurePair(credentials); +const server = createServer(options); +``` + +**After:** +```js +const { TLSSocket, createServer } = require('node:tls'); + +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +const server = createServer(options); +``` diff --git a/recipes/tls-createsecurepair-to-socket/codemod.yaml b/recipes/tls-createsecurepair-to-socket/codemod.yaml new file mode 100644 index 00000000..7e500026 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/codemod.yaml @@ -0,0 +1,24 @@ +schema_version: "1.0" +name: "@nodejs/tls-createsecurepair-to-socket" +version: 1.0.0 +description: Handle DEP0064 by transforming `createSecurePair` to `TLSSocket` +author: Leonardo Trevizo +license: MIT +workflow: workflow.yaml +category: migration + +targets: + languages: + - javascript + - typescript + +keywords: + - transformation + - migration + - tls + - createSecurePair + - TLSSocket + +registry: + access: public + visibility: public diff --git a/recipes/tls-createsecurepair-to-socket/package.json b/recipes/tls-createsecurepair-to-socket/package.json new file mode 100644 index 00000000..59dae59d --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/package.json @@ -0,0 +1,24 @@ +{ + "name": "@nodejs/tls-createsecurepair-to-socket", + "version": "1.0.0", + "description": "Handle DEP0064 replacing `tls.createSecurePair()` with `tls.TLSSocket()`", + "type": "module", + "scripts": { + "test": "npx codemod jssg test -l typescript ./src/workflow.ts ./" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/nodejs/userland-migrations.git", + "directory": "recipes/tls-createsecurepair-to-socket", + "bugs": "https://github.com/nodejs/userland-migrations/issues" + }, + "author": "Leo Trevizo", + "license": "MIT", + "homepage": "https://github.com/nodejs/userland-migrations/blob/main/recipes/tls-createsecurepair-to-socket/README.md", + "devDependencies": { + "@codemod.com/jssg-types": "^1.0.9" + }, + "dependencies": { + "@nodejs/codemod-utils": "*" + } +} diff --git a/recipes/tls-createsecurepair-to-socket/src/workflow.ts b/recipes/tls-createsecurepair-to-socket/src/workflow.ts new file mode 100644 index 00000000..011735cf --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/src/workflow.ts @@ -0,0 +1,172 @@ +import type { SgRoot, SgNode, Edit } from '@codemod.com/jssg-types/main'; +import type JS from '@codemod.com/jssg-types/langs/javascript'; +import { getNodeImportStatements } from '@nodejs/codemod-utils/ast-grep/import-statement'; +import { getNodeRequireCalls } from '@nodejs/codemod-utils/ast-grep/require-call'; +import { resolveBindingPath } from '@nodejs/codemod-utils/ast-grep/resolve-binding-path'; + +type CallSite = { call: SgNode; binding: string }; + +export default function transform(root: SgRoot): string | null { + const rootNode = root.root(); + const tlsStmts = [ + ...getNodeImportStatements(root, 'node:tls'), + ...getNodeImportStatements(root, 'tls'), + ...getNodeRequireCalls(root, 'node:tls'), + ...getNodeRequireCalls(root, 'tls'), + ]; + if (tlsStmts.length === 0) return null; + + const cspBindings = unique( + tlsStmts + .map(s => resolveBindingPath(s as unknown as SgNode, '$.createSecurePair')) + .filter(Boolean) as string[] + ); + if (cspBindings.length === 0) return null; + + const callSites = findCreateSecurePairCalls(rootNode, cspBindings); + const edits: Edit[] = []; + + for (const { call, binding } of callSites) { + const a = getText(call.getMatch('A')); + const b = getText(call.getMatch('B')); + const c = getText(call.getMatch('C')); + const d = getText(call.getMatch('D')); + const options = buildOptions(a, b, c, d); + const isNamespace = binding.includes('.'); + const replacement = isNamespace + ? `new ${binding.replace(/\.createSecurePair$/, '.TLSSocket')}(underlyingSocket, ${options})` + : `new TLSSocket(underlyingSocket, ${options})`; + edits.push(call.replace(replacement)); + } + + edits.push(...renamePairAssignedVariables(rootNode, cspBindings)); + edits.push(...rewriteTlsImports(rootNode)); + if (edits.length === 0) return null; + return rootNode.commitEdits(edits); +} + +function findCreateSecurePairCalls(rootNode: SgNode, bindings: string[]): CallSite[] { + return bindings.flatMap(binding => + rootNode + .findAll({ + rule: { + any: [ + { pattern: `${binding}($A, $B, $C, $D)` }, + { pattern: `${binding}($A, $B, $C)` }, + { pattern: `${binding}($A, $B)` }, + { pattern: `${binding}($A)` }, + { pattern: `${binding}()` }, + ], + }, + }) + .map(n => ({ call: n as SgNode, binding })) + ); +} + +function buildOptions(a?: string | null, b?: string | null, c?: string | null, d?: string | null): string { + const kv: string[] = []; + if (a) kv.push(`secureContext: ${a}`); + if (b) kv.push(`isServer: ${b}`); + if (c) kv.push(`requestCert: ${c}`); + if (d) kv.push(`rejectUnauthorized: ${d}`); + return `{ ${kv.join(', ')} }`; +} + +function getText(node: SgNode | undefined): string | null { + const t = node?.text()?.trim(); + return t || null; +} + +function unique(arr: T[]): T[] { + return Array.from(new Set(arr)); +} + +function renamePairAssignedVariables(rootNode: SgNode, bindings: string[]): Edit[] { + const edits: Edit[] = []; + for (const binding of bindings) { + const decls = rootNode.findAll({ + rule: { + kind: 'variable_declarator', + has: { + field: 'value', + kind: 'call_expression', + pattern: `${binding}($$$ARGS)`, + }, + }, + }); + for (const decl of decls) { + const name = decl.field('name'); + if (name && name.kind() === 'identifier' && name.text() === 'pair') { + edits.push(name.replace('socket')); + } + } + } + return edits; +} + + +function rewriteTlsImports(rootNode: SgNode): Edit[] { + const edits: Edit[] = []; + const tlsStmts = rootNode.findAll({ + rule: { + any: [ + { pattern: `import $$ANY from 'tls'` }, + { pattern: `import $$ANY from 'node:tls'` }, + { pattern: `const $$ANY = require('tls')` }, + { pattern: `const $$ANY = require('node:tls')` }, + ], + }, + }); + + for (const stmt of tlsStmts) { + const code = stmt.text(); + if (/\bimport\s+\*\s+as\s+\w+\s+from\s+['"](tls|node:tls)['"]/.test(code)) continue; + { + const m = code.match( + /import\s+(?:(?[\w$]+)\s*,\s*)?\{\s*(?[^}]*)\s*\}\s*from\s*['"](tls|node:tls)['"]\s*;?/, + ); + if (m?.groups) { + const def = m.groups.def || ''; + const namesRaw = m.groups.names || ''; + const names = namesRaw + .split(',') + .map(s => s.trim()) + .filter(Boolean) + .map(s => s.replace(/\s+as\s+\w+$/, '')); + + if (names.includes('createSecurePair')) { + const kept = Array.from( + new Set(names.filter(n => n !== 'createSecurePair').concat('TLSSocket')), + ); + const left = def ? `${def}, ` : ''; + const rebuilt = `import ${left}{ ${kept.join(', ')} } from 'node:tls';`; + edits.push(stmt.replace(rebuilt)); + continue; + } + } + } + { + const m = code.match( + /const\s*\{\s*(?[^}]*)\s*\}\s*=\s*require\(\s*['"](tls|node:tls)['"]\s*\)\s*;?/, + ); + if (m?.groups) { + const namesRaw = m.groups.names || ''; + const names = namesRaw + .split(',') + .map(s => s.trim()) + .filter(Boolean); + + if (names.includes('createSecurePair')) { + const kept = Array.from( + new Set(names.filter(n => n !== 'createSecurePair').concat('TLSSocket')), + ); + const src = /node:tls/.test(code) ? 'node:tls' : 'tls'; + const rebuilt = `const { ${kept.join(', ')} } = require('${src}');`; + edits.push(stmt.replace(rebuilt)); + } + } + } + } + + return edits; +} diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-basic.js b/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-basic.js new file mode 100644 index 00000000..aade280a --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-basic.js @@ -0,0 +1,2 @@ +const { TLSSocket } = require('node:tls'); +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-flags.js b/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-flags.js new file mode 100644 index 00000000..7f6653dd --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-flags.js @@ -0,0 +1,2 @@ +const { TLSSocket } = require('node:tls'); +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true, requestCert: true, rejectUnauthorized: false }); diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-namespace-basic.js b/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-namespace-basic.js new file mode 100644 index 00000000..a4845d28 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-namespace-basic.js @@ -0,0 +1,2 @@ +const tls = require('node:tls'); +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/esm-named-basic.js b/recipes/tls-createsecurepair-to-socket/tests/expected/esm-named-basic.js new file mode 100644 index 00000000..946f330a --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/expected/esm-named-basic.js @@ -0,0 +1,2 @@ +import { TLSSocket } from 'node:tls'; +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/esm-namespace-basic.js b/recipes/tls-createsecurepair-to-socket/tests/expected/esm-namespace-basic.js new file mode 100644 index 00000000..9255483a --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/expected/esm-namespace-basic.js @@ -0,0 +1,2 @@ +import * as tls from 'node:tls'; +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/mixed-with-other-symbols.js b/recipes/tls-createsecurepair-to-socket/tests/expected/mixed-with-other-symbols.js new file mode 100644 index 00000000..ae0e16c1 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/expected/mixed-with-other-symbols.js @@ -0,0 +1,3 @@ +const { createServer, TLSSocket } = require('node:tls'); +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +const server = createServer(options); diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-basic.js b/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-basic.js new file mode 100644 index 00000000..85389cf3 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-basic.js @@ -0,0 +1,2 @@ +const { createSecurePair } = require('node:tls'); +const pair = createSecurePair(credentials); diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-flags.js b/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-flags.js new file mode 100644 index 00000000..33c62eb0 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-flags.js @@ -0,0 +1,2 @@ +const { createSecurePair } = require('node:tls'); +const pair = createSecurePair(credentials, true, true, false); diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/cjs-namespace-basic.js b/recipes/tls-createsecurepair-to-socket/tests/input/cjs-namespace-basic.js new file mode 100644 index 00000000..4ad73152 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/input/cjs-namespace-basic.js @@ -0,0 +1,2 @@ +const tls = require('node:tls'); +const pair = tls.createSecurePair(credentials); diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/esm-named-basic.js b/recipes/tls-createsecurepair-to-socket/tests/input/esm-named-basic.js new file mode 100644 index 00000000..9dccd7ed --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/input/esm-named-basic.js @@ -0,0 +1,2 @@ +import { createSecurePair } from 'node:tls'; +const pair = createSecurePair(credentials); diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/esm-namespace-basic.js b/recipes/tls-createsecurepair-to-socket/tests/input/esm-namespace-basic.js new file mode 100644 index 00000000..28119184 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/input/esm-namespace-basic.js @@ -0,0 +1,2 @@ +import * as tls from 'node:tls'; +const pair = tls.createSecurePair(credentials); diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/mixed-with-other-symbols.js b/recipes/tls-createsecurepair-to-socket/tests/input/mixed-with-other-symbols.js new file mode 100644 index 00000000..e6a341db --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/tests/input/mixed-with-other-symbols.js @@ -0,0 +1,3 @@ +const { createSecurePair, createServer } = require('node:tls'); +const pair = createSecurePair(credentials); +const server = createServer(options); diff --git a/recipes/tls-createsecurepair-to-socket/workflow.yaml b/recipes/tls-createsecurepair-to-socket/workflow.yaml new file mode 100644 index 00000000..1b82d8a3 --- /dev/null +++ b/recipes/tls-createsecurepair-to-socket/workflow.yaml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/codemod-com/codemod/refs/heads/main/schemas/workflow.json + +version: "1" + +nodes: + - id: apply-transforms + name: Apply AST Transformations + type: automatic + steps: + - name: Handle DEP0064 via replacing deprecated `tls.createSecurePair()` to `tls.Socket`. + js-ast-grep: + js_file: src/workflow.ts + base_path: . + include: + - "**/*.js" + - "**/*.jsx" + - "**/*.mjs" + - "**/*.cjs" + - "**/*.cts" + - "**/*.mts" + - "**/*.ts" + - "**/*.tsx" + exclude: + - "**/node_modules/**" + language: typescript From 60e516edae05b09be66ac567c73bc933e608c4d6 Mon Sep 17 00:00:00 2001 From: Leonardo Trevizo Date: Wed, 5 Nov 2025 22:45:08 -0600 Subject: [PATCH 02/12] fix: updated 'tls-createsecurepair-to-socket' to a kebab-case compliant '`tls-create-secure-pair-to-tls-socket`. ' --- .../README.md | 0 .../codemod.yaml | 2 +- .../package.json | 6 +++--- .../src/workflow.ts | 0 .../tests/expected/cjs-destructured-basic.js | 0 .../tests/expected/cjs-destructured-flags.js | 0 .../tests/expected/cjs-namespace-basic.js | 0 .../tests/expected/esm-named-basic.js | 0 .../tests/expected/esm-namespace-basic.js | 0 .../tests/expected/mixed-with-other-symbols.js | 0 .../tests/input/cjs-destructured-basic.js | 0 .../tests/input/cjs-destructured-flags.js | 0 .../tests/input/cjs-namespace-basic.js | 0 .../tests/input/esm-named-basic.js | 0 .../tests/input/esm-namespace-basic.js | 0 .../tests/input/mixed-with-other-symbols.js | 0 .../workflow.yaml | 0 17 files changed, 4 insertions(+), 4 deletions(-) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/README.md (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/codemod.yaml (88%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/package.json (78%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/src/workflow.ts (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/expected/cjs-destructured-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/expected/cjs-destructured-flags.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/expected/cjs-namespace-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/expected/esm-named-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/expected/esm-namespace-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/expected/mixed-with-other-symbols.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/input/cjs-destructured-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/input/cjs-destructured-flags.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/input/cjs-namespace-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/input/esm-named-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/input/esm-namespace-basic.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/tests/input/mixed-with-other-symbols.js (100%) rename recipes/{tls-createsecurepair-to-socket => tls-create-secure-pair-to-tls-socket}/workflow.yaml (100%) diff --git a/recipes/tls-createsecurepair-to-socket/README.md b/recipes/tls-create-secure-pair-to-tls-socket/README.md similarity index 100% rename from recipes/tls-createsecurepair-to-socket/README.md rename to recipes/tls-create-secure-pair-to-tls-socket/README.md diff --git a/recipes/tls-createsecurepair-to-socket/codemod.yaml b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml similarity index 88% rename from recipes/tls-createsecurepair-to-socket/codemod.yaml rename to recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml index 7e500026..978eb8c9 100644 --- a/recipes/tls-createsecurepair-to-socket/codemod.yaml +++ b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml @@ -1,5 +1,5 @@ schema_version: "1.0" -name: "@nodejs/tls-createsecurepair-to-socket" +name: "@nodejs/tls-create-secure-pair-to-tls-socket" version: 1.0.0 description: Handle DEP0064 by transforming `createSecurePair` to `TLSSocket` author: Leonardo Trevizo diff --git a/recipes/tls-createsecurepair-to-socket/package.json b/recipes/tls-create-secure-pair-to-tls-socket/package.json similarity index 78% rename from recipes/tls-createsecurepair-to-socket/package.json rename to recipes/tls-create-secure-pair-to-tls-socket/package.json index 59dae59d..88d0efbf 100644 --- a/recipes/tls-createsecurepair-to-socket/package.json +++ b/recipes/tls-create-secure-pair-to-tls-socket/package.json @@ -1,5 +1,5 @@ { - "name": "@nodejs/tls-createsecurepair-to-socket", + "name": "@nodejs/tls-create-secure-pair-to-tls-socket", "version": "1.0.0", "description": "Handle DEP0064 replacing `tls.createSecurePair()` with `tls.TLSSocket()`", "type": "module", @@ -9,12 +9,12 @@ "repository": { "type": "git", "url": "git+https://github.com/nodejs/userland-migrations.git", - "directory": "recipes/tls-createsecurepair-to-socket", + "directory": "recipes/tls-create-secure-pair-to-tls-socket", "bugs": "https://github.com/nodejs/userland-migrations/issues" }, "author": "Leo Trevizo", "license": "MIT", - "homepage": "https://github.com/nodejs/userland-migrations/blob/main/recipes/tls-createsecurepair-to-socket/README.md", + "homepage": "https://github.com/nodejs/userland-migrations/blob/main/recipes/tls-create-secure-pair-to-tls-socket/README.md", "devDependencies": { "@codemod.com/jssg-types": "^1.0.9" }, diff --git a/recipes/tls-createsecurepair-to-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts similarity index 100% rename from recipes/tls-createsecurepair-to-socket/src/workflow.ts rename to recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-flags.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-flags.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/expected/cjs-destructured-flags.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-flags.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/cjs-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-namespace-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/expected/cjs-namespace-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-namespace-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/esm-named-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/expected/esm-named-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/esm-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-namespace-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/expected/esm-namespace-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-namespace-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/expected/mixed-with-other-symbols.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/mixed-with-other-symbols.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/expected/mixed-with-other-symbols.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/expected/mixed-with-other-symbols.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-flags.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-flags.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/input/cjs-destructured-flags.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-flags.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/cjs-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-namespace-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/input/cjs-namespace-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-namespace-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/esm-named-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/input/esm-named-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/esm-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-namespace-basic.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/input/esm-namespace-basic.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-namespace-basic.js diff --git a/recipes/tls-createsecurepair-to-socket/tests/input/mixed-with-other-symbols.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/mixed-with-other-symbols.js similarity index 100% rename from recipes/tls-createsecurepair-to-socket/tests/input/mixed-with-other-symbols.js rename to recipes/tls-create-secure-pair-to-tls-socket/tests/input/mixed-with-other-symbols.js diff --git a/recipes/tls-createsecurepair-to-socket/workflow.yaml b/recipes/tls-create-secure-pair-to-tls-socket/workflow.yaml similarity index 100% rename from recipes/tls-createsecurepair-to-socket/workflow.yaml rename to recipes/tls-create-secure-pair-to-tls-socket/workflow.yaml From 697778bfc19417fb0f384331eda01042863f1d36 Mon Sep 17 00:00:00 2001 From: Leonardo Trevizo Date: Sun, 9 Nov 2025 23:11:03 -0600 Subject: [PATCH 03/12] docs(`tls-createSecurePair-deprecation`): switch to diff examples; add ESM default and dynamic import cases --- .../README.md | 148 ++++++++---------- 1 file changed, 66 insertions(+), 82 deletions(-) diff --git a/recipes/tls-create-secure-pair-to-tls-socket/README.md b/recipes/tls-create-secure-pair-to-tls-socket/README.md index 2b34cd3d..d66f541a 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/README.md +++ b/recipes/tls-create-secure-pair-to-tls-socket/README.md @@ -6,115 +6,99 @@ See [DEP0064](https://nodejs.org/api/deprecations.html#dep0064-tlscreatesecurepa ## Examples -### Case 1: Basic `createSecurePair` usage - -**Before:** -```js -const { createSecurePair } = require('node:tls'); - -const pair = createSecurePair(credentials); -``` - -**After:** -```js -const { TLSSocket } = require('node:tls'); - -const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +### 1) Basic `createSecurePair` usage +```diff +-const { createSecurePair } = require('node:tls'); +-const pair = createSecurePair(credentials); ++const { TLSSocket } = require('node:tls'); ++const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); ``` --- -### Case 2: Namespace import - -**Before:** -```js -const tls = require('node:tls'); - -const pair = tls.createSecurePair(credentials); -``` - -**After:** -```js -const tls = require('node:tls'); - -const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); +### 2) Namespace import (CJS) +```diff +-const tls = require('node:tls'); +-const pair = tls.createSecurePair(credentials); ++const tls = require('node:tls'); ++const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); ``` --- -### Case 3: With server context - -**Before:** -```js -const { createSecurePair } = require('node:tls'); - -const pair = createSecurePair(credentials, true, true, false); -``` - -**After:** -```js -const { TLSSocket } = require('node:tls'); - -const socket = new TLSSocket(underlyingSocket, { - secureContext: credentials, - isServer: true, - requestCert: true, - rejectUnauthorized: false -}); +### 3) With server context +```diff +-const { createSecurePair } = require('node:tls'); +-const pair = createSecurePair(credentials, true, true, false); ++const { TLSSocket } = require('node:tls'); ++const socket = new TLSSocket(underlyingSocket, { ++ secureContext: credentials, ++ isServer: true, ++ requestCert: true, ++ rejectUnauthorized: false ++}); ``` --- -### Case 4: ESM import - -**Before:** -```js -import { createSecurePair } from 'node:tls'; - -const pair = createSecurePair(credentials); +### 4) ESM named import +```diff +-import { createSecurePair } from 'node:tls'; +-const pair = createSecurePair(credentials); ++import { TLSSocket } from 'node:tls'; ++const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); ``` -**After:** -```js -import { TLSSocket } from 'node:tls'; +--- -const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +### 5) ESM namespace import +```diff +-import * as tls from 'node:tls'; +-const pair = tls.createSecurePair(credentials); ++import * as tls from 'node:tls'; ++const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); ``` --- -### Case 5: ESM namespace import - -**Before:** -```js -import * as tls from 'node:tls'; - -const pair = tls.createSecurePair(credentials); +### 6) Mixed usage with other TLS functions +```diff +-const { createSecurePair, createServer } = require('node:tls'); +-const pair = createSecurePair(credentials); +-const server = createServer(options); ++const { TLSSocket, createServer } = require('node:tls'); ++const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); ++const server = createServer(options); ``` -**After:** -```js -import * as tls from 'node:tls'; +--- -const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); +### 7) ESM default import +```diff +-import tls from 'node:tls'; +-const pair = tls.createSecurePair(credentials); ++import tls, { TLSSocket } from 'node:tls'; ++const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); ``` --- -### Case 6: Mixed usage with other TLS functions - -**Before:** -```js -const { createSecurePair, createServer } = require('node:tls'); - -const pair = createSecurePair(credentials); -const server = createServer(options); +### 8) ESM dynamic import (assignment) +```diff +-const tls = await import('node:tls'); +-const pair = tls.createSecurePair(credentials); ++const tls = await import('node:tls'); ++const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); ``` -**After:** -```js -const { TLSSocket, createServer } = require('node:tls'); +--- -const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); -const server = createServer(options); +### 9) ESM dynamic import (thenable) +```diff +-import('node:tls').then(tls => { +- const pair = tls.createSecurePair(credentials); +-}); ++import('node:tls').then(tls => { ++ const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); ++}); ``` From cecef622ec05f64074b0a5e6210814518f4a83d3 Mon Sep 17 00:00:00 2001 From: Leonardo Trevizo Date: Sun, 9 Nov 2025 23:13:20 -0600 Subject: [PATCH 04/12] chore(deps): update lockfile --- package-lock.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/package-lock.json b/package-lock.json index 3084e4d7..1c926add 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1509,6 +1509,10 @@ "resolved": "recipes/rmdir", "link": true }, + "node_modules/@nodejs/tls-create-secure-pair-to-tls-socket": { + "resolved": "recipes/tls-create-secure-pair-to-tls-socket", + "link": true + }, "node_modules/@nodejs/tmpdir-to-tmpdir": { "resolved": "recipes/tmpdir-to-tmpdir", "link": true @@ -4399,6 +4403,17 @@ "@codemod.com/jssg-types": "^1.0.9" } }, + "recipes/tls-create-secure-pair-to-tls-socket": { + "name": "@nodejs/tls-create-secure-pair-to-tls-socket", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@nodejs/codemod-utils": "*" + }, + "devDependencies": { + "@codemod.com/jssg-types": "^1.0.9" + } + }, "recipes/tmpdir-to-tmpdir": { "name": "@nodejs/tmpdir-to-tmpdir", "version": "1.0.0", From c88d03643a0bc82ddf9e6f0c1d1c29738d846fb0 Mon Sep 17 00:00:00 2001 From: Leonardo Trevizo Date: Sun, 9 Nov 2025 23:21:19 -0600 Subject: [PATCH 05/12] feat(`tls-createSecurePair-deprecation`): modify workflow logic (included default and dynamic ESM imports + needed refactors as PR comments) WHAT Changed: - AST-based migration - ESM/default/dynamic cases - Normalize rewritten CJS requires to `node:tls` as suggested to code section - Remove duplicated `getNodeImportStatements/getNodeRequireCalls` invocations that attempted to handle `'node:tls'` vs `'tls'` --- .../src/workflow.ts | 262 +++++++++++------- 1 file changed, 163 insertions(+), 99 deletions(-) diff --git a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts index 011735cf..4065c6fc 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -9,23 +9,16 @@ type CallSite = { call: SgNode; binding: string }; export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const tlsStmts = [ - ...getNodeImportStatements(root, 'node:tls'), ...getNodeImportStatements(root, 'tls'), - ...getNodeRequireCalls(root, 'node:tls'), ...getNodeRequireCalls(root, 'tls'), ]; - if (tlsStmts.length === 0) return null; - - const cspBindings = unique( - tlsStmts - .map(s => resolveBindingPath(s as unknown as SgNode, '$.createSecurePair')) - .filter(Boolean) as string[] - ); - if (cspBindings.length === 0) return null; - - const callSites = findCreateSecurePairCalls(rootNode, cspBindings); + const cspBindings = unique([ + ...tlsStmts.map(s => resolveBindingPath(s as unknown as SgNode, '$.createSecurePair')).filter(Boolean) as string[], + ...collectDefaultImportBindings(tlsStmts), + ...collectDynamicImportIdentifiers(rootNode), + ]); + const callSites: CallSite[] = [...findCreateSecurePairCalls(rootNode)]; const edits: Edit[] = []; - for (const { call, binding } of callSites) { const a = getText(call.getMatch('A')); const b = getText(call.getMatch('B')); @@ -38,29 +31,35 @@ export default function transform(root: SgRoot): string | null { : `new TLSSocket(underlyingSocket, ${options})`; edits.push(call.replace(replacement)); } - edits.push(...renamePairAssignedVariables(rootNode, cspBindings)); edits.push(...rewriteTlsImports(rootNode)); if (edits.length === 0) return null; return rootNode.commitEdits(edits); } -function findCreateSecurePairCalls(rootNode: SgNode, bindings: string[]): CallSite[] { - return bindings.flatMap(binding => - rootNode - .findAll({ - rule: { - any: [ - { pattern: `${binding}($A, $B, $C, $D)` }, - { pattern: `${binding}($A, $B, $C)` }, - { pattern: `${binding}($A, $B)` }, - { pattern: `${binding}($A)` }, - { pattern: `${binding}()` }, - ], - }, - }) - .map(n => ({ call: n as SgNode, binding })) - ); +function findCreateSecurePairCalls(rootNode: SgNode): CallSite[] { + const pats = [ + '$X.createSecurePair($A, $B, $C, $D)', + '$X.createSecurePair($A, $B, $C)', + '$X.createSecurePair($A, $B)', + '$X.createSecurePair($A)', + '$X.createSecurePair()', + 'createSecurePair($A, $B, $C, $D)', + 'createSecurePair($A, $B, $C)', + 'createSecurePair($A, $B)', + 'createSecurePair($A)', + 'createSecurePair()', + ]; + const out: CallSite[] = []; + for (const p of pats) { + const nodes = rootNode.findAll({ rule: { kind: 'call_expression', pattern: p } }); + for (const n of nodes) { + const x = (n as SgNode).getMatch('X')?.text(); + const binding = x ? `${x}.createSecurePair` : 'createSecurePair'; + out.push({ call: n as SgNode, binding }); + } + } + return out; } function buildOptions(a?: string | null, b?: string | null, c?: string | null, d?: string | null): string { @@ -81,92 +80,157 @@ function unique(arr: T[]): T[] { return Array.from(new Set(arr)); } -function renamePairAssignedVariables(rootNode: SgNode, bindings: string[]): Edit[] { +function renamePairAssignedVariables(rootNode: SgNode, _bindings: string[]): Edit[] { const edits: Edit[] = []; - for (const binding of bindings) { - const decls = rootNode.findAll({ - rule: { - kind: 'variable_declarator', - has: { - field: 'value', - kind: 'call_expression', - pattern: `${binding}($$$ARGS)`, - }, + const decls = rootNode.findAll({ + rule: { + kind: 'variable_declarator', + has: { + field: 'value', + kind: 'call_expression', + any: [ + { pattern: '$X.createSecurePair($$$ARGS)' }, + { pattern: 'createSecurePair($$$ARGS)' }, + ], }, - }); - for (const decl of decls) { - const name = decl.field('name'); - if (name && name.kind() === 'identifier' && name.text() === 'pair') { - edits.push(name.replace('socket')); - } + }, + }); + for (const decl of decls) { + const name = decl.field('name'); + if (name && name.kind() === 'identifier' && name.text() === 'pair') { + edits.push(name.replace('socket')); } } return edits; } - function rewriteTlsImports(rootNode: SgNode): Edit[] { const edits: Edit[] = []; - const tlsStmts = rootNode.findAll({ + const esmNamed = rootNode.findAll({ rule: { - any: [ - { pattern: `import $$ANY from 'tls'` }, - { pattern: `import $$ANY from 'node:tls'` }, - { pattern: `const $$ANY = require('tls')` }, - { pattern: `const $$ANY = require('node:tls')` }, + kind: 'import_statement', + all: [ + { has: { kind: 'import_clause', has: { kind: 'named_imports' } } }, + { + has: { + field: 'source', + any: [{ pattern: '\'tls\'' }, { pattern: '"tls"' }, { pattern: '\'node:tls\'' }, { pattern: '"node:tls"' }], + }, + }, ], + not: { has: { kind: 'namespace_import' } }, }, }); - - for (const stmt of tlsStmts) { - const code = stmt.text(); - if (/\bimport\s+\*\s+as\s+\w+\s+from\s+['"](tls|node:tls)['"]/.test(code)) continue; - { - const m = code.match( - /import\s+(?:(?[\w$]+)\s*,\s*)?\{\s*(?[^}]*)\s*\}\s*from\s*['"](tls|node:tls)['"]\s*;?/, - ); - if (m?.groups) { - const def = m.groups.def || ''; - const namesRaw = m.groups.names || ''; - const names = namesRaw - .split(',') - .map(s => s.trim()) - .filter(Boolean) - .map(s => s.replace(/\s+as\s+\w+$/, '')); - - if (names.includes('createSecurePair')) { - const kept = Array.from( - new Set(names.filter(n => n !== 'createSecurePair').concat('TLSSocket')), - ); - const left = def ? `${def}, ` : ''; - const rebuilt = `import ${left}{ ${kept.join(', ')} } from 'node:tls';`; - edits.push(stmt.replace(rebuilt)); - continue; - } + for (const decl of esmNamed) { + const srcText = decl.field('source')?.text()?.replace(/['"]/g, '') || ''; + if (srcText !== 'tls' && srcText !== 'node:tls') continue; + const named = decl.find({ rule: { kind: 'named_imports' } }); + if (!named) continue; + const specs = named.findAll({ rule: { kind: 'import_specifier' } }); + const hasCSP = specs.some(s => s.field('name')?.text() === 'createSecurePair'); + if (!hasCSP) continue; + const kept: string[] = []; + for (const s of specs) { + const imported = s.field('name')?.text(); + const maybeAlias = s.field('alias')?.text(); + if (imported && imported !== 'createSecurePair') { + kept.push(maybeAlias ? `${imported} as ${maybeAlias}` : imported); } } - { - const m = code.match( - /const\s*\{\s*(?[^}]*)\s*\}\s*=\s*require\(\s*['"](tls|node:tls)['"]\s*\)\s*;?/, - ); - if (m?.groups) { - const namesRaw = m.groups.names || ''; - const names = namesRaw - .split(',') - .map(s => s.trim()) - .filter(Boolean); - - if (names.includes('createSecurePair')) { - const kept = Array.from( - new Set(names.filter(n => n !== 'createSecurePair').concat('TLSSocket')), - ); - const src = /node:tls/.test(code) ? 'node:tls' : 'tls'; - const rebuilt = `const { ${kept.join(', ')} } = require('${src}');`; - edits.push(stmt.replace(rebuilt)); - } + if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); + const def = decl.find({ rule: { kind: 'import_clause', has: { field: 'name', kind: 'identifier' } } })?.field('name')?.text(); + const rebuilt = def ? `import ${def}, { ${kept.join(', ')} } from '${srcText}';` : `import { ${kept.join(', ')} } from '${srcText}';`; + edits.push(decl.replace(rebuilt)); + } + const cjsNamed = rootNode.findAll({ + rule: { + kind: 'variable_declarator', + all: [ + { has: { field: 'name', kind: 'object_pattern' } }, + { + has: { + field: 'value', + any: [ + { pattern: 'require(\'tls\')' }, + { pattern: 'require("tls")' }, + { pattern: 'require(\'node:tls\')' }, + { pattern: 'require("node:tls")' }, + ], + }, + }, + ], + }, + }); + for (const decl of cjsNamed) { + const obj = decl.field('name'); + if (!obj) continue; + const props = obj.findAll({ rule: { any: [{ kind: 'pair_pattern' }, { kind: 'shorthand_property_identifier_pattern' }] } }); + const hasCSP = props.some(p => + p.kind() === 'pair_pattern' + ? p.field('key')?.text() === 'createSecurePair' || p.field('value')?.text() === 'createSecurePair' + : p.text() === 'createSecurePair' + ); + if (!hasCSP) continue; + const kept: string[] = []; + for (const p of props) { + let name = ''; + let alias = ''; + if (p.kind() === 'pair_pattern') { + name = p.field('key')?.text() || ''; + alias = p.field('value')?.text() || ''; + } else { + name = p.text(); + alias = name; + } + if (!name || name === 'createSecurePair') continue; + kept.push(alias && alias !== name ? `${name}: ${alias}` : name); + } + if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); + let stmt: SgNode = decl; + let cur: SgNode | undefined = decl; + while (cur) { + const k = cur.kind(); + if (k === 'lexical_declaration' || k === 'variable_declaration') { + stmt = cur; + break; } + cur = cur.parent?.(); } + edits.push(stmt.replace(`const { ${kept.join(', ')} } = require('node:tls');`)); } - return edits; } + +function collectDefaultImportBindings(tlsStmts: SgNode[]): string[] { + const out: string[] = []; + for (const stmt of tlsStmts) { + if (stmt.kind() !== 'import_declaration') continue; + const src = stmt.field('source')?.text()?.replace(/['"]/g, ''); + if (!/^(node:)?tls$/.test(src || '')) continue; + const def = stmt.find({ rule: { kind: 'import_clause', has: { field: 'name', kind: 'identifier' } } })?.field('name')?.text(); + if (def) out.push(`${def}.createSecurePair`); + } + return out; +} + +function collectDynamicImportIdentifiers(rootNode: SgNode): string[] { + const out: string[] = []; + const pats = [ + 'const $ID = await import(\'tls\')', + 'const $ID = await import("tls")', + 'const $ID = await import(\'node:tls\')', + 'const $ID = await import("node:tls")', + 'const $ID = import(\'tls\')', + 'const $ID = import("tls")', + 'const $ID = import(\'node:tls\')', + 'const $ID = import("node:tls")', + ]; + for (const p of pats) { + const nodes = rootNode.findAll({ rule: { pattern: p } }); + for (const n of nodes) { + const id = n.getMatch('ID')?.text(); + if (id) out.push(`${id}.createSecurePair`); + } + } + return Array.from(new Set(out)); +} From 5aca91e49be85ae803471a8ef98e36ba320d2bc0 Mon Sep 17 00:00:00 2001 From: Leonardo Trevizo Date: Sun, 9 Nov 2025 23:24:28 -0600 Subject: [PATCH 06/12] test(`tls-createSecurePair-deprecation`): cover ESM default import and dynamic import (await/then) WHAT : - ESM default import - ESM dynamic import (await assignment) - ESM dynamic import (then callback) --- .../tests/expected/cjs-named.js | 2 ++ .../tests/expected/dynamic-import-assign.js | 2 ++ .../tests/expected/dynamic-import-then.js | 3 +++ .../tests/input/cjs-named.js | 2 ++ .../tests/input/dynamic-import-assign.js | 2 ++ .../tests/input/dynamic-import-then.js | 3 +++ 6 files changed, 14 insertions(+) create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-named.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-assign.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-then.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-named.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-assign.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-then.js diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-named.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-named.js new file mode 100644 index 00000000..aade280a --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-named.js @@ -0,0 +1,2 @@ +const { TLSSocket } = require('node:tls'); +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-assign.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-assign.js new file mode 100644 index 00000000..c6fd3cea --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-assign.js @@ -0,0 +1,2 @@ +const tls = await import('node:tls'); +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-then.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-then.js new file mode 100644 index 00000000..ef1bd895 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-then.js @@ -0,0 +1,3 @@ +import('node:tls').then(tls => { + const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); +}); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-named.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-named.js new file mode 100644 index 00000000..85389cf3 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-named.js @@ -0,0 +1,2 @@ +const { createSecurePair } = require('node:tls'); +const pair = createSecurePair(credentials); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-assign.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-assign.js new file mode 100644 index 00000000..fe969fef --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-assign.js @@ -0,0 +1,2 @@ +const tls = await import('node:tls'); +const pair = tls.createSecurePair(credentials); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-then.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-then.js new file mode 100644 index 00000000..6ee9842f --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-then.js @@ -0,0 +1,3 @@ +import('node:tls').then(tls => { + const pair = tls.createSecurePair(credentials); +}); From bc480f6c78bb8a90daa063cde3b19147b84da2f2 Mon Sep 17 00:00:00 2001 From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:22:49 +0100 Subject: [PATCH 07/12] WIP --- .../src/workflow.ts | 371 +++++++++++++++--- .../tests/expected/cjs-destructured-alias.js | 4 + .../tests/expected/dynamic-import-function.js | 3 + .../expected/esm-already-has-tlssocket.js | 5 + .../tests/expected/esm-default-import.js | 2 + .../tests/expected/esm-mixed-imports.js | 4 + .../tests/expected/esm-named-alias.js | 4 + .../tests/expected/multiple-calls.js | 8 + .../tests/expected/nested-calls.js | 12 + .../tests/expected/no-changes-needed.js | 4 + .../tests/expected/not-from-tls.js | 3 + .../tests/input/cjs-destructured-alias.js | 4 + .../tests/input/dynamic-import-function.js | 3 + .../tests/input/esm-already-has-tlssocket.js | 5 + .../tests/input/esm-default-import.js | 2 + .../tests/input/esm-mixed-imports.js | 4 + .../tests/input/esm-named-alias.js | 4 + .../tests/input/multiple-calls.js | 8 + .../tests/input/nested-calls.js | 12 + .../tests/input/no-changes-needed.js | 4 + .../tests/input/not-from-tls.js | 3 + 21 files changed, 405 insertions(+), 64 deletions(-) create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-alias.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-function.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-already-has-tlssocket.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-default-import.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-mixed-imports.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-alias.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/multiple-calls.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/nested-calls.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/no-changes-needed.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/expected/not-from-tls.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-alias.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-function.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-already-has-tlssocket.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-default-import.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-mixed-imports.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-alias.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/multiple-calls.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/nested-calls.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/no-changes-needed.js create mode 100644 recipes/tls-create-secure-pair-to-tls-socket/tests/input/not-from-tls.js diff --git a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts index 4065c6fc..fed28e02 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -1,29 +1,54 @@ import type { SgRoot, SgNode, Edit } from '@codemod.com/jssg-types/main'; import type JS from '@codemod.com/jssg-types/langs/javascript'; -import { getNodeImportStatements } from '@nodejs/codemod-utils/ast-grep/import-statement'; -import { getNodeRequireCalls } from '@nodejs/codemod-utils/ast-grep/require-call'; import { resolveBindingPath } from '@nodejs/codemod-utils/ast-grep/resolve-binding-path'; +import { getModuleDependencies } from '@nodejs/codemod-utils/ast-grep/module-dependencies'; type CallSite = { call: SgNode; binding: string }; export default function transform(root: SgRoot): string | null { const rootNode = root.root(); - const tlsStmts = [ - ...getNodeImportStatements(root, 'tls'), - ...getNodeRequireCalls(root, 'tls'), - ]; + const tlsStmts = getModuleDependencies(root, 'tls'); const cspBindings = unique([ - ...tlsStmts.map(s => resolveBindingPath(s as unknown as SgNode, '$.createSecurePair')).filter(Boolean) as string[], + ...(tlsStmts + .filter((s) => { + const kind = s.kind(); + return ( + kind === 'lexical_declaration' || + kind === 'variable_declarator' || + kind === 'import_statement' || + kind === 'import_clause' + ); + }) + .map((s) => + resolveBindingPath(s as unknown as SgNode, '$.createSecurePair'), + ) + .filter(Boolean) as string[]), + ...collectNamedImportAliases(tlsStmts, 'createSecurePair'), + ...collectCjsAliases(rootNode), ...collectDefaultImportBindings(tlsStmts), ...collectDynamicImportIdentifiers(rootNode), + ...collectDynamicImportThenBindings(rootNode), ]); - const callSites: CallSite[] = [...findCreateSecurePairCalls(rootNode)]; + const callSites: CallSite[] = findCallsMatchingBindings( + rootNode, + cspBindings, + ); const edits: Edit[] = []; + for (const { call, binding } of callSites) { - const a = getText(call.getMatch('A')); - const b = getText(call.getMatch('B')); - const c = getText(call.getMatch('C')); - const d = getText(call.getMatch('D')); + // Get arguments + const args = call.field('arguments'); + if (!args) continue; + + // Extract up to 4 arguments + const argNodes = args + .children() + .filter((n) => n.kind() !== '(' && n.kind() !== ')' && n.kind() !== ','); + const a = argNodes[0] ? getText(argNodes[0]) : null; + const b = argNodes[1] ? getText(argNodes[1]) : null; + const c = argNodes[2] ? getText(argNodes[2]) : null; + const d = argNodes[3] ? getText(argNodes[3]) : null; + const options = buildOptions(a, b, c, d); const isNamespace = binding.includes('.'); const replacement = isNamespace @@ -32,75 +57,120 @@ export default function transform(root: SgRoot): string | null { edits.push(call.replace(replacement)); } edits.push(...renamePairAssignedVariables(rootNode, cspBindings)); + edits.push(...rewriteTlsImports(rootNode)); + if (edits.length === 0) return null; + return rootNode.commitEdits(edits); } -function findCreateSecurePairCalls(rootNode: SgNode): CallSite[] { - const pats = [ - '$X.createSecurePair($A, $B, $C, $D)', - '$X.createSecurePair($A, $B, $C)', - '$X.createSecurePair($A, $B)', - '$X.createSecurePair($A)', - '$X.createSecurePair()', - 'createSecurePair($A, $B, $C, $D)', - 'createSecurePair($A, $B, $C)', - 'createSecurePair($A, $B)', - 'createSecurePair($A)', - 'createSecurePair()', - ]; +function findCallsMatchingBindings( + rootNode: SgNode, + bindings: string[], +): CallSite[] { const out: CallSite[] = []; - for (const p of pats) { - const nodes = rootNode.findAll({ rule: { kind: 'call_expression', pattern: p } }); - for (const n of nodes) { - const x = (n as SgNode).getMatch('X')?.text(); - const binding = x ? `${x}.createSecurePair` : 'createSecurePair'; - out.push({ call: n as SgNode, binding }); + + // Find all call expressions + const calls = rootNode.findAll({ + rule: { kind: 'call_expression' }, + }); + + for (const call of calls) { + const callee = call.field('function'); + if (!callee) continue; + + let binding: string; + if (callee.kind() === 'member_expression') { + // tls.createSecurePair or similar + const obj = callee.field('object'); + const prop = callee.field('property'); + if (!obj || !prop) continue; + binding = `${obj.text()}.${prop.text()}`; + } else if (callee.kind() === 'identifier') { + // createSecurePair or csp (alias) + binding = callee.text(); + } else { + continue; + } + + // Only include calls that match our bindings + if (bindings.includes(binding)) { + out.push({ call, binding }); } } + return out; } -function buildOptions(a?: string | null, b?: string | null, c?: string | null, d?: string | null): string { +function buildOptions( + secureContext?: string | null, + isServer?: string | null, + requestCert?: string | null, + rejectUnauthorized?: string | null, +) { const kv: string[] = []; - if (a) kv.push(`secureContext: ${a}`); - if (b) kv.push(`isServer: ${b}`); - if (c) kv.push(`requestCert: ${c}`); - if (d) kv.push(`rejectUnauthorized: ${d}`); + if (secureContext) kv.push(`secureContext: ${secureContext}`); + if (isServer) kv.push(`isServer: ${isServer}`); + if (requestCert) kv.push(`requestCert: ${requestCert}`); + if (rejectUnauthorized) kv.push(`rejectUnauthorized: ${rejectUnauthorized}`); return `{ ${kv.join(', ')} }`; } function getText(node: SgNode | undefined): string | null { - const t = node?.text()?.trim(); - return t || null; + return node?.text()?.trim() || null; } function unique(arr: T[]): T[] { return Array.from(new Set(arr)); } -function renamePairAssignedVariables(rootNode: SgNode, _bindings: string[]): Edit[] { +function renamePairAssignedVariables( + rootNode: SgNode, + bindings: string[], +): Edit[] { const edits: Edit[] = []; const decls = rootNode.findAll({ rule: { kind: 'variable_declarator', - has: { - field: 'value', - kind: 'call_expression', - any: [ - { pattern: '$X.createSecurePair($$$ARGS)' }, - { pattern: 'createSecurePair($$$ARGS)' }, - ], - }, + all: [ + { has: { field: 'name', kind: 'identifier' } }, + { has: { field: 'value', kind: 'call_expression' } }, + ], }, }); + for (const decl of decls) { + const callExpr = decl.field('value'); + if (!callExpr) continue; + + // Check if this call is from the tls module + const callee = callExpr.field('function'); + if (!callee) continue; + + let binding: string; + if (callee.kind() === 'member_expression') { + // tls.createSecurePair or similar + const obj = callee.field('object'); + const prop = callee.field('property'); + if (!obj || !prop) continue; + binding = `${obj.text()}.${prop.text()}`; + } else if (callee.kind() === 'identifier') { + // createSecurePair or csp (alias) + binding = callee.text(); + } else { + continue; + } + + // Only rename if it's from the tls module + if (!bindings.includes(binding)) continue; + const name = decl.field('name'); if (name && name.kind() === 'identifier' && name.text() === 'pair') { edits.push(name.replace('socket')); } } + return edits; } @@ -114,20 +184,28 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { { has: { field: 'source', - any: [{ pattern: '\'tls\'' }, { pattern: '"tls"' }, { pattern: '\'node:tls\'' }, { pattern: '"node:tls"' }], + any: [ + { pattern: "'tls'" }, + { pattern: '"tls"' }, + { pattern: "'node:tls'" }, + { pattern: '"node:tls"' }, + ], }, }, ], not: { has: { kind: 'namespace_import' } }, }, }); + for (const decl of esmNamed) { const srcText = decl.field('source')?.text()?.replace(/['"]/g, '') || ''; if (srcText !== 'tls' && srcText !== 'node:tls') continue; const named = decl.find({ rule: { kind: 'named_imports' } }); if (!named) continue; const specs = named.findAll({ rule: { kind: 'import_specifier' } }); - const hasCSP = specs.some(s => s.field('name')?.text() === 'createSecurePair'); + const hasCSP = specs.some( + (s) => s.field('name')?.text() === 'createSecurePair', + ); if (!hasCSP) continue; const kept: string[] = []; for (const s of specs) { @@ -138,8 +216,18 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { } } if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); - const def = decl.find({ rule: { kind: 'import_clause', has: { field: 'name', kind: 'identifier' } } })?.field('name')?.text(); - const rebuilt = def ? `import ${def}, { ${kept.join(', ')} } from '${srcText}';` : `import { ${kept.join(', ')} } from '${srcText}';`; + const def = decl + .find({ + rule: { + kind: 'import_clause', + has: { field: 'name', kind: 'identifier' }, + }, + }) + ?.field('name') + ?.text(); + const rebuilt = def + ? `import ${def}, { ${kept.join(', ')} } from '${srcText}';` + : `import { ${kept.join(', ')} } from '${srcText}';`; edits.push(decl.replace(rebuilt)); } const cjsNamed = rootNode.findAll({ @@ -151,9 +239,9 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { has: { field: 'value', any: [ - { pattern: 'require(\'tls\')' }, + { pattern: "require('tls')" }, { pattern: 'require("tls")' }, - { pattern: 'require(\'node:tls\')' }, + { pattern: "require('node:tls')" }, { pattern: 'require("node:tls")' }, ], }, @@ -161,14 +249,23 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { ], }, }); + for (const decl of cjsNamed) { const obj = decl.field('name'); if (!obj) continue; - const props = obj.findAll({ rule: { any: [{ kind: 'pair_pattern' }, { kind: 'shorthand_property_identifier_pattern' }] } }); - const hasCSP = props.some(p => + const props = obj.findAll({ + rule: { + any: [ + { kind: 'pair_pattern' }, + { kind: 'shorthand_property_identifier_pattern' }, + ], + }, + }); + const hasCSP = props.some((p) => p.kind() === 'pair_pattern' - ? p.field('key')?.text() === 'createSecurePair' || p.field('value')?.text() === 'createSecurePair' - : p.text() === 'createSecurePair' + ? p.field('key')?.text() === 'createSecurePair' || + p.field('value')?.text() === 'createSecurePair' + : p.text() === 'createSecurePair', ); if (!hasCSP) continue; const kept: string[] = []; @@ -186,8 +283,10 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { kept.push(alias && alias !== name ? `${name}: ${alias}` : name); } if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); + let stmt: SgNode = decl; let cur: SgNode | undefined = decl; + while (cur) { const k = cur.kind(); if (k === 'lexical_declaration' || k === 'variable_declaration') { @@ -196,35 +295,48 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { } cur = cur.parent?.(); } - edits.push(stmt.replace(`const { ${kept.join(', ')} } = require('node:tls');`)); + edits.push( + stmt.replace(`const { ${kept.join(', ')} } = require('node:tls');`), + ); } return edits; } function collectDefaultImportBindings(tlsStmts: SgNode[]): string[] { const out: string[] = []; + for (const stmt of tlsStmts) { if (stmt.kind() !== 'import_declaration') continue; const src = stmt.field('source')?.text()?.replace(/['"]/g, ''); if (!/^(node:)?tls$/.test(src || '')) continue; - const def = stmt.find({ rule: { kind: 'import_clause', has: { field: 'name', kind: 'identifier' } } })?.field('name')?.text(); + const def = stmt + .find({ + rule: { + kind: 'import_clause', + has: { field: 'name', kind: 'identifier' }, + }, + }) + ?.field('name') + ?.text(); if (def) out.push(`${def}.createSecurePair`); } + return out; } function collectDynamicImportIdentifiers(rootNode: SgNode): string[] { const out: string[] = []; const pats = [ - 'const $ID = await import(\'tls\')', + "const $ID = await import('tls')", 'const $ID = await import("tls")', - 'const $ID = await import(\'node:tls\')', + "const $ID = await import('node:tls')", 'const $ID = await import("node:tls")', - 'const $ID = import(\'tls\')', + "const $ID = import('tls')", 'const $ID = import("tls")', - 'const $ID = import(\'node:tls\')', + "const $ID = import('node:tls')", 'const $ID = import("node:tls")', ]; + for (const p of pats) { const nodes = rootNode.findAll({ rule: { pattern: p } }); for (const n of nodes) { @@ -232,5 +344,136 @@ function collectDynamicImportIdentifiers(rootNode: SgNode): string[] { if (id) out.push(`${id}.createSecurePair`); } } - return Array.from(new Set(out)); + + return unique(out); +} + +function collectDynamicImportThenBindings(rootNode: SgNode): string[] { + const out: string[] = []; + + // Use simpler patterns that are known to work + const patterns = [ + "import('tls').then($CB)", + 'import("tls").then($CB)', + "import('node:tls').then($CB)", + 'import("node:tls").then($CB)', + ]; + + for (const pattern of patterns) { + const calls = rootNode.findAll({ rule: { pattern } }); + + for (const call of calls) { + const callback = call.getMatch('CB'); + if (!callback) continue; + + let paramName: string | undefined; + + if (callback.kind() === 'arrow_function') { + // Arrow function: tls => ... + const param = callback.field('parameter'); + if (param && param.kind() === 'identifier') { + paramName = param.text(); + } else { + // Arrow function with parentheses: (tls) => ... + const params = callback.field('parameters'); + if (params) { + const identifiers = params.findAll({ + rule: { kind: 'identifier' }, + }); + if (identifiers.length > 0) { + paramName = identifiers[0].text(); + } + } + } + } else if (callback.kind() === 'function_expression') { + // Function expression: function(tls) { ... } + const params = callback.field('parameters'); + if (params) { + const identifiers = params.findAll({ rule: { kind: 'identifier' } }); + if (identifiers.length > 0) { + paramName = identifiers[0].text(); + } + } + } + + if (paramName) { + out.push(`${paramName}.createSecurePair`); + } + } + } + + return unique(out); +} + +function collectNamedImportAliases( + tlsStmts: SgNode[], + importName: string, +): string[] { + const out: string[] = []; + + for (const stmt of tlsStmts) { + if (stmt.kind() !== 'import_declaration') continue; + + const specifiers = stmt.findAll({ + rule: { + kind: 'import_specifier', + has: { field: 'alias', kind: 'identifier' }, + }, + }); + + for (const spec of specifiers) { + const name = spec.field('name')?.text(); + const alias = spec.field('alias')?.text(); + if (name === importName && alias) { + out.push(alias); + } + } + } + + return out; +} + +function collectCjsAliases(rootNode: SgNode): string[] { + const out: string[] = []; + + const decls = rootNode.findAll({ + rule: { + kind: 'variable_declarator', + all: [ + { has: { field: 'name', kind: 'object_pattern' } }, + { + has: { + field: 'value', + any: [ + { pattern: "require('tls')" }, + { pattern: 'require("tls")' }, + { pattern: "require('node:tls')" }, + { pattern: 'require("node:tls")' }, + ], + }, + }, + ], + }, + }); + + for (const decl of decls) { + const objPattern = decl.field('name'); + if (!objPattern) continue; + + const pairPatterns = objPattern.findAll({ + rule: { + kind: 'pair_pattern', + has: { field: 'key', pattern: 'createSecurePair' }, + }, + }); + + for (const pair of pairPatterns) { + const value = pair.field('value')?.text(); + if (value) { + out.push(value); + } + } + } + + return unique(out); } diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-alias.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-alias.js new file mode 100644 index 00000000..fb233f4f --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-alias.js @@ -0,0 +1,4 @@ +const { TLSSocket } = require('node:tls'); + +// Using an alias in CJS +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-function.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-function.js new file mode 100644 index 00000000..f44d4897 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/dynamic-import-function.js @@ -0,0 +1,3 @@ +import('node:tls').then(function (tls) { + const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); +}); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-already-has-tlssocket.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-already-has-tlssocket.js new file mode 100644 index 00000000..51e36fef --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-already-has-tlssocket.js @@ -0,0 +1,5 @@ +import { TLSSocket } from 'node:tls'; + +// Already has TLSSocket in imports +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +const existingSocket = new TLSSocket(socket, {}); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-default-import.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-default-import.js new file mode 100644 index 00000000..941426a9 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-default-import.js @@ -0,0 +1,2 @@ +import tls from 'node:tls'; +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-mixed-imports.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-mixed-imports.js new file mode 100644 index 00000000..0d18ed04 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-mixed-imports.js @@ -0,0 +1,4 @@ +import tls, { createServer } from 'node:tls'; + +const server = createServer(options); +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-alias.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-alias.js new file mode 100644 index 00000000..1306c64d --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-alias.js @@ -0,0 +1,4 @@ +import { TLSSocket } from 'node:tls'; + +// Using an alias +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/multiple-calls.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/multiple-calls.js new file mode 100644 index 00000000..986cccdf --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/multiple-calls.js @@ -0,0 +1,8 @@ +const { TLSSocket } = require('node:tls'); + +// Multiple calls with different arguments +const pair1 = new TLSSocket(underlyingSocket, {}); +const pair2 = new TLSSocket(underlyingSocket, { secureContext: credentials }); +const pair3 = new TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true }); +const pair4 = new TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true, requestCert: false }); +const pair5 = new TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true, requestCert: false, rejectUnauthorized: true }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/nested-calls.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/nested-calls.js new file mode 100644 index 00000000..463f0081 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/nested-calls.js @@ -0,0 +1,12 @@ +const tls = require('node:tls'); + +function setupTLS() { + const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); + return pair; +} + +class TLSManager { + init() { + this.pair = new tls.TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true }); + } +} diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/no-changes-needed.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/no-changes-needed.js new file mode 100644 index 00000000..28cc6216 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/no-changes-needed.js @@ -0,0 +1,4 @@ +const { TLSSocket } = require('node:tls'); + +// Code that already uses TLSSocket - should not change +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/not-from-tls.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/not-from-tls.js new file mode 100644 index 00000000..8e3f80cf --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/not-from-tls.js @@ -0,0 +1,3 @@ +// Without tls module - should not transform +const createSecurePair = someOtherModule.createSecurePair; +const pair = createSecurePair(credentials); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-alias.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-alias.js new file mode 100644 index 00000000..b6236075 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-alias.js @@ -0,0 +1,4 @@ +const { createSecurePair: csp } = require('node:tls'); + +// Using an alias in CJS +const pair = csp(credentials, true); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-function.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-function.js new file mode 100644 index 00000000..ce198886 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/dynamic-import-function.js @@ -0,0 +1,3 @@ +import('node:tls').then(function (tls) { + const pair = tls.createSecurePair(credentials); +}); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-already-has-tlssocket.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-already-has-tlssocket.js new file mode 100644 index 00000000..34889666 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-already-has-tlssocket.js @@ -0,0 +1,5 @@ +import { createSecurePair, TLSSocket } from 'node:tls'; + +// Already has TLSSocket in imports +const pair = createSecurePair(credentials); +const existingSocket = new TLSSocket(socket, {}); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-default-import.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-default-import.js new file mode 100644 index 00000000..3b456881 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-default-import.js @@ -0,0 +1,2 @@ +import tls from 'node:tls'; +const pair = tls.createSecurePair(credentials); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-mixed-imports.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-mixed-imports.js new file mode 100644 index 00000000..b115e395 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-mixed-imports.js @@ -0,0 +1,4 @@ +import tls, { createServer } from 'node:tls'; + +const server = createServer(options); +const pair = tls.createSecurePair(credentials); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-alias.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-alias.js new file mode 100644 index 00000000..cfc1085c --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-alias.js @@ -0,0 +1,4 @@ +import { createSecurePair as csp } from 'node:tls'; + +// Using an alias +const pair = csp(credentials); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/multiple-calls.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/multiple-calls.js new file mode 100644 index 00000000..4e93d447 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/multiple-calls.js @@ -0,0 +1,8 @@ +const { createSecurePair } = require('node:tls'); + +// Multiple calls with different arguments +const pair1 = createSecurePair(); +const pair2 = createSecurePair(credentials); +const pair3 = createSecurePair(credentials, true); +const pair4 = createSecurePair(credentials, true, false); +const pair5 = createSecurePair(credentials, true, false, true); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/nested-calls.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/nested-calls.js new file mode 100644 index 00000000..ec7f1b0c --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/nested-calls.js @@ -0,0 +1,12 @@ +const tls = require('node:tls'); + +function setupTLS() { + const pair = tls.createSecurePair(credentials); + return pair; +} + +class TLSManager { + init() { + this.pair = tls.createSecurePair(credentials, true); + } +} diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/no-changes-needed.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/no-changes-needed.js new file mode 100644 index 00000000..28cc6216 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/no-changes-needed.js @@ -0,0 +1,4 @@ +const { TLSSocket } = require('node:tls'); + +// Code that already uses TLSSocket - should not change +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/not-from-tls.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/not-from-tls.js new file mode 100644 index 00000000..8e3f80cf --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/not-from-tls.js @@ -0,0 +1,3 @@ +// Without tls module - should not transform +const createSecurePair = someOtherModule.createSecurePair; +const pair = createSecurePair(credentials); From da7d3c8ccacc46b2a59ff8bd70795d54ec834d77 Mon Sep 17 00:00:00 2001 From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:37:55 +0100 Subject: [PATCH 08/12] Update workflow.ts --- .../src/workflow.ts | 411 +++++++----------- 1 file changed, 154 insertions(+), 257 deletions(-) diff --git a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts index fed28e02..dc025851 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -3,104 +3,72 @@ import type JS from '@codemod.com/jssg-types/langs/javascript'; import { resolveBindingPath } from '@nodejs/codemod-utils/ast-grep/resolve-binding-path'; import { getModuleDependencies } from '@nodejs/codemod-utils/ast-grep/module-dependencies'; -type CallSite = { call: SgNode; binding: string }; - export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const tlsStmts = getModuleDependencies(root, 'tls'); - const cspBindings = unique([ - ...(tlsStmts - .filter((s) => { - const kind = s.kind(); - return ( - kind === 'lexical_declaration' || - kind === 'variable_declarator' || - kind === 'import_statement' || - kind === 'import_clause' - ); - }) - .map((s) => - resolveBindingPath(s as unknown as SgNode, '$.createSecurePair'), - ) - .filter(Boolean) as string[]), - ...collectNamedImportAliases(tlsStmts, 'createSecurePair'), - ...collectCjsAliases(rootNode), - ...collectDefaultImportBindings(tlsStmts), - ...collectDynamicImportIdentifiers(rootNode), - ...collectDynamicImportThenBindings(rootNode), - ]); - const callSites: CallSite[] = findCallsMatchingBindings( - rootNode, - cspBindings, - ); + + if (!tlsStmts.length) return null; + + const cspBindings = collectAllBindings(tlsStmts); + + if (!cspBindings.length) return null; + const edits: Edit[] = []; - for (const { call, binding } of callSites) { - // Get arguments + // Transform all createSecurePair calls + const calls = rootNode.findAll({ rule: { kind: 'call_expression' } }); + + for (const call of calls) { + const callee = call.field('function'); + if (!callee) continue; + + const binding = getCallBinding(callee); + if (!binding || !cspBindings.includes(binding)) continue; + + // Extract arguments const args = call.field('arguments'); if (!args) continue; - // Extract up to 4 arguments const argNodes = args .children() .filter((n) => n.kind() !== '(' && n.kind() !== ')' && n.kind() !== ','); - const a = argNodes[0] ? getText(argNodes[0]) : null; - const b = argNodes[1] ? getText(argNodes[1]) : null; - const c = argNodes[2] ? getText(argNodes[2]) : null; - const d = argNodes[3] ? getText(argNodes[3]) : null; - - const options = buildOptions(a, b, c, d); - const isNamespace = binding.includes('.'); - const replacement = isNamespace + + const options = buildOptions( + argNodes[0]?.text() || null, + argNodes[1]?.text() || null, + argNodes[2]?.text() || null, + argNodes[3]?.text() || null, + ); + + const replacement = binding.includes('.') ? `new ${binding.replace(/\.createSecurePair$/, '.TLSSocket')}(underlyingSocket, ${options})` : `new TLSSocket(underlyingSocket, ${options})`; + edits.push(call.replace(replacement)); } - edits.push(...renamePairAssignedVariables(rootNode, cspBindings)); + // Rename variables named 'pair' to 'socket' + edits.push(...renamePairVariables(rootNode, cspBindings)); + + // Update imports edits.push(...rewriteTlsImports(rootNode)); - if (edits.length === 0) return null; + if (!edits.length) return null; return rootNode.commitEdits(edits); } -function findCallsMatchingBindings( - rootNode: SgNode, - bindings: string[], -): CallSite[] { - const out: CallSite[] = []; - - // Find all call expressions - const calls = rootNode.findAll({ - rule: { kind: 'call_expression' }, - }); - - for (const call of calls) { - const callee = call.field('function'); - if (!callee) continue; - - let binding: string; - if (callee.kind() === 'member_expression') { - // tls.createSecurePair or similar - const obj = callee.field('object'); - const prop = callee.field('property'); - if (!obj || !prop) continue; - binding = `${obj.text()}.${prop.text()}`; - } else if (callee.kind() === 'identifier') { - // createSecurePair or csp (alias) - binding = callee.text(); - } else { - continue; - } - - // Only include calls that match our bindings - if (bindings.includes(binding)) { - out.push({ call, binding }); - } +function getCallBinding(callee: SgNode): string | null { + if (callee.kind() === 'member_expression') { + const obj = callee.field('object'); + const prop = callee.field('property'); + if (!obj || !prop) return null; + return `${obj.text()}.${prop.text()}`; } - - return out; + if (callee.kind() === 'identifier') { + return callee.text(); + } + return null; } function buildOptions( @@ -114,27 +82,21 @@ function buildOptions( if (isServer) kv.push(`isServer: ${isServer}`); if (requestCert) kv.push(`requestCert: ${requestCert}`); if (rejectUnauthorized) kv.push(`rejectUnauthorized: ${rejectUnauthorized}`); - return `{ ${kv.join(', ')} }`; -} - -function getText(node: SgNode | undefined): string | null { - return node?.text()?.trim() || null; + return kv.length > 0 ? `{ ${kv.join(', ')} }` : '{}'; } function unique(arr: T[]): T[] { return Array.from(new Set(arr)); } -function renamePairAssignedVariables( - rootNode: SgNode, - bindings: string[], -): Edit[] { +function renamePairVariables(rootNode: SgNode, bindings: string[]): Edit[] { const edits: Edit[] = []; + const decls = rootNode.findAll({ rule: { kind: 'variable_declarator', all: [ - { has: { field: 'name', kind: 'identifier' } }, + { has: { field: 'name', pattern: 'pair' } }, { has: { field: 'value', kind: 'call_expression' } }, ], }, @@ -144,29 +106,14 @@ function renamePairAssignedVariables( const callExpr = decl.field('value'); if (!callExpr) continue; - // Check if this call is from the tls module const callee = callExpr.field('function'); if (!callee) continue; - let binding: string; - if (callee.kind() === 'member_expression') { - // tls.createSecurePair or similar - const obj = callee.field('object'); - const prop = callee.field('property'); - if (!obj || !prop) continue; - binding = `${obj.text()}.${prop.text()}`; - } else if (callee.kind() === 'identifier') { - // createSecurePair or csp (alias) - binding = callee.text(); - } else { - continue; - } - - // Only rename if it's from the tls module - if (!bindings.includes(binding)) continue; + const binding = getCallBinding(callee); + if (!binding || !bindings.includes(binding)) continue; const name = decl.field('name'); - if (name && name.kind() === 'identifier' && name.text() === 'pair') { + if (name && name.kind() === 'identifier') { edits.push(name.replace('socket')); } } @@ -176,6 +123,8 @@ function renamePairAssignedVariables( function rewriteTlsImports(rootNode: SgNode): Edit[] { const edits: Edit[] = []; + + // Handle ESM named imports const esmNamed = rootNode.findAll({ rule: { kind: 'import_statement', @@ -200,13 +149,16 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { for (const decl of esmNamed) { const srcText = decl.field('source')?.text()?.replace(/['"]/g, '') || ''; if (srcText !== 'tls' && srcText !== 'node:tls') continue; + const named = decl.find({ rule: { kind: 'named_imports' } }); if (!named) continue; + const specs = named.findAll({ rule: { kind: 'import_specifier' } }); const hasCSP = specs.some( (s) => s.field('name')?.text() === 'createSecurePair', ); if (!hasCSP) continue; + const kept: string[] = []; for (const s of specs) { const imported = s.field('name')?.text(); @@ -215,7 +167,9 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { kept.push(maybeAlias ? `${imported} as ${maybeAlias}` : imported); } } + if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); + const def = decl .find({ rule: { @@ -225,11 +179,15 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { }) ?.field('name') ?.text(); + const rebuilt = def ? `import ${def}, { ${kept.join(', ')} } from '${srcText}';` : `import { ${kept.join(', ')} } from '${srcText}';`; + edits.push(decl.replace(rebuilt)); } + + // Handle CJS destructured requires const cjsNamed = rootNode.findAll({ rule: { kind: 'variable_declarator', @@ -253,6 +211,7 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { for (const decl of cjsNamed) { const obj = decl.field('name'); if (!obj) continue; + const props = obj.findAll({ rule: { any: [ @@ -261,13 +220,16 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { ], }, }); + const hasCSP = props.some((p) => p.kind() === 'pair_pattern' ? p.field('key')?.text() === 'createSecurePair' || p.field('value')?.text() === 'createSecurePair' : p.text() === 'createSecurePair', ); + if (!hasCSP) continue; + const kept: string[] = []; for (const p of props) { let name = ''; @@ -282,6 +244,7 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { if (!name || name === 'createSecurePair') continue; kept.push(alias && alias !== name ? `${name}: ${alias}` : name); } + if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); let stmt: SgNode = decl; @@ -295,185 +258,119 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { } cur = cur.parent?.(); } + edits.push( stmt.replace(`const { ${kept.join(', ')} } = require('node:tls');`), ); } + return edits; } -function collectDefaultImportBindings(tlsStmts: SgNode[]): string[] { - const out: string[] = []; +function collectAllBindings(tlsStmts: SgNode[]): string[] { + const bindings: string[] = []; for (const stmt of tlsStmts) { - if (stmt.kind() !== 'import_declaration') continue; - const src = stmt.field('source')?.text()?.replace(/['"]/g, ''); - if (!/^(node:)?tls$/.test(src || '')) continue; - const def = stmt - .find({ + const kind = stmt.kind(); + + // Use resolveBindingPath for standard imports/requires + if ( + kind === 'lexical_declaration' || + kind === 'variable_declarator' || + kind === 'import_statement' || + kind === 'import_clause' + ) { + const resolved = resolveBindingPath( + stmt as unknown as SgNode, + '$.createSecurePair', + ); + if (resolved) bindings.push(resolved); + } + + // Handle ESM aliases: import { createSecurePair as csp } from 'tls' + if (kind === 'import_statement') { + const specs = stmt.findAll({ rule: { - kind: 'import_clause', - has: { field: 'name', kind: 'identifier' }, + kind: 'import_specifier', + has: { field: 'alias', kind: 'identifier' }, }, - }) - ?.field('name') - ?.text(); - if (def) out.push(`${def}.createSecurePair`); - } - - return out; -} + }); -function collectDynamicImportIdentifiers(rootNode: SgNode): string[] { - const out: string[] = []; - const pats = [ - "const $ID = await import('tls')", - 'const $ID = await import("tls")', - "const $ID = await import('node:tls')", - 'const $ID = await import("node:tls")', - "const $ID = import('tls')", - 'const $ID = import("tls")', - "const $ID = import('node:tls')", - 'const $ID = import("node:tls")', - ]; - - for (const p of pats) { - const nodes = rootNode.findAll({ rule: { pattern: p } }); - for (const n of nodes) { - const id = n.getMatch('ID')?.text(); - if (id) out.push(`${id}.createSecurePair`); + for (const spec of specs) { + if (spec.field('name')?.text() === 'createSecurePair') { + const alias = spec.field('alias')?.text(); + if (alias) bindings.push(alias); + } + } } - } - - return unique(out); -} -function collectDynamicImportThenBindings(rootNode: SgNode): string[] { - const out: string[] = []; - - // Use simpler patterns that are known to work - const patterns = [ - "import('tls').then($CB)", - 'import("tls").then($CB)', - "import('node:tls').then($CB)", - 'import("node:tls").then($CB)', - ]; - - for (const pattern of patterns) { - const calls = rootNode.findAll({ rule: { pattern } }); - - for (const call of calls) { - const callback = call.getMatch('CB'); - if (!callback) continue; - - let paramName: string | undefined; - - if (callback.kind() === 'arrow_function') { - // Arrow function: tls => ... - const param = callback.field('parameter'); - if (param && param.kind() === 'identifier') { - paramName = param.text(); - } else { - // Arrow function with parentheses: (tls) => ... - const params = callback.field('parameters'); - if (params) { - const identifiers = params.findAll({ - rule: { kind: 'identifier' }, - }); - if (identifiers.length > 0) { - paramName = identifiers[0].text(); + // Handle CJS destructured aliases: const { createSecurePair: csp } = require('tls') + if (kind === 'variable_declarator') { + const objPattern = stmt.field('name'); + if (objPattern?.kind() === 'object_pattern') { + const pairs = objPattern.findAll({ rule: { kind: 'pair_pattern' } }); + for (const pair of pairs) { + if (pair.field('key')?.text() === 'createSecurePair') { + const alias = pair.field('value')?.text(); + if (alias && alias !== 'createSecurePair') { + bindings.push(alias); } } } - } else if (callback.kind() === 'function_expression') { - // Function expression: function(tls) { ... } - const params = callback.field('parameters'); - if (params) { - const identifiers = params.findAll({ rule: { kind: 'identifier' } }); - if (identifiers.length > 0) { - paramName = identifiers[0].text(); - } - } } - if (paramName) { - out.push(`${paramName}.createSecurePair`); - } - } - } - - return unique(out); -} - -function collectNamedImportAliases( - tlsStmts: SgNode[], - importName: string, -): string[] { - const out: string[] = []; - - for (const stmt of tlsStmts) { - if (stmt.kind() !== 'import_declaration') continue; - - const specifiers = stmt.findAll({ - rule: { - kind: 'import_specifier', - has: { field: 'alias', kind: 'identifier' }, - }, - }); - - for (const spec of specifiers) { - const name = spec.field('name')?.text(); - const alias = spec.field('alias')?.text(); - if (name === importName && alias) { - out.push(alias); + // Handle dynamic imports: const tls = await import('tls') + const value = stmt.field('value'); + if (value?.kind() === 'await_expression') { + const name = stmt.field('name'); + if (name?.kind() === 'identifier') { + bindings.push(`${name.text()}.createSecurePair`); + } } } - } - - return out; -} - -function collectCjsAliases(rootNode: SgNode): string[] { - const out: string[] = []; - const decls = rootNode.findAll({ - rule: { - kind: 'variable_declarator', - all: [ - { has: { field: 'name', kind: 'object_pattern' } }, - { - has: { - field: 'value', - any: [ - { pattern: "require('tls')" }, - { pattern: 'require("tls")' }, - { pattern: "require('node:tls')" }, - { pattern: 'require("node:tls")' }, - ], - }, - }, - ], - }, - }); - - for (const decl of decls) { - const objPattern = decl.field('name'); - if (!objPattern) continue; - - const pairPatterns = objPattern.findAll({ - rule: { - kind: 'pair_pattern', - has: { field: 'key', pattern: 'createSecurePair' }, - }, - }); + // Handle dynamic import .then(): import('tls').then(tls => ...) + // getModuleDependencies returns the expression_statement node + if (kind === 'expression_statement') { + const expr = stmt.children().find((c) => c.kind() === 'call_expression'); + if (expr?.kind() === 'call_expression') { + const func = expr.field('function'); + if (func?.kind() === 'member_expression') { + const prop = func.field('property'); + if (prop?.text() === 'then') { + const args = expr.field('arguments'); + const callback = args?.find({ + rule: { + any: [ + { kind: 'arrow_function' }, + { kind: 'function_expression' }, + ], + }, + }); - for (const pair of pairPatterns) { - const value = pair.field('value')?.text(); - if (value) { - out.push(value); + if (callback) { + let param: SgNode | undefined; + + if (callback.kind() === 'arrow_function') { + param = callback.field('parameter'); + if (!param) { + const params = callback.field('parameters'); + param = params?.find({ rule: { kind: 'identifier' } }); + } + } else if (callback.kind() === 'function_expression') { + const params = callback.field('parameters'); + param = params?.find({ rule: { kind: 'identifier' } }); + } + + if (param) { + bindings.push(`${param.text()}.createSecurePair`); + } + } + } + } } } } - return unique(out); + return unique(bindings); } From c7b610f6f25c457ba581715a10f6fbf5f6ea6f71 Mon Sep 17 00:00:00 2001 From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:43:10 +0100 Subject: [PATCH 09/12] Update package-lock.json --- package-lock.json | 958 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 954 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9a6d1be..9518b7c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,8 @@ }, "node_modules/@ast-grep/cli": { "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli/-/cli-0.25.7.tgz", + "integrity": "sha512-vklcPRFHPHkwHq05nb2Fuaj4BYNWxhr8GIdB6la090jWob9FdbM/Jz86vlQp2tRELb2rKzuHeksG8qDrbX4REg==", "hasInstallScript": true, "dependencies": { "detect-libc": "2.0.3" @@ -43,6 +45,8 @@ }, "node_modules/@ast-grep/cli-darwin-arm64": { "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-darwin-arm64/-/cli-darwin-arm64-0.25.7.tgz", + "integrity": "sha512-dkj8hy32mWuQwCJUEpnKwTS8tLE+e7dhvu6is+v5Q6AumOVlcL6PJWQsyaA4vedDm6XOGK9+WnyFpCnV3b5ouA==", "cpu": [ "arm64" ], @@ -55,8 +59,106 @@ "node": ">= 10" } }, + "node_modules/@ast-grep/cli-darwin-x64": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-darwin-x64/-/cli-darwin-x64-0.25.7.tgz", + "integrity": "sha512-FBdv7GH3llH5LI0S2yeqgQM5QEUHeoYMhw1pv+C439UeL5BBFFjI+LYVALciwsYzuq/DQDTnT2cM0JhYGajDLQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/cli-linux-arm64-gnu": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-0.25.7.tgz", + "integrity": "sha512-lsE+cSe4rFO8rvLhMM7PM3T83LlmV60H9dOH+1hq8thkWhLCL6vAJijEVWgAQDDvvZf3xnNVgG2GG4jOMfTuTQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/cli-linux-x64-gnu": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-linux-x64-gnu/-/cli-linux-x64-gnu-0.25.7.tgz", + "integrity": "sha512-uuF5GXgeUZtBrftJJYuQU7PvDT7Q9fJkKKwpIscEfQqLndri1tdYzzT9jKj2taWFlhiCVqLaDEHsdfTeWaVjZQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/cli-win32-arm64-msvc": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-0.25.7.tgz", + "integrity": "sha512-GSWRjOnWybzNP5rnvPb6lQ7lSPoEIl64gk4uHE1h+a2nnFhT9REWTKFcmNB2aG8VmKEz1gu0pxpg9HmBe2OUBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/cli-win32-ia32-msvc": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-0.25.7.tgz", + "integrity": "sha512-5p9PWbTeXaivQYixB+JkkpFKgY7G1Tm6R46Dhq6cHvKksiQ6lWlTOOmhl0QARtY7y3XP0MWuvjDEWCYrvYtO4A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/cli-win32-x64-msvc": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-x64-msvc/-/cli-win32-x64-msvc-0.25.7.tgz", + "integrity": "sha512-WjsRuyKTCeGWpMhvobzU/6HaWbseENPl5mNMZIKs8gsCpkUyTUfvV8/A2W29oHCgbDWRtixYppWtd87Qjpm6cg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@ast-grep/lang-bash": { "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@ast-grep/lang-bash/-/lang-bash-0.0.7.tgz", + "integrity": "sha512-tbPrTkmUv3YVKZZg8q51nAE5ItVVq6WzGPrJtiDKLZ3AdfRzZCOC2VgRwJBWD+VbFELqSVARKwXoQB6E8k+xug==", "dev": true, "hasInstallScript": true, "license": "ISC", @@ -74,6 +176,8 @@ }, "node_modules/@ast-grep/lang-json": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@ast-grep/lang-json/-/lang-json-0.0.6.tgz", + "integrity": "sha512-xb4OXtyuyY9RqUs5Af4Jb5hAJcBD0hGD1rJSQm1chJqdWOjhM6G7V2vHLx6B8M9uXuTBnaNs4U4OccMp+e95JQ==", "dev": true, "hasInstallScript": true, "license": "ISC", @@ -91,6 +195,8 @@ }, "node_modules/@ast-grep/napi": { "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.40.5.tgz", + "integrity": "sha512-hJA62OeBKUQT68DD2gDyhOqJxZxycqg8wLxbqjgqSzYttCMSDL9tiAQ9abgekBYNHudbJosm9sWOEbmCDfpX2A==", "dev": true, "license": "MIT", "engines": { @@ -110,6 +216,8 @@ }, "node_modules/@ast-grep/napi-darwin-arm64": { "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.40.5.tgz", + "integrity": "sha512-2F072fGN0WTq7KI3okuEnkGJVEHLbi56Bw1H6NAMf7j2mJJeQWsRyGOMcyNnUXZDeNdvoMH0OB2a5wwUegY/nQ==", "cpu": [ "arm64" ], @@ -123,13 +231,153 @@ "node": ">= 10" } }, + "node_modules/@ast-grep/napi-darwin-x64": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.40.5.tgz", + "integrity": "sha512-dJMidHZhhxuLBYNi6/FKI812jQ7wcFPSKkVPwviez2D+KvYagapUMAV/4dJ7FCORfguVk8Y0jpPAlYmWRT5nvA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-arm64-gnu": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.40.5.tgz", + "integrity": "sha512-nBRCbyoS87uqkaw4Oyfe5VO+SRm2B+0g0T8ME69Qry9ShMf41a2bTdpcQx9e8scZPogq+CTwDHo3THyBV71l9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-arm64-musl": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.40.5.tgz", + "integrity": "sha512-/qKsmds5FMoaEj6FdNzepbmLMtlFuBLdrAn9GIWCqOIcVcYvM1Nka8+mncfeXB/MFZKOrzQsQdPTWqrrQzXLrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-x64-gnu": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.40.5.tgz", + "integrity": "sha512-DP4oDbq7f/1A2hRTFLhJfDFR6aI5mRWdEfKfHzRItmlKsR9WlcEl1qDJs/zX9R2EEtIDsSKRzuJNfJllY3/W8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-x64-musl": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.40.5.tgz", + "integrity": "sha512-BRZUvVBPUNpWPo6Ns8chXVzxHPY+k9gpsubGTHy92Q26ecZULd/dTkWWdnvfhRqttsSQ9Pe/XQdi5+hDQ6RYcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-arm64-msvc": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.40.5.tgz", + "integrity": "sha512-y95zSEwc7vhxmcrcH0GnK4ZHEBQrmrszRBNQovzaciF9GUqEcCACNLoBesn4V47IaOp4fYgD2/EhGRTIBFb2Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-ia32-msvc": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.40.5.tgz", + "integrity": "sha512-K/u8De62iUnFCzVUs7FBdTZ2Jrgc5/DLHqjpup66KxZ7GIM9/HGME/O8aSoPkpcAeCD4TiTZ11C1i5p5H98hTg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-x64-msvc": { + "version": "0.40.5", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.40.5.tgz", + "integrity": "sha512-dqm5zg/o4Nh4VOQPEpMS23ot8HVd22gG0eg01t4CFcZeuzyuSgBlOL3N7xLbz3iH2sVkk7keuBwAzOIpTqziNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@ast-grep/setup-lang": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@ast-grep/setup-lang/-/setup-lang-0.0.6.tgz", + "integrity": "sha512-aSYZNF5nGQMxnwiA3Lcc8zi0AtpGlug47ADgqCgP/2n7p922FbnW7vo1rbW4kKjW72B/3mDdN7uvYidv8JnPnw==", "dev": true, "license": "ISC" }, "node_modules/@babel/code-frame": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -142,6 +390,8 @@ }, "node_modules/@babel/compat-data": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -149,6 +399,8 @@ }, "node_modules/@babel/core": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", "peer": true, "dependencies": { @@ -178,6 +430,8 @@ }, "node_modules/@babel/generator": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.28.5", @@ -192,6 +446,8 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "license": "MIT", "dependencies": { "@babel/types": "^7.27.3" @@ -202,6 +458,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.2", @@ -216,6 +474,8 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -235,6 +495,8 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -242,6 +504,8 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.28.5", @@ -253,6 +517,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -264,6 +530,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -279,6 +547,8 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "license": "MIT", "dependencies": { "@babel/types": "^7.27.1" @@ -289,6 +559,8 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -296,6 +568,8 @@ }, "node_modules/@babel/helper-replace-supers": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", "license": "MIT", "dependencies": { "@babel/helper-member-expression-to-functions": "^7.27.1", @@ -311,6 +585,8 @@ }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -322,6 +598,8 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -329,6 +607,8 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -336,6 +616,8 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -343,6 +625,8 @@ }, "node_modules/@babel/helpers": { "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", @@ -354,6 +638,8 @@ }, "node_modules/@babel/parser": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "license": "MIT", "dependencies": { "@babel/types": "^7.28.5" @@ -367,6 +653,8 @@ }, "node_modules/@babel/plugin-syntax-flow": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz", + "integrity": "sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -380,6 +668,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -393,6 +683,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -406,6 +698,8 @@ }, "node_modules/@babel/plugin-transform-class-properties": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", @@ -420,6 +714,8 @@ }, "node_modules/@babel/plugin-transform-flow-strip-types": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", + "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -434,6 +730,8 @@ }, "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -448,6 +746,8 @@ }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -461,6 +761,8 @@ }, "node_modules/@babel/plugin-transform-optional-chaining": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", + "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -475,6 +777,8 @@ }, "node_modules/@babel/plugin-transform-private-methods": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", @@ -489,6 +793,8 @@ }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -506,6 +812,8 @@ }, "node_modules/@babel/preset-flow": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.27.1.tgz", + "integrity": "sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -521,6 +829,8 @@ }, "node_modules/@babel/preset-typescript": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -538,6 +848,8 @@ }, "node_modules/@babel/register": { "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.28.3.tgz", + "integrity": "sha512-CieDOtd8u208eI49bYl4z1J22ySFw87IGwE+IswFEExH7e3rLgKb0WNQeumnacQ1+VoDJLYI5QFA3AJZuyZQfA==", "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", @@ -555,6 +867,8 @@ }, "node_modules/@babel/template": { "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -567,6 +881,8 @@ }, "node_modules/@babel/traverse": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -583,6 +899,8 @@ }, "node_modules/@babel/types": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -594,6 +912,8 @@ }, "node_modules/@biomejs/biome": { "version": "2.3.11", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.11.tgz", + "integrity": "sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -619,6 +939,8 @@ }, "node_modules/@biomejs/cli-darwin-arm64": { "version": "2.3.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.11.tgz", + "integrity": "sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA==", "cpu": [ "arm64" ], @@ -753,11 +1075,15 @@ }, "node_modules/@codemod.com/jssg-types": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@codemod.com/jssg-types/-/jssg-types-1.3.1.tgz", + "integrity": "sha512-poYNa8mfr8+4+kBPc3bAKBTaUtOQdg5z3voeGGAAr0tiTBvC4cmmoY/dyHXEWT8F+p8A1tWUnhmJZ4WQXV3HVA==", "dev": true, "license": "Apache-2.0" }, "node_modules/@codemod.com/workflow": { "version": "0.0.31", + "resolved": "https://registry.npmjs.org/@codemod.com/workflow/-/workflow-0.0.31.tgz", + "integrity": "sha512-8xmbxwjxr6d0ZUm3RS/eQqud2mUGXwQgf2v+YEjwQQVwOse6yShgoFljrg7ujvJlhzymivYloL0T0VSS9YubNw==", "license": "Apache-2.0", "dependencies": { "@ast-grep/cli": "^0.25.4", @@ -786,6 +1112,8 @@ }, "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi": { "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.25.7.tgz", + "integrity": "sha512-kDw/JNyOLttVbm2hl+55C9lXuUcuIFt31LQIpSptUkyTgI+2Cdqdeah2bNPe4/GQM2ysDjBDS4y1+9iQxMdJiw==", "license": "MIT", "engines": { "node": ">= 10" @@ -804,6 +1132,8 @@ }, "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-darwin-arm64": { "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.25.7.tgz", + "integrity": "sha512-qqI1JvB6ULgOUOVE3YviQNQ6KAYOnkiE8W5fNwVJGUgMkUuM8tUm1Nal3vfKCI7dnYgpcNlKxdTWGlbt7aHKNg==", "cpu": [ "arm64" ], @@ -816,8 +1146,138 @@ "node": ">= 10" } }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-darwin-x64": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.25.7.tgz", + "integrity": "sha512-gq1Cf7US322ZJYPrVnAnn6eBLS6xi5catb5t99Wu6Rbm67XadEc81gtPTbPeNIu8FGgPjvKUc010rts2ZZbJeA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-linux-arm64-gnu": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.25.7.tgz", + "integrity": "sha512-q+BzEC7wB7pkK+pQKbn4TVJThrEtvxjObz0okscPtxTNYvSJGv9jr3Nde5SYjdkfk8Ab4NgDMshVjKWVz2TSbQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-linux-arm64-musl": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.25.7.tgz", + "integrity": "sha512-SEqZ6y0UhzmvZS938jIgR04kgHAW70hJ8yF4x9AkcqEhbeyqgElxIE7ve50ukDzs70fAKccdV8zYmebYN/7iPg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-linux-x64-gnu": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.25.7.tgz", + "integrity": "sha512-8YuE/zTywTBb/iTm601JXTdWV2Redy9L9ab27aRD0hwX8FLmKUy8gK0fSo3xx+FyvSET49xkoR9tYdNaG2Wrkw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-linux-x64-musl": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.25.7.tgz", + "integrity": "sha512-sT3eslR50IU6lHfqvq/c7vpxksJiB3h1NjEy1LpG+CYPuoLsQaB8j9OQlX8TqgVlDty/d/13cSls1Y3n/pm9xw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-win32-arm64-msvc": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.25.7.tgz", + "integrity": "sha512-pDi9vyXzUbpiRwFTif6+R7ZIIVB1ZKcRUJLKSIPyYb39DcSX7aOuxQcSZderWnBrwPGxZKzdgztdQ16TuAz2IQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-win32-ia32-msvc": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.25.7.tgz", + "integrity": "sha512-WFSNDMI5L9N9dK5zFQ6N900nhraOSYtKns/2p/EKZIKPBDXJSzzhT/jBakCSDix1GUs8K0XgkDoq2rXmuiBqXA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codemod.com/workflow/node_modules/@ast-grep/napi-win32-x64-msvc": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.25.7.tgz", + "integrity": "sha512-HlsoVwQ9XrgNZ0JAmXgV5t8Ltx9tGyWZNS2UMY/2cvNU/SG9EpJLm1Bu9Mlk5seiJLbl28QTTbhZdfPKBzGTVQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@inquirer/external-editor": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", "license": "MIT", "dependencies": { "chardet": "^2.1.0", @@ -837,6 +1297,8 @@ }, "node_modules/@inquirer/figures": { "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.14.tgz", + "integrity": "sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==", "license": "MIT", "engines": { "node": ">=18" @@ -844,6 +1306,8 @@ }, "node_modules/@isaacs/cliui": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -859,6 +1323,8 @@ }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { "node": ">=12" @@ -869,6 +1335,8 @@ }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { "node": ">=12" @@ -879,10 +1347,14 @@ }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -898,6 +1370,8 @@ }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -911,6 +1385,8 @@ }, "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -926,6 +1402,8 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -934,6 +1412,8 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -942,6 +1422,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -949,10 +1431,14 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -961,6 +1447,8 @@ }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", "license": "MIT", "dependencies": { "debug": "^4.1.1" @@ -968,10 +1456,14 @@ }, "node_modules/@kwsites/promise-deferred": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "license": "MIT" }, "node_modules/@nodejs-loaders/alias": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@nodejs-loaders/alias/-/alias-2.1.2.tgz", + "integrity": "sha512-thHaBXfGUbu7WpMqWt6Fw2xA6eN4faMl8kNFO8ufb2Ae4B9+9RhAg4vai1bFvzlBtnSTvUPU6qDz7sbpImFAbA==", "license": "ISC", "dependencies": { "json5": "^2.2.3" @@ -1098,6 +1590,8 @@ }, "node_modules/@octokit/auth-token": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "license": "MIT", "engines": { "node": ">= 18" @@ -1105,6 +1599,8 @@ }, "node_modules/@octokit/core": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", "license": "MIT", "peer": true, "dependencies": { @@ -1122,6 +1618,8 @@ }, "node_modules/@octokit/endpoint": { "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", "license": "MIT", "dependencies": { "@octokit/types": "^13.1.0", @@ -1133,6 +1631,8 @@ }, "node_modules/@octokit/graphql": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", "license": "MIT", "dependencies": { "@octokit/request": "^8.4.1", @@ -1145,10 +1645,14 @@ }, "node_modules/@octokit/openapi-types": { "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { "version": "11.4.4-cjs.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.4-cjs.2.tgz", + "integrity": "sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==", "license": "MIT", "dependencies": { "@octokit/types": "^13.7.0" @@ -1162,6 +1666,8 @@ }, "node_modules/@octokit/plugin-request-log": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", "license": "MIT", "engines": { "node": ">= 18" @@ -1172,6 +1678,8 @@ }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "13.3.2-cjs.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.2-cjs.1.tgz", + "integrity": "sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==", "license": "MIT", "dependencies": { "@octokit/types": "^13.8.0" @@ -1185,6 +1693,8 @@ }, "node_modules/@octokit/request": { "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", "license": "MIT", "dependencies": { "@octokit/endpoint": "^9.0.6", @@ -1198,6 +1708,8 @@ }, "node_modules/@octokit/request-error": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", "license": "MIT", "dependencies": { "@octokit/types": "^13.1.0", @@ -1210,6 +1722,8 @@ }, "node_modules/@octokit/rest": { "version": "20.1.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.2.tgz", + "integrity": "sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==", "license": "MIT", "dependencies": { "@octokit/core": "^5.0.2", @@ -1223,6 +1737,8 @@ }, "node_modules/@octokit/types": { "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "license": "MIT", "dependencies": { "@octokit/openapi-types": "^24.2.0" @@ -1230,6 +1746,8 @@ }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "license": "MIT", "optional": true, "engines": { @@ -1238,6 +1756,8 @@ }, "node_modules/@sindresorhus/slugify": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", + "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==", "license": "MIT", "dependencies": { "@sindresorhus/transliterate": "^1.0.0", @@ -1252,6 +1772,8 @@ }, "node_modules/@sindresorhus/transliterate": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", + "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", "license": "MIT", "dependencies": { "escape-string-regexp": "^5.0.0" @@ -1265,6 +1787,8 @@ }, "node_modules/@types/jscodeshift": { "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.11.tgz", + "integrity": "sha512-d7CAfFGOupj5qCDqMODXxNz2/NwCv/Lha78ZFbnr6qpk3K98iSB8I+ig9ERE2+EeYML352VMRsjPyOpeA+04eQ==", "license": "MIT", "dependencies": { "ast-types": "^0.14.1", @@ -1273,13 +1797,18 @@ }, "node_modules/@types/node": { "version": "25.0.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz", + "integrity": "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } }, "node_modules/@types/node-fetch": { "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -1288,6 +1817,8 @@ }, "node_modules/@typescript/native-preview": { "version": "7.0.0-dev.20260119.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20260119.1.tgz", + "integrity": "sha512-Tf74TdJVJlLRMN0W9VXK8jc0Gor9+wFRm40qTLt2JeHiPpSF5TEN/pHPjlf4Id1wDSJXH9p5/U1wFS3s5TS2PQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1305,6 +1836,8 @@ }, "node_modules/@typescript/native-preview-darwin-arm64": { "version": "7.0.0-dev.20260119.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20260119.1.tgz", + "integrity": "sha512-siuRD9Shh5gVrgYG5HEWxFxG/dkZa4ndupGWKMfM4DwMG7zLeFayi6sB9yiwpD0d203ts01D7uTnTCALdiWXmQ==", "cpu": [ "arm64" ], @@ -1401,6 +1934,8 @@ }, "node_modules/abort-controller": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" @@ -1411,6 +1946,8 @@ }, "node_modules/agentkeepalive": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", "dependencies": { "humanize-ms": "^1.2.1" @@ -1421,6 +1958,8 @@ }, "node_modules/ansi-escapes": { "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "license": "MIT", "dependencies": { "type-fest": "^0.21.3" @@ -1434,6 +1973,8 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { "node": ">=8" @@ -1441,6 +1982,8 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1454,6 +1997,8 @@ }, "node_modules/ast-types": { "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", "license": "MIT", "dependencies": { "tslib": "^2.0.1" @@ -1464,10 +2009,14 @@ }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", "license": "MIT", "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -1475,13 +2024,19 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, "node_modules/base-64": { - "version": "0.1.0" + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", + "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -1500,6 +2055,8 @@ }, "node_modules/baseline-browser-mapping": { "version": "2.8.24", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.24.tgz", + "integrity": "sha512-uUhTRDPXamakPyghwrUcjaGvvBqGrWvBHReoiULMIpOJVM9IYzQh83Xk2Onx5HlGI2o10NNCzcs9TG/S3TkwrQ==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -1507,10 +2064,14 @@ }, "node_modules/before-after-hook": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "license": "Apache-2.0" }, "node_modules/bl": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -1520,6 +2081,8 @@ }, "node_modules/brace-expansion": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -1527,6 +2090,8 @@ }, "node_modules/braces": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -1537,6 +2102,8 @@ }, "node_modules/browserslist": { "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", "funding": [ { "type": "opencollective", @@ -1569,6 +2136,8 @@ }, "node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -1591,10 +2160,14 @@ }, "node_modules/buffer-from": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -1606,6 +2179,8 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001753", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", "funding": [ { "type": "opencollective", @@ -1624,6 +2199,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -1638,10 +2215,14 @@ }, "node_modules/chardet": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", "license": "MIT" }, "node_modules/charenc": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "license": "BSD-3-Clause", "engines": { "node": "*" @@ -1649,6 +2230,8 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" @@ -1659,6 +2242,8 @@ }, "node_modules/cli-spinners": { "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "license": "MIT", "engines": { "node": ">=6" @@ -1669,6 +2254,8 @@ }, "node_modules/cli-width": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "license": "ISC", "engines": { "node": ">= 12" @@ -1676,6 +2263,8 @@ }, "node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "license": "MIT", "engines": { "node": ">=0.8" @@ -1683,6 +2272,8 @@ }, "node_modules/clone-deep": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", @@ -1695,6 +2286,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1705,10 +2298,14 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/colors-cli": { "version": "1.0.33", + "resolved": "https://registry.npmjs.org/colors-cli/-/colors-cli-1.0.33.tgz", + "integrity": "sha512-PWGsmoJFdOB0t+BeHgmtuoRZUQucOLl5ii81NBzOOGVxlgE04muFNHlR5j8i8MKbOPELBl3243AI6lGBTj5ICQ==", "license": "MIT", "bin": { "colors": "bin/colors" @@ -1719,6 +2316,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -1729,18 +2328,26 @@ }, "node_modules/commondir": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -1753,6 +2360,8 @@ }, "node_modules/crypt": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "license": "BSD-3-Clause", "engines": { "node": "*" @@ -1760,6 +2369,8 @@ }, "node_modules/debug": { "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1775,6 +2386,8 @@ }, "node_modules/dedent": { "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1788,6 +2401,8 @@ }, "node_modules/defaults": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "license": "MIT", "dependencies": { "clone": "^1.0.2" @@ -1798,6 +2413,8 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -1805,10 +2422,14 @@ }, "node_modules/deprecation": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "license": "ISC" }, "node_modules/detect-indent": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.2.tgz", + "integrity": "sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==", "license": "MIT", "engines": { "node": ">=12.20" @@ -1819,6 +2440,8 @@ }, "node_modules/detect-libc": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -1826,6 +2449,8 @@ }, "node_modules/detect-newline": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -1836,6 +2461,8 @@ }, "node_modules/diff": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -1843,6 +2470,8 @@ }, "node_modules/digest-fetch": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz", + "integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==", "license": "ISC", "dependencies": { "base-64": "^0.1.0", @@ -1851,6 +2480,8 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -1863,18 +2494,26 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.5.244", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/es-define-property": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -1882,6 +2521,8 @@ }, "node_modules/es-errors": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -1889,6 +2530,8 @@ }, "node_modules/es-object-atoms": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -1899,6 +2542,8 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -1912,6 +2557,8 @@ }, "node_modules/escalade": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { "node": ">=6" @@ -1919,6 +2566,8 @@ }, "node_modules/escape-string-regexp": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { "node": ">=12" @@ -1929,6 +2578,8 @@ }, "node_modules/esprima": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -1940,6 +2591,8 @@ }, "node_modules/event-target-shim": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", "engines": { "node": ">=6" @@ -1947,6 +2600,8 @@ }, "node_modules/filename-reserved-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -1957,6 +2612,8 @@ }, "node_modules/filenamify": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", + "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", "license": "MIT", "dependencies": { "filename-reserved-regex": "^3.0.0" @@ -1970,6 +2627,8 @@ }, "node_modules/fill-range": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -1980,6 +2639,8 @@ }, "node_modules/find-cache-dir": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "license": "MIT", "dependencies": { "commondir": "^1.0.1", @@ -1992,6 +2653,8 @@ }, "node_modules/find-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "license": "MIT", "dependencies": { "locate-path": "^3.0.0" @@ -2002,6 +2665,8 @@ }, "node_modules/flow-parser": { "version": "0.289.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.289.0.tgz", + "integrity": "sha512-w4sVnH6ddNAIxokoz0mGyiIIdzvqncFhAYW+RmkPbPSSTYozG6yhqAixzaWeBCQf2qqXJTlHkoKPnf/BAj8Ofw==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -2009,6 +2674,8 @@ }, "node_modules/foreground-child": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", @@ -2023,6 +2690,8 @@ }, "node_modules/form-data": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -2037,10 +2706,14 @@ }, "node_modules/form-data-encoder": { "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", "license": "MIT" }, "node_modules/formdata-node": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", "license": "MIT", "dependencies": { "node-domexception": "1.0.0", @@ -2052,6 +2725,8 @@ }, "node_modules/formdata-node/node_modules/web-streams-polyfill": { "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", "license": "MIT", "engines": { "node": ">= 14" @@ -2059,10 +2734,14 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2070,6 +2749,8 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2077,6 +2758,8 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -2099,6 +2782,8 @@ }, "node_modules/get-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -2110,6 +2795,8 @@ }, "node_modules/git-up": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", "license": "MIT", "dependencies": { "is-ssh": "^1.4.0", @@ -2118,6 +2805,8 @@ }, "node_modules/git-url-parse": { "version": "14.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-14.1.0.tgz", + "integrity": "sha512-8xg65dTxGHST3+zGpycMMFZcoTzAdZ2dOtu4vmgIfkTFnVHBxHMzBC2L1k8To7EmrSiHesT8JgPLT91VKw1B5g==", "license": "MIT", "dependencies": { "git-up": "^7.0.0" @@ -2125,6 +2814,8 @@ }, "node_modules/glob": { "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -2143,6 +2834,8 @@ }, "node_modules/gopd": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -2153,10 +2846,14 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { "node": ">=8" @@ -2164,6 +2861,8 @@ }, "node_modules/has-symbols": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -2174,6 +2873,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -2187,6 +2888,8 @@ }, "node_modules/hasown": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -2197,6 +2900,8 @@ }, "node_modules/humanize-ms": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", "dependencies": { "ms": "^2.0.0" @@ -2204,6 +2909,8 @@ }, "node_modules/iconv-lite": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -2218,6 +2925,8 @@ }, "node_modules/ieee754": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -2236,6 +2945,8 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "license": "MIT", "engines": { "node": ">=0.8.19" @@ -2243,6 +2954,9 @@ }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -2251,10 +2965,14 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/inquirer": { "version": "9.3.8", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.8.tgz", + "integrity": "sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==", "license": "MIT", "dependencies": { "@inquirer/external-editor": "^1.0.2", @@ -2276,10 +2994,14 @@ }, "node_modules/is-buffer": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "license": "MIT" }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" @@ -2287,6 +3009,8 @@ }, "node_modules/is-interactive": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "license": "MIT", "engines": { "node": ">=8" @@ -2294,6 +3018,8 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -2301,6 +3027,8 @@ }, "node_modules/is-plain-object": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "license": "MIT", "dependencies": { "isobject": "^3.0.1" @@ -2311,6 +3039,8 @@ }, "node_modules/is-ssh": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", + "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", "license": "MIT", "dependencies": { "protocols": "^2.0.1" @@ -2318,6 +3048,8 @@ }, "node_modules/is-unicode-supported": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "license": "MIT", "engines": { "node": ">=10" @@ -2328,10 +3060,14 @@ }, "node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2339,6 +3075,8 @@ }, "node_modules/jackspeak": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -2352,10 +3090,14 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, "node_modules/jscodeshift": { "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", "license": "MIT", "dependencies": { "@babel/core": "^7.23.0", @@ -2393,6 +3135,8 @@ }, "node_modules/jscodeshift/node_modules/ast-types": { "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", "license": "MIT", "dependencies": { "tslib": "^2.0.1" @@ -2403,6 +3147,8 @@ }, "node_modules/jscodeshift/node_modules/recast": { "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", "license": "MIT", "dependencies": { "ast-types": "^0.16.1", @@ -2417,6 +3163,8 @@ }, "node_modules/jsesc": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -2427,6 +3175,8 @@ }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -2437,6 +3187,8 @@ }, "node_modules/kind-of": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2444,6 +3196,8 @@ }, "node_modules/locate-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "license": "MIT", "dependencies": { "p-locate": "^3.0.0", @@ -2455,10 +3209,14 @@ }, "node_modules/lodash-es": { "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "license": "MIT", "dependencies": { "chalk": "^4.1.0", @@ -2473,6 +3231,8 @@ }, "node_modules/lru-cache": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -2480,6 +3240,8 @@ }, "node_modules/magic-string": { "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -2487,6 +3249,8 @@ }, "node_modules/make-dir": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "license": "MIT", "dependencies": { "pify": "^4.0.1", @@ -2498,6 +3262,8 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "license": "ISC", "bin": { "semver": "bin/semver" @@ -2505,6 +3271,8 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -2512,6 +3280,8 @@ }, "node_modules/md5": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "license": "BSD-3-Clause", "dependencies": { "charenc": "0.0.2", @@ -2521,6 +3291,8 @@ }, "node_modules/micromatch": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -2532,6 +3304,8 @@ }, "node_modules/mime-db": { "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -2539,6 +3313,8 @@ }, "node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -2549,6 +3325,8 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "engines": { "node": ">=6" @@ -2556,6 +3334,8 @@ }, "node_modules/minimatch": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -2569,6 +3349,8 @@ }, "node_modules/minipass": { "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -2576,10 +3358,14 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/mute-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -2587,10 +3373,14 @@ }, "node_modules/neo-async": { "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, "node_modules/node-dir": { "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", "license": "MIT", "dependencies": { "minimatch": "^3.0.2" @@ -2601,6 +3391,8 @@ }, "node_modules/node-dir/node_modules/brace-expansion": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -2609,6 +3401,8 @@ }, "node_modules/node-dir/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -2619,6 +3413,9 @@ }, "node_modules/node-domexception": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", "funding": [ { "type": "github", @@ -2636,6 +3433,8 @@ }, "node_modules/node-fetch": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -2654,10 +3453,14 @@ }, "node_modules/node-releases": { "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "license": "MIT" }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", "dependencies": { "wrappy": "1" @@ -2665,6 +3468,8 @@ }, "node_modules/onetime": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -2678,6 +3483,8 @@ }, "node_modules/openai": { "version": "4.23.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.23.0.tgz", + "integrity": "sha512-ey2CXh1OTcTUa0AWZWuTpgA9t5GuAG3DVU1MofCRUI7fQJij8XJ3Sr0VtgxoAE69C9wbHBMCux8Z/IQZfSwHiA==", "license": "Apache-2.0", "dependencies": { "@types/node": "^18.11.18", @@ -2696,6 +3503,8 @@ }, "node_modules/openai/node_modules/@types/node": { "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -2703,10 +3512,14 @@ }, "node_modules/openai/node_modules/undici-types": { "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "license": "MIT" }, "node_modules/ora": { "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "license": "MIT", "dependencies": { "bl": "^4.1.0", @@ -2728,6 +3541,8 @@ }, "node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -2741,6 +3556,8 @@ }, "node_modules/p-locate": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "license": "MIT", "dependencies": { "p-limit": "^2.0.0" @@ -2751,6 +3568,8 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "license": "MIT", "engines": { "node": ">=6" @@ -2758,10 +3577,14 @@ }, "node_modules/package-json-from-dist": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, "node_modules/parse-path": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.1.0.tgz", + "integrity": "sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==", "license": "MIT", "dependencies": { "protocols": "^2.0.0" @@ -2769,6 +3592,8 @@ }, "node_modules/parse-url": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", "license": "MIT", "dependencies": { "parse-path": "^7.0.0" @@ -2776,6 +3601,8 @@ }, "node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "license": "MIT", "engines": { "node": ">=4" @@ -2783,6 +3610,8 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2790,6 +3619,8 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", "engines": { "node": ">=8" @@ -2797,6 +3628,8 @@ }, "node_modules/path-scurry": { "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -2811,14 +3644,20 @@ }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, "node_modules/picocolors": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -2829,6 +3668,8 @@ }, "node_modules/pify": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "license": "MIT", "engines": { "node": ">=6" @@ -2836,6 +3677,8 @@ }, "node_modules/pirates": { "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "license": "MIT", "engines": { "node": ">= 6" @@ -2843,6 +3686,8 @@ }, "node_modules/pkg-dir": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "license": "MIT", "dependencies": { "find-up": "^3.0.0" @@ -2853,6 +3698,8 @@ }, "node_modules/prettier": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" @@ -2866,10 +3713,14 @@ }, "node_modules/protocols": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", + "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", "license": "MIT" }, "node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -2882,6 +3733,8 @@ }, "node_modules/recast": { "version": "0.20.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", + "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", "license": "MIT", "dependencies": { "ast-types": "0.14.2", @@ -2895,6 +3748,8 @@ }, "node_modules/restore-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "license": "MIT", "dependencies": { "onetime": "^5.1.0", @@ -2906,10 +3761,15 @@ }, "node_modules/restore-cursor/node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, "node_modules/rimraf": { "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -2920,6 +3780,8 @@ }, "node_modules/rimraf/node_modules/brace-expansion": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -2928,6 +3790,9 @@ }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -2946,6 +3811,8 @@ }, "node_modules/rimraf/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -2956,6 +3823,8 @@ }, "node_modules/run-async": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -2963,6 +3832,8 @@ }, "node_modules/rxjs": { "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -2970,6 +3841,8 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -2988,10 +3861,14 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2999,6 +3876,8 @@ }, "node_modules/shallow-clone": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "license": "MIT", "dependencies": { "kind-of": "^6.0.2" @@ -3009,6 +3888,8 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -3019,6 +3900,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", "engines": { "node": ">=8" @@ -3026,6 +3909,8 @@ }, "node_modules/signal-exit": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "license": "ISC", "engines": { "node": ">=14" @@ -3036,6 +3921,8 @@ }, "node_modules/simple-git": { "version": "3.30.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", "license": "MIT", "dependencies": { "@kwsites/file-exists": "^1.1.1", @@ -3049,6 +3936,8 @@ }, "node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -3056,6 +3945,8 @@ }, "node_modules/source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -3064,6 +3955,8 @@ }, "node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -3071,6 +3964,8 @@ }, "node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -3084,6 +3979,8 @@ "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -3096,6 +3993,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -3107,6 +4006,8 @@ "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -3117,6 +4018,8 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -3127,6 +4030,8 @@ }, "node_modules/temp": { "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", "license": "MIT", "dependencies": { "rimraf": "~2.6.2" @@ -3137,10 +4042,14 @@ }, "node_modules/tiny-invariant": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -3151,10 +4060,14 @@ }, "node_modules/tr46": { "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, "node_modules/tree-kill": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "license": "MIT", "bin": { "tree-kill": "cli.js" @@ -3162,6 +4075,8 @@ }, "node_modules/ts-invariant": { "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", "license": "MIT", "dependencies": { "tslib": "^2.1.0" @@ -3172,10 +4087,14 @@ }, "node_modules/tslib": { "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/type-fest": { "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -3186,14 +4105,20 @@ }, "node_modules/undici-types": { "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/universal-user-agent": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "license": "ISC" }, "node_modules/update-browserslist-db": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "funding": [ { "type": "opencollective", @@ -3222,10 +4147,14 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/wcwidth": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "license": "MIT", "dependencies": { "defaults": "^1.0.3" @@ -3233,6 +4162,8 @@ }, "node_modules/web-streams-polyfill": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "license": "MIT", "engines": { "node": ">= 8" @@ -3240,10 +4171,14 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -3252,6 +4187,8 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -3265,6 +4202,8 @@ }, "node_modules/wrap-ansi": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -3278,6 +4217,8 @@ "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -3293,10 +4234,14 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, "node_modules/write-file-atomic": { "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "license": "ISC", "dependencies": { "graceful-fs": "^4.1.11", @@ -3306,14 +4251,20 @@ }, "node_modules/write-file-atomic/node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, "node_modules/yallist": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, "node_modules/yaml": { "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -3324,6 +4275,8 @@ }, "node_modules/yoctocolors-cjs": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", "license": "MIT", "engines": { "node": ">=18" @@ -3354,9 +4307,6 @@ "@codemod.com/jssg-types": "^1.3.1" } }, - "recipes/cjs-to-esm": { - "extraneous": true - }, "recipes/correct-ts-specifiers": { "name": "@nodejs/correct-ts-specifiers", "version": "1.0.0", From 02bc9ae22d079e3b830ac707f2f925b7236cfda8 Mon Sep 17 00:00:00 2001 From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:00:30 +0100 Subject: [PATCH 10/12] simplify --- .../src/workflow.ts | 59 ++++++------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts index dc025851..1262ff15 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -51,7 +51,7 @@ export default function transform(root: SgRoot): string | null { edits.push(...renamePairVariables(rootNode, cspBindings)); // Update imports - edits.push(...rewriteTlsImports(rootNode)); + edits.push(...rewriteTlsImports(tlsStmts)); if (!edits.length) return null; @@ -121,30 +121,19 @@ function renamePairVariables(rootNode: SgNode, bindings: string[]): Edit[] { return edits; } -function rewriteTlsImports(rootNode: SgNode): Edit[] { +function rewriteTlsImports( + nodeImportStatements: Array> = [], +): Edit[] { const edits: Edit[] = []; // Handle ESM named imports - const esmNamed = rootNode.findAll({ - rule: { - kind: 'import_statement', - all: [ - { has: { kind: 'import_clause', has: { kind: 'named_imports' } } }, - { - has: { - field: 'source', - any: [ - { pattern: "'tls'" }, - { pattern: '"tls"' }, - { pattern: "'node:tls'" }, - { pattern: '"node:tls"' }, - ], - }, - }, - ], - not: { has: { kind: 'namespace_import' } }, - }, - }); + const esmNamed = nodeImportStatements + .map((stmt) => stmt) + .filter((stmt) => { + const named = stmt.find({ rule: { kind: 'named_imports' } }); + const namespace = stmt.find({ rule: { kind: 'namespace_import' } }); + return named && !namespace; + }); for (const decl of esmNamed) { const srcText = decl.field('source')?.text()?.replace(/['"]/g, '') || ''; @@ -188,24 +177,14 @@ function rewriteTlsImports(rootNode: SgNode): Edit[] { } // Handle CJS destructured requires - const cjsNamed = rootNode.findAll({ - rule: { - kind: 'variable_declarator', - all: [ - { has: { field: 'name', kind: 'object_pattern' } }, - { - has: { - field: 'value', - any: [ - { pattern: "require('tls')" }, - { pattern: 'require("tls")' }, - { pattern: "require('node:tls')" }, - { pattern: 'require("node:tls")' }, - ], - }, - }, - ], - }, + const cjsNamed = nodeImportStatements.filter((stmt) => { + if (stmt.kind() !== 'variable_declarator') return false; + + const name = stmt.field('name'); + const value = stmt.field('value'); + if (!name || name.kind() !== 'object_pattern' || !value) return false; + + return true; }); for (const decl of cjsNamed) { From 26c1af555101da8fdec2e74d1ff8e43ba7eae3b7 Mon Sep 17 00:00:00 2001 From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:46:29 +0100 Subject: [PATCH 11/12] Update workflow.ts --- .../src/workflow.ts | 338 +++++++++--------- 1 file changed, 166 insertions(+), 172 deletions(-) diff --git a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts index 1262ff15..6c621484 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -51,7 +51,9 @@ export default function transform(root: SgRoot): string | null { edits.push(...renamePairVariables(rootNode, cspBindings)); // Update imports - edits.push(...rewriteTlsImports(tlsStmts)); + edits.push(...rewriteTlsImports(tlsStmts.filter(s => + s.kind() === 'import_statement' || s.kind() === 'variable_declarator' + ))); if (!edits.length) return null; @@ -121,129 +123,108 @@ function renamePairVariables(rootNode: SgNode, bindings: string[]): Edit[] { return edits; } -function rewriteTlsImports( - nodeImportStatements: Array> = [], -): Edit[] { +function rewriteTlsImports(nodeImportStatements: SgNode[]): Edit[] { const edits: Edit[] = []; - // Handle ESM named imports - const esmNamed = nodeImportStatements - .map((stmt) => stmt) - .filter((stmt) => { - const named = stmt.find({ rule: { kind: 'named_imports' } }); - const namespace = stmt.find({ rule: { kind: 'namespace_import' } }); - return named && !namespace; - }); - - for (const decl of esmNamed) { - const srcText = decl.field('source')?.text()?.replace(/['"]/g, '') || ''; - if (srcText !== 'tls' && srcText !== 'node:tls') continue; - - const named = decl.find({ rule: { kind: 'named_imports' } }); - if (!named) continue; - - const specs = named.findAll({ rule: { kind: 'import_specifier' } }); - const hasCSP = specs.some( - (s) => s.field('name')?.text() === 'createSecurePair', - ); - if (!hasCSP) continue; - - const kept: string[] = []; - for (const s of specs) { - const imported = s.field('name')?.text(); - const maybeAlias = s.field('alias')?.text(); - if (imported && imported !== 'createSecurePair') { - kept.push(maybeAlias ? `${imported} as ${maybeAlias}` : imported); - } + for (const stmt of nodeImportStatements) { + if (stmt.kind() === 'import_statement') { + const edit = rewriteEsmImport(stmt); + if (edit) edits.push(edit); + } else if (stmt.kind() === 'variable_declarator') { + const edit = rewriteCjsRequire(stmt); + if (edit) edits.push(edit); } + } - if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); - - const def = decl - .find({ - rule: { - kind: 'import_clause', - has: { field: 'name', kind: 'identifier' }, - }, - }) - ?.field('name') - ?.text(); - - const rebuilt = def - ? `import ${def}, { ${kept.join(', ')} } from '${srcText}';` - : `import { ${kept.join(', ')} } from '${srcText}';`; + return edits; +} - edits.push(decl.replace(rebuilt)); - } +function rewriteEsmImport(stmt: SgNode): Edit | null { + const named = stmt.find({ rule: { kind: 'named_imports' } }); + const namespace = stmt.find({ rule: { kind: 'namespace_import' } }); + if (!named || namespace) return null; - // Handle CJS destructured requires - const cjsNamed = nodeImportStatements.filter((stmt) => { - if (stmt.kind() !== 'variable_declarator') return false; + const srcText = stmt.field('source')?.text()?.replace(/['"]/g, '') || ''; + if (srcText !== 'tls' && srcText !== 'node:tls') return null; - const name = stmt.field('name'); - const value = stmt.field('value'); - if (!name || name.kind() !== 'object_pattern' || !value) return false; + const specs = named.findAll({ rule: { kind: 'import_specifier' } }); + if (!specs.some((s) => s.field('name')?.text() === 'createSecurePair')) return null; - return true; - }); + const kept = specs + .filter((s) => s.field('name')?.text() !== 'createSecurePair') + .map((s) => { + const imported = s.field('name')?.text(); + const alias = s.field('alias')?.text(); + return alias ? `${imported} as ${alias}` : imported; + }); - for (const decl of cjsNamed) { - const obj = decl.field('name'); - if (!obj) continue; + if (!kept.includes('TLSSocket')) kept.push('TLSSocket'); - const props = obj.findAll({ + const defaultImport = stmt + .find({ rule: { - any: [ - { kind: 'pair_pattern' }, - { kind: 'shorthand_property_identifier_pattern' }, - ], + kind: 'import_clause', + has: { field: 'name', kind: 'identifier' }, }, - }); + }) + ?.field('name') + ?.text(); - const hasCSP = props.some((p) => - p.kind() === 'pair_pattern' - ? p.field('key')?.text() === 'createSecurePair' || - p.field('value')?.text() === 'createSecurePair' - : p.text() === 'createSecurePair', - ); + const rebuilt = defaultImport + ? `import ${defaultImport}, { ${kept.join(', ')} } from '${srcText}';` + : `import { ${kept.join(', ')} } from '${srcText}';`; + + return stmt.replace(rebuilt); +} - if (!hasCSP) continue; +function rewriteCjsRequire(stmt: SgNode): Edit | null { + const name = stmt.field('name'); + if (!name || name.kind() !== 'object_pattern') return null; - const kept: string[] = []; - for (const p of props) { - let name = ''; - let alias = ''; + const props = name.findAll({ + rule: { + any: [ + { kind: 'pair_pattern' }, + { kind: 'shorthand_property_identifier_pattern' }, + ], + }, + }); + + const hasCSP = props.some((p) => + p.kind() === 'pair_pattern' + ? p.field('key')?.text() === 'createSecurePair' || + p.field('value')?.text() === 'createSecurePair' + : p.text() === 'createSecurePair', + ); + if (!hasCSP) return null; + + const kept = props + .filter((p) => { + const key = p.kind() === 'pair_pattern' ? p.field('key')?.text() : p.text(); + return key !== 'createSecurePair'; + }) + .map((p) => { if (p.kind() === 'pair_pattern') { - name = p.field('key')?.text() || ''; - alias = p.field('value')?.text() || ''; - } else { - name = p.text(); - alias = name; + const key = p.field('key')?.text(); + const val = p.field('value')?.text(); + return val && val !== key ? `${key}: ${val}` : key; } - if (!name || name === 'createSecurePair') continue; - kept.push(alias && alias !== name ? `${name}: ${alias}` : name); - } - - if (kept.indexOf('TLSSocket') === -1) kept.push('TLSSocket'); + return p.text(); + }); - let stmt: SgNode = decl; - let cur: SgNode | undefined = decl; + if (!kept.includes('TLSSocket')) kept.push('TLSSocket'); - while (cur) { - const k = cur.kind(); - if (k === 'lexical_declaration' || k === 'variable_declaration') { - stmt = cur; - break; - } - cur = cur.parent?.(); + let decl: SgNode = stmt; + let cur = stmt.parent?.(); + while (cur) { + if (cur.kind() === 'lexical_declaration' || cur.kind() === 'variable_declaration') { + decl = cur; + break; } - - edits.push( - stmt.replace(`const { ${kept.join(', ')} } = require('node:tls');`), - ); + cur = cur.parent?.(); } - return edits; + return decl.replace(`const { ${kept.join(', ')} } = require('node:tls');`); } function collectAllBindings(tlsStmts: SgNode[]): string[] { @@ -268,88 +249,101 @@ function collectAllBindings(tlsStmts: SgNode[]): string[] { // Handle ESM aliases: import { createSecurePair as csp } from 'tls' if (kind === 'import_statement') { - const specs = stmt.findAll({ - rule: { - kind: 'import_specifier', - has: { field: 'alias', kind: 'identifier' }, - }, - }); - - for (const spec of specs) { - if (spec.field('name')?.text() === 'createSecurePair') { - const alias = spec.field('alias')?.text(); - if (alias) bindings.push(alias); - } - } + const alias = getEsmAlias(stmt); + if (alias) bindings.push(alias); } // Handle CJS destructured aliases: const { createSecurePair: csp } = require('tls') if (kind === 'variable_declarator') { - const objPattern = stmt.field('name'); - if (objPattern?.kind() === 'object_pattern') { - const pairs = objPattern.findAll({ rule: { kind: 'pair_pattern' } }); - for (const pair of pairs) { - if (pair.field('key')?.text() === 'createSecurePair') { - const alias = pair.field('value')?.text(); - if (alias && alias !== 'createSecurePair') { - bindings.push(alias); - } - } - } - } + const cjsAlias = getCjsAlias(stmt); + if (cjsAlias) bindings.push(cjsAlias); // Handle dynamic imports: const tls = await import('tls') - const value = stmt.field('value'); - if (value?.kind() === 'await_expression') { - const name = stmt.field('name'); - if (name?.kind() === 'identifier') { - bindings.push(`${name.text()}.createSecurePair`); - } - } + const awaitBinding = getAwaitImportBinding(stmt); + if (awaitBinding) bindings.push(awaitBinding); } // Handle dynamic import .then(): import('tls').then(tls => ...) - // getModuleDependencies returns the expression_statement node if (kind === 'expression_statement') { - const expr = stmt.children().find((c) => c.kind() === 'call_expression'); - if (expr?.kind() === 'call_expression') { - const func = expr.field('function'); - if (func?.kind() === 'member_expression') { - const prop = func.field('property'); - if (prop?.text() === 'then') { - const args = expr.field('arguments'); - const callback = args?.find({ - rule: { - any: [ - { kind: 'arrow_function' }, - { kind: 'function_expression' }, - ], - }, - }); - - if (callback) { - let param: SgNode | undefined; - - if (callback.kind() === 'arrow_function') { - param = callback.field('parameter'); - if (!param) { - const params = callback.field('parameters'); - param = params?.find({ rule: { kind: 'identifier' } }); - } - } else if (callback.kind() === 'function_expression') { - const params = callback.field('parameters'); - param = params?.find({ rule: { kind: 'identifier' } }); - } - - if (param) { - bindings.push(`${param.text()}.createSecurePair`); - } - } - } - } - } + const thenBinding = getThenImportBinding(stmt); + if (thenBinding) bindings.push(thenBinding); } } return unique(bindings); } + +function getEsmAlias(stmt: SgNode): string | null { + const specs = stmt.findAll({ + rule: { + kind: 'import_specifier', + has: { field: 'alias', kind: 'identifier' }, + }, + }); + + for (const spec of specs) { + if (spec.field('name')?.text() === 'createSecurePair') { + return spec.field('alias')?.text() || null; + } + } + return null; +} + +function getCjsAlias(stmt: SgNode): string | null { + const objPattern = stmt.field('name'); + if (objPattern?.kind() !== 'object_pattern') return null; + + const pairs = objPattern.findAll({ rule: { kind: 'pair_pattern' } }); + for (const pair of pairs) { + if (pair.field('key')?.text() === 'createSecurePair') { + const alias = pair.field('value')?.text(); + if (alias && alias !== 'createSecurePair') { + return alias; + } + } + } + return null; +} + +function getAwaitImportBinding(stmt: SgNode): string | null { + const value = stmt.field('value'); + if (value?.kind() !== 'await_expression') return null; + + const name = stmt.field('name'); + if (name?.kind() === 'identifier') { + return `${name.text()}.createSecurePair`; + } + return null; +} + +function getThenImportBinding(stmt: SgNode): string | null { + const expr = stmt.children().find((c) => c.kind() === 'call_expression'); + if (!expr || expr.kind() !== 'call_expression') return null; + + const func = expr.field('function'); + if (func?.kind() !== 'member_expression') return null; + + const prop = func.field('property'); + if (prop?.text() !== 'then') return null; + + const args = expr.field('arguments'); + const callback = args?.find({ + rule: { + any: [ + { kind: 'arrow_function' }, + { kind: 'function_expression' }, + ], + }, + }); + + if (!callback) return null; + + let param: SgNode | undefined; + if (callback.kind() === 'arrow_function') { + param = callback.field('parameter') || callback.field('parameters')?.find({ rule: { kind: 'identifier' } }); + } else if (callback.kind() === 'function_expression') { + param = callback.field('parameters')?.find({ rule: { kind: 'identifier' } }); + } + + return param ? `${param.text()}.createSecurePair` : null; +} From da6a021db2bb47a9eb16aa4d4d52f5273f474ebd Mon Sep 17 00:00:00 2001 From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:49:12 +0100 Subject: [PATCH 12/12] use `is` --- .../src/workflow.ts | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts index 6c621484..0463cf9e 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -51,9 +51,13 @@ export default function transform(root: SgRoot): string | null { edits.push(...renamePairVariables(rootNode, cspBindings)); // Update imports - edits.push(...rewriteTlsImports(tlsStmts.filter(s => - s.kind() === 'import_statement' || s.kind() === 'variable_declarator' - ))); + edits.push( + ...rewriteTlsImports( + tlsStmts.filter( + (s) => s.is('import_statement') || s.is('variable_declarator'), + ), + ), + ); if (!edits.length) return null; @@ -61,13 +65,13 @@ export default function transform(root: SgRoot): string | null { } function getCallBinding(callee: SgNode): string | null { - if (callee.kind() === 'member_expression') { + if (callee.is('member_expression')) { const obj = callee.field('object'); const prop = callee.field('property'); if (!obj || !prop) return null; return `${obj.text()}.${prop.text()}`; } - if (callee.kind() === 'identifier') { + if (callee.is('identifier')) { return callee.text(); } return null; @@ -115,7 +119,7 @@ function renamePairVariables(rootNode: SgNode, bindings: string[]): Edit[] { if (!binding || !bindings.includes(binding)) continue; const name = decl.field('name'); - if (name && name.kind() === 'identifier') { + if (name.is('identifier')) { edits.push(name.replace('socket')); } } @@ -127,10 +131,10 @@ function rewriteTlsImports(nodeImportStatements: SgNode[]): Edit[] { const edits: Edit[] = []; for (const stmt of nodeImportStatements) { - if (stmt.kind() === 'import_statement') { + if (stmt.is('import_statement')) { const edit = rewriteEsmImport(stmt); if (edit) edits.push(edit); - } else if (stmt.kind() === 'variable_declarator') { + } else if (stmt.is('variable_declarator')) { const edit = rewriteCjsRequire(stmt); if (edit) edits.push(edit); } @@ -148,7 +152,8 @@ function rewriteEsmImport(stmt: SgNode): Edit | null { if (srcText !== 'tls' && srcText !== 'node:tls') return null; const specs = named.findAll({ rule: { kind: 'import_specifier' } }); - if (!specs.some((s) => s.field('name')?.text() === 'createSecurePair')) return null; + if (!specs.some((s) => s.field('name')?.text() === 'createSecurePair')) + return null; const kept = specs .filter((s) => s.field('name')?.text() !== 'createSecurePair') @@ -179,7 +184,7 @@ function rewriteEsmImport(stmt: SgNode): Edit | null { function rewriteCjsRequire(stmt: SgNode): Edit | null { const name = stmt.field('name'); - if (!name || name.kind() !== 'object_pattern') return null; + if (!name || !name.is('object_pattern')) return null; const props = name.findAll({ rule: { @@ -191,7 +196,7 @@ function rewriteCjsRequire(stmt: SgNode): Edit | null { }); const hasCSP = props.some((p) => - p.kind() === 'pair_pattern' + p.is('pair_pattern') ? p.field('key')?.text() === 'createSecurePair' || p.field('value')?.text() === 'createSecurePair' : p.text() === 'createSecurePair', @@ -200,11 +205,11 @@ function rewriteCjsRequire(stmt: SgNode): Edit | null { const kept = props .filter((p) => { - const key = p.kind() === 'pair_pattern' ? p.field('key')?.text() : p.text(); + const key = p.is('pair_pattern') ? p.field('key')?.text() : p.text(); return key !== 'createSecurePair'; }) .map((p) => { - if (p.kind() === 'pair_pattern') { + if (p.is('pair_pattern')) { const key = p.field('key')?.text(); const val = p.field('value')?.text(); return val && val !== key ? `${key}: ${val}` : key; @@ -217,7 +222,7 @@ function rewriteCjsRequire(stmt: SgNode): Edit | null { let decl: SgNode = stmt; let cur = stmt.parent?.(); while (cur) { - if (cur.kind() === 'lexical_declaration' || cur.kind() === 'variable_declaration') { + if (cur.is('lexical_declaration') || cur.is('variable_declaration')) { decl = cur; break; } @@ -310,15 +315,15 @@ function getAwaitImportBinding(stmt: SgNode): string | null { if (value?.kind() !== 'await_expression') return null; const name = stmt.field('name'); - if (name?.kind() === 'identifier') { + if (name.is('identifier')) { return `${name.text()}.createSecurePair`; } return null; } function getThenImportBinding(stmt: SgNode): string | null { - const expr = stmt.children().find((c) => c.kind() === 'call_expression'); - if (!expr || expr.kind() !== 'call_expression') return null; + const expr = stmt.children().find((c) => c.is('call_expression')); + if (!expr || !expr.is('call_expression')) return null; const func = expr.field('function'); if (func?.kind() !== 'member_expression') return null; @@ -329,20 +334,21 @@ function getThenImportBinding(stmt: SgNode): string | null { const args = expr.field('arguments'); const callback = args?.find({ rule: { - any: [ - { kind: 'arrow_function' }, - { kind: 'function_expression' }, - ], + any: [{ kind: 'arrow_function' }, { kind: 'function_expression' }], }, }); if (!callback) return null; let param: SgNode | undefined; - if (callback.kind() === 'arrow_function') { - param = callback.field('parameter') || callback.field('parameters')?.find({ rule: { kind: 'identifier' } }); - } else if (callback.kind() === 'function_expression') { - param = callback.field('parameters')?.find({ rule: { kind: 'identifier' } }); + if (callback.is('arrow_function')) { + param = + callback.field('parameter') || + callback.field('parameters')?.find({ rule: { kind: 'identifier' } }); + } else if (callback.is('function_expression')) { + param = callback + .field('parameters') + ?.find({ rule: { kind: 'identifier' } }); } return param ? `${param.text()}.createSecurePair` : null;