New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

copypack

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

copypack - npm Package Compare versions

Comparing version

to
1.0.7

dist/utils.d.ts

88

dist/cli.js
#!/usr/bin/env node
import ts from "typescript";
import { run } from "./copypack.js";
const [relativeProjectPath, ...sourcePackages] = ts.sys.args;
if (!relativeProjectPath) {
throw new Error("Missing relative project path");
import { run, watch } from "./copypack.js";
import { parseArgs } from "node:util";
import { resolve } from "node:path";
import { greenColor, redColor } from "./utils.js";
import { readFileSync } from "node:fs";
const cliArgsOptions = {
strict: true,
options: {
source: {
type: "string",
short: "s",
default: process.cwd(),
},
target: {
type: "string",
short: "t",
},
matchers: {
type: "string",
short: "m",
multiple: true,
default: ["packages/*/package.json"],
},
watch: {
type: "boolean",
short: "w",
},
version: {
type: "boolean",
short: "v",
},
help: {
type: "boolean",
short: "h",
},
},
};
const { values: { help, source, target, matchers, watch: watchMode, version: versionMode, }, } = parseArgs(cliArgsOptions);
const version = loadPackageJson().version;
if (versionMode) {
console.log(version);
process.exit(0);
}
if (!sourcePackages.length) {
sourcePackages.push("packages/*/package.json");
if (help) {
printHelp();
process.exit(0);
}
run(ts.sys.getCurrentDirectory(), relativeProjectPath, sourcePackages);
console.log(greenColor(`Running to copypack version: ${version}`));
if (!matchers) {
console.log(redColor("Missing matchers"));
process.exit(1);
}
if (!source) {
console.log(redColor("Missing source project path"));
process.exit(1);
}
if (!target) {
console.log(redColor("Missing target project path"));
process.exit(1);
}
if (watchMode) {
watch(resolve(source), resolve(target), matchers);
}
else {
run(resolve(source), resolve(target), matchers);
}
function printHelp() {
console.log(`
Usage: copypack [options]
Options:
-s, --source <path> Source project path (default: current working directory)
-t, --target <path> Target project path
-m, --matchers <glob> Ts based glob patterns to match package.json files (default: packages/*/package.json) (multiple)
-w, --watch Watch mode
-v, --version Print copypack version
-h, --help Print this message
`);
}
function loadPackageJson() {
return JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
}
//# sourceMappingURL=cli.js.map

3

dist/copypack.d.ts

@@ -1,2 +0,3 @@

export declare function run(context: string, targetProjectRelativePath: string, sourcePackagesFilter: string[]): void;
export declare function watch(sourceProjectPath: string, targetProjectPath: string, sourcePackagesMatchers: string[]): void;
export declare function run(sourceProjectPath: string, targetProjectPath: string, sourcePackagesMatchers: string[]): void;
//# sourceMappingURL=copypack.d.ts.map
import ts from "typescript";
import fs from "node:fs";
import path from "node:path";
export function run(context, targetProjectRelativePath, sourcePackagesFilter) {
const targetProjectPath = path.join(context, targetProjectRelativePath);
import watcher from "@parcel/watcher";
import { debounce, greenColor, darkGrayColor, redColor } from "./utils.js";
export function watch(sourceProjectPath, targetProjectPath, sourcePackagesMatchers) {
const debounceTime = 1000;
const tryRun = debounce(() => {
try {
console.log(greenColor("Running..."));
run(sourceProjectPath, targetProjectPath, sourcePackagesMatchers);
}
catch (error) {
console.error(error);
}
}, debounceTime);
watcher.subscribe(sourceProjectPath, (err) => {
if (err) {
console.error(err);
}
else {
log(redColor(`Changes detected, running in ${debounceTime / 1000} seconds.`));
tryRun();
}
});
}
export function run(sourceProjectPath, targetProjectPath, sourcePackagesMatchers) {
const targetNodeModulesPath = getExistingNodeModulesPath(targetProjectPath);
const packageJsonPaths = ts.sys.readDirectory(context, undefined, undefined, sourcePackagesFilter);
const packageJsonPaths = ts.sys.readDirectory(sourceProjectPath, undefined, undefined, sourcePackagesMatchers);
if (!targetNodeModulesPath) {

@@ -12,5 +34,5 @@ throw new Error(nodeModulesNotFound(targetProjectPath));

if (packageJsonPaths.length === 0) {
throw new Error(noPackageJsonFound(sourcePackagesFilter));
throw new Error(noPackageJsonFound(sourcePackagesMatchers));
}
console.log(start(packageJsonPaths.length, targetNodeModulesPath));
log(start(packageJsonPaths.length, targetNodeModulesPath));
for (const filePath of packageJsonPaths) {

@@ -21,25 +43,85 @@ try {

const currentPackageDirPath = path.dirname(filePath);
const targetPackageLocation = path.join(targetNodeModulesPath, pkg.name);
if (fs.existsSync(targetPackageLocation) &&
fs.statSync(targetPackageLocation).isDirectory()) {
fs.rmSync(targetPackageLocation, { recursive: true });
fs.mkdirSync(targetPackageLocation, { recursive: true });
fs.cpSync(currentPackageDirPath, targetPackageLocation, {
const targetPackagePath = path.join(targetNodeModulesPath, pkg.name);
const targetPackageJsonPath = path.join(targetPackagePath, "package.json");
if (fs.existsSync(targetPackagePath) &&
fs.statSync(targetPackagePath).isDirectory()) {
reportPackageDependencyChanges(targetPackageJsonPath, pkg);
fs.rmSync(targetPackagePath, { recursive: true });
fs.mkdirSync(targetPackagePath, { recursive: true });
fs.cpSync(currentPackageDirPath, targetPackagePath, {
recursive: true,
});
console.log(copied(pkg.name));
log(greenColor(copied(pkg.name)));
}
else {
console.log(skipped(pkg.name, "does not exist in target node_modules"));
log(darkGrayColor(skipped(pkg.name, "does not exist in target node_modules")));
}
}
else {
console.log(skipped(filePath, "no package name"));
log(redColor(skipped(filePath, "no package name")));
}
}
catch (error) {
console.log(skipped(filePath, "error while reading or parsing package.json", error));
log(redColor(skipped(filePath, "error while reading or parsing package.json", error)));
}
}
}
function reportPackageDependencyChanges(targetPackageJsonPath, pkg) {
const targetPkg = JSON.parse(ts.sys.readFile(targetPackageJsonPath) || "null");
if (!targetPkg) {
throw new Error(`Could not read ${targetPackageJsonPath}`);
}
reportChangesInDependencies(pkg.dependencies || {}, targetPkg.dependencies || {}, "dependencies");
reportChangesInDependencies(pkg.devDependencies || {}, targetPkg.devDependencies || {}, "devDependencies");
reportChangesInDependencies(pkg.peerDependencies || {}, targetPkg.peerDependencies || {}, "peerDependencies");
reportChangesInDependencies(pkg.optionalDependencies || {}, targetPkg.optionalDependencies || {}, "optionalDependencies");
}
function reportChangesInDependencies(currentDependencies, targetDependencies, key) {
const currentDependencyNames = new Set(Object.keys(currentDependencies));
const targetDependencyNames = new Set(Object.keys(targetDependencies));
const addedDependencies = [];
const removedDependencies = [];
const updatedDependencies = [];
if (currentDependencyNames.size || targetDependencyNames.size) {
log(`Checking changes in ${key}...`);
}
for (const dependencyName of currentDependencyNames) {
if (!targetDependencyNames.has(dependencyName)) {
addedDependencies.push({
dependencyName,
version: currentDependencies[dependencyName],
});
}
else if (currentDependencies[dependencyName] !== targetDependencies[dependencyName]) {
updatedDependencies.push({
dependencyName,
currentVersion: currentDependencies[dependencyName],
targetVersion: targetDependencies[dependencyName],
});
}
}
for (const dependencyName of targetDependencyNames) {
if (!currentDependencyNames.has(dependencyName)) {
removedDependencies.push(dependencyName);
}
}
if (removedDependencies.length > 0) {
log("Removed dependencies:");
for (const removedDependency of removedDependencies) {
log(removedDependency);
}
}
if (addedDependencies.length > 0) {
log("Added dependencies:");
for (const addedDependency of addedDependencies) {
log(`${addedDependency.dependencyName}: ${addedDependency.version}`);
}
}
if (updatedDependencies.length > 0) {
log("Updated dependencies:");
for (const updatedDependency of updatedDependencies) {
log(`${updatedDependency.dependencyName}: ${updatedDependency.currentVersion} -> ${updatedDependency.targetVersion}`);
}
}
}
function getExistingNodeModulesPath(targetProjectPath) {

@@ -55,7 +137,8 @@ const targetNodeModulesPath = path.join(targetProjectPath, "node_modules");

}
const log = (message) => console.log(message);
const copied = (pkg) => `COPIED: ${pkg}`;
const skipped = (pkg, reason, error) => `SKIPPED: ${pkg} (${reason})${error ? `\n${error}` : ""}`;
const start = (count, path) => `Start copying ${count === 1 ? "package" : "packages"} to ${path}`;
const start = (count, path) => `Start copying ${count} ${count === 1 ? "package" : "packages"} to ${path}`;
const nodeModulesNotFound = (path) => `node_modules does not exist or not a directory in: ${path}`;
const noPackageJsonFound = (filters) => `No package.json files found for the given patterns [${filters}]`;
//# sourceMappingURL=copypack.js.map

@@ -8,5 +8,3 @@ import { run } from "./copypack.js";

try {
run(path.join(testDirAbs, "source-package"), "../target-package", [
"packages/*/package.json",
]);
run(path.join(testDirAbs, "source-package"), path.join(testDirAbs, "target-package"), ["packages/*/package.json"]);
const content = fs.readFileSync(path.join(testDirAbs, "target-package", "node_modules", "source-package", "file.js"), "utf8");

@@ -13,0 +11,0 @@ if (content !== "// this is the file from the source package!") {

{
"name": "copypack",
"version": "1.0.6",
"version": "1.0.7",
"description": "like links but copies",

@@ -19,5 +19,7 @@ "type": "module",

"dependencies": {
"@parcel/watcher": "^2.1.0",
"@types/node": "^20.1.5",
"type-fest": "^3.10.0",
"typescript": "^5.0.4"
}
}
#!/usr/bin/env node
import ts from "typescript";
import { run } from "./copypack.js";
import { run, watch } from "./copypack.js";
import { parseArgs, ParseArgsConfig } from "node:util";
import { resolve } from "node:path";
import { greenColor, redColor } from "./utils.js";
import { readFileSync } from "node:fs";
const [relativeProjectPath, ...sourcePackages] = ts.sys.args;
const cliArgsOptions = {
strict: true,
options: {
source: {
type: "string" as const,
short: "s",
default: process.cwd(),
},
target: {
type: "string" as const,
short: "t",
},
matchers: {
type: "string" as const,
short: "m",
multiple: true,
default: ["packages/*/package.json"] as string[],
},
watch: {
type: "boolean" as const,
short: "w",
},
version: {
type: "boolean" as const,
short: "v",
},
help: {
type: "boolean" as const,
short: "h",
},
},
} as const satisfies ParseArgsConfig;
if (!relativeProjectPath) {
throw new Error("Missing relative project path");
const {
values: {
help,
source,
target,
matchers,
watch: watchMode,
version: versionMode,
},
} = parseArgs(cliArgsOptions);
const version = loadPackageJson().version;
if (versionMode) {
console.log(version);
process.exit(0);
}
if (!sourcePackages.length) {
sourcePackages.push("packages/*/package.json");
if (help) {
printHelp();
process.exit(0);
}
run(ts.sys.getCurrentDirectory(), relativeProjectPath, sourcePackages);
console.log(greenColor(`Running to copypack version: ${version}`));
if (!matchers) {
console.log(redColor("Missing matchers"));
process.exit(1);
}
if (!source) {
console.log(redColor("Missing source project path"));
process.exit(1);
}
if (!target) {
console.log(redColor("Missing target project path"));
process.exit(1);
}
if (watchMode) {
watch(resolve(source), resolve(target), matchers);
} else {
run(resolve(source), resolve(target), matchers);
}
function printHelp() {
console.log(`
Usage: copypack [options]
Options:
-s, --source <path> Source project path (default: current working directory)
-t, --target <path> Target project path
-m, --matchers <glob> Ts based glob patterns to match package.json files (default: packages/*/package.json) (multiple)
-w, --watch Watch mode
-v, --version Print copypack version
-h, --help Print this message
`);
}
function loadPackageJson(): { version: string } {
return JSON.parse(
readFileSync(new URL("../package.json", import.meta.url), "utf8")
);
}

@@ -11,5 +11,7 @@ import { run } from "./copypack.js";

try {
run(path.join(testDirAbs, "source-package"), "../target-package", [
"packages/*/package.json",
]);
run(
path.join(testDirAbs, "source-package"),
path.join(testDirAbs, "target-package"),
["packages/*/package.json"]
);
const content = fs.readFileSync(

@@ -16,0 +18,0 @@ path.join(

import ts from "typescript";
import fs from "node:fs";
import path from "node:path";
import watcher from "@parcel/watcher";
import type { PackageJson } from "type-fest";
import { debounce, greenColor, darkGrayColor, redColor } from "./utils.js";
export function watch(
sourceProjectPath: string,
targetProjectPath: string,
sourcePackagesMatchers: string[]
) {
const debounceTime = 1000;
const tryRun = debounce(() => {
try {
console.log(greenColor("Running..."));
run(sourceProjectPath, targetProjectPath, sourcePackagesMatchers);
} catch (error) {
console.error(error);
}
}, debounceTime);
watcher.subscribe(sourceProjectPath, (err) => {
if (err) {
console.error(err);
} else {
log(
redColor(`Changes detected, running in ${debounceTime / 1000} seconds.`)
);
tryRun();
}
});
}
export function run(
context: string,
targetProjectRelativePath: string,
sourcePackagesFilter: string[]
sourceProjectPath: string,
targetProjectPath: string,
sourcePackagesMatchers: string[]
) {
const targetProjectPath = path.join(context, targetProjectRelativePath);
const targetNodeModulesPath = getExistingNodeModulesPath(targetProjectPath);
const packageJsonPaths = ts.sys.readDirectory(
context,
sourceProjectPath,
undefined,
undefined,
sourcePackagesFilter
sourcePackagesMatchers
);

@@ -24,6 +53,6 @@

if (packageJsonPaths.length === 0) {
throw new Error(noPackageJsonFound(sourcePackagesFilter));
throw new Error(noPackageJsonFound(sourcePackagesMatchers));
}
console.log(start(packageJsonPaths.length, targetNodeModulesPath));
log(start(packageJsonPaths.length, targetNodeModulesPath));

@@ -35,27 +64,37 @@ for (const filePath of packageJsonPaths) {

const currentPackageDirPath = path.dirname(filePath);
const targetPackageLocation = path.join(
targetNodeModulesPath,
pkg.name
const targetPackagePath = path.join(targetNodeModulesPath, pkg.name);
const targetPackageJsonPath = path.join(
targetPackagePath,
"package.json"
);
if (
fs.existsSync(targetPackageLocation) &&
fs.statSync(targetPackageLocation).isDirectory()
fs.existsSync(targetPackagePath) &&
fs.statSync(targetPackagePath).isDirectory()
) {
fs.rmSync(targetPackageLocation, { recursive: true });
fs.mkdirSync(targetPackageLocation, { recursive: true });
fs.cpSync(currentPackageDirPath, targetPackageLocation, {
reportPackageDependencyChanges(targetPackageJsonPath, pkg);
fs.rmSync(targetPackagePath, { recursive: true });
fs.mkdirSync(targetPackagePath, { recursive: true });
fs.cpSync(currentPackageDirPath, targetPackagePath, {
recursive: true,
});
console.log(copied(pkg.name));
log(greenColor(copied(pkg.name)));
} else {
console.log(
skipped(pkg.name, "does not exist in target node_modules")
log(
darkGrayColor(
skipped(pkg.name, "does not exist in target node_modules")
)
);
}
} else {
console.log(skipped(filePath, "no package name"));
log(redColor(skipped(filePath, "no package name")));
}
} catch (error) {
console.log(
skipped(filePath, "error while reading or parsing package.json", error)
log(
redColor(
skipped(
filePath,
"error while reading or parsing package.json",
error
)
)
);

@@ -66,2 +105,102 @@ }

function reportPackageDependencyChanges(
targetPackageJsonPath: string,
pkg: PackageJson
) {
const targetPkg = JSON.parse(
ts.sys.readFile(targetPackageJsonPath) || "null"
) as PackageJson | null;
if (!targetPkg) {
throw new Error(`Could not read ${targetPackageJsonPath}`);
}
reportChangesInDependencies(
pkg.dependencies || {},
targetPkg.dependencies || {},
"dependencies"
);
reportChangesInDependencies(
pkg.devDependencies || {},
targetPkg.devDependencies || {},
"devDependencies"
);
reportChangesInDependencies(
pkg.peerDependencies || {},
targetPkg.peerDependencies || {},
"peerDependencies"
);
reportChangesInDependencies(
pkg.optionalDependencies || {},
targetPkg.optionalDependencies || {},
"optionalDependencies"
);
}
function reportChangesInDependencies(
currentDependencies: Partial<Record<string, string>>,
targetDependencies: Partial<Record<string, string>>,
key:
| "dependencies"
| "devDependencies"
| "peerDependencies"
| "optionalDependencies"
) {
const currentDependencyNames = new Set(Object.keys(currentDependencies));
const targetDependencyNames = new Set(Object.keys(targetDependencies));
const addedDependencies = [];
const removedDependencies = [];
const updatedDependencies = [];
if (currentDependencyNames.size || targetDependencyNames.size) {
log(`Checking changes in ${key}...`);
}
for (const dependencyName of currentDependencyNames) {
if (!targetDependencyNames.has(dependencyName)) {
addedDependencies.push({
dependencyName,
version: currentDependencies[dependencyName],
});
} else if (
currentDependencies[dependencyName] !== targetDependencies[dependencyName]
) {
updatedDependencies.push({
dependencyName,
currentVersion: currentDependencies[dependencyName],
targetVersion: targetDependencies[dependencyName],
});
}
}
for (const dependencyName of targetDependencyNames) {
if (!currentDependencyNames.has(dependencyName)) {
removedDependencies.push(dependencyName);
}
}
if (removedDependencies.length > 0) {
log("Removed dependencies:");
for (const removedDependency of removedDependencies) {
log(removedDependency);
}
}
if (addedDependencies.length > 0) {
log("Added dependencies:");
for (const addedDependency of addedDependencies) {
log(`${addedDependency.dependencyName}: ${addedDependency.version}`);
}
}
if (updatedDependencies.length > 0) {
log("Updated dependencies:");
for (const updatedDependency of updatedDependencies) {
log(
`${updatedDependency.dependencyName}: ${updatedDependency.currentVersion} -> ${updatedDependency.targetVersion}`
);
}
}
}
function getExistingNodeModulesPath(targetProjectPath: string) {

@@ -79,2 +218,3 @@ const targetNodeModulesPath = path.join(targetProjectPath, "node_modules");

const log = (message: string) => console.log(message);
const copied = (pkg: string) => `COPIED: ${pkg}`;

@@ -84,3 +224,3 @@ const skipped = (pkg: string, reason: string, error?: unknown) =>

const start = (count: number, path: string) =>
`Start copying ${count === 1 ? "package" : "packages"} to ${path}`;
`Start copying ${count} ${count === 1 ? "package" : "packages"} to ${path}`;
const nodeModulesNotFound = (path: string) =>

@@ -87,0 +227,0 @@ `node_modules does not exist or not a directory in: ${path}`;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet