Skip to content
Merged
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
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
NPM_TOKEN=replace-with-your-github-package-token
IMAGEKIT_PUBLIC_KEY=replace-with-imagekit-public-key
IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your-endpoint/
IMAGEKIT_PRIVATE_KEY=replace-with-imagekit-private-key
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ module.exports = {
'jsx-a11y/click-events-have-key-events': 0,
'jsx-a11y/no-static-element-interactions': 0,
'import/prefer-default-export': 0,
'import/no-unresolved': [
'error',
{ ignore: ['^@appbaseio/reactivesearch-playground$'] },
],
'react/no-unknown-property': ['error', { ignore: ['css'] }],
},
};
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 16
node-version: 20
cache: yarn

- name: Install dependencies
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 16
node-version: 20
cache: yarn
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Yarn audit
run: yarn audit --groups dependencies
run: node ./scripts/audit-gate.js
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ cypress.env.json
*.DS_Store

dist
samples/moviesData.json
.idea

# sentry
Expand Down
3 changes: 0 additions & 3 deletions .npmrc

This file was deleted.

2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v16
20.18.0
2 changes: 0 additions & 2 deletions .yarnrc

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ There is currently no guaranteed maintenance SLA.

## Requirements

- Node.js 16.x (see `.nvmrc` / Volta config)
- Node.js 20.x (see `.nvmrc` / Volta config)
- Yarn 1.x

