From 10255779edc6b38cd99999d21fb896ba2fed1c3a Mon Sep 17 00:00:00 2001 From: weareoutman Date: Wed, 22 Nov 2023 18:35:18 +0800 Subject: [PATCH] feat(): treat other bricks as peer dependencies --- .../bin/post-build-next-bricks.js | 32 +++++ .../bin/pre-build-next-bricks.js | 109 ++++++++++++++++++ packages/build-next-bricks/package.json | 5 +- 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100755 packages/build-next-bricks/bin/post-build-next-bricks.js create mode 100755 packages/build-next-bricks/bin/pre-build-next-bricks.js diff --git a/packages/build-next-bricks/bin/post-build-next-bricks.js b/packages/build-next-bricks/bin/post-build-next-bricks.js new file mode 100755 index 0000000000..7cb79c05e2 --- /dev/null +++ b/packages/build-next-bricks/bin/post-build-next-bricks.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node +import path from "node:path"; +import { existsSync } from "node:fs"; +import { copyFile, readdir, rm } from "node:fs/promises"; + +const bricksDir = path.join(process.cwd(), "bricks"); + +try { + const dirents = await readdir(bricksDir, { withFileTypes: true }); + + await Promise.all( + dirents.map(async (item) => { + if (!item.isDirectory()) { + return; + } + + const packageDir = path.join(bricksDir, item.name); + const packageJsonPath = path.join(packageDir, "package.json"); + const packageJsonBakPath = path.join(packageDir, "package.json.bak"); + if (!existsSync(packageJsonBakPath)) { + return; + } + + // Resume backed-up package.json. + await copyFile(packageJsonBakPath, packageJsonPath); + await rm(packageJsonBakPath); + }) + ); +} catch (e) { + console.error(e); + process.exitCode = 1; +} diff --git a/packages/build-next-bricks/bin/pre-build-next-bricks.js b/packages/build-next-bricks/bin/pre-build-next-bricks.js new file mode 100755 index 0000000000..02aa4147ad --- /dev/null +++ b/packages/build-next-bricks/bin/pre-build-next-bricks.js @@ -0,0 +1,109 @@ +#!/usr/bin/env node +import path from "node:path"; +import { copyFile, readFile, readdir, writeFile } from "node:fs/promises"; +import { existsSync } from "node:fs"; +import * as prettier from "prettier"; + +const bricksDir = path.join(process.cwd(), "bricks"); + +const matchBrickPackages = (key) => /^@(?:next-)?bricks\//.test(key); + +try { + const dirents = await readdir(bricksDir, { withFileTypes: true }); + + await Promise.all( + dirents.map(async (item) => { + if (!item.isDirectory()) { + return; + } + + const packageDir = path.join(bricksDir, item.name); + const packageJsonPath = path.join(packageDir, "package.json"); + if (!existsSync(packageJsonPath)) { + return; + } + + const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8")); + + const dependencies = packageJson.dependencies || {}; + const devDependencies = packageJson.devDependencies || {}; + const peerDependencies = packageJson.peerDependencies || {}; + + // If error was thrown when building, thus pre-build was performed but post-build wasn't, + // so we handle this situation: remove deps that is copied when pre-building. + let changed = false; + for (const [dep, version] of Object.entries(peerDependencies)) { + if (dependencies[dep] === version) { + delete dependencies[dep]; + changed = true; + } + if (devDependencies[dep] === version) { + delete devDependencies[dep]; + changed = true; + } + } + if (changed) { + await writeFile( + packageJsonPath, + await prettier.format(JSON.stringify(packageJson, null, 2), { + filepath: packageJsonPath, + }) + ); + } + + // If there were still "@next-bricks/*" in dependencies or devDependencies, + // throw an error. Should put them into peerDependencies. + if ( + Object.keys(dependencies) + .concat(Object.keys(devDependencies)) + .some(matchBrickPackages) + ) { + throw new Error( + `Please put other "@next-bricks/*" into peerDependencies instead of dependencies or devDependencies for your brick package: ${packageJson.name}` + ); + } + }) + ); + + await Promise.all( + dirents.map(async (item) => { + if (!item.isDirectory()) { + return; + } + + const packageDir = path.join(bricksDir, item.name); + const packageJsonPath = path.join(packageDir, "package.json"); + const packageJsonBakPath = path.join(packageDir, "package.json.bak"); + if (!existsSync(packageJsonPath)) { + return; + } + + const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8")); + + const peerDependencies = packageJson.peerDependencies || {}; + const bricksPeerDependencies = + Object.keys(peerDependencies).filter(matchBrickPackages); + if (bricksPeerDependencies.length === 0) { + return; + } + // Make a copy as backup file. + await copyFile(packageJsonPath, packageJsonBakPath); + + // Copy "@next-bricks/*" from peerDependencies to devDependencies. + const devDependencies = (packageJson.devDependencies ??= {}); + for (const dep of bricksPeerDependencies) { + devDependencies[dep] = peerDependencies[dep]; + } + + await writeFile( + packageJsonPath, + await prettier.format(JSON.stringify(packageJson, null, 2), { + filepath: packageJsonPath, + }) + ); + }) + ); +} catch (e) { + console.error(e); + process.exitCode = 1; +} diff --git a/packages/build-next-bricks/package.json b/packages/build-next-bricks/package.json index 8cfd08ff4d..cd91da7aa8 100644 --- a/packages/build-next-bricks/package.json +++ b/packages/build-next-bricks/package.json @@ -7,7 +7,9 @@ "type": "module", "typings": "./index.d.ts", "bin": { - "build-next-bricks": "./bin/build-next-bricks.js" + "build-next-bricks": "./bin/build-next-bricks.js", + "pre-build-next-bricks": "./bin/pre-build-next-bricks.js", + "post-build-next-bricks": "./bin/post-build-next-bricks.js" }, "files": [ "bin", @@ -46,6 +48,7 @@ "postcss": "^8.4.31", "postcss-loader": "^7.3.3", "postcss-preset-env": "^9.3.0", + "prettier": "^3.0.3", "style-loader": "^3.3.3", "typescript": "^5.2.2", "webpack": "^5.89.0"