New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@pinpt/cli

Package Overview
Dependencies
Maintainers
4
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pinpt/cli - npm Package Compare versions

Comparing version
0.0.2
to
0.0.3
+128
lib/deploy.mjs
import fs from 'fs';
import path from 'path';
import FormData from 'form-data';
import AdmZip from 'adm-zip';
import vm from 'vm';
import tmp from 'tmp';
import picomatch from 'picomatch';
import ora from 'ora';
import c from 'kleur';
import progress from 'cli-progress';
import { debug, error, walkSync, apiRequest } from './util.mjs';
const createMatcher = (buf) => {
const tok = buf.toString().trim().split(/\n/);
const matchers = tok.filter(Boolean).map((c) => picomatch(c, { posixSlashes: true }));
return (filepath) => {
for (let c = 0; c < matchers.length; c++) {
if (matchers[c](filepath)) {
// console.log('MATCH ->', filepath);
return true;
}
}
// console.log('NOT MATCH ->', filepath);
return false;
};
};
// none of these files we actually need to build the app for deployment or to run it
const builtIns = createMatcher(`
node_modules/**
.git/**
.github/**
.next/**
.gitignore
.npmignore
.dockerignore
.prettierignore
.pinpointignore
README*
LICENSE*
prettier.config.js
**/*.zip
**/*.tar
**/*.gzip
`);
const createFilter = (basedir, matcher) => (filepath) => {
const fn = path.relative(basedir, filepath);
if (matcher) {
if (matcher(fn)) {
return false;
}
}
return builtIns(fn) === false;
};
const upload = async (fn, config) => {
const buf = fs.readFileSync(config);
const script = new vm.Script(buf.toString(), { filename: config });
const context = { module: { exports: {} } };
script.runInNewContext(context);
const siteId = context.module.exports.siteId;
if (!siteId) {
throw new Error(`No required siteId variable found in ${config}`);
}
const p = new progress.SingleBar({
format: '' + c.green('{bar}') + ' {percentage}% || {value}/{total} Chunks',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true,
clearOnComplete: true,
});
p.start(100, 0);
const spinner = ora('Validating ...');
const body = new FormData();
body.append('upload', fs.createReadStream(fn));
await apiRequest('', `/site/${siteId}/theme/upload2`, {
noSpinner: true,
method: 'POST',
body,
onProgress: (progress) => {
p.update(100 * progress.percent);
if (progress.percent === 1) {
p.stop();
spinner.start();
}
},
});
spinner.succeed(c.bold('Deployed ... 🚀'));
};
export const deploy = async ({ args }) => {
if (args && args[0] === 'deploy') {
const config = path.join(process.cwd(), 'pinpoint.config.js');
if (!fs.existsSync(config)) {
error(`Couldn't find ${config}. Please make sure you're running this command from a Pinpoint project`, true);
}
const tmpfile = tmp.fileSync();
const spinner = ora('Creating deployment package ...').start();
try {
const ignore = path.join(process.cwd(), '.pinpointignore');
let matcher = null;
if (fs.existsSync(ignore)) {
matcher = createMatcher(fs.readFileSync(ignore).toString());
}
const files = walkSync(process.cwd(), createFilter(process.cwd(), matcher));
const zip = new AdmZip();
files.forEach((fn) => {
debug(`Adding ${fn} to zip...`);
zip.addLocalFile(fn);
});
zip.writeZip(tmpfile.name);
spinner.succeed(c.bold('Created deployment package'));
await upload(tmpfile.name, config);
} catch (ex) {
spinner.fail(ex.message);
process.exit(1);
} finally {
tmpfile.removeCallback();
}
}
};
+2
-0

@@ -8,2 +8,3 @@ import { init } from './util.mjs';

import { signup } from './signup.mjs';
import { deploy } from './deploy.mjs';

@@ -18,2 +19,3 @@ export const run = async ({ meta, args, options, optionSpec, commandSpec }) => {

await logout({ meta, args, options, optionSpec, commandSpec });
await deploy({ meta, args, options, optionSpec, commandSpec });
};

@@ -9,5 +9,7 @@ import CFonts from 'cfonts';

import terminalLink from 'terminal-link';
import getstream from 'get-stream';
import si from 'systeminformation';
import c from 'kleur';
import { fileURLToPath } from 'url';
import FormData from 'form-data';

@@ -174,5 +176,16 @@ export const tick = (message) => {

export const apiRequest = async (help, basepath, params) => {
const { body = null, method = 'POST', quiet = false, failOnError = true, apiKey, checkSuccess } = params;
const {
body = null,
method = 'POST',
quiet = false,
failOnError = true,
apiKey,
checkSuccess,
onProgress,
noSpinner,
} = params;
const spinner = ora({ text: quiet ? '' : c.magenta(help), discardStdin: true, interval: 80 });
spinner.start();
if (!noSpinner) {
spinner.start();
}
const _apiKey = apiKey || getAPIKey();

@@ -187,15 +200,43 @@ const headers = {};

const url = `https://${_options.host}${basepath}`;
if (body) {
const _method = body ? method : 'GET';
const isStream = body instanceof FormData;
const _body = body ? (isStream ? body : JSON.stringify(body)) : undefined;
if (body && !isStream) {
headers['Content-Type'] = 'application/json';
}
const _method = body ? method : 'GET';
debug(`requesting ${_method} ${url}`);
try {
const res = await got(url, {
headers,
method: _method,
responseType: 'json',
body: body ? JSON.stringify(body) : undefined,
throwHttpErrors: false,
});
let g;
let p;
if (isStream) {
g = got.stream.post(url, {
headers,
responseType: 'json',
body: _body,
throwHttpErrors: false,
});
if (onProgress) {
g.on('uploadProgress', onProgress);
}
g.resume();
p = new Promise((resolve, reject) => {
g.on('response', async (response) => {
// stream the stream as a response body
const resp = JSON.parse(await getstream(g));
const _response = { ...response, body: resp };
resolve(_response);
});
g.on('error', reject);
});
} else {
g = got(url, {
headers,
method: _method,
responseType: 'json',
body: _body,
throwHttpErrors: false,
});
p = g;
}
const res = await p;
debug(`responded ${_method} ${url} ${JSON.stringify(res.body)}`);

@@ -242,1 +283,25 @@ if (res.body && res.body.success) {

};
export const walkSync = (dir, filter, found = []) => {
const files = fs.readdirSync(dir);
files.forEach((file) => {
const filepath = path.join(dir, file);
const stats = fs.statSync(filepath);
if (stats.isDirectory()) {
if (filter) {
if (!filter(filepath)) {
return;
}
}
walkSync(filepath, filter, found);
} else if (stats.isFile()) {
if (filter) {
if (!filter(filepath)) {
return;
}
}
found.push(filepath);
}
});
return found;
};
{
"name": "@pinpt/cli",
"version": "0.0.2",
"version": "0.0.3",
"description": "Pinpoint CLI",

@@ -32,9 +32,14 @@ "bin": {

"dependencies": {
"adm-zip": "^0.5.5",
"arg": "^5.0.0",
"cfonts": "^2.9.3",
"cli-progress": "^3.9.0",
"execa": "^5.1.1",
"form-data": "^4.0.0",
"fs-extra": "^10.0.0",
"get-stream": "^6.0.1",
"got": "^11.8.2",
"kleur": "^4.1.4",
"ora": "^5.4.1",
"picomatch": "^2.3.0",
"prompts": "^2.4.1",

@@ -41,0 +46,0 @@ "recursive-copy": "^2.0.13",