## Setup
Expand Down
2 changes: 1 addition & 1 deletion cypress/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
plugins: ['cypress'],
env: {
'cypress/global': true,
'cypress/globals': true,
},
rules: {
'cypress/no-assigning-return-values': 'error',
Expand Down
58 changes: 1 addition & 57 deletions extract-shopify.sh
Original file line number Diff line number Diff line change
@@ -1,60 +1,4 @@
#!/bin/bash
set -euo pipefail

GITHUB_TOKEN="${GITHUB_TOKEN:-}"

if ! command -v jq >/dev/null 2>&1; then
echo "jq is required to extract templates."
echo "Install jq and retry (macOS: brew install jq)."
exit 1
fi

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEMPLATES_DIR="$ROOT_DIR/templates"

rm -rf "$TEMPLATES_DIR"
mkdir -p "$TEMPLATES_DIR"

jq -c '.[]' "$ROOT_DIR/template-sources.json" | while read -r i; do
version=$(echo "${i}" | jq -r '.version')
commit=$(echo "${i}" | jq -r '.commit')
branch=$(echo "${i}" | jq -r '.branch')
organization=$(echo "${i}" | jq -r '.organization')
repository=$(echo "${i}" | jq -r '.repository')
repositoryType=$(echo "${i}" | jq -r '.repositoryType')

if [ -n "$version" ] && [ "$version" != "null" ]; then
url="https://codeload.github.com/$organization/$repository/legacy.zip/refs/tags/$version"
fileName="$repository@$version"
elif [ -n "$commit" ] && [ "$commit" != "null" ]; then
url="https://codeload.github.com/$organization/$repository/legacy.zip/$commit"
fileName="$repository@$commit"
elif [ -n "$branch" ] && [ "$branch" != "null" ]; then
url="https://codeload.github.com/$organization/$repository/legacy.zip/refs/heads/$branch"
fileName="$repository@$branch"
else
url="https://api.github.com/repos/$organization/$repository/zipball/"
fileName="$repository"
fi

if [ "$repositoryType" = "private" ] && [ -z "$GITHUB_TOKEN" ]; then
echo "Skipping private repository $organization/$repository (missing GITHUB_TOKEN)"
continue
fi

targetDir="$TEMPLATES_DIR/$fileName"
mkdir -p "$targetDir"
cd "$targetDir"

if [ "$repositoryType" = "private" ]; then
curl -sS \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token $GITHUB_TOKEN" \
"$url" > file.zip
else
curl -sS "$url" > file.zip
fi

unzip -oq file.zip
rm -f file.zip
done
exec node "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scripts/extract-templates.js"
21 changes: 12 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@
"license": "MIT",
"private": false,
"engines": {
"node": ">=14"
"node": ">=20"
},
"scripts": {
"dev": "NODE_ENV=development webpack-dev-server --mode development . --history-api-fallback --hot --progress --port 3333 --no-client-overlay",
"dev": "node ./scripts/generate-movies-sample.js && NODE_ENV=development webpack-dev-server --mode development . --history-api-fallback --hot --progress --port 3333 --no-client-overlay",
"lint": "eslint --cache .",
"build": "NODE_ENV=production node ./scripts/create-env.js && node --max_old_space_size=8192 ./node_modules/webpack/bin/webpack.js --mode production --progress",
"build": "node ./scripts/extract-templates.js && node preinstall-server.js && node ./scripts/generate-movies-sample.js && NODE_ENV=production node ./scripts/create-env.js && node --max_old_space_size=8192 ./node_modules/webpack/bin/webpack.js --mode production --progress",
"glow": "glow --watch",
"format": "prettier --write --use-tabs 'src/!(batteries*)**/**/*.js'",
"analyze": "source-map-explorer 'dist/*.js'",
"test": "jest --env node --config ./jest.config.json",
"cypress:run": "cypress run",
"cypress:open": " cypress open",
"cypress:chrome": "cypress run --headless chrome",
"preinstall": "./extract-shopify.sh && node preinstall-server.js"
"cypress:install": "npx cypress@5.6.0 install",
"setup:templates": "node ./scripts/extract-templates.js && node preinstall-server.js",
"postinstall": "node ./scripts/build-playground.js && node ./scripts/patch-importer.js"
},
"husky": {
"hooks": {
Expand Down Expand Up @@ -50,7 +52,6 @@
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^1.0.0",
"css-minimizer-webpack-plugin": "^3.1.1",
"cypress": "^5.0.0",
"cypress-plugin-tab": "^1.0.5",
"cypress-terminal-report": "^1.4.1",
"cypress-xpath": "^1.6.1",
Expand Down Expand Up @@ -84,7 +85,7 @@
"dependencies": {
"@ant-design/icons": "^4.0.0",
"@appbaseio/importer": "^0.1.4",
"@appbaseio-confidential/reactivesearch-playground": "^1.3.0-beta.6",
"@appbaseio/reactivesearch-playground": "github:appbaseio/reactivesearch-playground#e7060229f4baee86b90a94f92c8a66ff17aaa6e4",
"@appbaseio/react-filter-box": "^3.4.1",
"@appbaseio/reactivemaps": "^3.0.0-beta.14",
"@appbaseio/reactivesearch": "^4.3.0",
Expand All @@ -102,7 +103,6 @@
"brace": "^0.11.1",
"can-ndjson-stream": "^1.0.2",
"codesandbox": "1.2.16",
"d3-scale": "^2.1.2",
"diff-match-patch": "1.0.5",
"dompurify": "^3.2.4",
"dotenv": "^8.0.0",
Expand All @@ -119,7 +119,7 @@
"is-cidr": "^4.0.2",
"is-valid-domain": "^0.1.6",
"js-yaml": "^4.1.0",
"jsondiffpatch": "^0.4.1",
"jsondiffpatch": "^0.7.6",
"jszip": "^3.7.1",
"lint-staged": "^10.1.7",
"lodash": "^4.17.10",
Expand Down Expand Up @@ -163,8 +163,11 @@
"util": "^0.12.4",
"uuid": "^8.3.2"
},
"resolutions": {
"uuid": "8.3.2"
},
"volta": {
"node": "16.20.2",
"node": "20.18.0",
"yarn": "1.22.19"
}
}
54 changes: 17 additions & 37 deletions preinstall-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ const https = require('https');
const fs = require('fs');
const path = require('path');
const templatesConstants = require('./template-sources.json');
const ROOT_DIR = path.resolve(__dirname);

function readProjectFile(filePath, encoding) {
return fs.readFileSync(path.join(ROOT_DIR, path.relative(ROOT_DIR, filePath)), {
encoding,
});
}

var walk = function (dir, done) {
let results = [];
Expand Down Expand Up @@ -71,49 +78,22 @@ async function generateTemplatesOutput() {

if (err) throw err;

results.forEach((path) => {
results.forEach((filePath) => {
// Read file contents and store in files.js
const fileName = path.split(`${file}`)[1];
if (fileName.includes('.ico') || fileName.includes('.png')) {
const data = fs.readFileSync(
`./${
path.split('arc-dashboard/')[1] ||
path.split('repo/')[1] ||
path.split('vercel/path0/')[1]
}`,
{
encoding: 'base64',
},
);
filesObj[fileName] = data; //content for files.js
const relativeFileName = filePath.split(`${file}`)[1];
if (relativeFileName.includes('.ico') || relativeFileName.includes('.png')) {
const fileData = readProjectFile(filePath, 'base64');
filesObj[relativeFileName] = fileData; //content for files.js
} else {
if (!fileName.includes('build')) {
const data = fs.readFileSync(
`./${
path.split('arc-dashboard/')[1] ||
path.split('repo/')[1] ||
path.split('vercel/path0/')[1]
}`,
{
encoding: 'utf8',
},
);
filesObj[fileName] = data; //content for files.js
if (!relativeFileName.includes('build')) {
const fileData = readProjectFile(filePath, 'utf8');
filesObj[relativeFileName] = fileData; //content for files.js
}
}

// Check if manifest file exists in the repo
if (data.manifest_path === path.split(`${file}/`)[1]) {
const templateData = fs.readFileSync(
`./${
path.split('arc-dashboard/')[1] ||
path.split('repo/')[1] ||
path.split('vercel/path0/')[1]
}`,
{
encoding: 'utf8',
},
);
if (data.manifest_path === filePath.split(`${file}/`)[1]) {
const templateData = readProjectFile(filePath, 'utf8');

templateOutputObj = {
...data,
Expand Down
80 changes: 80 additions & 0 deletions scripts/audit-gate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const { execSync } = require('child_process');

const FAIL_SEVERITIES = new Set(['critical']);

function parseAuditOutput(output) {
const counts = {
critical: 0,
high: 0,
moderate: 0,
low: 0,
info: 0,
};

for (const line of output.split('\n')) {
if (!line.trim()) {
continue;
}

try {
const entry = JSON.parse(line);

if (entry.type === 'auditSummary' && entry.data?.vulnerabilities) {
return { ...counts, ...entry.data.vulnerabilities };
}

if (entry.type === 'auditAdvisory' && entry.data?.advisory?.severity) {
const { severity } = entry.data.advisory;
if (severity in counts) {
counts[severity] += 1;
}
}
} catch (error) {
// Ignore non-JSON lines from yarn audit output.
}
}

return counts;
}

function printSummary(counts) {
console.log('Yarn audit vulnerability summary (dependencies only):');
console.log(` critical: ${counts.critical}`);
console.log(` high: ${counts.high}`);
console.log(` moderate: ${counts.moderate}`);
console.log(` low: ${counts.low}`);
console.log(` info: ${counts.info}`);
}

function main() {
let output = '';

try {
output = execSync('yarn audit --groups dependencies --json', {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
maxBuffer: 50 * 1024 * 1024,
});
} catch (error) {
output = `${error.stdout || ''}${error.stderr || ''}`;
}

const counts = parseAuditOutput(output);
printSummary(counts);

const hasBlockingVulnerabilities = [...FAIL_SEVERITIES].some(
(severity) => counts[severity] > 0,
);

if (hasBlockingVulnerabilities) {
console.error(
'\nAudit gate failed: critical severity vulnerabilities must be resolved.',
);
process.exit(1);
}

console.log('\nAudit gate passed: no critical severity vulnerabilities.');
process.exit(0);
}

main();
Loading
Loading