@iannisz/node-cms
Advanced tools
Comparing version 0.0.22 to 0.0.23
{ | ||
"name": "@iannisz/node-cms", | ||
"version": "0.0.22", | ||
"version": "0.0.23", | ||
"description": "Node CMS", | ||
@@ -16,2 +16,3 @@ "main": "index.js", | ||
"@types/node": "^14.0.19", | ||
"@types/socket.io-client": "^1.4.33", | ||
"apache-js-workers": "^0.0.8", | ||
@@ -18,0 +19,0 @@ "chalk": "^4.1.0", |
@@ -10,3 +10,3 @@ var searchParams = new URLSearchParams(window.location.search); | ||
var password = $('#password').value; | ||
request('/admin-panel/workers/login.node.js', 'POST', { username: username, password: password }) | ||
request('/admin-panel/workers/login.node.js', { username: username, password: password }) | ||
.then(function (token) { | ||
@@ -13,0 +13,0 @@ Cookies.set('token', token); |
@@ -13,3 +13,3 @@ const searchParams = new URLSearchParams(window.location.search) | ||
request('/admin-panel/workers/login.node.js', 'POST', { username, password }) | ||
request('/admin-panel/workers/login.node.js', { username, password }) | ||
.then(token => { | ||
@@ -16,0 +16,0 @@ Cookies.set('token', token) |
@@ -154,7 +154,7 @@ /* | ||
return new Promise(function (resolve, reject) { | ||
request('/admin-panel/workers/get-pages.node.js', 'POST', { | ||
request('/admin-panel/workers/get-pages.node.js', { | ||
token: Cookies.get('token') | ||
}) | ||
.then(function (res) { | ||
db = JSON.parse(res); | ||
db = res.body; | ||
resolve(); | ||
@@ -296,3 +296,3 @@ }) | ||
} | ||
return [4 /*yield*/, request('/admin-panel/workers/swap-pages.node.js', 'POST', { | ||
return [4 /*yield*/, request('/admin-panel/workers/swap-pages.node.js', { | ||
suToken: suToken, page1: page1, page2: page2 | ||
@@ -346,3 +346,3 @@ }) | ||
} | ||
return [4 /*yield*/, request('/admin-panel/workers/update-page.node.js', 'POST', { | ||
return [4 /*yield*/, request('/admin-panel/workers/update-page.node.js', { | ||
suToken: suToken, pageContent: pageContent, pageId: pageId | ||
@@ -402,3 +402,3 @@ }) | ||
.then(function (suToken) { | ||
request('/admin-panel/workers/add-page.node.js', 'POST', { | ||
request('/admin-panel/workers/add-page.node.js', { | ||
suToken: suToken, pageType: pageType, pageContent: pageContent | ||
@@ -443,3 +443,3 @@ }) | ||
.then(function (suToken) { | ||
request('/admin-panel/workers/delete-page.node.js', 'POST', { | ||
request('/admin-panel/workers/delete-page.node.js', { | ||
suToken: suToken, | ||
@@ -642,3 +642,3 @@ pageId: page.id | ||
// Send the request | ||
request('/admin-panel/workers/fileupload.node.js', 'POST', body, files) | ||
request('/admin-panel/workers/fileupload.node.js', body, files) | ||
.then(resolve) | ||
@@ -907,3 +907,3 @@ .catch(handleRequestError); | ||
return new Promise(function (resolve, reject) { | ||
request('/admin-panel/workers/get-files.node.js', 'POST', { | ||
request('/admin-panel/workers/get-files.node.js', { | ||
path: path, | ||
@@ -913,3 +913,3 @@ token: Cookies.get('token') | ||
.then(function (res) { | ||
var fileArray = JSON.parse(res).files; | ||
var fileArray = res.body.files; | ||
resolve(fileArray); | ||
@@ -1071,3 +1071,3 @@ }) | ||
var filePaths = selectedFiles.map(function (f) { return path + f.name; }); | ||
request('/admin-panel/workers/delete-multiple-files.node.js', 'POST', { | ||
request('/admin-panel/workers/delete-multiple-files.node.js', { | ||
suToken: suToken, | ||
@@ -1099,3 +1099,3 @@ filePaths: filePaths | ||
.then(function (suToken) { | ||
request('/admin-panel/workers/copy-files.node.js', 'POST', { | ||
request('/admin-panel/workers/copy-files.node.js', { | ||
suToken: suToken, | ||
@@ -1131,3 +1131,3 @@ sources: selectedFiles.map(function (selectedFile) { return selectedFile.path; }), | ||
.then(function (suToken) { | ||
request('/admin-panel/workers/move-files.node.js', 'POST', { | ||
request('/admin-panel/workers/move-files.node.js', { | ||
suToken: suToken, | ||
@@ -1181,3 +1181,3 @@ sources: selectedFiles.map(function (selectedFile) { return selectedFile.path; }), | ||
.then(function (suToken) { | ||
request('/admin-panel/workers/delete-file.node.js', 'POST', { | ||
request('/admin-panel/workers/delete-file.node.js', { | ||
suToken: suToken, | ||
@@ -1223,3 +1223,3 @@ filePath: filePath | ||
suToken = _a.sent(); | ||
return [4 /*yield*/, request("/admin-panel/workers/" + mode + "-file-different-name.node.js", 'POST', { | ||
return [4 /*yield*/, request("/admin-panel/workers/" + mode + "-file-different-name.node.js", { | ||
suToken: suToken, | ||
@@ -1281,3 +1281,3 @@ source: sourcePath, | ||
suToken = _a.sent(); | ||
return [4 /*yield*/, request('/admin-panel/workers/move-file-different-name.node.js', 'POST', { | ||
return [4 /*yield*/, request('/admin-panel/workers/move-file-different-name.node.js', { | ||
suToken: suToken, | ||
@@ -1336,3 +1336,3 @@ source: sourcePath, | ||
suToken = _a.sent(); | ||
return [4 /*yield*/, request('/admin-panel/workers/create-new-directory.node.js', 'POST', { | ||
return [4 /*yield*/, request('/admin-panel/workers/create-new-directory.node.js', { | ||
suToken: suToken, | ||
@@ -1339,0 +1339,0 @@ newDirectoryPath: newDirectoryPath |
@@ -145,7 +145,7 @@ /* | ||
return new Promise((resolve, reject) => { | ||
request('/admin-panel/workers/get-pages.node.js', 'POST', { | ||
request('/admin-panel/workers/get-pages.node.js', { | ||
token: Cookies.get('token') | ||
}) | ||
.then(res => { | ||
db = JSON.parse(res) | ||
db = res.body | ||
resolve() | ||
@@ -382,3 +382,3 @@ }) | ||
await request('/admin-panel/workers/swap-pages.node.js', 'POST', { | ||
await request('/admin-panel/workers/swap-pages.node.js', { | ||
suToken, page1, page2 | ||
@@ -449,3 +449,3 @@ }) | ||
await request('/admin-panel/workers/update-page.node.js', 'POST', { | ||
await request('/admin-panel/workers/update-page.node.js', { | ||
suToken, pageContent, pageId | ||
@@ -523,3 +523,3 @@ }) | ||
.then(suToken => { | ||
request('/admin-panel/workers/add-page.node.js', 'POST', { | ||
request('/admin-panel/workers/add-page.node.js', { | ||
suToken, pageType, pageContent | ||
@@ -579,3 +579,3 @@ }) | ||
.then(suToken => { | ||
request('/admin-panel/workers/delete-page.node.js', 'POST', { | ||
request('/admin-panel/workers/delete-page.node.js', { | ||
suToken, | ||
@@ -857,3 +857,3 @@ pageId: page.id | ||
path = '/' | ||
) => new Promise<string>(resolve => { | ||
) => new Promise<SocketResponse>(resolve => { | ||
getSuToken() | ||
@@ -878,3 +878,3 @@ .then(suToken => { | ||
request('/admin-panel/workers/fileupload.node.js', 'POST', body, files) | ||
request('/admin-panel/workers/fileupload.node.js', body, files) | ||
.then(resolve) | ||
@@ -1287,3 +1287,3 @@ .catch(handleRequestError) | ||
const getFiles = (path = '/') => new Promise<_File[]>((resolve, reject) => { | ||
request('/admin-panel/workers/get-files.node.js', 'POST', { | ||
request('/admin-panel/workers/get-files.node.js', { | ||
path, | ||
@@ -1293,3 +1293,3 @@ token: Cookies.get('token') | ||
.then(res => { | ||
const fileArray = JSON.parse(res).files as _File[] | ||
const fileArray = res.body.files as _File[] | ||
resolve(fileArray) | ||
@@ -1528,3 +1528,3 @@ }) | ||
request('/admin-panel/workers/delete-multiple-files.node.js', 'POST', { | ||
request('/admin-panel/workers/delete-multiple-files.node.js', { | ||
suToken, | ||
@@ -1562,3 +1562,3 @@ filePaths | ||
.then(suToken => { | ||
request('/admin-panel/workers/copy-files.node.js', 'POST', { | ||
request('/admin-panel/workers/copy-files.node.js', { | ||
suToken, | ||
@@ -1610,3 +1610,3 @@ sources: selectedFiles.map( | ||
.then(suToken => { | ||
request('/admin-panel/workers/move-files.node.js', 'POST', { | ||
request('/admin-panel/workers/move-files.node.js', { | ||
suToken, | ||
@@ -1726,3 +1726,3 @@ sources: selectedFiles.map( | ||
.then(suToken => { | ||
request('/admin-panel/workers/delete-file.node.js', 'POST', { | ||
request('/admin-panel/workers/delete-file.node.js', { | ||
suToken, | ||
@@ -1770,3 +1770,3 @@ filePath | ||
await request(`/admin-panel/workers/${ mode }-file-different-name.node.js`, 'POST', { | ||
await request(`/admin-panel/workers/${ mode }-file-different-name.node.js`, { | ||
suToken, | ||
@@ -1836,3 +1836,3 @@ source: sourcePath, | ||
await request('/admin-panel/workers/move-file-different-name.node.js', 'POST', { | ||
await request('/admin-panel/workers/move-file-different-name.node.js', { | ||
suToken, | ||
@@ -1898,3 +1898,3 @@ source: sourcePath, | ||
await request('/admin-panel/workers/create-new-directory.node.js', 'POST', { | ||
await request('/admin-panel/workers/create-new-directory.node.js', { | ||
suToken, | ||
@@ -1901,0 +1901,0 @@ newDirectoryPath |
@@ -51,3 +51,3 @@ // Save superuser token in memory | ||
_a.trys.push([1, 3, , 16]); | ||
return [4 /*yield*/, request('/admin-panel/workers/get-su-token.node.js', 'POST', { loginData: loginData }) | ||
return [4 /*yield*/, request('/admin-panel/workers/get-su-token.node.js', { loginData: loginData }) | ||
// Open the padlock icon | ||
@@ -60,3 +60,3 @@ ]; | ||
// Set the suToken globally | ||
globalSuToken = res; | ||
globalSuToken = res.body; | ||
return [2 /*return*/, globalSuToken]; | ||
@@ -63,0 +63,0 @@ case 3: |
@@ -17,3 +17,3 @@ // Save superuser token in memory | ||
const res = await request('/admin-panel/workers/get-su-token.node.js', 'POST', { loginData }) | ||
const res = await request('/admin-panel/workers/get-su-token.node.js', { loginData }) | ||
@@ -27,3 +27,3 @@ // Open the padlock icon | ||
globalSuToken = res | ||
globalSuToken = res.body | ||
return globalSuToken | ||
@@ -30,0 +30,0 @@ |
@@ -49,8 +49,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
var _this = this; | ||
var request = function (url, method, body, files) { | ||
if (method === void 0) { method = 'GET'; } | ||
var request = function (url, body, files) { | ||
if (body === void 0) { body = {}; } | ||
if (files === void 0) { files = []; } | ||
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { | ||
var req, start, size, reqBody, fileMetas, files_1, files_1_1, file, fileMeta, pointer, rawBody, addTobody, i, fileMeta, fileData; | ||
var socket, reqBody, files_1, files_1_1, file, fileMeta, stream, reader, chunk, end, e_1_1; | ||
var e_1, _a; | ||
@@ -60,65 +59,68 @@ return __generator(this, function (_b) { | ||
case 0: | ||
req = new XMLHttpRequest(); | ||
req.onreadystatechange = function () { | ||
if (req.readyState == 4) { | ||
if (req.status >= 200 && req.status < 300) { | ||
resolve(req.response); | ||
socket = io({ | ||
transportOptions: { | ||
polling: { | ||
extraHeaders: { | ||
path: url | ||
} | ||
} | ||
else { | ||
reject({ status: req.status, response: req.responseText }); | ||
} | ||
} | ||
}; | ||
req.open(method, url); | ||
start = Date.now(); | ||
size = 0; | ||
reqBody = stringToUint8Array(JSON.stringify(body)); | ||
size += reqBody.byteLength; | ||
fileMetas = []; | ||
try { | ||
for (files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) { | ||
file = files_1_1.value; | ||
fileMeta = stringToUint8Array("\n--------------------file\n" + JSON.stringify({ | ||
name: file.name, | ||
lastModified: file.lastModified, | ||
size: file.size, | ||
type: file.type | ||
}) + "\n"); | ||
size += fileMeta.byteLength + file.size; | ||
fileMetas.push(fileMeta); | ||
}); | ||
socket.on('response', function (res) { | ||
if (res.status >= 200 && res.status < 300) { | ||
resolve(res); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (files_1_1 && !files_1_1.done && (_a = files_1.return)) _a.call(files_1); | ||
else { | ||
reject({ status: res.status, response: res.body }); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
pointer = 0; | ||
rawBody = new Uint8Array(size); | ||
addTobody = function (data) { | ||
rawBody.set(data, pointer); | ||
pointer += data.byteLength; | ||
}; | ||
// Add body | ||
addTobody(reqBody); | ||
i = 0; | ||
}); | ||
reqBody = stringToUint8Array(JSON.stringify(body)); | ||
socket.emit('data', reqBody.buffer); | ||
_b.label = 1; | ||
case 1: | ||
if (!(i < files.length)) return [3 /*break*/, 4]; | ||
fileMeta = fileMetas[i]; | ||
return [4 /*yield*/, files[i].arrayBuffer()]; | ||
_b.trys.push([1, 7, 8, 9]); | ||
files_1 = __values(files), files_1_1 = files_1.next(); | ||
_b.label = 2; | ||
case 2: | ||
fileData = _b.sent(); | ||
addTobody(fileMeta); | ||
addTobody(new Uint8Array(fileData)); | ||
if (!!files_1_1.done) return [3 /*break*/, 6]; | ||
file = files_1_1.value; | ||
fileMeta = stringToUint8Array("\n--------------------file\n" + JSON.stringify({ | ||
name: file.name, | ||
lastModified: file.lastModified, | ||
size: file.size, | ||
type: file.type | ||
}) + "\n"); | ||
socket.emit('data', fileMeta.buffer); | ||
stream = file.stream(); | ||
reader = stream.getReader(); | ||
_b.label = 3; | ||
case 3: | ||
i++; | ||
return [3 /*break*/, 1]; | ||
if (!true) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, reader.read()]; | ||
case 4: | ||
console.log('prepared request in ' + (Date.now() - start) + 'ms'); | ||
req.send(rawBody); | ||
return [2 /*return*/]; | ||
chunk = _b.sent(); | ||
if (!chunk.done) { | ||
socket.emit('data', chunk.value.buffer); | ||
} | ||
else { | ||
end = stringToUint8Array("\n--------------------end"); | ||
socket.emit('data', end.buffer); | ||
return [3 /*break*/, 5]; | ||
} | ||
return [3 /*break*/, 3]; | ||
case 5: | ||
files_1_1 = files_1.next(); | ||
return [3 /*break*/, 2]; | ||
case 6: return [3 /*break*/, 9]; | ||
case 7: | ||
e_1_1 = _b.sent(); | ||
e_1 = { error: e_1_1 }; | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
try { | ||
if (files_1_1 && !files_1_1.done && (_a = files_1.return)) _a.call(files_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
return [7 /*endfinally*/]; | ||
case 9: return [2 /*return*/]; | ||
} | ||
@@ -125,0 +127,0 @@ }); |
@@ -1,37 +0,38 @@ | ||
type HTTPMethod = 'GET' | 'POST' | ||
interface SocketResponse { | ||
status: number | ||
body: any | ||
} | ||
const request = ( | ||
url: string, | ||
method: HTTPMethod = 'GET', | ||
body: Object = {}, | ||
files: File[] = [] | ||
): Promise<string> => { | ||
): Promise<SocketResponse> => { | ||
return new Promise(async (resolve, reject) => { | ||
const req = new XMLHttpRequest() | ||
req.onreadystatechange = () => { | ||
if (req.readyState == 4) { | ||
if (req.status >= 200 && req.status < 300) { | ||
resolve(req.response) | ||
} else { | ||
reject({ status: req.status, response: req.responseText }) | ||
const socket = io({ | ||
transportOptions: { | ||
polling: { | ||
extraHeaders: { | ||
path: url | ||
} | ||
} | ||
} | ||
} | ||
}) | ||
req.open(method, url) | ||
socket.on('response', (res: SocketResponse) => { | ||
if (res.status >= 200 && res.status < 300) { | ||
resolve(res) | ||
} else { | ||
reject({ status: res.status, response: res.body }) | ||
} | ||
}) | ||
const start = Date.now() | ||
let size = 0 | ||
// Create body | ||
const reqBody = stringToUint8Array(JSON.stringify(body)) | ||
size += reqBody.byteLength | ||
socket.emit('data', reqBody.buffer) | ||
// Create file metas | ||
const fileMetas: Uint8Array[] = [] | ||
for (let file of files) { | ||
@@ -47,33 +48,19 @@ const fileMeta = stringToUint8Array( | ||
size += fileMeta.byteLength + file.size | ||
fileMetas.push(fileMeta) | ||
} | ||
socket.emit('data', fileMeta.buffer) | ||
// Create raw body | ||
const stream: ReadableStream<Uint8Array> = file.stream() | ||
const reader = stream.getReader() | ||
let pointer = 0 | ||
const rawBody = new Uint8Array(size) | ||
while (true) { | ||
const chunk = await reader.read() | ||
const addTobody = (data: Uint8Array) => { | ||
rawBody.set(data, pointer) | ||
pointer += data.byteLength | ||
if (!chunk.done) { | ||
socket.emit('data', chunk.value.buffer) | ||
} else { | ||
const end = stringToUint8Array(`\n--------------------end`) | ||
socket.emit('data', end.buffer) | ||
break | ||
} | ||
} | ||
} | ||
// Add body | ||
addTobody(reqBody) | ||
// Add each file | ||
for (let i = 0; i < files.length; i++) { | ||
const fileMeta = fileMetas[i] | ||
const fileData = await files[i].arrayBuffer() | ||
addTobody(fileMeta) | ||
addTobody(new Uint8Array(fileData)) | ||
} | ||
console.log('prepared request in ' + (Date.now() - start) + 'ms') | ||
req.send(rawBody) | ||
}) | ||
@@ -80,0 +67,0 @@ } |
"use strict"; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -22,32 +33,41 @@ var apache_js_workers_1 = require("apache-js-workers"); | ||
// Authenticated, try to store all files | ||
var e_1, _a; | ||
var path = apache_js_workers_1.req.body.path; | ||
try { | ||
for (var fileIndex in apache_js_workers_1.req.files) { | ||
var file = apache_js_workers_1.req.files[fileIndex]; | ||
var i = 0; | ||
// Parse File Name and File Extension | ||
var fileName = file.name.split('.').slice(0, -1).join('.'); | ||
var fileExtension = file.name.split('.').slice(-1).join(''); | ||
// Loop until a non-existing file path is found | ||
while (true) { | ||
// Create suffix for copies | ||
var suffix = (i == 0) ? '' : '-' + i.toString(); | ||
var filePath = __dirname + "/../../content" + path + "/" + fileName + suffix + "." + fileExtension; | ||
i++; | ||
// If the File Path exists, try again | ||
if (fs.existsSync(filePath)) { | ||
continue; | ||
try { | ||
for (var _b = __values(apache_js_workers_1.req.files), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var file = _c.value; | ||
var i = 0; | ||
// Parse File Name and File Extension | ||
var fileName = file.name.split('.').slice(0, -1).join('.'); | ||
var fileExtension = file.name.split('.').slice(-1).join(''); | ||
// Loop until a non-existing file path is found | ||
while (true) { | ||
// Create suffix for copies | ||
var suffix = (i == 0) ? '' : '-' + i.toString(); | ||
var filePath = path_1.resolve(__dirname + "/../../content" + path + "/" + fileName + suffix + "." + fileExtension); | ||
i++; | ||
// If the File Path exists, try again | ||
if (fs.existsSync(filePath)) { | ||
continue; | ||
} | ||
if (dotDotSlashAttack(filePath)) { | ||
// Send 403 error | ||
apache_js_workers_1.res.statusCode = 403; | ||
apache_js_workers_1.res.send('Forbidden'); | ||
throw "POSSIBLE DOT-DOT-SLASH ATTACK! user tried to upload to this path: " + filePath; | ||
} | ||
// Write the file if the File Path does not exist, and break the loop | ||
fs.writeFileSync(filePath, file.data); | ||
break; | ||
} | ||
if (dotDotSlashAttack(filePath)) { | ||
// Send 403 error | ||
apache_js_workers_1.res.statusCode = 403; | ||
apache_js_workers_1.res.send('Forbidden'); | ||
console.warn("POSSIBLE DOT-DOT-SLASH ATTACK! user tried to upload to this path: " + filePath); | ||
return; | ||
} | ||
// Write the file if the File Path does not exist, and break the loop | ||
fs.writeFileSync(filePath, file.data); | ||
break; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
apache_js_workers_1.res.send('Files uploaded!'); | ||
@@ -54,0 +74,0 @@ } |
@@ -32,4 +32,3 @@ import { req, res } from 'apache-js-workers' | ||
try { | ||
for (let fileIndex in req.files) { | ||
const file = req.files[fileIndex] | ||
for (let file of req.files) { | ||
let i = 0 | ||
@@ -48,3 +47,3 @@ | ||
const suffix = (i == 0) ? '' : '-' + i.toString() | ||
const filePath = `${ __dirname }/../../content${ path }/${ fileName }${ suffix }.${ fileExtension }` | ||
const filePath = resolvePath(`${ __dirname }/../../content${ path }/${ fileName }${ suffix }.${ fileExtension }`) | ||
@@ -64,6 +63,4 @@ i++ | ||
res.send('Forbidden') | ||
console.warn(`POSSIBLE DOT-DOT-SLASH ATTACK! user tried to upload to this path: ${ filePath }`) | ||
return | ||
throw `POSSIBLE DOT-DOT-SLASH ATTACK! user tried to upload to this path: ${ filePath }` | ||
} | ||
@@ -70,0 +67,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
358857
8082
10
+ Added@types/socket.io-client@1.4.36(transitive)