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

losant-cli

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

losant-cli - npm Package Compare versions

Comparing version 1.2.1 to 1.2.2

lib/meta-data-helpers.js

8

CHANGELOG.md

@@ -36,2 +36,8 @@ # Losant CLI Changelog

* watch command now has a queueing process incase you have slow internet or a lot of changes at once.
* watch command now has a queueing process incase you have slow internet or a lot of changes at once.
## Losant CLI v1.2.2
### Fixed
* sanitizing experience file names
const path = require('path');
const sanitizeFilename = require('sanitize-filename');
const template = require('lodash-template');
module.exports = {

@@ -7,4 +10,34 @@ experience: {

localStatusParams: [ path.join(path.sep, '{components,layouts,pages}', '*.hbs') ],
// eslint-disable-next-line no-template-curly-in-string
remoteStatusParams: [ path.join('experience', '${viewType}s', '${name}.hbs'), 'body' ]
remoteStatusParams: [
(resource, { newFilesSet = new Set(), currentFileMap }) => {
let localStatus;
for (const [ , value ] of currentFileMap) {
if (value.id === resource.id && (!value.name || value.name === resource.name)) {
localStatus = value;
break;
}
}
if (localStatus) {
return localStatus.file;
}
const dir = path.join('experience', `${resource.viewType}s`);
let filename = sanitizeFilename(resource.name);
if (!filename) {
filename = resource.id;
}
const filePath = path.join(dir, `${filename}.hbs`);
if (!newFilesSet.has(filePath) && !currentFileMap.has(filePath)) {
return filePath;
} else {
let counter = 1;
let counterFilePath = path.join(dir, `${filename}-${counter}.hbs`);
while (currentFileMap.get(counterFilePath) || newFilesSet.has(counterFilePath)) {
counterFilePath = path.join(dir, `${filename}-${counter}.hbs`);
counter++;
}
return counterFilePath;
}
},
'body'
]
},

@@ -15,4 +48,4 @@ files: {

localStatusParams: [ path.join(path.sep, '**') ],
// eslint-disable-next-line no-template-curly-in-string
remoteStatusParams: [ 'files${parentDirectory}${name}', 's3etag', { skipMd5Creation: true } ]
// files never need to be sanitized cause that is ensured in the model
remoteStatusParams: [ template('files${parentDirectory}${name}'), 's3etag', { skipMd5Creation: true } ] // eslint-disable-line no-template-curly-in-string
},

@@ -23,4 +56,6 @@ dataTables: {

localStatusParams: [ path.join(path.sep, '*.csv' )],
// eslint-disable-next-line no-template-curly-in-string
remoteStatusParams: [ path.join('dataTables', '${name}-${id}.csv') ]
remoteStatusParams: [ (resource) => {
const sanitizedName = sanitizeFilename(resource.name);
return path.join('dataTables', `${sanitizedName}-${resource.id}.csv`);
} ]
},

@@ -27,0 +62,0 @@ options: {

54

lib/get-downloader.js

@@ -9,3 +9,2 @@ const paginateRequest = require('./paginate-request');

saveLocalMeta,
checksum,
logResult,

@@ -28,2 +27,3 @@ logProcessing,

const { rollbarLog } = require('./rollbar');
const { buildMetaDataObj } = require('./meta-data-helpers');

@@ -71,5 +71,6 @@ const getDownloader = ({

const downloadResults = await allSettledSerial(async (remoteStatus) => {
logProcessing(remoteStatus.file);
const file = remoteStatus.file;
logProcessing(file);
const localStatus = localStatusByFile[file];
if (!command.force) {
const localStatus = localStatusByFile[remoteStatus.file];
const { conflict } = getComparativeStatus(localStatus, remoteStatus);

@@ -80,3 +81,3 @@ if (conflict) {

type: 'list',
message: `A conflict has been dected in ${remoteStatus.file}, how do you want to handle this?`,
message: `A conflict has been detected in ${file}, how do you want to handle this?`,
choices: [

@@ -89,3 +90,3 @@ { name: 'Do nothing, and resolve the conflict later.', value: null },

if (!handleConflict) {
return logResult('conflict', remoteStatus.file, 'redBright');
return logResult('conflict', file, 'redBright');
}

@@ -95,13 +96,7 @@ if (handleConflict === 'local') {

// faking that the local status and the remote status match so there is no conflict when uploading
meta[remoteStatus.file] = {
file: remoteStatus.file,
id: remoteStatus.id,
md5: remoteStatus.remoteMd5,
remoteTime: remoteStatus.remoteModTime,
localTime: Date.now()
};
return logResult('unmodified', remoteStatus.file);
meta[file] = buildMetaDataObj({ remoteStatus });
return logResult('unmodified', file);
} else {
// e.g. make the local a "new" state, since the remote file was deleted.
delete meta[remoteStatus.file];
delete meta[file];
return; // purposefully not printing anything out

@@ -113,3 +108,4 @@ }

if (remoteStatus.status === 'unmodified') {
return logResult('unmodified', remoteStatus.file);
meta[file] = buildMetaDataObj({ remoteStatus });
return logResult('unmodified', file);
}

@@ -119,14 +115,14 @@ if (remoteStatus.status === 'deleted') {

try {
if (await pathExists(remoteStatus.file)) {
await remove(remoteStatus.file);
if (await pathExists(file)) {
await remove(file);
}
} catch (e) {
return logError(`An Error occurred when trying to delete file ${remoteStatus.file} with the message ${e.message}`);
return logError(`An Error occurred when trying to delete file ${file} with the message ${e.message}`);
}
delete meta[remoteStatus.file];
delete meta[file];
}
return logResult('deleted', remoteStatus.file, 'yellow');
return logResult('deleted', file, 'yellow');
}
if (!command.dryRun) {
await ensureDir(path.dirname(remoteStatus.file));
await ensureDir(path.dirname(file));
let data;

@@ -136,18 +132,12 @@ try {

} catch (e) {
return logError(`An Error occurred when trying to download data for file ${remoteStatus.file} with the message ${e.message}`);
return logError(`An Error occurred when trying to download data for file ${file} with the message ${e.message}`);
}
try {
await writeFile(remoteStatus.file, data);
await writeFile(file, data);
} catch (e) {
return logError(`An Error occurred when trying to write the file ${remoteStatus.file} with the message ${e.message}`);
return logError(`An Error occurred when trying to write the file ${file} with the message ${e.message}`);
}
meta[remoteStatus.file] = {
file: remoteStatus.file,
id: remoteStatus.id, // can probably remove
md5: checksum(data),
remoteTime: remoteStatus.remoteModTime,
localTime: Date.now()
};
meta[file] = buildMetaDataObj({ remoteStatus });
}
logResult('downloaded', remoteStatus.file, 'green');
logResult('downloaded', file, 'green');
didDownload = true;

@@ -154,0 +144,0 @@ }, values(remoteStatusByFile));

@@ -20,3 +20,2 @@ const paginateRequest = require('./paginate-request');

const { rollbarLog } = require('./rollbar');
const sanitize = require('sanitize-filename');

@@ -34,5 +33,2 @@ const getExporter = ({

items = await paginateRequest(api[apiType].get, { applicationId });
items.forEach((item) => {
item.name = sanitize(item.name);
});
} catch (e) {

@@ -49,2 +45,3 @@ return logError(e);

});
if (command.dryRun) {

@@ -51,0 +48,0 @@ logResult('DRY RUN');

@@ -7,2 +7,3 @@ const path = require('path');

const { files, experience } = require('./constants');
const { buildMetaDataObj } = require('./meta-data-helpers');

@@ -37,10 +38,4 @@ const experienceParams = {

},
postUpsertUpdateMeta: async (view, meta, item) => {
const remoteTime = (new Date(view.lastUpdated)).getTime();
meta[item.file] = {
id: view.id,
md5: checksum(view.body),
remoteTime,
localTime: item.localModTime * 1000
};
postUpsertUpdateMeta: async (view, meta, localStatus) => {
meta[localStatus.file] = buildMetaDataObj({ resource: view, md5: checksum(view.body), localStatus });
}

@@ -82,4 +77,4 @@ };

},
postUpsertUpdateMeta: async (result, meta, item) => {
const body = await readFile(item.file);
postUpsertUpdateMeta: async (result, meta, localStatus) => {
const body = await readFile(localStatus.file);
let s3etag;

@@ -103,10 +98,5 @@ try {

} catch (e) {
throw new Error(`An Error occurred when trying to upload ${item.name} to s3 with the message ${e.message}`);
throw new Error(`An Error occurred when trying to upload ${localStatus.name} to s3 with the message ${e.message}`);
}
meta[item.file] = {
id: result.id,
md5: s3etag,
remoteTime: new Date(result.lastUpdated).getTime(),
localTime: item.localModTime * 1000
};
meta[localStatus.file] = buildMetaDataObj({ resource: result, md5: s3etag, localStatus });
}

@@ -113,0 +103,0 @@ };

@@ -18,2 +18,3 @@ const paginateRequest = require('./paginate-request');

const { isEmpty, merge, values, keys } = require('omnibelt');
const { buildMetaDataObj } = require('./meta-data-helpers');

@@ -84,14 +85,10 @@ const getUploader = ({

}
const remoteInfo = remoteStatusByFile[stat.file] || {};
const remoteStatus = remoteStatusByFile[stat.file] || {};
if (
(stat === 'added' && remoteInfo === 'added') ||
(stat === 'modified' && remoteInfo === 'modified')
(stat === 'added' && remoteStatus === 'added') ||
(stat === 'modified' && remoteStatus === 'modified')
) {
if (stat.localMd5 === remoteInfo.remoteMd5) {
meta[stat.file] = {
id: remoteInfo.id,
md5: remoteInfo.remoteMd5,
remoteTime: remoteInfo.remoteModTime,
localTime: stat.localModTime * 1000
};
if (stat.localMd5 === remoteStatus.remoteMd5) {
meta[stat.file] = buildMetaDataObj({ remoteStatus, localStatus: stat });
return logResult('uploaded', stat.file, 'green');

@@ -98,0 +95,0 @@ }

@@ -8,3 +8,2 @@ const getApi = require('./get-api');

const minimatch = require('minimatch');
const template = require('lodash-template');
const c = require('chalk');

@@ -282,7 +281,7 @@ const ssLog = require('single-line-log');

size: stats.size,
name: path.basename(relFile, path.extname(globPattern)),
name: meta[relFile] ? meta[relFile].name : path.basename(relFile, path.extname(globPattern)),
origModTime: meta[relFile] ? Math.trunc(meta[relFile].localTime): undefined,
localModTime: Math.trunc(stats.mtime.getTime()),
origMd5: meta[relFile] ? meta[relFile].md5 : undefined,
localMd5: utils.checksum(await readFile(file))
localMd5: utils.checksum(await readFile(relFile))
};

@@ -300,5 +299,5 @@ if (!statObj.id) {

statusByFile[file] = {
name: meta[file].name,
id: meta[file].id,
file: file,
name: path.basename(file, path.extname(globPattern)),
origModTime: Math.trunc(meta[file].localTime / 1000),

@@ -314,14 +313,13 @@ localModTime: undefined,

getShallowRemoteStatus: async (localFiles, resources, pathTemplate) => {
getShallowRemoteStatus: async (localFiles, resources, getFilePath) => {
if (!resources) { return {}; }
const statusByFile = {};
const compiledTemplate = template(pathTemplate);
resources.forEach((resource) => {
const file = path.normalize(compiledTemplate(resource));
const statObj = {
id: resource.id,
file,
name: resource.name,
status: 'found'
};
const file = path.normalize(getFilePath(resource, { currentFileMap: localFiles, skipIdCheck: true }));
statObj.file = file;
statusByFile[file] = statObj;

@@ -340,15 +338,17 @@ localFiles.delete(file);

getRemoteStatus: async (type, resources, pathTemplate, contentProperty, options = {}) => {
getRemoteStatus: async (type, resources, getFilePath, contentProperty, options = {}) => {
const statusByFile = {};
const meta = await utils.loadLocalMeta(type) || {};
const metaByFile = {};
const metaByFile = new Map();
const metaFiles = new Set();
keys(meta).forEach((file) => {
const currentFiles = new Set(keys(meta));
currentFiles.forEach((file) => {
const item = meta[file];
metaByFile[file] = Object.assign({}, item, { file: file });
metaByFile.set(file, Object.assign({}, item, { file: file }));
metaFiles.add(file);
});
const compiledTemplate = template(pathTemplate);
const newFilesSet = new Set();
resources.forEach((resource) => {
const file = path.normalize(compiledTemplate(resource));
const file = path.normalize(getFilePath(resource, { newFilesSet, currentFileMap: metaByFile }));
metaFiles.delete(file);

@@ -367,8 +367,9 @@ const mtime = new Date(resource.lastUpdated);

name: resource.name,
origModTime: metaByFile[file] ? metaByFile[file].remoteTime: undefined,
origModTime: metaByFile.has(file) ? metaByFile.get(file).remoteTime: undefined,
remoteModTime: mtime.getTime(),
origMd5: metaByFile[file] ? metaByFile[file].md5 : undefined,
origMd5: metaByFile.has(file) ? metaByFile.get(file).md5 : undefined,
remoteMd5
};
if (!metaByFile[file]) {
if (!metaByFile.has(file)) {
newFilesSet.add(file);
statObj.status = 'added';

@@ -382,11 +383,12 @@ } else if (statObj.remoteMd5 !== statObj.origMd5) {

});
metaFiles.forEach((id) => {
const file = metaByFile[id].file;
statusByFile[metaByFile[id].file] = {
id: id,
// anything left over are existing files that where no longer found in the API
metaFiles.forEach((file) => {
const metaObj = metaByFile.get(file);
statusByFile[file] = {
id: metaObj.id,
file,
name: path.basename(metaByFile[id].file, type !== 'files' ? path.extname(metaByFile[id].file) : undefined),
origModTime: Math.trunc(metaByFile[id].file.remoteTime / 1000),
name: metaObj.name || path.basename(file, type !== 'files' ? path.extname(file) : undefined),
origModTime: Math.trunc(metaObj.remoteTime / 1000),
remoteModTime: undefined,
origMd5: metaByFile[id].file.md5,
origMd5: metaObj.md5,
remoteMd5: undefined,

@@ -428,6 +430,6 @@ status: 'deleted'

},
// this function will not work for experiences...just a heads up
getShallowStatus: async ({ items, remoteStatusParams, localStatusParams, dir, pattern }) => {
const localFiles = await utils.getShallowLocalStatus(dir, ...localStatusParams);
const remoteStatusByFile = await utils.getShallowRemoteStatus(new Map(localFiles), items, ...remoteStatusParams);
const remoteStatusByFile = await utils.getShallowRemoteStatus(localFiles, items, ...remoteStatusParams);

@@ -434,0 +436,0 @@ if (pattern) {

{
"name": "losant-cli",
"version": "1.2.1",
"version": "1.2.2",
"description": "Losant Command Line Interface",

@@ -35,31 +35,31 @@ "license": "MIT",

"dependencies": {
"@rjhilgefort/export-dir": "^1.1.0",
"@rjhilgefort/export-dir": "^1.1.3",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"cli-table3": "^0.5.1",
"commander": "^2.19.0",
"csv-stringify": "^5.3.0",
"commander": "^2.20.3",
"csv-stringify": "^5.5.0",
"death": "^1.1.0",
"error": "^7.0.2",
"error": "^7.2.0",
"find-file-up": "^2.0.1",
"form-data": "^2.3.3",
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"inquirer": "^6.2.0",
"form-data": "^3.0.0",
"fs-extra": "^8.1.0",
"glob": "^7.1.6",
"inquirer": "^7.1.0",
"js-yaml": "^3.12.0",
"jsonwebtoken": "^8.5.1",
"lodash-template": "^1.0.0",
"losant-rest": "2.3.7",
"mime-types": "^2.1.21",
"losant-rest": "2.5.1",
"mime-types": "^2.1.27",
"minimatch": "^3.0.4",
"moment": "^2.22.2",
"omnibelt": "^1.3.1",
"pad": "^2.2.1",
"proper-lockfile": "^3.0.2",
"request": "^2.88.0",
"request-promise": "^4.2.2",
"rollbar": "^2.5.0",
"moment": "^2.25.3",
"omnibelt": "^1.3.3",
"pad": "^3.2.0",
"proper-lockfile": "^4.1.1",
"request": "^2.88.2",
"request-promise": "^4.2.5",
"rollbar": "^2.15.2",
"sanitize-filename": "^1.6.2",
"single-line-log": "^1.1.2",
"update-notifier": "^2.3.0"
"update-notifier": "^4.1.0"
},

@@ -69,8 +69,8 @@ "devDependencies": {

"husky": "^1.1.4",
"lint-staged": "^8.0.4",
"lint-staged": "^8.2.1",
"mocha": "^5.2.0",
"nock": "^10.0.2",
"rimraf": "^2.6.2",
"rimraf": "^3.0.2",
"should": "^13.2.3",
"sinon": "^7.1.1"
"sinon": "^9.0.2"
},

@@ -77,0 +77,0 @@ "lint-staged": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc