diff --git a/scripts/check-deps.js b/scripts/check-deps.js index f75b8642..bb839935 100644 --- a/scripts/check-deps.js +++ b/scripts/check-deps.js @@ -10,13 +10,18 @@ const path = require("path"); // Node built-ins (not in package.json but valid to import) const BUILTINS = new Set([ - "assert", "buffer", "child_process", "cluster", "crypto", "dgram", + "assert", "assert/strict", "buffer", "child_process", "cluster", "crypto", "dgram", "dns", "domain", "events", "fs", "http", "http2", "https", "module", - "net", "os", "path", "perf_hooks", "process", "punycode", "querystring", - "readline", "repl", "stream", "string_decoder", "timers", "tls", "tty", + "net", "node", "os", "path", "perf_hooks", "process", "punycode", "querystring", + "readline", "repl", "stream", "string_decoder", "test", "timers", "tls", "tty", "url", "util", "v8", "vm", "wasi", "worker_threads", "zlib", ]); +// Node.js built-in submodules (node:xxx format) +const NODE_BUILTINS = new Set([ + "node:test", "node:assert", "node:assert/strict", +]); + // Next.js / framework aliases that resolve internally const FRAMEWORK_ALIASES = new Set([ "next", "react", "react-dom", @@ -74,6 +79,7 @@ function collectMissingDeps(files, allDeps, cwd = process.cwd()) { for (const mod of extractImports(src)) { // Skip relative imports, path aliases (@/ is the src alias — not a pkg) if (mod.startsWith(".") || mod.startsWith("/") || mod.startsWith("@/")) continue; + if (mod.startsWith("node:") && NODE_BUILTINS.has(mod)) continue; const pkgName = extractPackageName(mod); if (BUILTINS.has(pkgName) || FRAMEWORK_ALIASES.has(pkgName)) continue; if (allDeps.has(pkgName)) continue; diff --git a/src/lib/crypto.test.ts b/src/lib/crypto.test.ts new file mode 100644 index 00000000..ef2aa941 --- /dev/null +++ b/src/lib/crypto.test.ts @@ -0,0 +1,49 @@ +import { encryptToken, decryptToken } from './crypto'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; + +describe('encryptToken', () => { + it('should encrypt and decrypt a token successfully', () => { + const token = 'test-token-12345'; + const { encrypted, iv } = encryptToken(token); + const decrypted = decryptToken(encrypted, iv); + assert.strictEqual(decrypted, token); + }); + + it('should return different ciphertext for same input due to random IV', () => { + const token = 'test-token'; + const result1 = encryptToken(token); + const result2 = encryptToken(token); + assert.notStrictEqual(result1.encrypted, result2.encrypted); + assert.notStrictEqual(result1.iv, result2.iv); + }); +}); + +describe('decryptToken', () => { + it('should return null on invalid hex input with odd length', () => { + const { encrypted, iv } = encryptToken('test'); + const invalidEncrypted = encrypted.slice(0, -1); + const result = decryptToken(invalidEncrypted, iv); + assert.strictEqual(result, null); + }); + + it('should return null on invalid hex input with non-hex characters', () => { + const { encrypted, iv } = encryptToken('test'); + const invalidEncrypted = encrypted.replace('a', 'x'); + const result = decryptToken(invalidEncrypted, iv); + assert.strictEqual(result, null); + }); + + it('should return null on invalid IV length', () => { + const { encrypted } = encryptToken('test'); + const invalidIv = '0'.repeat(20); + const result = decryptToken(encrypted, invalidIv); + assert.strictEqual(result, null); + }); + + it('should return null on encrypted token that is too short', () => { + const { iv } = encryptToken('test'); + const result = decryptToken('aabbcc', iv); + assert.strictEqual(result, null); + }); +});