diff --git a/packages/identity-obj-proxy/CHANGELOG.md b/packages/identity-obj-proxy/CHANGELOG.md new file mode 100644 index 00000000..bbeabc66 --- /dev/null +++ b/packages/identity-obj-proxy/CHANGELOG.md @@ -0,0 +1,10 @@ +# @opensourceframework/identity-obj-proxy + +## 3.0.1 + +### Patch Changes + +- Initial release as `@opensourceframework/identity-obj-proxy`. +- Forked from `identity-obj-proxy` v3.0.0. +- Modernized build system to ESM + CJS using `tsup`. +- Added TypeScript type definitions. diff --git a/packages/identity-obj-proxy/README.md b/packages/identity-obj-proxy/README.md new file mode 100644 index 00000000..4fdf5eb0 --- /dev/null +++ b/packages/identity-obj-proxy/README.md @@ -0,0 +1,48 @@ +# @opensourceframework/identity-obj-proxy + +> An identity object using ES6 proxies. A maintained drop-in replacement for `identity-obj-proxy`. + +This is a modern, actively maintained fork of the [original `identity-obj-proxy`](https://github.com/keyanzhang/identity-obj-proxy) package, which has been abandoned since 2022. It is fully backwards compatible and functions as a drop-in replacement. + +## Why use this? + +`identity-obj-proxy` is heavily used in the React/Next.js ecosystem for mocking CSS modules in Jest configurations. As the Node.js and Jest ecosystems have modernized, the original unmaintained package can cause compatibility issues or security warnings. + +This fork is maintained by the **OpenSource Framework** team, ensuring it stays compatible with modern JavaScript environments (ESM, Node 20+, etc.). + +## Installation + +```bash +npm install -D @opensourceframework/identity-obj-proxy +# or +yarn add -D @opensourceframework/identity-obj-proxy +# or +pnpm add -D @opensourceframework/identity-obj-proxy +``` + +## Usage (Jest) + +In your `jest.config.js`: + +```javascript +module.exports = { + moduleNameMapper: { + "\\.(css|less|scss|sass)$": "@opensourceframework/identity-obj-proxy" + } +}; +``` + +## How it works + +When you import a CSS module in your tests, it replaces the import with a proxy object that simply returns the key. + +```javascript +import styles from './styles.module.css'; + +console.log(styles.foo); // "foo" +console.log(styles.bar); // "bar" +``` + +## License + +MIT diff --git a/packages/identity-obj-proxy/package.json b/packages/identity-obj-proxy/package.json new file mode 100644 index 00000000..a4184953 --- /dev/null +++ b/packages/identity-obj-proxy/package.json @@ -0,0 +1,69 @@ +{ + "name": "@opensourceframework/identity-obj-proxy", + "version": "3.0.1", + "description": "An identity object using ES6 proxies. A maintained drop-in replacement for the unmaintained identity-obj-proxy.", + "keywords": [ + "proxy", + "proxies", + "identity", + "jest", + "mock" + ], + "author": "OpenSource Framework Contributors (fork), Original: Keyan Zhang", + "license": "MIT", + "type": "module", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist", + "README.md", + "LICENSE", + "CHANGELOG.md" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "lint": "eslint .", + "typecheck": "tsc --noEmit", + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage", + "clean": "rm -rf dist coverage node_modules" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@vitest/coverage-v8": "^2.1.9", + "tsup": "^8.5.1", + "typescript": "^5.9.3", + "vitest": "^2.1.9" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/riceharvest/opensourceframework.git", + "directory": "packages/identity-obj-proxy" + }, + "bugs": { + "url": "https://github.com/riceharvest/opensourceframework/issues?q=is%3Aissue+is%3Aopen+identity-obj-proxy" + }, + "homepage": "https://github.com/riceharvest/opensourceframework/tree/main/packages/identity-obj-proxy#readme", + "engines": { + "node": ">=18.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/identity-obj-proxy/src/index.ts b/packages/identity-obj-proxy/src/index.ts new file mode 100644 index 00000000..42a9f808 --- /dev/null +++ b/packages/identity-obj-proxy/src/index.ts @@ -0,0 +1,17 @@ +/** + * An identity object using ES6 proxies. + * Useful for mocking CSS modules in Jest where `styles.foo` evaluates to `"foo"`. + */ +const idObj = new Proxy( + {}, + { + get: function getter(_target, key) { + if (key === '__esModule') { + return false; + } + return key; + }, + } +); + +export default idObj; diff --git a/packages/identity-obj-proxy/test/index.test.ts b/packages/identity-obj-proxy/test/index.test.ts new file mode 100644 index 00000000..87bb9d8b --- /dev/null +++ b/packages/identity-obj-proxy/test/index.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest'; +import idObj from '../src/index'; + +describe('identity-obj-proxy', () => { + it('returns the requested key as a string', () => { + // @ts-expect-error - testing proxy behavior + expect(idObj.foo).toBe('foo'); + // @ts-expect-error - testing proxy behavior + expect(idObj.bar).toBe('bar'); + // @ts-expect-error - testing proxy behavior + expect(idObj['some-complex-key']).toBe('some-complex-key'); + }); + + it('returns false for __esModule to support ES module interop', () => { + // @ts-expect-error - testing proxy behavior + expect(idObj.__esModule).toBe(false); + }); +}); diff --git a/packages/identity-obj-proxy/tsconfig.json b/packages/identity-obj-proxy/tsconfig.json new file mode 100644 index 00000000..316737d5 --- /dev/null +++ b/packages/identity-obj-proxy/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": ["src/**/*", "test/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/identity-obj-proxy/tsup.config.ts b/packages/identity-obj-proxy/tsup.config.ts new file mode 100644 index 00000000..58b99d18 --- /dev/null +++ b/packages/identity-obj-proxy/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['cjs', 'esm'], + dts: true, + clean: true, + sourcemap: true, + treeshake: true, + target: 'es2022', +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7d47367..ce677900 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,6 +184,24 @@ importers: specifier: ^2.1.9 version: 2.1.9(@types/node@25.4.0)(happy-dom@20.8.3)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@25.4.0)(typescript@5.9.3))(terser@5.46.0) + packages/identity-obj-proxy: + devDependencies: + '@types/node': + specifier: ^22.0.0 + version: 22.19.15 + '@vitest/coverage-v8': + specifier: ^2.1.9 + version: 2.1.9(vitest@2.1.9(@types/node@22.19.15)(happy-dom@20.8.3)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(terser@5.46.0)) + tsup: + specifier: ^8.5.1 + version: 8.5.1(@swc/core@1.15.13)(jiti@2.6.1)(postcss@8.5.8)(tsx@4.19.3)(typescript@5.9.3)(yaml@2.8.2) + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vitest: + specifier: ^2.1.9 + version: 2.1.9(@types/node@22.19.15)(happy-dom@20.8.3)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(terser@5.46.0) + packages/next-auth: dependencies: '@babel/runtime': @@ -12393,6 +12411,14 @@ snapshots: '@types/node': 22.19.11 optional: true + '@inquirer/confirm@5.1.21(@types/node@22.19.15)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.19.15) + '@inquirer/type': 3.0.10(@types/node@22.19.15) + optionalDependencies: + '@types/node': 22.19.15 + optional: true + '@inquirer/confirm@5.1.21(@types/node@24.10.13)': dependencies: '@inquirer/core': 10.3.2(@types/node@24.10.13) @@ -12436,6 +12462,20 @@ snapshots: '@types/node': 22.19.11 optional: true + '@inquirer/core@10.3.2(@types/node@22.19.15)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.19.15) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.19.15 + optional: true + '@inquirer/core@10.3.2(@types/node@24.10.13)': dependencies: '@inquirer/ansi': 1.0.2 @@ -12489,6 +12529,11 @@ snapshots: '@types/node': 22.19.11 optional: true + '@inquirer/type@3.0.10(@types/node@22.19.15)': + optionalDependencies: + '@types/node': 22.19.15 + optional: true + '@inquirer/type@3.0.10(@types/node@24.10.13)': optionalDependencies: '@types/node': 24.10.13 @@ -14176,6 +14221,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@22.19.15)(happy-dom@20.8.3)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(terser@5.46.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magic-string: 0.30.21 + magicast: 0.3.5 + std-env: 3.10.0 + test-exclude: 7.0.2 + tinyrainbow: 1.2.0 + vitest: 2.1.9(@types/node@22.19.15)(happy-dom@20.8.3)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(terser@5.46.0) + transitivePeerDependencies: + - supports-color + '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@25.4.0)(happy-dom@20.8.3)(jsdom@24.1.3)(lightningcss@1.32.0)(msw@2.12.10(@types/node@25.4.0)(typescript@5.9.3))(terser@5.46.0))': dependencies: '@ampproject/remapping': 2.3.0 @@ -14273,6 +14336,15 @@ snapshots: msw: 2.12.10(@types/node@22.19.11)(typescript@5.9.3) vite: 5.4.21(@types/node@22.19.11)(lightningcss@1.32.0)(terser@5.46.0) + '@vitest/mocker@2.1.9(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(vite@5.4.21(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.12.10(@types/node@22.19.15)(typescript@5.9.3) + vite: 5.4.21(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0) + '@vitest/mocker@2.1.9(msw@2.12.10(@types/node@25.4.0)(typescript@5.9.3))(vite@5.4.21(@types/node@25.4.0)(lightningcss@1.32.0)(terser@5.46.0))': dependencies: '@vitest/spy': 2.1.9 @@ -19310,6 +19382,32 @@ snapshots: - '@types/node' optional: true + msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.21(@types/node@22.19.15) + '@mswjs/interceptors': 0.41.3 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.1.1 + graphql: 16.13.1 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.10.1 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.0 + type-fest: 5.4.4 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + optional: true + msw@2.12.10(@types/node@24.10.13)(typescript@5.9.3): dependencies: '@inquirer/confirm': 5.1.21(@types/node@24.10.13) @@ -22413,6 +22511,24 @@ snapshots: - supports-color - terser + vite-node@2.1.9(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-node@2.1.9(@types/node@25.4.0)(lightningcss@1.32.0)(terser@5.46.0): dependencies: cac: 6.7.14 @@ -22474,6 +22590,17 @@ snapshots: lightningcss: 1.32.0 terser: 5.46.0 + vite@5.4.21(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0): + dependencies: + esbuild: 0.25.12 + postcss: 8.5.8 + rollup: 4.59.0 + optionalDependencies: + '@types/node': 22.19.15 + fsevents: 2.3.3 + lightningcss: 1.32.0 + terser: 5.46.0 + vite@5.4.21(@types/node@25.4.0)(lightningcss@1.32.0)(terser@5.46.0): dependencies: esbuild: 0.25.12 @@ -22647,6 +22774,43 @@ snapshots: - supports-color - terser + vitest@2.1.9(@types/node@22.19.15)(happy-dom@20.8.3)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(terser@5.46.0): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.3))(vite@5.4.21(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0) + vite-node: 2.1.9(@types/node@22.19.15)(lightningcss@1.32.0)(terser@5.46.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.19.15 + happy-dom: 20.8.3 + jsdom: 25.0.1 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vitest@2.1.9(@types/node@25.4.0)(happy-dom@20.8.3)(jsdom@24.1.3)(lightningcss@1.32.0)(msw@2.12.10(@types/node@25.4.0)(typescript@5.9.3))(terser@5.46.0): dependencies: '@vitest/expect': 2.1.9