mirror of
https://github.com/bcomnes/deploy-to-neocities.git
synced 2026-01-21 08:51:54 +00:00
Update deps
This commit is contained in:
174
node_modules/async-neocities/index.js
generated
vendored
Normal file
174
node_modules/async-neocities/index.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
const assert = require('nanoassert')
|
||||
const fetch = require('node-fetch')
|
||||
const { URL } = require('url')
|
||||
const qs = require('qs')
|
||||
const os = require('os')
|
||||
const { createReadStream } = require('fs')
|
||||
const FormData = require('form-data')
|
||||
const { handleResponse } = require('fetch-errors')
|
||||
const afw = require('async-folder-walker')
|
||||
const pkg = require('./package.json')
|
||||
const { neocitiesLocalDiff } = require('./lib/folder-diff')
|
||||
|
||||
const defaultURL = 'https://neocities.org'
|
||||
|
||||
class NeocitiesAPIClient {
|
||||
static getKey (sitename, password, opts) {
|
||||
assert(sitename, 'must pass sitename as first arg')
|
||||
assert(typeof sitename === 'string', 'user arg must be a string')
|
||||
assert(password, 'must pass a password as the second arg')
|
||||
assert(typeof password, 'password arg must be a string')
|
||||
|
||||
opts = Object.assign({
|
||||
baseURL: defaultURL
|
||||
}, opts)
|
||||
|
||||
const baseURL = opts.baseURL
|
||||
delete opts.baseURL
|
||||
|
||||
const url = new URL('/api/key', baseURL)
|
||||
url.username = sitename
|
||||
url.password = password
|
||||
return fetch(url, opts)
|
||||
}
|
||||
|
||||
constructor (apiKey, opts) {
|
||||
assert(apiKey, 'must pass apiKey as first argument')
|
||||
assert(typeof apiKey === 'string', 'apiKey must be a string')
|
||||
opts = Object.assign({
|
||||
url: defaultURL
|
||||
})
|
||||
|
||||
this.opts = opts
|
||||
this.url = opts.url
|
||||
this.apiKey = apiKey
|
||||
}
|
||||
|
||||
get defaultHeaders () {
|
||||
return {
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
Accept: 'application/json',
|
||||
'User-Agent': `deploy-to-neocities/${pkg.version} (${os.type()})`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic get request to neocities
|
||||
*/
|
||||
get (endpoint, quieries, opts) {
|
||||
assert(endpoint, 'must pass endpoint as first argument')
|
||||
opts = Object.assign({
|
||||
method: 'GET'
|
||||
}, opts)
|
||||
opts.headers = Object.assign({}, this.defaultHeaders, opts.headers)
|
||||
|
||||
let path = `/api/${endpoint}`
|
||||
if (quieries) path += `?${qs.stringify(quieries)}`
|
||||
|
||||
const url = new URL(path, this.url)
|
||||
return fetch(url, opts)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic post request to neocities
|
||||
*/
|
||||
post (endpoint, formEntries, opts) {
|
||||
assert(endpoint, 'must pass endpoint as first argument')
|
||||
const form = new FormData()
|
||||
opts = Object.assign({
|
||||
method: 'POST',
|
||||
body: form
|
||||
}, opts)
|
||||
|
||||
for (const { name, value } of formEntries) {
|
||||
form.append(name, value)
|
||||
}
|
||||
|
||||
opts.headers = Object.assign(
|
||||
{},
|
||||
this.defaultHeaders,
|
||||
form.getHeaders(),
|
||||
opts.headers)
|
||||
|
||||
const url = new URL(`/api/${endpoint}`, this.url)
|
||||
return fetch(url, opts)
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload files to neocities
|
||||
*/
|
||||
upload (files) {
|
||||
const formEntries = files.map(({ name, path }) => {
|
||||
const streamCtor = (next) => next(createReadStream(path))
|
||||
streamCtor.path = path
|
||||
return {
|
||||
name,
|
||||
value: streamCtor
|
||||
}
|
||||
})
|
||||
|
||||
return this.post('upload', formEntries).then(handleResponse)
|
||||
}
|
||||
|
||||
/**
|
||||
* delete files from your website
|
||||
*/
|
||||
delete (filenames) {
|
||||
assert(filenames, 'filenames is a required first argument')
|
||||
assert(Array.isArray(filenames), 'filenames argument must be an array of file paths in your website')
|
||||
|
||||
const formEntries = filenames.map(file => ({
|
||||
name: 'filenames[]',
|
||||
value: file
|
||||
}))
|
||||
|
||||
return this.post('delete', formEntries).then(handleResponse)
|
||||
}
|
||||
|
||||
list (queries) {
|
||||
// args.path: Path to list
|
||||
return this.get('list', queries).then(handleResponse)
|
||||
}
|
||||
|
||||
/**
|
||||
* info returns info on your site, or optionally on a sitename querystrign
|
||||
* @param {Object} args Querystring arguments to include (e.g. sitename)
|
||||
* @return {Promise} Fetch request promise
|
||||
*/
|
||||
info (queries) {
|
||||
// args.sitename: sitename to get info on
|
||||
return this.get('info', queries).then(handleResponse)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy a folder to neocities, skipping already uploaded files and optionally cleaning orphaned files.
|
||||
* @param {String} folder The path of the folder to deploy.
|
||||
* @param {Object} opts Options object.
|
||||
* @param {Boolean} opts.cleanup Boolean to delete orphaned files nor not. Defaults to false.
|
||||
* @param {Boolean} opts.statsCb Get access to stat info before uploading is complete.
|
||||
* @return {Promise} Promise containing stats about the deploy
|
||||
*/
|
||||
async deploy (folder, opts) {
|
||||
opts = {
|
||||
cleanup: false, // delete remote orphaned files
|
||||
statsCb: () => {},
|
||||
...opts
|
||||
}
|
||||
|
||||
const [localFiles, remoteFiles] = await Promise.all([
|
||||
afw.allFiles(folder, { shaper: f => f }),
|
||||
this.list()
|
||||
])
|
||||
|
||||
const { filesToUpload, filesToDelete, filesSkipped } = await neocitiesLocalDiff(remoteFiles.files, localFiles)
|
||||
opts.statsCb({ filesToUpload, filesToDelete, filesSkipped })
|
||||
const work = []
|
||||
if (filesToUpload.length > 0) work.push(this.upload(filesToUpload))
|
||||
if (opts.cleanup && filesToDelete.length > 0) { work.push(this.delete(filesToDelete)) }
|
||||
|
||||
await Promise.all(work)
|
||||
|
||||
return { filesToUpload, filesToDelete, filesSkipped }
|
||||
}
|
||||
}
|
||||
module.exports = NeocitiesAPIClient
|
||||
Reference in New Issue
Block a user