From ab1f2291612394d6c104aaef77d3bb8c2cea81e0 Mon Sep 17 00:00:00 2001 From: Justin Hernandez Date: Sun, 10 Aug 2025 22:26:29 -0700 Subject: [PATCH] feat: modernize circuits build pipeline (#876) * Add tsup build for circuits * sort package.json * cr feedback * circuits fixes * fixes --- circuits/package.json | 26 +++++++++++- circuits/scripts/organize-types.mjs | 34 +++++++++++++++ circuits/scripts/postBuild.mjs | 65 +++++++++++++++++++++++++++++ circuits/scripts/shimConfigs.js | 2 + circuits/src/index.ts | 24 +++++++++++ circuits/src/testing/index.ts | 25 +++++++++++ circuits/tsconfig.cjs.json | 10 +++++ circuits/tsconfig.json | 8 ++-- circuits/tsconfig.types.json | 15 +++++++ circuits/tsup.config.ts | 35 ++++++++++++++++ yarn.lock | 1 + 11 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 circuits/scripts/organize-types.mjs create mode 100644 circuits/scripts/postBuild.mjs create mode 100644 circuits/scripts/shimConfigs.js create mode 100644 circuits/src/index.ts create mode 100644 circuits/src/testing/index.ts create mode 100644 circuits/tsconfig.cjs.json create mode 100644 circuits/tsconfig.types.json create mode 100644 circuits/tsup.config.ts diff --git a/circuits/package.json b/circuits/package.json index 19eed4bd0..e81661d97 100644 --- a/circuits/package.json +++ b/circuits/package.json @@ -5,14 +5,37 @@ "license": "MIT", "author": "self team", "type": "module", + "exports": { + ".": { + "types": "./dist/esm/index.d.ts", + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.cjs" + }, + "./testing": { + "types": "./dist/esm/testing/index.d.ts", + "import": "./dist/esm/testing/index.js", + "require": "./dist/cjs/testing/index.cjs" + }, + "./circuits/*": "./circuits/*" + }, + "main": "./dist/cjs/index.cjs", + "module": "./dist/esm/index.js", + "types": "./dist/esm/index.d.ts", + "files": [ + "dist/**/*", + "circuits/**/*" + ], "scripts": { - "build": "tsc", + "build": "tsup && yarn build:types && yarn postbuild", + "postbuild": "node ./scripts/postBuild.mjs", "build-all": "bash scripts/build/build_register_circuits.sh && bash scripts/build/build_register_circuits_id.sh && bash scripts/build/build_dsc_circuits.sh && bash scripts/build/build_disclose_circuits.sh", "build-disclose": "bash scripts/build/build_disclose_circuits.sh", "build-dsc": "bash scripts/build/build_dsc_circuits.sh", "build-register": "bash scripts/build/build_register_circuits.sh", "build-register-id": "bash scripts/build/build_register_circuits_id.sh", "build:deps": "yarn workspaces foreach --from @selfxyz/circuits --topological-dev --recursive run build", + "build:types": "tsc -p tsconfig.types.json && node scripts/organize-types.mjs", + "build:watch": "tsup --watch", "download": "bash scripts/server/download_circuits_from_AWS.sh", "format": "prettier --write .", "install-circuits": "yarn workspaces focus @selfxyz/circuits", @@ -81,6 +104,7 @@ "prettier": "^3.3.3", "ts-mocha": "^10.0.0", "tsconfig-paths": "^4.2.0", + "tsup": "^8.5.0", "tsx": "^4.20.3" }, "engines": { diff --git a/circuits/scripts/organize-types.mjs b/circuits/scripts/organize-types.mjs new file mode 100644 index 000000000..d72a8ca8d --- /dev/null +++ b/circuits/scripts/organize-types.mjs @@ -0,0 +1,34 @@ +import fs from 'fs'; +import path from 'path'; + +// Move type declarations to correct locations +const srcIndexTypes = 'dist/esm/src/index.d.ts'; +const destIndexTypes = 'dist/esm/index.d.ts'; +const srcTestingDir = 'dist/esm/src/testing'; +const destTestingDir = 'dist/esm/testing'; + +// Copy main index.d.ts +if (fs.existsSync(srcIndexTypes)) { + fs.copyFileSync(srcIndexTypes, destIndexTypes); + console.log('✓ Copied index.d.ts'); +} + +// Copy testing directory +if (fs.existsSync(srcTestingDir)) { + fs.cpSync(srcTestingDir, destTestingDir, { recursive: true }); + console.log('✓ Copied testing types'); +} + +// Clean up intermediate directories +const srcDir = 'dist/esm/src'; +const testsDir = 'dist/esm/tests'; +if (fs.existsSync(srcDir)) { + fs.rmSync(srcDir, { recursive: true, force: true }); + console.log('✓ Cleaned up src directory'); +} +if (fs.existsSync(testsDir)) { + fs.rmSync(testsDir, { recursive: true, force: true }); + console.log('✓ Cleaned up tests directory'); +} + +console.log('Type declarations organized successfully!'); diff --git a/circuits/scripts/postBuild.mjs b/circuits/scripts/postBuild.mjs new file mode 100644 index 000000000..051b5f300 --- /dev/null +++ b/circuits/scripts/postBuild.mjs @@ -0,0 +1,65 @@ +import { writeFileSync, mkdirSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { shimConfigs } from './shimConfigs.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const DIST = path.resolve(__dirname, '..', 'dist'); + +// Read package version +const packageJsonPath = path.resolve(__dirname, '..', 'package.json'); +const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); + +writeFileSync(path.join(DIST, 'esm', 'package.json'), JSON.stringify({ type: 'module' }, null, 4)); +writeFileSync( + path.join(DIST, 'cjs', 'package.json'), + JSON.stringify({ type: 'commonjs' }, null, 4) +); + +// Initialize dist package.json (filled after shims) +const distPackageJson = { + name: '@selfxyz/circuits', + version: packageJson.version, + type: 'module', + exports: { '.': './esm/index.js' }, +}; + +function toPosix(p) { + return p.split(path.sep).join('/'); +} + +function createShim(shimPath, targetPath) { + const shimDir = path.join(DIST, shimPath); + mkdirSync(shimDir, { recursive: true }); + const esmTarget = targetPath; // e.g. ./esm/utils/rsa.js (posix-like expected) + const cjsTarget = esmTarget.replace('/esm/', '/cjs/').replace(/\.js$/, '.cjs'); + + // ESM shim entry + writeFileSync( + path.join(shimDir, 'index.js'), + `// Shim for @selfxyz/circuits/${shimPath}\nexport * from '${esmTarget.replace(/\.js$/, '')}';\nexport { default } from '${esmTarget.replace(/\.js$/, '')}';\n` + ); + // CJS shim entry + writeFileSync( + path.join(shimDir, 'index.cjs'), + `// Shim for @selfxyz/circuits/${shimPath}\nmodule.exports = require('${cjsTarget}');\n` + ); + // Types shim + writeFileSync( + path.join(shimDir, 'index.d.ts'), + `// Types for @selfxyz/circuits/${shimPath}\nexport * from '${esmTarget.replace(/\.js$/, '')}';\nexport { default } from '${esmTarget.replace(/\.js$/, '')}';\n` + ); + + // Add subpath export for this shim + const subpath = `./${toPosix(shimPath)}`; + distPackageJson.exports[subpath] = { + import: `./${toPosix(path.relative(DIST, path.join(shimDir, 'index.js')))}`, + require: `./${toPosix(path.relative(DIST, path.join(shimDir, 'index.cjs')))}`, + }; +} + +// Materialize shims and export map +shimConfigs.forEach((config) => createShim(config.shimPath, config.targetPath)); + +// Finally write dist/package.json (after exports are populated) +writeFileSync(path.join(DIST, 'package.json'), JSON.stringify(distPackageJson, null, 4)); diff --git a/circuits/scripts/shimConfigs.js b/circuits/scripts/shimConfigs.js new file mode 100644 index 000000000..3f91b8799 --- /dev/null +++ b/circuits/scripts/shimConfigs.js @@ -0,0 +1,2 @@ +// Shim configurations for @selfxyz/circuits +export const shimConfigs = []; diff --git a/circuits/src/index.ts b/circuits/src/index.ts new file mode 100644 index 000000000..7336c44d5 --- /dev/null +++ b/circuits/src/index.ts @@ -0,0 +1,24 @@ +// Main circuits package runtime API +// This package provides circuit definitions and related utilities + +// Circuit metadata and constants +export const CIRCUITS_VERSION = '0.0.1'; + +// Supported signature algorithms +export const SUPPORTED_SIGNATURE_ALGORITHMS = [ + 'rsa_sha256_65537_2048', + 'rsa_sha256_65537_3072', + 'rsa_sha256_65537_4096', + 'rsa_sha1_65537_2048', + 'rsa_sha512_65537_4096', + 'rsapss_sha256_65537_32_3072', + 'rsapss_sha256_65537_32_4096', + 'rsapss_sha256_3_32_3072', + 'rsapss_sha384_65537_48_3072', + 'rsapss_sha512_65537_64_4096', +] as const; + +export type SupportedSignatureAlgorithm = (typeof SUPPORTED_SIGNATURE_ALGORITHMS)[number]; + +// Note: Test utilities have been moved to a dedicated './testing' export +// Import test utilities via: import { ... } from '@selfxyz/circuits/testing' diff --git a/circuits/src/testing/index.ts b/circuits/src/testing/index.ts new file mode 100644 index 000000000..e516609c9 --- /dev/null +++ b/circuits/src/testing/index.ts @@ -0,0 +1,25 @@ +// Re-export utility functions for generating mock inputs in circuit tests +export { generateMockRsaPkcs1v1_5Inputs } from '../../tests/utils/generateMockInputsInCircuits.js'; +export { + generateMockRsaPssInputs, + generateMalleableRsaPssInputs, +} from '../../tests/utils/generateMockInputsRsaPss.js'; + +// Re-export test case configurations +export { + sigAlgs as registerSigAlgs, + fullSigAlgs as registerFullSigAlgs, +} from '../../tests/register/test_cases.js'; +export { + sigAlgs as registerIdSigAlgs, + fullSigAlgs as registerIdFullSigAlgs, +} from '../../tests/register_id/test_cases.js'; +export { + sigAlgs as dscSigAlgs, + fullSigAlgs as dscFullSigAlgs, +} from '../../tests/dsc/test_cases.js'; +export { + fullAlgorithms as rsaPssFullAlgorithms, + sigAlgs as rsaPssSigAlgs, + AdditionalCases as rsaPssAdditionalCases, +} from '../../tests/utils/testcase/rsapss.js'; diff --git a/circuits/tsconfig.cjs.json b/circuits/tsconfig.cjs.json new file mode 100644 index 000000000..619b709d1 --- /dev/null +++ b/circuits/tsconfig.cjs.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS", + "moduleResolution": "Node", + "outDir": "./dist/cjs", + "declarationDir": "./dist/cjs", + "esModuleInterop": true + } +} diff --git a/circuits/tsconfig.json b/circuits/tsconfig.json index e7974216f..a7991e536 100644 --- a/circuits/tsconfig.json +++ b/circuits/tsconfig.json @@ -8,10 +8,12 @@ "module": "NodeNext", "allowJs": true, "checkJs": false, - "outDir": "./dist", - "baseUrl": "." + "outDir": "./dist/esm", + "declaration": false, + "baseUrl": ".", + "composite": false }, - "include": ["tests/**/*", "src/**/*"], + "include": ["tests/**/*", "tests/**/*.json", "src/**/*"], "exclude": ["node_modules"], "references": [ { diff --git a/circuits/tsconfig.types.json b/circuits/tsconfig.types.json new file mode 100644 index 000000000..9638cd723 --- /dev/null +++ b/circuits/tsconfig.types.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "declarationMap": false, + "outDir": "./dist/esm", + "declarationDir": "./dist/esm", + "composite": true, + "noEmit": false, + "rootDir": "." + }, + "include": ["src/**/*", "tests/**/*", "tests/**/*.json"], + "exclude": ["node_modules", "dist"] +} diff --git a/circuits/tsup.config.ts b/circuits/tsup.config.ts new file mode 100644 index 000000000..ce8a4a1f4 --- /dev/null +++ b/circuits/tsup.config.ts @@ -0,0 +1,35 @@ +import path from 'path'; +import { defineConfig } from 'tsup'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const entry = { + index: 'src/index.ts', +}; + +export default defineConfig([ + { + tsconfig: './tsconfig.json', + entry, + format: ['esm'], + outDir: path.resolve(__dirname, 'dist/esm'), + dts: false, + splitting: false, + clean: true, + sourcemap: true, + target: 'es2020', + }, + { + tsconfig: './tsconfig.cjs.json', + entry, + format: ['cjs'], + outDir: path.resolve(__dirname, 'dist/cjs'), + dts: false, + splitting: false, + clean: false, + sourcemap: true, + target: 'es2020', + }, +]); diff --git a/yarn.lock b/yarn.lock index 6669255e4..5e9c162bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4773,6 +4773,7 @@ __metadata: snarkjs: "npm:^0.7.1" ts-mocha: "npm:^10.0.0" tsconfig-paths: "npm:^4.2.0" + tsup: "npm:^8.5.0" tsx: "npm:^4.20.3" typescript: "npm:^5.3.3" languageName: unknown