diff --git a/package-lock.json b/package-lock.json index b73899e5..0adb4a36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1513,6 +1513,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 @@ -4414,6 +4418,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", diff --git a/recipes/tls-create-secure-pair-to-tls-socket/README.md b/recipes/tls-create-secure-pair-to-tls-socket/README.md new file mode 100644 index 00000000..d66f541a --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/README.md @@ -0,0 +1,104 @@ +# `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 + +### 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 }); +``` + +--- + +### 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 }); +``` + +--- + +### 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 ++}); +``` + +--- + +### 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 }); +``` + +--- + +### 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 }); +``` + +--- + +### 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); +``` + +--- + +### 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 }); +``` + +--- + +### 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 }); +``` + +--- + +### 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 }); ++}); +``` diff --git a/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml new file mode 100644 index 00000000..978eb8c9 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml @@ -0,0 +1,24 @@ +schema_version: "1.0" +name: "@nodejs/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/package.json b/recipes/tls-create-secure-pair-to-tls-socket/package.json new file mode 100644 index 00000000..88d0efbf --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/package.json @@ -0,0 +1,24 @@ +{ + "name": "@nodejs/tls-create-secure-pair-to-tls-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-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-create-secure-pair-to-tls-socket/README.md", + "devDependencies": { + "@codemod.com/jssg-types": "^1.0.9" + }, + "dependencies": { + "@nodejs/codemod-utils": "*" + } +} 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 new file mode 100644 index 00000000..4065c6fc --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-socket/src/workflow.ts @@ -0,0 +1,236 @@ +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, 'tls'), + ...getNodeRequireCalls(root, 'tls'), + ]; + 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')); + 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): 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 { + 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[] = []; + 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')); + } + } + return edits; +} + +function rewriteTlsImports(rootNode: SgNode): Edit[] { + const edits: Edit[] = []; + 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' } }, + }, + }); + 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); + } + } + 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)); +} diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-basic.js new file mode 100644 index 00000000..aade280a --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-flags.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-destructured-flags.js new file mode 100644 index 00000000..7f6653dd --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-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/cjs-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/cjs-namespace-basic.js new file mode 100644 index 00000000..a4845d28 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-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/expected/esm-named-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-named-basic.js new file mode 100644 index 00000000..946f330a --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/expected/esm-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/esm-namespace-basic.js new file mode 100644 index 00000000..9255483a --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/expected/mixed-with-other-symbols.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/expected/mixed-with-other-symbols.js new file mode 100644 index 00000000..ae0e16c1 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-basic.js new file mode 100644 index 00000000..85389cf3 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-flags.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-destructured-flags.js new file mode 100644 index 00000000..33c62eb0 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-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/cjs-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/cjs-namespace-basic.js new file mode 100644 index 00000000..4ad73152 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-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); +}); diff --git a/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-named-basic.js new file mode 100644 index 00000000..9dccd7ed --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/input/esm-namespace-basic.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/esm-namespace-basic.js new file mode 100644 index 00000000..28119184 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/tests/input/mixed-with-other-symbols.js b/recipes/tls-create-secure-pair-to-tls-socket/tests/input/mixed-with-other-symbols.js new file mode 100644 index 00000000..e6a341db --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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-create-secure-pair-to-tls-socket/workflow.yaml b/recipes/tls-create-secure-pair-to-tls-socket/workflow.yaml new file mode 100644 index 00000000..1b82d8a3 --- /dev/null +++ b/recipes/tls-create-secure-pair-to-tls-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