Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this change

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brunocroh i tried but nothing happened.

I think this is probably because of LF and CRLF thing. Changing that also didn't revert this change

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