diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0642e0b7ff65..4dabb694f83e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -301,15 +301,3 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
[stackoverflow]: https://stackoverflow.com/questions/tagged/angular-devkit
-## Updating the Public API
-Our Public API surface is tracked using golden files.
-
-You check all golden files by running:
-```bash
-pnpm public-api:check
-```
-
-If you modified the public API, the test will fail. To update the golden files you need to run:
-```bash
-pnpm public-api:update
-```
diff --git a/goldens/public-api/manage.js b/goldens/public-api/manage.js
deleted file mode 100644
index 569f2a6bd1e3..000000000000
--- a/goldens/public-api/manage.js
+++ /dev/null
@@ -1,54 +0,0 @@
-const {exec} = require('shelljs');
-const {Parser: parser} = require('yargs/helpers');
-
-// Remove all command line flags from the arguments.
-const argv = parser(process.argv.slice(2));
-// The command the user would like to run, either 'accept' or 'test'
-const USER_COMMAND = argv._[0];
-// The shell command to query for all Public API guard tests.
-const BAZEL_PUBLIC_API_TARGET_QUERY_CMD =
- `pnpm -s bazel query --output label 'kind(nodejs_test, ...) intersect attr("tags", "api_guard", ...)'`
-// Bazel targets for testing Public API goldens
-process.stdout.write('Gathering all Public API targets');
-const ALL_PUBLIC_API_TESTS = exec(BAZEL_PUBLIC_API_TARGET_QUERY_CMD, {silent: true})
- .trim()
- .split('\n')
- .map(test => test.trim());
-process.stdout.clearLine();
-process.stdout.cursorTo(0);
-// Bazel targets for generating Public API goldens
-const ALL_PUBLIC_API_ACCEPTS = ALL_PUBLIC_API_TESTS.map(test => `${test}.accept`);
-
-/**
- * Run the provided bazel commands on each provided target individually.
- */
-function runBazelCommandOnTargets(command, targets, present) {
- for (const target of targets) {
- process.stdout.write(`${present}: ${target}`);
- const commandResult = exec(`pnpm -s bazel ${command} ${target}`, {silent: true});
- process.stdout.clearLine();
- process.stdout.cursorTo(0);
- if (commandResult.code) {
- console.error(`Failed ${command}: ${target}`);
- console.group();
- console.error(commandResult.stdout || commandResult.stderr);
- console.groupEnd();
- } else {
- console.log(`Successful ${command}: ${target}`);
- }
- }
-}
-
-switch (USER_COMMAND) {
- case 'accept':
- runBazelCommandOnTargets('run', ALL_PUBLIC_API_ACCEPTS, 'Running');
- break;
- case 'test':
- runBazelCommandOnTargets('test', ALL_PUBLIC_API_TESTS, 'Testing');
- break;
- default:
- console.warn('Invalid command provided.');
- console.warn();
- console.warn(`Run this script with either "accept" and "test"`);
- break;
-}
diff --git a/package.json b/package.json
index 114d23740dc1..0a7e561dd329 100644
--- a/package.json
+++ b/package.json
@@ -21,9 +21,7 @@
"postinstall": "pnpm -s webdriver-update && husky",
"//webdriver-update-README": "ChromeDriver version must match Puppeteer Chromium version, see https://github.com/GoogleChrome/puppeteer/releases http://chromedriver.chromium.org/downloads",
"webdriver-update": "webdriver-manager update --standalone false --gecko false --versions.chrome 106.0.5249.21",
- "public-api:check": "node goldens/public-api/manage.js test",
"ng-dev": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only node_modules/@angular/ng-dev/bundles/cli.mjs",
- "public-api:update": "node goldens/public-api/manage.js accept",
"ts-circular-deps": "pnpm -s ng-dev ts-circular-deps --config ./scripts/circular-deps-test.conf.mjs",
"check-tooling-setup": "tsc --project .ng-dev/tsconfig.json",
"diff-release-package": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only scripts/diff-release-package.mts"
@@ -89,7 +87,6 @@
"@types/progress": "^2.0.3",
"@types/resolve": "^1.17.1",
"@types/semver": "^7.3.12",
- "@types/shelljs": "^0.8.11",
"@types/watchpack": "^2.4.4",
"@types/yargs": "^17.0.20",
"@types/yargs-parser": "^21.0.0",
@@ -134,7 +131,6 @@
"rollup-plugin-dts": "6.2.3",
"rollup-plugin-sourcemaps2": "0.5.4",
"semver": "7.7.3",
- "shelljs": "^0.10.0",
"source-map-support": "0.5.21",
"tar": "^7.0.0",
"ts-node": "^10.9.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3b97a55c8d64..61a35355c7a8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -148,9 +148,6 @@ importers:
'@types/semver':
specifier: ^7.3.12
version: 7.7.1
- '@types/shelljs':
- specifier: ^0.8.11
- version: 0.8.17
'@types/watchpack':
specifier: ^2.4.4
version: 2.4.4
@@ -283,9 +280,6 @@ importers:
semver:
specifier: 7.7.3
version: 7.7.3
- shelljs:
- specifier: ^0.10.0
- version: 0.10.0
source-map-support:
specifier: 0.5.21
version: 0.5.21
@@ -3633,9 +3627,6 @@ packages:
'@types/serve-static@1.15.9':
resolution: {integrity: sha512-dOTIuqpWLyl3BBXU3maNQsS4A3zuuoYRNIvYSxxhebPfXg2mzWQEPne/nlJ37yOse6uGgR386uTpdsx4D0QZWA==}
- '@types/shelljs@0.8.17':
- resolution: {integrity: sha512-IDksKYmQA2W9MkQjiyptbMmcQx+8+Ol6b7h6dPU5S05JyiQDSb/nZKnrMrZqGwgV6VkVdl6/SPCKPDlMRvqECg==}
-
'@types/sockjs@0.3.36':
resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==}
@@ -8092,10 +8083,6 @@ packages:
resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
engines: {node: '>= 0.4'}
- shelljs@0.10.0:
- resolution: {integrity: sha512-Jex+xw5Mg2qMZL3qnzXIfaxEtBaC4n7xifqaqtrZDdlheR70OGkydrPJWT0V1cA1k3nanC86x9FwAmQl6w3Klw==}
- engines: {node: '>=18'}
-
side-channel-list@1.0.0:
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
engines: {node: '>= 0.4'}
@@ -12225,11 +12212,6 @@ snapshots:
'@types/node': 22.18.11
'@types/send': 0.17.5
- '@types/shelljs@0.8.17':
- dependencies:
- '@types/node': 22.18.11
- glob: 11.0.3
-
'@types/sockjs@0.3.36':
dependencies:
'@types/node': 22.18.11
@@ -17652,11 +17634,6 @@ snapshots:
shell-quote@1.8.3: {}
- shelljs@0.10.0:
- dependencies:
- execa: 5.1.1
- fast-glob: 3.3.3
-
side-channel-list@1.0.0:
dependencies:
es-errors: 1.3.0
diff --git a/scripts/build-packages-dist.mts b/scripts/build-packages-dist.mts
index 441a3a2a021a..9a4fa1c764b9 100644
--- a/scripts/build-packages-dist.mts
+++ b/scripts/build-packages-dist.mts
@@ -14,9 +14,17 @@
import { BuiltPackage } from '@angular/ng-dev';
import { execSync } from 'node:child_process';
-import { chmodSync, copyFileSync, mkdirSync, rmSync } from 'node:fs';
+import {
+ chmodSync,
+ copyFileSync,
+ cpSync,
+ existsSync,
+ lstatSync,
+ mkdirSync,
+ readdirSync,
+ rmSync,
+} from 'node:fs';
import { dirname, join } from 'node:path';
-import sh from 'shelljs';
/** Name of the Bazel tag that will be used to find release package targets. */
const releaseTargetTag = 'release-package';
@@ -89,14 +97,15 @@ function buildReleasePackages(
// Archive output is created by the npm_package_archive target
const archiveOutputPath = directoryOutputPath + '_archive.tgz';
- if (sh.test('-d', directoryOutputPath)) {
- sh.chmod('-R', 'u+w', directoryOutputPath);
- sh.rm('-rf', directoryOutputPath);
+ if (existsSync(directoryOutputPath)) {
+ chmodRecursiveSync(directoryOutputPath, '0755');
+ rmSync(directoryOutputPath, { recursive: true, force: true });
}
- try {
+
+ if (existsSync(archiveOutputPath)) {
chmodSync(archiveOutputPath, '0755');
rmSync(archiveOutputPath, { force: true });
- } catch {}
+ }
});
// Build both the npm_package and npm_package_archive targets for each package
@@ -123,8 +132,8 @@ function buildReleasePackages(
mkdirSync(dirname(targetFolder), { recursive: true });
// Copy package contents to target directory
- sh.cp('-R', directoryOutputPath, targetFolder);
- sh.chmod('-R', 'u+w', targetFolder);
+ cpSync(directoryOutputPath, targetFolder, { recursive: true });
+ chmodRecursiveSync(targetFolder, '0755');
// Copy archive of package to target directory
const archiveTargetPath = join(distPath, `${pkgName.replace('/', '_')}.tgz`);
@@ -176,3 +185,25 @@ function exec(command: string, captureStdout?: true) {
return stdout.toString().trim();
}
}
+
+/**
+ * Recursively changes the permissions (mode) of a directory and all its contents (files and subdirectories).
+ * @param startPath The starting directory path.
+ * @param mode The new permissions mode (e.g., 0755).
+ */
+function chmodRecursiveSync(startPath: string, mode: string): void {
+ chmodSync(startPath, mode);
+
+ const files = readdirSync(startPath);
+
+ for (const file of files) {
+ const filePath = join(startPath, file);
+ const stat = lstatSync(filePath);
+
+ if (stat.isDirectory()) {
+ chmodRecursiveSync(filePath, mode);
+ } else {
+ chmodSync(filePath, mode);
+ }
+ }
+}
diff --git a/scripts/diff-release-package.mts b/scripts/diff-release-package.mts
index 2bf01aded3cd..8ec6b6df48db 100644
--- a/scripts/diff-release-package.mts
+++ b/scripts/diff-release-package.mts
@@ -18,10 +18,9 @@
import { GitClient } from '@angular/ng-dev';
import childProcess from 'node:child_process';
-import fs from 'node:fs';
+import fs, { chmodSync, lstatSync, readdirSync } from 'node:fs';
import os from 'node:os';
-import path from 'node:path';
-import sh from 'shelljs';
+import path, { join } from 'node:path';
// Do not remove `.git` as we use Git for comparisons later.
// Also preserve `uniqueId` as it's irrelevant for the diff and not included via Bazel.
@@ -130,6 +129,28 @@ async function deleteDir(dirPath: string) {
}
// Needed as Bazel artifacts are readonly and cannot be deleted otherwise.
- sh.chmod('-R', 'u+w', dirPath);
+ chmodRecursiveSync(dirPath, '0755');
await fs.promises.rm(dirPath, { recursive: true, force: true, maxRetries: 3 });
}
+
+/**
+ * Recursively changes the permissions (mode) of a directory and all its contents (files and subdirectories).
+ * @param startPath The starting directory path.
+ * @param mode The new permissions mode (e.g., 0755).
+ */
+function chmodRecursiveSync(startPath: string, mode: string): void {
+ chmodSync(startPath, mode);
+
+ const files = readdirSync(startPath);
+
+ for (const file of files) {
+ const filePath = join(startPath, file);
+ const stat = lstatSync(filePath);
+
+ if (stat.isDirectory()) {
+ chmodRecursiveSync(filePath, mode);
+ } else {
+ chmodSync(filePath, mode);
+ }
+ }
+}
diff --git a/scripts/templates/contributing.ejs b/scripts/templates/contributing.ejs
index b5bb997911ce..745d6d3500d2 100644
--- a/scripts/templates/contributing.ejs
+++ b/scripts/templates/contributing.ejs
@@ -291,15 +291,3 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
[stackoverflow]: https://stackoverflow.com/questions/tagged/angular-devkit
-## Updating the Public API
-Our Public API surface is tracked using golden files.
-
-You check all golden files by running:
-```bash
-pnpm public-api:check
-```
-
-If you modified the public API, the test will fail. To update the golden files you need to run:
-```bash
-pnpm public-api:update
-```