Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions bin/pos-cli-logs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#!/usr/bin/env node

const EventEmitter = require('events'),
path = require('path'),
url = require('url');
path = require('path');

const { program } = require('commander'),
notifier = require('node-notifier');
Expand Down Expand Up @@ -103,7 +102,7 @@ program
if (!program.quiet && data) {
let parts = [];
if (data.url) {
requestUrl = url.parse(`https://${data.url}`);
requestUrl = new URL(`https://${data.url}`);
let line = `path: ${requestUrl.pathname}`;
if (requestUrl.search) line += `${requestUrl.search}`;
parts.push(line);
Expand Down
75 changes: 68 additions & 7 deletions lib/apiRequest.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,75 @@
const requestPromise = require('request-promise');
const axios = require('axios');
const FormData = require('form-data');
const logger = require('./logger');
// const errors = require('request-promise/errors');

const apiRequest = ({ method = 'GET', uri, body, headers, formData, json = true, forever, request = requestPromise }) => {
const apiRequest = async ({ method = 'GET', uri, body, headers, formData, json = true, forever, request }) => {
logger.Debug(`[${method}] ${uri}`);

return request({method, uri, body, headers, formData, json, forever})
// when we catch the error here we are not able to react to them later
// .catch(errors.StatusCodeError, ServerError.handler)
// .catch(errors.RequestError, ServerError.requestHandler)
try {
// If a custom axios instance is provided, use it
const client = request || axios;

let config = {
method,
url: uri,
headers: headers || {},
};

if (formData) {
// Convert formData object to FormData instance
const form = new FormData();
Object.keys(formData).forEach(key => {
form.append(key, formData[key]);
});
config.data = form;
config.headers = { ...config.headers, ...form.getHeaders() };
} else if (body) {
config.data = body;
} else if (json && typeof json === 'object') {
// In request-promise, json can be an object to send as request body
config.data = json;
config.headers['Content-Type'] = 'application/json';
}

// Handle forever option (keep-alive connections)
if (forever) {
config.timeout = 0;
}

const response = await client(config);

// Return data directly if json is truthy, otherwise return full response
return json ? response.data : response;
} catch (error) {
// Re-throw with consistent error structure similar to request-promise
if (error.response) {
// Server responded with error status (StatusCodeError)
const err = new Error(error.response.data || error.message);
err.name = 'StatusCodeError';
err.statusCode = error.response.status;
err.response = {
body: error.response.data,
statusCode: error.response.status
};
err.options = {
uri: error.config?.url || uri
};
err.error = error.response.data;
throw err;
} else if (error.request) {
// Request was made but no response received (RequestError)
const err = new Error(error.message);
err.name = 'RequestError';
err.cause = error;
err.options = {
uri: error.config?.url || uri
};
throw err;
} else {
// Network or other error
throw error;
}
}
}

module.exports = {
Expand Down
20 changes: 13 additions & 7 deletions lib/assets.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const request = require('request-promise');
const axios = require('axios');
const packAssets = require('./assets/packAssets'),
manifestGenerate = require('./assets/manifest').manifestGenerate,
logger = require('./logger'),
Expand All @@ -17,12 +17,18 @@ const waitForUnpack = async fileUrl => {
logger.Debug(`Waiting for: ${fileUrl} to be deleted.`);
counter += 1;
if (fileExists) await sleep(1000);
fileExists = await request
.head(fileUrl)
.then(() => true)
.catch({ statusCode: 403 }, () => false)
.catch({ statusCode: 404 }, () => false)
.catch(error => logger.Error(error));

try {
await axios.head(fileUrl);
fileExists = true;
} catch (error) {
if (error.response && (error.response.status === 403 || error.response.status === 404)) {
fileExists = false;
} else {
logger.Error(error);
fileExists = false;
}
}
} while (fileExists && counter < 90);
};

Expand Down
39 changes: 24 additions & 15 deletions lib/data/fetchFiles.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
const fs = require('fs'),
request = require('request'),
url = require('url'),
axios = require('axios'),
path = require('path'),
shell = require('shelljs'),
flatten = require('lodash.flatten'),
Queue = require('async/queue'),
logger = require('./../logger');
const CONCURRENCY = 12;

const download = (uri, filename) => {
return new Promise((resolve, reject) => {
request.head(uri, (err, res, body) => {
if (err) {
logger.Warn(err);
reject(err);
} else {
request(uri)
.pipe(fs.createWriteStream(filename))
.on('close', () => resolve(filename));
}
const download = async (uri, filename) => {
try {
// Check if file exists first
await axios.head(uri);

// Download file as stream
const response = await axios({
method: 'get',
url: uri,
responseType: 'stream'
});

return new Promise((resolve, reject) => {
const writer = fs.createWriteStream(filename);
response.data.pipe(writer);
writer.on('finish', () => resolve(filename));
writer.on('error', reject);
});
});
} catch (err) {
logger.Warn(err);
throw err;
}
};

const filenameForUrl = uri => {
return path.basename(url.parse(uri).pathname);
const urlObj = new URL(uri);
return path.basename(urlObj.pathname);
};

const updateItem = (item, newUrl) => {
Expand Down
6 changes: 3 additions & 3 deletions lib/directories.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ const computed = {
};

const methods = {
toWatch: () => computed.ALLOWED.filter(fs.existsSync),
currentApp: () => [app.APP, app.LEGACY_APP].filter(fs.existsSync)[0],
available: () => computed.ALLOWED.filter(fs.existsSync)
toWatch: () => computed.ALLOWED.filter(path => path && fs.existsSync(path)),
currentApp: () => [app.APP, app.LEGACY_APP].filter(path => path && fs.existsSync(path))[0],
available: () => computed.ALLOWED.filter(path => path && fs.existsSync(path))
};

module.exports = Object.assign({}, app, internal, computed, methods);
2 changes: 1 addition & 1 deletion lib/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const config = {
const _paths = customConfig => [customConfig, config.CONFIG, config.LEGACY_CONFIG];

const _getConfigPath = customConfig => {
const firstExistingConfig = _paths(customConfig).filter(fs.existsSync)[0];
const firstExistingConfig = _paths(customConfig).filter(path => path && fs.existsSync(path))[0];
logger.Debug(`[_getConfigPath] First existing config file: ${firstExistingConfig}`);
return path.resolve(firstExistingConfig || config.CONFIG);
};
Expand Down
81 changes: 40 additions & 41 deletions lib/presignUrl.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,65 @@
const fs = require('fs'),
url = require('url'),
request = require('request-promise'),
axios = require('axios'),
mime = require('mime'),
logger = require('./logger'),
Portal = require('./portal');

const deployServiceUrl = () => process.env.DEPLOY_SERVICE_URL || url.resolve(process.env.MARKETPLACE_URL, '/api/private/urls');
const deployServiceUrl = () => {
if (process.env.DEPLOY_SERVICE_URL) {
return process.env.DEPLOY_SERVICE_URL;
}
const baseUrl = new URL(process.env.MARKETPLACE_URL);
return new URL('/api/private/urls', baseUrl).href;
};

const presignUrl = (s3FileName, fileName) => {
const presignUrl = async (s3FileName, fileName) => {
const serviceUrl = `${deployServiceUrl()}/presign-url`;
const params = {
fileName: s3FileName,
contentLength: fs.statSync(fileName)['size'],
contentType: mime.getType(fileName)
};

return request
.get({
url: serviceUrl,
headers: {
token: process.env.MARKETPLACE_TOKEN,
marketplace_domain: url.parse(process.env.MARKETPLACE_URL).hostname
},
qs: params,
json: true
})
.then(body => {
return { uploadUrl: body.url, accessUrl: url.parse(body.accessUrl).href };
});
const marketplaceUrl = new URL(process.env.MARKETPLACE_URL);
const response = await axios.get(serviceUrl, {
headers: {
token: process.env.MARKETPLACE_TOKEN,
marketplace_domain: marketplaceUrl.hostname
},
params: params
});

const accessUrl = new URL(response.data.accessUrl);
return { uploadUrl: response.data.url, accessUrl: accessUrl.href };
};

const presignDirectory = path => {
const presignDirectory = async path => {
const serviceUrl = `${deployServiceUrl()}/presign-directory`;
const params = { directory: path };

return request
.get({
url: serviceUrl,
headers: {
token: process.env.MARKETPLACE_TOKEN,
marketplace_domain: url.parse(process.env.MARKETPLACE_URL).hostname
},
qs: params,
json: true
})
.then(body => body);
const marketplaceUrl = new URL(process.env.MARKETPLACE_URL);
const response = await axios.get(serviceUrl, {
headers: {
token: process.env.MARKETPLACE_TOKEN,
marketplace_domain: marketplaceUrl.hostname
},
params: params
});

return response.data;
};

const presignUrlForPortal = (token, moduleName, filename) => {
const presignUrlForPortal = async (token, moduleName, filename) => {
const serviceUrl = `${Portal.url()}/api/pos_modules/${moduleName}/presign_url`;
logger.Debug(token);
return request
.get({
url: serviceUrl,
headers: {
Authorization: `Bearer ${token}`
},
json: true
})
.then(body => {
return { uploadUrl: body.upload_url, accessUrl: body.access_url };
});

const response = await axios.get(serviceUrl, {
headers: {
Authorization: `Bearer ${token}`
}
});

return { uploadUrl: response.data.upload_url, accessUrl: response.data.access_url };
};

module.exports = {
Expand Down
4 changes: 2 additions & 2 deletions lib/proxy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const requestPromise = require('request-promise');
const axios = require('axios');

const { apiRequest } = require('./apiRequest');
const logger = require('./logger');
Expand All @@ -22,7 +22,7 @@ class Gateway {
const censored = Object.assign({}, headers, { Authorization: 'Token: <censored>' });
logger.Debug(`Request headers: ${JSON.stringify(censored, null, 2)}`);

this.authorizedRequest = requestPromise.defaults({ headers });
this.authorizedRequest = axios.create({ headers });
}

apiRequest({ method = 'GET', uri, formData, json = true, forever }) {
Expand Down
Loading
Loading