Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 9 additions & 3 deletions scripts/check-deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand Down
49 changes: 49 additions & 0 deletions src/lib/crypto.test.ts
Original file line number Diff line number Diff line change
@@ -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);
});
});
Loading