@sveltejs/app-utils
Advanced tools
Comparing version 1.0.0-next.1 to 1.0.0-next.2
# @sveltejs/app-utils | ||
## 1.0.0-next.2 | ||
### Patch Changes | ||
- 73dd998: Check file/directory exists before copying | ||
- b800049: Include type declarations | ||
## 1.0.0-next.1 | ||
@@ -4,0 +11,0 @@ |
@@ -1,7 +0,8 @@ | ||
import { mkdirSync, statSync, readdirSync, copyFileSync } from 'fs'; | ||
import { basename, join, dirname } from 'path'; | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
function mkdirp(dir) { | ||
/** @param {string} dir */ | ||
export function mkdirp(dir) { | ||
try { | ||
mkdirSync(dir, { recursive: true }); | ||
fs.mkdirSync(dir, { recursive: true }); | ||
} catch (e) { | ||
@@ -13,15 +14,26 @@ if (e.code === 'EEXIST') return; | ||
function copy(from, to, filter = () => true) { | ||
if (!filter(basename(from))) return []; | ||
/** @param {string} path */ | ||
export function rimraf(path) { | ||
(fs.rmSync || fs.rmdirSync)(path, { recursive: true, force: true }); | ||
} | ||
/** | ||
* @param {string} from | ||
* @param {string} to | ||
* @param {(basename: string) => boolean} filter | ||
*/ | ||
export function copy(from, to, filter = () => true) { | ||
if (!fs.existsSync(from)) return []; | ||
if (!filter(path.basename(from))) return []; | ||
const files = []; | ||
const stats = statSync(from); | ||
const stats = fs.statSync(from); | ||
if (stats.isDirectory()) { | ||
readdirSync(from).forEach((file) => { | ||
files.push(...copy(join(from, file), join(to, file))); | ||
fs.readdirSync(from).forEach((file) => { | ||
files.push(...copy(path.join(from, file), path.join(to, file))); | ||
}); | ||
} else { | ||
mkdirp(dirname(to)); | ||
copyFileSync(from, to); | ||
mkdirp(path.dirname(to)); | ||
fs.copyFileSync(from, to); | ||
files.push(to); | ||
@@ -32,4 +44,1 @@ } | ||
} | ||
export { copy, mkdirp }; | ||
//# sourceMappingURL=index.js.map |
@@ -1,221 +0,1 @@ | ||
function read_only_form_data() { | ||
const map = new Map(); | ||
return { | ||
append(key, value) { | ||
if (map.has(key)) { | ||
map.get(key).push(value); | ||
} else { | ||
map.set(key, [value]); | ||
} | ||
}, | ||
data: new ReadOnlyFormData(map) | ||
}; | ||
} | ||
class ReadOnlyFormData { | ||
#map; | ||
constructor(map) { | ||
this.#map = map; | ||
} | ||
get(key) { | ||
const value = this.#map.get(key); | ||
return value && value[0]; | ||
} | ||
getAll(key) { | ||
return this.#map.get(key); | ||
} | ||
has(key) { | ||
return this.#map.has(key); | ||
} | ||
*[Symbol.iterator]() { | ||
for (const [key, value] of this.#map) { | ||
for (let i = 0; i < value.length; i += 1) { | ||
yield [key, value[i]]; | ||
} | ||
} | ||
} | ||
*entries() { | ||
for (const [key, value] of this.#map) { | ||
for (let i = 0; i < value.length; i += 1) { | ||
yield [key, value[i]]; | ||
} | ||
} | ||
} | ||
*keys() { | ||
for (const [key, value] of this.#map) { | ||
for (let i = 0; i < value.length; i += 1) { | ||
yield key; | ||
} | ||
} | ||
} | ||
*values() { | ||
for (const [, value] of this.#map) { | ||
for (let i = 0; i < value.length; i += 1) { | ||
yield value; | ||
} | ||
} | ||
} | ||
} | ||
function get_body(req) { | ||
const headers = req.headers; | ||
const has_body = | ||
headers['content-type'] !== undefined && | ||
// https://github.com/jshttp/type-is/blob/c1f4388c71c8a01f79934e68f630ca4a15fffcd6/index.js#L81-L95 | ||
(headers['transfer-encoding'] !== undefined || !isNaN(Number(headers['content-length']))); | ||
if (!has_body) return Promise.resolve(undefined); | ||
const [type, ...directives] = headers['content-type'].split(/;\s*/); | ||
switch (type) { | ||
case 'application/octet-stream': | ||
return get_buffer(req); | ||
case 'text/plain': | ||
return get_text(req); | ||
case 'application/json': | ||
return get_json(req); | ||
case 'application/x-www-form-urlencoded': | ||
return get_urlencoded(req); | ||
case 'multipart/form-data': { | ||
const boundary = directives.find((directive) => directive.startsWith('boundary=')); | ||
if (!boundary) throw new Error('Missing boundary'); | ||
return get_multipart(req, boundary.slice('boundary='.length)); | ||
} | ||
default: | ||
throw new Error(`Invalid Content-Type ${type}`); | ||
} | ||
} | ||
async function get_json(req) { | ||
return JSON.parse(await get_text(req)); | ||
} | ||
async function get_urlencoded(req) { | ||
const text = await get_text(req); | ||
const { data, append } = read_only_form_data(); | ||
text | ||
.replace(/\+/g, ' ') | ||
.split('&') | ||
.forEach((str) => { | ||
const [key, value] = str.split('='); | ||
append(decodeURIComponent(key), decodeURIComponent(value)); | ||
}); | ||
return data; | ||
} | ||
async function get_multipart(req, boundary) { | ||
const text = await get_text(req); | ||
const parts = text.split(`--${boundary}`); | ||
const nope = () => { | ||
throw new Error('Malformed form data'); | ||
}; | ||
if (parts[0] !== '' || parts[parts.length - 1].trim() !== '--') { | ||
nope(); | ||
} | ||
const { data, append } = read_only_form_data(); | ||
parts.slice(1, -1).forEach((part) => { | ||
const match = /\s*([\s\S]+?)\r\n\r\n([\s\S]*)\s*/.exec(part); | ||
const raw_headers = match[1]; | ||
const body = match[2].trim(); | ||
let key; | ||
raw_headers.split('\r\n').forEach((str) => { | ||
const [raw_header, ...raw_directives] = str.split('; '); | ||
let [name, value] = raw_header.split(': '); | ||
name = name.toLowerCase(); | ||
const directives = {}; | ||
raw_directives.forEach((raw_directive) => { | ||
const [name, value] = raw_directive.split('='); | ||
directives[name] = JSON.parse(value); // TODO is this right? | ||
}); | ||
if (name === 'content-disposition') { | ||
if (value !== 'form-data') nope(); | ||
if (directives.filename) { | ||
// TODO we probably don't want to do this automatically | ||
throw new Error('File upload is not yet implemented'); | ||
} | ||
if (directives.name) { | ||
key = directives.name; | ||
} | ||
} | ||
}); | ||
if (!key) nope(); | ||
append(key, body); | ||
}); | ||
return data; | ||
} | ||
function get_text(req) { | ||
return new Promise((fulfil, reject) => { | ||
let data = ''; | ||
req.on('error', reject); | ||
req.on('data', (chunk) => { | ||
data += chunk; | ||
}); | ||
req.on('end', () => { | ||
fulfil(data); | ||
}); | ||
}); | ||
} | ||
function get_buffer(req) { | ||
return new Promise((fulfil, reject) => { | ||
let data = new Uint8Array(0); | ||
req.on('error', reject); | ||
req.on('data', (chunk) => { | ||
const new_data = new Uint8Array(data.length + chunk.length); | ||
for (let i = 0; i < data.length; i += 1) { | ||
new_data[i] = data[i]; | ||
} | ||
for (let i = 0; i < chunk.length; i += 1) { | ||
new_data[i + data.length] = chunk[i]; | ||
} | ||
data = new_data; | ||
}); | ||
req.on('end', () => { | ||
fulfil(data.buffer); | ||
}); | ||
}); | ||
} | ||
export { get_body }; | ||
//# sourceMappingURL=index.js.map | ||
export { get_body } from './get_body/index.js'; |
{ | ||
"name": "@sveltejs/app-utils", | ||
"version": "1.0.0-next.1", | ||
"version": "1.0.0-next.2", | ||
"scripts": { | ||
"clean": "node rimraf.js files http renderer", | ||
"dev": "npm run clean && rollup -cw", | ||
"build": "npm run clean && rollup -c", | ||
"lint": "eslint --ignore-path .gitignore \"**/*.{ts,js,svelte}\" && npm run check-format", | ||
"build": "tsc", | ||
"format": "prettier --write . --config ../../.prettierrc --ignore-path .gitignore", | ||
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore", | ||
"prepublishOnly": "npm run build", | ||
"test": "uvu" | ||
"test": "uvu", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"dependencies": { | ||
"mime": "^2.5.0" | ||
}, | ||
"devDependencies": { | ||
"@types/mime": "^2.0.3", | ||
"@types/node": "^14.14.22", | ||
"@types/node-fetch": "^2.5.8", | ||
"devalue": "^2.0.1", | ||
"node-fetch": "^2.6.1", | ||
"rollup": "^2.38.3", | ||
"svelte": "^3.32.1" | ||
"typescript": "^4.2.2", | ||
"uvu": "^0.5.1" | ||
}, | ||
@@ -37,5 +28,4 @@ "type": "module", | ||
"files", | ||
"http", | ||
"renderer" | ||
"http" | ||
] | ||
} |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
0
3
13
338
13015
3
2
- Removedmime@^2.5.0
- Removedmime@2.6.0(transitive)