mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Merge pull request #26 from AikidoSec/npm-workspace-multiple-packages
Setup npm workspace to support multiple packages
This commit is contained in:
commit
471b3efe4a
74 changed files with 156 additions and 64 deletions
11
.github/CONTRIBUTING
vendored
11
.github/CONTRIBUTING
vendored
|
|
@ -21,15 +21,20 @@ Report issues on our [GitHub Issues page](https://github.com/AikidoSec/safe-chai
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
**Workspace Structure:**
|
||||||
|
- `packages/safe-chain/` - Main CLI package
|
||||||
|
- `test/e2e/` - End-to-end tests
|
||||||
|
|
||||||
**Setup:**
|
**Setup:**
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install # Installs dependencies for all workspaces
|
||||||
```
|
```
|
||||||
|
|
||||||
**Commands:**
|
**Commands:**
|
||||||
- `npm test` - Run tests
|
- `npm test` - Run unit tests
|
||||||
- `npm run test:watch` - Watch mode
|
- `npm run test:e2e` - Run end-to-end tests
|
||||||
- `npm run lint` - Check code style
|
- `npm run lint` - Check code style
|
||||||
|
- `npm run test --workspace=packages/safe-chain` - Test specific workspace
|
||||||
|
|
||||||
**Requirements:**
|
**Requirements:**
|
||||||
- Node.js 18+
|
- Node.js 18+
|
||||||
|
|
|
||||||
15
.github/workflows/build-and-release.yml
vendored
15
.github/workflows/build-and-release.yml
vendored
|
|
@ -27,15 +27,24 @@ jobs:
|
||||||
version="${{ github.ref_name }}"
|
version="${{ github.ref_name }}"
|
||||||
echo "tag=$version" >> $GITHUB_OUTPUT
|
echo "tag=$version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set the version
|
- name: Set the version in safe-chain package
|
||||||
run: npm --no-git-tag-version version ${{ steps.get_version.outputs.tag }}
|
run: npm --no-git-tag-version version ${{ steps.get_version.outputs.tag }} --workspace=packages/safe-chain
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
- name: Copy documentation files to package
|
||||||
|
run: |
|
||||||
|
cp README.md packages/safe-chain/
|
||||||
|
cp LICENSE packages/safe-chain/
|
||||||
|
cp -r docs packages/safe-chain/
|
||||||
|
|
||||||
- name: Publish to npm
|
- name: Publish to npm
|
||||||
run: |
|
run: |
|
||||||
echo "Publishing version ${{ steps.get_version.outputs.tag }} to NPM"
|
echo "Publishing version ${{ steps.get_version.outputs.tag }} to NPM"
|
||||||
npm publish --access public
|
npm publish --workspace=packages/safe-chain --access public
|
||||||
env:
|
env:
|
||||||
NPM_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
NPM_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||||
|
|
|
||||||
18
.github/workflows/test-on-pr.yml
vendored
18
.github/workflows/test-on-pr.yml
vendored
|
|
@ -29,13 +29,19 @@ jobs:
|
||||||
- name: Run ESLint
|
- name: Run ESLint
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Create package tarball
|
||||||
|
run: npm pack --workspace=packages/safe-chain
|
||||||
|
|
||||||
|
- name: Upload package tarball
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: safe-chain-package
|
||||||
|
path: aikidosec-safe-chain-*.tgz
|
||||||
|
|
||||||
e2e-tests:
|
e2e-tests:
|
||||||
name: Run E2E tests
|
name: Run E2E tests
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: "test/e2e"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|
@ -46,11 +52,11 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: "lts/*"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies (root)
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Run unit tests
|
- name: Run E2E tests
|
||||||
run: npm test
|
run: npm run test:e2e
|
||||||
|
|
||||||
- name: Clean up Docker resources
|
- name: Clean up Docker resources
|
||||||
if: always()
|
if: always()
|
||||||
|
|
|
||||||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -138,4 +138,9 @@ dist
|
||||||
|
|
||||||
# Vite logs files
|
# Vite logs files
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
|
||||||
|
# AI
|
||||||
|
Claude.md
|
||||||
|
.claude
|
||||||
|
.reference
|
||||||
|
|
@ -22,5 +22,5 @@ export default defineConfig([
|
||||||
},
|
},
|
||||||
rules: {},
|
rules: {},
|
||||||
},
|
},
|
||||||
globalIgnores(['test/e2e']),
|
globalIgnores(['test/e2e', 'node_modules']),
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
78
package-lock.json
generated
78
package-lock.json
generated
|
|
@ -1,29 +1,16 @@
|
||||||
{
|
{
|
||||||
"name": "@aikidosec/safe-chain",
|
"name": "aikido-safe-chain-workspace",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@aikidosec/safe-chain",
|
"name": "aikido-safe-chain-workspace",
|
||||||
"version": "1.0.0",
|
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"workspaces": [
|
||||||
"@inquirer/prompts": "^7.4.1",
|
"packages/*",
|
||||||
"abbrev": "^3.0.1",
|
"test/e2e"
|
||||||
"chalk": "^5.4.1",
|
],
|
||||||
"npm-registry-fetch": "^18.0.2",
|
|
||||||
"ora": "^8.2.0",
|
|
||||||
"semver": "^7.7.2"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"aikido-npm": "bin/aikido-npm.js",
|
|
||||||
"aikido-npx": "bin/aikido-npx.js",
|
|
||||||
"aikido-pnpm": "bin/aikido-pnpm.js",
|
|
||||||
"aikido-pnpx": "bin/aikido-pnpx.js",
|
|
||||||
"aikido-yarn": "bin/aikido-yarn.js",
|
|
||||||
"safe-chain": "bin/safe-chain.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.26.0",
|
"@eslint/js": "^9.26.0",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.26.0",
|
||||||
|
|
@ -32,6 +19,14 @@
|
||||||
"typescript-eslint": "^8.32.0"
|
"typescript-eslint": "^8.32.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@aikidosec/safe-chain": {
|
||||||
|
"resolved": "packages/safe-chain",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
|
"node_modules/@aikidosec/safe-chain-e2e-tests": {
|
||||||
|
"resolved": "test/e2e",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
|
||||||
|
|
@ -3876,6 +3871,12 @@
|
||||||
"node": "^18.17.0 || >=20.5.0"
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nan": {
|
||||||
|
"version": "2.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz",
|
||||||
|
"integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/natural-compare": {
|
"node_modules/natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
|
|
@ -3892,6 +3893,16 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-pty": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "^2.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/npm-package-arg": {
|
"node_modules/npm-package-arg": {
|
||||||
"version": "12.0.2",
|
"version": "12.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz",
|
||||||
|
|
@ -5764,6 +5775,35 @@
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.24.1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"packages/safe-chain": {
|
||||||
|
"name": "@aikidosec/safe-chain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/prompts": "^7.4.1",
|
||||||
|
"abbrev": "^3.0.1",
|
||||||
|
"chalk": "^5.4.1",
|
||||||
|
"npm-registry-fetch": "^18.0.2",
|
||||||
|
"ora": "^8.2.0",
|
||||||
|
"semver": "^7.7.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"aikido-npm": "bin/aikido-npm.js",
|
||||||
|
"aikido-npx": "bin/aikido-npx.js",
|
||||||
|
"aikido-pnpm": "bin/aikido-pnpm.js",
|
||||||
|
"aikido-pnpx": "bin/aikido-pnpx.js",
|
||||||
|
"aikido-yarn": "bin/aikido-yarn.js",
|
||||||
|
"safe-chain": "bin/safe-chain.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test/e2e": {
|
||||||
|
"name": "@aikidosec/safe-chain-e2e-tests",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"node-pty": "^1.0.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
package.json
39
package.json
|
|
@ -1,36 +1,22 @@
|
||||||
{
|
{
|
||||||
"name": "@aikidosec/safe-chain",
|
"name": "aikido-safe-chain-workspace",
|
||||||
"version": "1.0.0",
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"workspaces": [
|
||||||
|
"packages/*",
|
||||||
|
"test/e2e"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node --test --experimental-test-module-mocks 'src/**/*.spec.js'",
|
"test": "npm run test --workspace=packages/safe-chain",
|
||||||
"test:watch": "node --test --watch --experimental-test-module-mocks 'src/**/*.spec.js'",
|
"test:e2e": "npm run test --workspace=test/e2e",
|
||||||
"lint": "eslint ."
|
"lint": "npm run lint --workspace=packages/safe-chain"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/AikidoSec/safe-chain.git"
|
"url": "git+https://github.com/AikidoSec/safe-chain.git"
|
||||||
},
|
},
|
||||||
"bin": {
|
|
||||||
"aikido-npm": "bin/aikido-npm.js",
|
|
||||||
"aikido-npx": "bin/aikido-npx.js",
|
|
||||||
"aikido-yarn": "bin/aikido-yarn.js",
|
|
||||||
"aikido-pnpm": "bin/aikido-pnpm.js",
|
|
||||||
"aikido-pnpx": "bin/aikido-pnpx.js",
|
|
||||||
"safe-chain": "bin/safe-chain.js"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Aikido Security",
|
"author": "Aikido Security",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"description": "The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), and [pnpx](https://pnpm.io/cli/dlx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, or pnpx from downloading or running the malware.",
|
|
||||||
"dependencies": {
|
|
||||||
"@inquirer/prompts": "^7.4.1",
|
|
||||||
"abbrev": "^3.0.1",
|
|
||||||
"chalk": "^5.4.1",
|
|
||||||
"npm-registry-fetch": "^18.0.2",
|
|
||||||
"ora": "^8.2.0",
|
|
||||||
"semver": "^7.7.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.26.0",
|
"@eslint/js": "^9.26.0",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.26.0",
|
||||||
|
|
@ -38,11 +24,6 @@
|
||||||
"globals": "^16.1.0",
|
"globals": "^16.1.0",
|
||||||
"typescript-eslint": "^8.32.0"
|
"typescript-eslint": "^8.32.0"
|
||||||
},
|
},
|
||||||
"main": "eslint.config.js",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/AikidoSec/safe-chain/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/AikidoSec/safe-chain#readme",
|
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"brace-expansion@<=2.0.2": "2.0.2"
|
"brace-expansion@<=2.0.2": "2.0.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
packages/safe-chain/.npmignore
Normal file
5
packages/safe-chain/.npmignore
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Test files
|
||||||
|
src/**/*.spec.js
|
||||||
|
|
||||||
|
# Package files
|
||||||
|
*.tgz
|
||||||
40
packages/safe-chain/package.json
Normal file
40
packages/safe-chain/package.json
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "@aikidosec/safe-chain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node --test --experimental-test-module-mocks 'src/**/*.spec.js'",
|
||||||
|
"test:watch": "node --test --watch --experimental-test-module-mocks 'src/**/*.spec.js'",
|
||||||
|
"lint": "eslint ."
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"aikido-npm": "bin/aikido-npm.js",
|
||||||
|
"aikido-npx": "bin/aikido-npx.js",
|
||||||
|
"aikido-yarn": "bin/aikido-yarn.js",
|
||||||
|
"aikido-pnpm": "bin/aikido-pnpm.js",
|
||||||
|
"aikido-pnpx": "bin/aikido-pnpx.js",
|
||||||
|
"safe-chain": "bin/safe-chain.js"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Aikido Security",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"description": "The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), and [pnpx](https://pnpm.io/cli/dlx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, or pnpx from downloading or running the malware.",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/prompts": "^7.4.1",
|
||||||
|
"abbrev": "^3.0.1",
|
||||||
|
"chalk": "^5.4.1",
|
||||||
|
"npm-registry-fetch": "^18.0.2",
|
||||||
|
"ora": "^8.2.0",
|
||||||
|
"semver": "^7.7.2"
|
||||||
|
},
|
||||||
|
"main": "src/main.js",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/AikidoSec/safe-chain/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/AikidoSec/safe-chain#readme",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/AikidoSec/safe-chain.git",
|
||||||
|
"directory": "packages/safe-chain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,13 +6,13 @@ ENV CI=true
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package files first for better caching
|
# Copy package files first for better caching
|
||||||
COPY package*.json ./
|
COPY packages/safe-chain/package*.json ./
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
# Copy the rest of the application
|
# Copy the rest of the application
|
||||||
COPY . .
|
COPY packages/safe-chain ./
|
||||||
|
|
||||||
# Build the application
|
# Build the application
|
||||||
RUN npm --no-git-tag-version version 1.0.0 --allow-same-version
|
RUN npm --no-git-tag-version version 1.0.0 --allow-same-version
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@aikidosec/safe-chain-e2e-tests",
|
"name": "@aikidosec/safe-chain-e2e-tests",
|
||||||
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "End-to-end tests for the Aikido Safe Chain",
|
"description": "End-to-end tests for the Aikido Safe Chain",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue