From e2f4c2f073974b57ce458db3f0e9eaba0d00e82e Mon Sep 17 00:00:00 2001 From: Roman Vyakhirev Date: Thu, 29 Oct 2026 14:16:28 +0100 Subject: [PATCH] chore(automation-utils): replace shelljs file helpers with node:fs Use node:fs/promises for rm, mkdir and cp in automation/utils and the charts-web and data-widgets scripts, and remove shelljs from automation/utils. shell.ts keeps small helpers where node:fs has no direct equivalent: - findFiles: glob that fails when a pattern matches nothing, like shelljs find - move: rename with a copy and remove fallback across file systems, like mv - makeWritableRecursive: chmod -R a+rw zip() now switches directories with process.chdir instead of pushd/popd. --- automation/utils/bin/rui-create-gh-release.ts | 7 +- .../utils/bin/rui-include-oss-in-artifact.ts | 5 +- automation/utils/bin/rui-oss-clearance.ts | 10 +-- automation/utils/package.json | 1 - automation/utils/src/monorepo.ts | 13 ++-- automation/utils/src/mpk.ts | 6 +- automation/utils/src/oss-clearance.ts | 18 ++--- automation/utils/src/shell.ts | 63 +++++++++++------ automation/utils/src/steps.ts | 67 +++++++++---------- .../modules/data-widgets/scripts/start.ts | 4 +- .../charts-web/scripts/build.mts | 24 ++++--- pnpm-lock.yaml | 18 +---- 12 files changed, 121 insertions(+), 115 deletions(-) diff --git a/automation/utils/bin/rui-create-gh-release.ts b/automation/utils/bin/rui-create-gh-release.ts index 412269ffe0..88146dc43a 100755 --- a/automation/utils/bin/rui-create-gh-release.ts +++ b/automation/utils/bin/rui-create-gh-release.ts @@ -4,7 +4,7 @@ import { updateChangelogsAndCreatePR } from "../src/changelog.ts"; import { gh } from "../src/github.ts"; import { addRemoteWithAuthentication } from "../src/index.ts"; import { getPublishedInfo } from "../src/package-info.ts"; -import { exec, find } from "../src/shell.ts"; +import { exec, findFiles } from "../src/shell.ts"; async function resolveChangelogBranch(releaseTag: string, remoteName: string): Promise { const { stdout } = await exec(`git rev-parse --abbrev-ref HEAD`, { stdio: "pipe" }); @@ -75,10 +75,7 @@ async function main(): Promise { // Create release console.log("Creating Github release..."); - const mpk = find(join(path, "dist", version, "*.mpk")).toString(); - if (!mpk) { - throw new Error("MPK file not found"); - } + const [mpk] = findFiles(join(path, "dist", version, "*.mpk")); await gh.createGithubReleaseFrom({ title: `${appName} v${version}`, diff --git a/automation/utils/bin/rui-include-oss-in-artifact.ts b/automation/utils/bin/rui-include-oss-in-artifact.ts index 015df0a0b4..8be75baad4 100755 --- a/automation/utils/bin/rui-include-oss-in-artifact.ts +++ b/automation/utils/bin/rui-include-oss-in-artifact.ts @@ -1,12 +1,11 @@ #!/usr/bin/env node -import { mkdtemp, stat } from "node:fs/promises"; +import { mkdtemp, rm, stat } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import chalk from "chalk"; import { gh } from "../src/github.ts"; import { includeReadmeOssIntoMpk } from "../src/oss-clearance.ts"; -import { rm } from "../src/shell.ts"; /** * This script processes GitHub release artifacts to include READMEOSS HTML files into MPK files. @@ -107,7 +106,7 @@ async function main(): Promise { } finally { // Cleanup temp files console.log(chalk.gray("🧹 Cleaning up temporary files...")); - await rm("-rf", tmpFolder); + await rm(tmpFolder, { recursive: true, force: true }); } } diff --git a/automation/utils/bin/rui-oss-clearance.ts b/automation/utils/bin/rui-oss-clearance.ts index c8eb884b80..045201fde4 100755 --- a/automation/utils/bin/rui-oss-clearance.ts +++ b/automation/utils/bin/rui-oss-clearance.ts @@ -3,7 +3,8 @@ // Enable quiet mode for fetch calls to reduce logging noise process.env.FETCH_QUIET = "true"; -import { homedir } from "node:os"; +import { cp, mkdtemp, rm, stat } from "node:fs/promises"; +import { homedir, tmpdir } from "node:os"; import { basename, join } from "path"; import chalk from "chalk"; import enquirer from "enquirer"; @@ -331,8 +332,6 @@ async function handleIncludeAsEmbeddedAction(release: GitHubDraftRelease, readme printInfo(`Found MPK: ${mpkAsset.name} (${mpkAsset.size} bytes)`); // Create temp folder - const { mkdtemp } = await import("node:fs/promises"); - const { tmpdir } = await import("node:os"); const tmpFolder = await mkdtemp(join(tmpdir(), "mpk-oss-embed-")); const mpkPath = join(tmpFolder, mpkAsset.name); const htmlPath = join(tmpFolder, basename(readmeToInclude)); @@ -344,7 +343,6 @@ async function handleIncludeAsEmbeddedAction(release: GitHubDraftRelease, readme printProgressCheck("Download completed"); // Copy HTML to temp folder - const { cp } = await import("../src/shell.ts"); await cp(readmeToInclude, htmlPath); // Embed HTML into MPK @@ -353,7 +351,6 @@ async function handleIncludeAsEmbeddedAction(release: GitHubDraftRelease, readme printProgressCheck("Merge completed"); // Get modified MPK size - const { stat } = await import("node:fs/promises"); const modifiedMpkStats = await stat(mpkPath); const sizeDiff = modifiedMpkStats.size - mpkAsset.size; printInfo(`Modified MPK size: ${modifiedMpkStats.size} bytes (+${sizeDiff} bytes)`); @@ -400,8 +397,7 @@ async function handleIncludeAsEmbeddedAction(release: GitHubDraftRelease, readme } finally { // Cleanup temp files printProgress("Cleaning up temporary files..."); - const { rm } = await import("../src/shell.ts"); - await rm("-rf", tmpFolder); + await rm(tmpFolder, { recursive: true, force: true }); } } diff --git a/automation/utils/package.json b/automation/utils/package.json index ce59e31868..501ef05acd 100644 --- a/automation/utils/package.json +++ b/automation/utils/package.json @@ -66,7 +66,6 @@ "node-fetch": "^2.7.0", "ora": "^5.4.1", "peggy": "5.1.0", - "shelljs": "^0.8.5", "zod": "^3.25.76" } } diff --git a/automation/utils/src/monorepo.ts b/automation/utils/src/monorepo.ts index dcfb4f6ed5..a2f9575f0b 100644 --- a/automation/utils/src/monorepo.ts +++ b/automation/utils/src/monorepo.ts @@ -1,6 +1,8 @@ +import { cp, mkdir } from "node:fs/promises"; +import { basename } from "node:path"; import enquirer from "enquirer"; import { oraPromise } from "./cli-utils.ts"; -import { cp, exec, find, mkdir } from "./shell.ts"; +import { exec, findFiles } from "./shell.ts"; const { prompt } = enquirer; @@ -40,14 +42,15 @@ export async function resolvePackagePath(npmPackageName: string): Promise { const packages = await listPackages(packageNames); - const paths = [...find(packages.map(p => `${p.path}/dist/${p.version}/*.mpk`))]; - return paths; + return findFiles(...packages.map(p => `${p.path}/dist/${p.version}/*.mpk`)); } export async function copyMpkFiles(packageNames: string[], dest: string): Promise { const paths = await getMpkPaths(packageNames); - mkdir("-p", dest); - cp(paths, dest); + await mkdir(dest, { recursive: true }); + for (const path of paths) { + await cp(path, `${dest}/${basename(path)}`); + } } export async function selectPackage(): Promise { diff --git a/automation/utils/src/mpk.ts b/automation/utils/src/mpk.ts index d997cb3796..188354f5c7 100644 --- a/automation/utils/src/mpk.ts +++ b/automation/utils/src/mpk.ts @@ -1,6 +1,6 @@ import { basename, join } from "path"; import type { ModuleInfo } from "./package-info.ts"; -import { exec, find } from "./shell.ts"; +import { exec, findFiles } from "./shell.ts"; import type { Version } from "./version.ts"; async function ensureMxBuildDockerImageExists(version: string): Promise { @@ -28,7 +28,7 @@ export async function createModuleMpkInDocker( console.log(`Creating module ${moduleName} using mxbuild:${version}...`); // Build testProject via mxbuild - const mprPath = find(`${sourceDir}/*.mpr`)[0]; + const [mprPath] = findFiles(`${sourceDir}/*.mpr`); const projectFile = basename(mprPath); const args = [ // update widgets @@ -61,5 +61,5 @@ export async function createMPK(tmpFolder: string, info: ModuleInfo, excludeFile info.marketplace.minimumMXVersion, excludeFilesRegExp ); - return find(join(tmpFolder, info.mpkName))[0]; + return findFiles(join(tmpFolder, info.mpkName))[0]; } diff --git a/automation/utils/src/oss-clearance.ts b/automation/utils/src/oss-clearance.ts index 65cf1f56eb..56ae320732 100644 --- a/automation/utils/src/oss-clearance.ts +++ b/automation/utils/src/oss-clearance.ts @@ -1,12 +1,12 @@ import { createHash } from "node:crypto"; import { createReadStream } from "node:fs"; -import { mkdtemp, stat } from "node:fs/promises"; +import { cp, mkdir, mkdtemp, rm, stat } from "node:fs/promises"; import { homedir, tmpdir } from "node:os"; import { pipeline } from "node:stream/promises"; import { basename, join, parse } from "path"; import { globSync } from "glob"; import type { GitHubReleaseAsset } from "./github.ts"; -import { chmod, cp, exec, mkdir, mv, rm, unzip, zip } from "./shell.ts"; +import { exec, makeWritableRecursive, move, unzip, zip } from "./shell.ts"; export async function computeSha256(filePath: string): Promise { const hash = createHash("sha256"); @@ -64,7 +64,7 @@ export async function createSBomGeneratorFolderStructure( ): Promise<[folder: string, assetPath: string]> { const tmpFolder = await mkdtemp(join(tmpdir(), "tmp_OSS_Clearance_Artifacts_")); const artifactsFolder = join(tmpFolder, "SBOM_GENERATOR", assetNameAndVersion); - await mkdir("-p", artifactsFolder); + await mkdir(artifactsFolder, { recursive: true }); return [tmpFolder, join(artifactsFolder, `${assetNameAndVersion}.mpk`)]; } @@ -92,10 +92,10 @@ export async function generateSBomArtifactsInFolder( const ossArtifactZip = join(resultsFolder, archiveName); // move to final destination - await mv(ossArtifactZip, finalPath); + await move(ossArtifactZip, finalPath); // removing tmp folder - await rm("-rf", tmpFolder); + await rm(tmpFolder, { recursive: true, force: true }); } export async function includeReadmeOssIntoMpk(readmeOssPath: string, mpkPath: string): Promise { @@ -103,16 +103,16 @@ export async function includeReadmeOssIntoMpk(readmeOssPath: string, mpkPath: st const unzipTarget = join(mpkEntry.dir, "tmp"); // unzip - rm("-rf", unzipTarget); + await rm(unzipTarget, { recursive: true, force: true }); await unzip(mpkPath, unzipTarget); - chmod("-R", "a+rw", unzipTarget); + await makeWritableRecursive(unzipTarget); // Copy the READMEOSS file to the target directory - cp(readmeOssPath, unzipTarget); + await cp(readmeOssPath, join(unzipTarget, basename(readmeOssPath))); // zip it back await zip(unzipTarget, mpkPath); // remove tmp folder - rm("-rf", unzipTarget); + await rm(unzipTarget, { recursive: true, force: true }); } diff --git a/automation/utils/src/shell.ts b/automation/utils/src/shell.ts index 76975f2525..a011fa4ad1 100644 --- a/automation/utils/src/shell.ts +++ b/automation/utils/src/shell.ts @@ -1,17 +1,8 @@ +import { globSync } from "node:fs"; +import { access, chmod, cp, lstat, readdir, rename, rm } from "node:fs/promises"; +import { join } from "node:path"; import crossZip from "cross-zip"; import execa from "execa"; -import shelljs from "shelljs"; - -// shelljs is CommonJS, so named imports are not available under native ESM -const { config } = shelljs; - -// Enable fast fail for all shelljs commands -config.fatal = true; -// Only the file system helpers in use are exported; commands run through execa (see exec below). -// KNOWN ISSUES: -// - mv don't throw error https://github.com/shelljs/shelljs/issues/878 -export const { chmod, cp, find, mkdir, mv, rm } = shelljs; -const { ls, popd, pushd } = shelljs; export function exec(command: string, options?: execa.Options): execa.ExecaChildProcess { const { stdio = "inherit", ...execaOptions } = options ?? {}; @@ -19,19 +10,53 @@ export function exec(command: string, options?: execa.Options): execa.ExecaChild return execa(command, { shell: true, stdio, ...execaOptions }); } -export function ensureFileExists(file: string): void { - const silentState = config.silent; - config.silent = true; - ls(file); - config.silent = silentState; +export async function ensureFileExists(file: string): Promise { + await access(file); +} + +/** Expand glob patterns, failing when a pattern matches nothing. */ +export function findFiles(...patterns: string[]): string[] { + return patterns.flatMap(pattern => { + const matches = globSync(pattern); + if (matches.length === 0) { + throw new Error(`No files match '${pattern}'`); + } + return matches; + }); +} + +/** Move a file or directory, falling back to copy and remove when rename crosses file systems. */ +export async function move(source: string, dest: string): Promise { + try { + await rename(source, dest); + } catch (error) { + if ((error as NodeJS.ErrnoException).code !== "EXDEV") { + throw error; + } + await cp(source, dest, { recursive: true }); + await rm(source, { recursive: true, force: true }); + } +} + +/** Add read and write permissions for everyone to a directory and everything inside it (`chmod -R a+rw`). */ +export async function makeWritableRecursive(dir: string): Promise { + const entries = await readdir(dir, { recursive: true }); + for (const path of [dir, ...entries.map(entry => join(dir, entry))]) { + const stats = await lstat(path); + if (!stats.isSymbolicLink()) { + // eslint-disable-next-line no-bitwise -- permission bits are a bitmask + await chmod(path, stats.mode | 0o666); + } + } } export async function zip(dir: string, fileName: string): Promise { return new Promise((resolve, reject) => { // cross-zip has no cwd option, it zips relative to the process directory - pushd("-q", dir); + const cwd = process.cwd(); + process.chdir(dir); crossZip.zip(".", fileName, err => { - popd("-q"); + process.chdir(cwd); if (err) { reject(err); } else { diff --git a/automation/utils/src/steps.ts b/automation/utils/src/steps.ts index d3b5dad673..971611d42c 100644 --- a/automation/utils/src/steps.ts +++ b/automation/utils/src/steps.ts @@ -1,5 +1,5 @@ -import { readFile, writeFile } from "node:fs/promises"; -import { dirname, join, parse, relative, resolve } from "path"; +import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; +import { basename, dirname, join, parse, relative, resolve } from "path"; import chalk from "chalk"; import { type CommonBuildConfig, @@ -13,7 +13,7 @@ import { copyMpkFiles, getMpkPaths } from "./monorepo.ts"; import { createModuleMpkInDocker } from "./mpk.ts"; import type { ModuleInfo, PackageInfo, WidgetInfo } from "./package-info.ts"; import { addFilesToPackageXml, type PackageType } from "./package-xml.ts"; -import { chmod, cp, ensureFileExists, exec, mkdir, rm, unzip, zip } from "./shell.ts"; +import { ensureFileExists, exec, makeWritableRecursive, move, unzip, zip } from "./shell.ts"; type Step = (params: { info: Info; config: Config }) => Promise; @@ -39,7 +39,7 @@ export const logStep = (name: string): void => console.info(`[step]: ${name}`); export async function removeDist({ config }: CommonStepParams): Promise { logStep("Remove dist"); - rm("-rf", config.paths.dist); + await rm(config.paths.dist, { recursive: true, force: true }); } export async function cloneTestProject({ info, config }: CommonStepParams): Promise { @@ -47,7 +47,7 @@ export async function cloneTestProject({ info, config }: CommonStepParams): Prom const { testProject } = info; const clone = process.env.CI ? cloneRepoShallow : cloneRepo; - rm("-rf", config.paths.targetProject); + await rm(config.paths.targetProject, { recursive: true, force: true }); await clone({ remoteUrl: testProject!.githubUrl, branch: testProject!.branchName, @@ -86,10 +86,10 @@ export function copyFilesToMpk( console.log(`Input MPK: ${relative(paths.package, mpk)}`); - ensureFileExists(output.files.mpk); + await ensureFileExists(output.files.mpk); - rm("-rf", target); - mkdir("-p", target); + await rm(target, { recursive: true, force: true }); + await mkdir(target, { recursive: true }); console.info("Unzip module mpk"); await unzip(mpk, target); @@ -99,8 +99,8 @@ export function copyFilesToMpk( const dest = resolve(target, file.pkgPath); console.info(`Copy ${join(file.filePath)} to ${join(file.pkgPath)}`); - mkdir("-p", dirname(dest)); - cp(source, dest); + await mkdir(dirname(dest), { recursive: true }); + await cp(source, dest); } console.info(`Update file entries in package.xml`); @@ -111,9 +111,9 @@ export function copyFilesToMpk( ); console.info("Create module zip archive"); - rm(mpk); + await rm(mpk); await zip(target, mpk); - rm("-rf", target); + await rm(target, { recursive: true, force: true }); }; } @@ -124,17 +124,16 @@ export async function copyThemesourceToProject({ config }: ModuleStepParams): Pr const { output, paths } = config; console.info("Remove module themesource in targetProject"); - rm("-rf", output.dirs.themesource); + await rm(output.dirs.themesource, { recursive: true, force: true }); console.info("Copy module themesource to targetProject"); - mkdir("-p", output.dirs.themesource); - cp("-R", `${paths.themesource}/*`, output.dirs.themesource); + await cp(paths.themesource, output.dirs.themesource, { recursive: true }); } export function copyActionsFiles(files: string[]): (params: ModuleStepParams) => Promise { return async ({ config }) => { logStep("Copy JS Action(s) files"); const { paths, output } = config; - mkdir("-p", join(output.dirs.javascriptsource, "actions")); + await mkdir(join(output.dirs.javascriptsource, "actions"), { recursive: true }); for (const file of files) { const src = join(paths.javascriptsource, "actions", file); @@ -175,28 +174,30 @@ async function insertWidgetsIntoMpk( const packageXml = join(tmpDir, "package.xml"); const packageFilePaths = widgetPaths.map(p => `widgets/${parse(p).base}`); - rm("-rf", tmpDir); + await rm(tmpDir, { recursive: true, force: true }); console.info("Unzip module mpk"); await unzip(mpk, tmpDir); - mkdir("-p", widgetsOut); - chmod("-R", "a+rw", tmpDir); + await mkdir(widgetsOut, { recursive: true }); + await makeWritableRecursive(tmpDir); console.info(`Add ${widgetPaths.length} widgets to ${mpkEntry.base}`); - cp(widgetPaths, widgetsOut); + for (const widgetPath of widgetPaths) { + await cp(widgetPath, join(widgetsOut, basename(widgetPath))); + } if (additionalFiles) { for (const { src, destRelative } of additionalFiles) { - cp(src, join(tmpDir, destRelative)); + await cp(src, join(tmpDir, destRelative)); } } console.info(`Add file entries to package.xml`); await addFilesToPackageXml(packageXml, packageFilePaths, "modelerProject"); - rm(mpk); + await rm(mpk); console.info("Create module zip archive"); await zip(tmpDir, mpk); - rm("-rf", tmpDir); + await rm(tmpDir, { recursive: true, force: true }); } export async function addWidgetsToMpk({ config }: ModuleStepParams): Promise { @@ -229,10 +230,8 @@ export async function moveModuleToDist({ info, config }: ModuleStepParams): Prom const { output, paths } = config; console.info(`Move ${info.mpkName} to dist`); - mkdir("-p", join(paths.dist, info.version.format())); - // Can't use mv because of https://github.com/shelljs/shelljs/issues/878 - cp(output.files.modulePackage, output.files.mpk); - rm(output.files.modulePackage); + await mkdir(join(paths.dist, info.version.format()), { recursive: true }); + await move(output.files.modulePackage, output.files.mpk); } export async function pushUpdateToTestProject({ info, config }: ModuleStepParams): Promise { @@ -264,7 +263,7 @@ export async function pushUpdateToTestProject({ info, config }: ModuleStepParams export async function writeModuleVersion({ config, info }: ModuleStepParams): Promise { logStep("Write module version"); - mkdir("-p", config.output.dirs.themesource); + await mkdir(config.output.dirs.themesource, { recursive: true }); await writeFile(join(config.output.dirs.themesource, ".version"), info.version.format()); } @@ -274,9 +273,9 @@ export async function copyModuleLicense({ config }: ModuleStepParams): Promise { @@ -284,10 +283,10 @@ export async function writeVersionAndLicenseToJSActions({ config, info }: Module const { paths, output } = config; const license = join(paths.package, "LICENSE"); - ensureFileExists(license); + await ensureFileExists(license); - mkdir("-p", output.dirs.javascriptsource); - cp(license, output.dirs.javascriptsource); + await mkdir(output.dirs.javascriptsource, { recursive: true }); + await cp(license, join(output.dirs.javascriptsource, "LICENSE")); await writeFile(join(config.output.dirs.javascriptsource, ".version"), info.version.format()); } diff --git a/packages/modules/data-widgets/scripts/start.ts b/packages/modules/data-widgets/scripts/start.ts index f3d5f796cd..51e6d79f57 100755 --- a/packages/modules/data-widgets/scripts/start.ts +++ b/packages/modules/data-widgets/scripts/start.ts @@ -1,14 +1,14 @@ #!/usr/bin/env node +import { mkdir } from "node:fs/promises"; import { join } from "path"; import concurrently from "concurrently"; -import { mkdir } from "@mendix/automation-utils/shell"; import { getModuleConfigs } from "@mendix/automation-utils/utils"; async function main(): Promise { const [, config] = await getModuleConfigs(process.cwd()); - mkdir("-p", config.paths.targetProject); + await mkdir(config.paths.targetProject, { recursive: true }); await concurrently( [ diff --git a/packages/pluggableWidgets/charts-web/scripts/build.mts b/packages/pluggableWidgets/charts-web/scripts/build.mts index 64742ed7ab..031a1a1a60 100755 --- a/packages/pluggableWidgets/charts-web/scripts/build.mts +++ b/packages/pluggableWidgets/charts-web/scripts/build.mts @@ -1,9 +1,10 @@ #!/usr/bin/env node -import { cp, mkdir, rm, unzip, zip } from "@mendix/automation-utils/shell"; +import { unzip, zip } from "@mendix/automation-utils/shell"; import { logStep, removeDist, runWidgetSteps, type WidgetStepParams } from "@mendix/automation-utils/steps"; import { getWidgetInfo, listPackages } from "@mendix/automation-utils/utils"; -import { dirname, join } from "node:path"; +import { cp, mkdir, rm } from "node:fs/promises"; +import { basename, dirname, join } from "node:path"; // Charts specific steps @@ -16,7 +17,8 @@ async function repackChartWidgets({ config }: WidgetStepParams): Promise { const packages = await listPackages(dependencies); const widgets = await Promise.all(packages.map(({ path }) => getWidgetInfo(path))); - mkdir("-p", [paths.tmp, dirname(output.files.mpk)]); + await mkdir(paths.tmp, { recursive: true }); + await mkdir(dirname(output.files.mpk), { recursive: true }); console.info("Unpacking mpks and create correct file tree..."); for (const pkg of widgets) { @@ -24,17 +26,17 @@ async function repackChartWidgets({ config }: WidgetStepParams): Promise { const contentDir = join(paths.tmp, pkg.mxpackage.name); const pkgSource = join(contentDir, "com"); const pkgXml = join(contentDir, "package.xml"); - mkdir("-p", contentDir); + await mkdir(contentDir, { recursive: true }); await unzip(pkg.mpk, contentDir); - cp("-r", pkgSource, paths.tmp); - rm("-rf", pkgSource); - rm(pkgXml); + await cp(pkgSource, join(paths.tmp, "com"), { recursive: true }); + await rm(pkgSource, { recursive: true, force: true }); + await rm(pkgXml); } console.log("Copying package.xml..."); - cp(join(paths.package, "src", "package.xml"), join(paths.tmp, "package.xml")); + await cp(join(paths.package, "src", "package.xml"), join(paths.tmp, "package.xml")); console.log("Copying License.txt..."); - cp(join(paths.package, "../../../LICENSE"), join(paths.tmp, "License.txt")); + await cp(join(paths.package, "../../../LICENSE"), join(paths.tmp, "License.txt")); console.log("Creating mpk..."); await zip(paths.tmp, output.files.mpk); } @@ -49,8 +51,8 @@ async function main(): Promise { if (copyToProject) { logStep("Copy widget to targetProject"); const dir = join(config.paths.targetProject, "widgets"); - mkdir("-p", dir); - cp(config.output.files.mpk, dir); + await mkdir(dir, { recursive: true }); + await cp(config.output.files.mpk, join(dir, basename(config.output.files.mpk))); } } ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1eddfb4bcf..029d77e48f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,9 +219,6 @@ importers: peggy: specifier: 5.1.0 version: 5.1.0 - shelljs: - specifier: ^0.8.5 - version: 0.8.5 zod: specifier: ^3.25.76 version: 3.25.76 @@ -374,7 +371,7 @@ importers: version: link:../../shared/eslint-config-web-widgets '@mendix/pluggable-widgets-tools': specifier: 11.13.0 - version: 11.13.0(patch_hash=1879adf9f5f058d67d2e08e79916d5adce82416899758529f812f4207c064fed)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@24.12.4)(canvas@3.2.3)(eslint@10.13.0(jiti@2.6.1))(jest-util@30.4.1)(picomatch@4.0.5)(prettier@3.9.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tslib@2.8.1) + version: 11.13.0(patch_hash=1879adf9f5f058d67d2e08e79916d5adce82416899758529f812f4207c064fed)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@24.12.4)(canvas@3.2.3)(eslint@10.13.0(jiti@2.6.1))(jest-util@30.4.1)(prettier@3.9.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tslib@2.8.1) '@mendix/prettier-config-web-widgets': specifier: workspace:* version: link:../../shared/prettier-config-web-widgets @@ -399,7 +396,7 @@ importers: version: link:../../shared/eslint-config-web-widgets '@mendix/pluggable-widgets-tools': specifier: 11.13.0 - version: 11.13.0(patch_hash=1879adf9f5f058d67d2e08e79916d5adce82416899758529f812f4207c064fed)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@24.12.4)(canvas@3.2.3)(eslint@10.13.0(jiti@2.6.1))(jest-util@30.4.1)(prettier@3.9.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tslib@2.8.1) + version: 11.13.0(patch_hash=1879adf9f5f058d67d2e08e79916d5adce82416899758529f812f4207c064fed)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@24.12.4)(canvas@3.2.3)(eslint@10.13.0(jiti@2.6.1))(jest-util@30.4.1)(picomatch@4.0.5)(prettier@3.9.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tslib@2.8.1) '@mendix/prettier-config-web-widgets': specifier: workspace:* version: link:../../shared/prettier-config-web-widgets @@ -10441,11 +10438,6 @@ packages: resolution: {integrity: sha512-Jex+xw5Mg2qMZL3qnzXIfaxEtBaC4n7xifqaqtrZDdlheR70OGkydrPJWT0V1cA1k3nanC86x9FwAmQl6w3Klw==} engines: {node: '>=18'} - shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - shelljs@0.9.2: resolution: {integrity: sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==} engines: {node: '>=18'} @@ -20161,12 +20153,6 @@ snapshots: execa: 5.1.1 fast-glob: 3.3.3 - shelljs@0.8.5: - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - shelljs@0.9.2: dependencies: execa: 1.0.0