Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
39f92b0
feat(crypto-fips): add migration recipe for transitioning from crypto…
max-programming Aug 13, 2025
0b7a664
Use one-liner arrow function
max-programming Aug 13, 2025
17c3bc9
chore(vscode): revert settings json file to default
max-programming Aug 13, 2025
078fecd
refactor(crypto-fips): streamline crypto base path retrieval and impr…
max-programming Aug 13, 2025
7cd8777
refactor(crypto-fips): use generators for crypto base path collection
max-programming Aug 13, 2025
866e1fc
refactor(crypto-fips): enhance code formatting and improve readability
max-programming Aug 13, 2025
7200be7
refactor(crypto-fips): rename functions and variables for clarity in …
max-programming Aug 13, 2025
b4d9c0c
refactor(crypto-fips): implement transformation for crypto.fips to ge…
max-programming Aug 13, 2025
fe9ec48
refactor(crypto-fips): update README examplesto have import statement
max-programming Aug 13, 2025
8c3bd84
refactor(crypto-fips): use existing utility function and reformat cod…
max-programming Aug 13, 2025
91a80be
refactor(crypto-fips): added missing jsdoc for a functions
max-programming Aug 13, 2025
92a829e
refactor(crypto-fips): add an extra line
max-programming Aug 13, 2025
515da7d
docs(crypto-fips): fix description
max-programming Aug 15, 2025
a475efa
Merge branch 'main' into crypto-fips
max-programming Aug 28, 2025
1e2f114
Merge remote-tracking branch 'upstream/main' into crypto-fips
max-programming Oct 13, 2025
07856fb
chore: update @codemod.com/jssg-types dependency to version 1.0.9 in …
max-programming Oct 13, 2025
9ce214e
feat(crypto-fips): enhance transform function to handle crypto.fips b…
max-programming Oct 13, 2025
034d8ed
Merge branch 'main' into crypto-fips
max-programming Oct 19, 2025
a09c7a2
fix lockfile
max-programming Oct 19, 2025
206c72e
Added many-to-many support to the updateBinding utility function
max-programming Oct 19, 2025
021b88a
Handle many-to-many "aliased" imports in update-binding util
max-programming Oct 19, 2025
f7e10f7
refactor: use the updateBinding utility function
max-programming Oct 19, 2025
d1977a8
chore: follow convention for test case names
max-programming Oct 19, 2025
2fb1f50
fix: correct test case name
max-programming Oct 19, 2025
91c8019
refactor: improve binding handling in update-binding utility
max-programming Oct 19, 2025
596670c
fix: failing test cases
max-programming Oct 19, 2025
bef68ce
Merge branch 'main' into crypto-fips
max-programming Oct 23, 2025
2131f72
Change all arrows to ligature arrow
max-programming Oct 24, 2025
0caa4bd
Change name from crypto-fips to crypto-fips-to-getFips
max-programming Oct 24, 2025
de3d804
make biome the default formatter for TypeScript and JavaScript
max-programming Oct 24, 2025
ff4b850
Use getNodeImportCalls
max-programming Oct 24, 2025
24e7c1d
Added a testcase for dynamic imports
max-programming Oct 24, 2025
e9de77a
docs: dynamic imports in jsdoc
max-programming Oct 24, 2025
f5c847f
fix: remove redundant escape regex function
max-programming Oct 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
{
"editor.formatOnSave": true,
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.updateImportsOnFileMove.enabled": "always",
"editor.formatOnPaste": true,
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 100,
"[markdown]": {
"editor.wordWrap": "off"
}
"editor.formatOnSave": true,
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.updateImportsOnFileMove.enabled": "always",
"editor.formatOnPaste": true,
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 100,
"[javascript][typescript][json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[markdown]": {
"editor.wordWrap": "off"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
18 changes: 17 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions recipes/crypto-fips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# `crypto.fips` DEP0093

This recipe provides a guide for migrating from the deprecated `crypto.fips` to `crypto.getFips()` and `crypto.setFips()`.

See [DEP0093](https://nodejs.org/api/deprecations.html#DEP0093).

## Examples

**Before:**

```js
// Using crypto.fips
crypto.fips;

// Using crypto.fips = true
crypto.fips = true;

// Using crypto.fips = false
crypto.fips = false;
```

**After:**

```js
// Using crypto.getFips()
crypto.getFips();

// Using crypto.setFips(true)
crypto.setFips(true);

// Using crypto.setFips(false)
crypto.setFips(false);
```
21 changes: 21 additions & 0 deletions recipes/crypto-fips/codemod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
schema_version: "1.0"
name: "@nodejs/crypto-fips"
version: 1.0.0
description: Handle DEP0093 via transforming `crypto.fips` to `crypto.getFips()` and `crypto.setFips()`
author: Usman S.
license: MIT
workflow: workflow.yaml
category: migration

targets:
languages:
- javascript
- typescript

keywords:
- transformation
- migration

registry:
access: public
visibility: public
24 changes: 24 additions & 0 deletions recipes/crypto-fips/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@nodejs/crypto-fips",
"version": "1.0.0",
"description": "Handle DEP0093 via transforming `crypto.fips` to `crypto.getFips()` and `crypto.setFips()`",
"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/crypto-fips",
"bugs": "https://github.com/nodejs/userland-migrations/issues"
},
"author": "Usman S.",
"license": "MIT",
"homepage": "https://github.com/nodejs/userland-migrations/blob/main/recipes/crypto-fips/README.md",
"devDependencies": {
"@codemod.com/jssg-types": "^1.0.3"
},
"dependencies": {
"@nodejs/codemod-utils": "*"
}
}
95 changes: 95 additions & 0 deletions recipes/crypto-fips/src/workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
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 type { SgRoot, Edit, SgNode } from '@codemod.com/jssg-types/main';

function escapeRegExp(input: string): string {
return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

/**
* Transform function that converts deprecated crypto.fips calls
* to the new crypto.getFips() and crypto.setFips() syntax.
*
* Handles:
* 1. crypto.fips -> crypto.getFips()
* 2. crypto.fips = true -> crypto.setFips(true)
* 3. crypto.fips = false -> crypto.setFips(false)
*/
export default function transform(root: SgRoot): string | null {
const rootNode = root.root();
let hasChanges = false;
const edits: Edit[] = [];

const cryptoBases = new Set<string>();
setCryptoBases(getNodeRequireCalls(root, 'crypto'), cryptoBases);
setCryptoBases(getNodeImportStatements(root, 'crypto'), cryptoBases);

const assignmentResult = replaceAssignments(rootNode, cryptoBases);
edits.push(...assignmentResult.edits);
hasChanges = assignmentResult.hasChanges;

const readResult = replaceReads(rootNode, cryptoBases);
edits.push(...readResult.edits);
hasChanges = readResult.hasChanges;

if (!hasChanges) return null;
return rootNode.commitEdits(edits);
}

function setCryptoBases(statements: SgNode[], cryptoBases: Set<string>) {
for (const stmt of statements) {
const resolvedPath = resolveBindingPath(stmt, '$.fips');
if (!resolvedPath || !resolvedPath.includes('.')) continue;
cryptoBases.add(resolvedPath.slice(0, resolvedPath.lastIndexOf('.')));
}
}

function replaceAssignments(rootNode: SgNode, cryptoBases: Set<string>) {
const edits: Edit[] = [];
let hasChanges = false;

for (const base of cryptoBases) {
const assignments = rootNode.findAll({
rule: {
pattern: `${base}.fips = $VALUE`,
},
});

for (const assign of assignments) {
const valueText = assign.getMatch('VALUE')?.text() ?? '';
const basePropRegex = new RegExp(
`\\b${escapeRegExp(base)}\\.fips\\b`,
'g',
);
const transformedValue = valueText.replace(
basePropRegex,
`${base}.getFips()`,
);
edits.push(assign.replace(`${base}.setFips(${transformedValue})`));
hasChanges = true;
}
}

return { edits, hasChanges };
}

function replaceReads(rootNode: SgNode, cryptoBases: Set<string>) {
const edits: Edit[] = [];
let hasChanges = false;

for (const base of cryptoBases) {
const reads = rootNode.findAll({
rule: {
pattern: `${base}.fips`,
},
});

for (const read of reads) {
edits.push(read.replace(`${base}.getFips()`));
hasChanges = true;
}
}

return { edits, hasChanges };
}
5 changes: 5 additions & 0 deletions recipes/crypto-fips/tests/expected/file-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const crypto = require("node:crypto");

if (crypto.getFips()) {
console.log("FIPS mode is enabled");
}
3 changes: 3 additions & 0 deletions recipes/crypto-fips/tests/expected/file-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const crypto = require("node:crypto");

crypto.setFips(true);
6 changes: 6 additions & 0 deletions recipes/crypto-fips/tests/expected/file-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const crypto = require("node:crypto");

if (process.env.ENABLE_FIPS === "true") {
crypto.setFips(true);
}
console.log("FIPS enabled:", crypto.getFips());
4 changes: 4 additions & 0 deletions recipes/crypto-fips/tests/expected/file-4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import crypto from "node:crypto";

const fipsStatus = crypto.getFips();
crypto.setFips(!fipsStatus);
4 changes: 4 additions & 0 deletions recipes/crypto-fips/tests/expected/file-5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const nodeCrypto = require("node:crypto");

const currentFips = nodeCrypto.getFips();
nodeCrypto.setFips(!currentFips);
4 changes: 4 additions & 0 deletions recipes/crypto-fips/tests/expected/file-6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const crypto = require("node:crypto");

console.log("FIPS enabled:", crypto.getFips());
crypto.setFips(crypto.getFips() || process.env.FORCE_FIPS);
5 changes: 5 additions & 0 deletions recipes/crypto-fips/tests/input/file-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const crypto = require("node:crypto");

if (crypto.fips) {
console.log("FIPS mode is enabled");
}
3 changes: 3 additions & 0 deletions recipes/crypto-fips/tests/input/file-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const crypto = require("node:crypto");

crypto.fips = true;
6 changes: 6 additions & 0 deletions recipes/crypto-fips/tests/input/file-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const crypto = require("node:crypto");

if (process.env.ENABLE_FIPS === "true") {
crypto.fips = true;
}
console.log("FIPS enabled:", crypto.fips);
4 changes: 4 additions & 0 deletions recipes/crypto-fips/tests/input/file-4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import crypto from "node:crypto";

const fipsStatus = crypto.fips;
crypto.fips = !fipsStatus;
4 changes: 4 additions & 0 deletions recipes/crypto-fips/tests/input/file-5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const nodeCrypto = require("node:crypto");

const currentFips = nodeCrypto.fips;
nodeCrypto.fips = !currentFips;
4 changes: 4 additions & 0 deletions recipes/crypto-fips/tests/input/file-6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const crypto = require("node:crypto");

console.log("FIPS enabled:", crypto.fips);
crypto.fips = crypto.fips || process.env.FORCE_FIPS;
23 changes: 23 additions & 0 deletions recipes/crypto-fips/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"allowJs": true,
"alwaysStrict": true,
"baseUrl": "./",
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": true,
"lib": ["ESNext", "DOM"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noImplicitThis": true,
"removeComments": true,
"strict": true,
"stripInternal": true,
"target": "esnext"
},
"include": ["./"],
"exclude": [
"tests/**"
]
}
25 changes: 25 additions & 0 deletions recipes/crypto-fips/workflow.yaml
Original file line number Diff line number Diff line change
@@ -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 DEP0093 via transforming `crypto.fips` to `crypto.getFips()`, `crypto.setFips()` to `crypto.setFips(true)` and `crypto.setFips(false)`.
js-ast-grep:
js_file: src/workflow.ts
base_path: .
include:
- "**/*.js"
- "**/*.jsx"
- "**/*.mjs"
- "**/*.cjs"
- "**/*.cts"
- "**/*.mts"
- "**/*.ts"
- "**/*.tsx"
exclude:
- "**/node_modules/**"
language: typescript