Switch back over to CJS. sa la vie

This commit is contained in:
Bret Comnes 2019-12-26 16:50:42 -07:00
parent 364b8fc2ed
commit abc9656e71
No known key found for this signature in database
GPG Key ID: 3705F4634DC3A1AC
11 changed files with 183 additions and 1841 deletions

17
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/test.js"
}
]
}

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# deploy-to-neocities
## See also
- [Neocities API Docs](https://neocities.org/api)
- [neocities/neocities-node](https://github.com/neocities/neocities-node): Node api

1678
dist/bundle.cjs.js vendored

File diff suppressed because it is too large Load Diff

BIN
fixtures/toot.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

BIN
fixtures/tootzzz.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,4 +1,4 @@
// Set options as a parameter, environment variable, or rc file.
// eslint-disable-next-line no-global-assign const { NeocitiesAPIClient } = require('./lib/client.js')
require = require('esm')(module/* , options */);
module.exports = require('./main.js'); module.exports = { NeocitiesAPIClient }

View File

@ -1,134 +1,124 @@
import assert from 'nanoassert'; const assert = require('nanoassert')
import fetch from 'node-fetch'; const fetch = require('node-fetch')
import { URL } from 'url'; const { URL } = require('url')
import qs from 'qs'; const qs = require('qs')
import pkg from '../package.json'; const os = require('os')
import os from 'os'; const { createReadStream } = require('fs')
const FormData = require('form-data')
const { handleResponse } = require('fetch-errors')
const pkg = require('../package.json')
const defaultURL = 'https://neocities.org/api'; const defaultURL = 'https://neocities.org'
export class NeocitiesAPIClient { class NeocitiesAPIClient {
static getKey (sitename, password, opts) { static getKey (sitename, password, opts) {
assert(sitename, 'must pass sitename as first arg'); assert(sitename, 'must pass sitename as first arg')
assert(typeof sitename === 'string', 'user arg must be a string'); assert(typeof sitename === 'string', 'user arg must be a string')
assert(password, 'must pass a password as the second arg'); assert(password, 'must pass a password as the second arg')
assert(typeof password, 'password arg must be a string'); assert(typeof password, 'password arg must be a string')
opts = Object.assign({ opts = Object.assign({
url: defaultURL url: defaultURL
}, opts); }, opts)
return fetch(); return fetch()
} }
constructor (apiKey, opts) { constructor (apiKey, opts) {
assert(apiKey, 'must pass apiKey as first argument'); assert(apiKey, 'must pass apiKey as first argument')
assert(typeof apiKey === 'string', 'apiKey must be a string'); assert(typeof apiKey === 'string', 'apiKey must be a string')
opts = Object.assign({ opts = Object.assign({
url: defaultURL url: defaultURL
}); })
this.opts = opts; this.opts = opts
this.url = opts.url; this.url = opts.url
this.apiKey = apiKey; this.apiKey = apiKey
} }
request (endpoint, args, opts) { get defaultHeaders () {
assert(endpoint, 'must pass endpoint as first argument'); return {
opts = Object.assign({}, opts);
opts.headers = Object.assign({
Authorization: `Bearer ${this.apiKey}`, Authorization: `Bearer ${this.apiKey}`,
Accept: 'application/json', Accept: 'application/json',
'User-Agent': `deploy-to-neocities/${pkg.version} (${os.type()})` 'User-Agent': `deploy-to-neocities/${pkg.version} (${os.type()})`
}, opts.headers); }
let path = `/api/${endpoint}`;
if (args) path += `?${qs.stringify(args)}`;
const url = new URL(path, this.url);
return fetch(url, opts);
} }
get (endpoint, args, opts) { get (endpoint, quieries, opts) {
assert(endpoint, 'must pass endpoint as first argument')
opts = Object.assign({ opts = Object.assign({
method: 'GET' method: 'GET'
}, opts); }, opts)
return this.request(endpoint, args, 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)
} }
post (endpoint, args, opts) { post (endpoint, formEntries, opts) {
assert(endpoint, 'must pass endpoint as first argument')
const form = new FormData()
opts = Object.assign({ opts = Object.assign({
method: 'POST' method: 'POST',
}, opts); body: form
return this.request(endpoint, args, opts); }, 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) { upload (files) {
throw new Error('NOT IMPLEMENTED'); const formEntries = files.map(({ name, path }) => {
} return {
name,
value: createReadStream(path)
}
})
deploy (folder) { return this.post('upload', formEntries).then(handleResponse)
throw new Error('NOT IMPLEMENTED');
} }
delete (filenames) { delete (filenames) {
const args = { assert(filenames, 'filenames is a required first argument')
filenames assert(Array.isArray(filenames), 'filenames argument must be an array of file paths in your website')
};
return this.post('/delete', args); const formEntries = filenames.map(file => ({
name: 'filenames[]',
value: file
}))
return this.post('delete', formEntries).then(handleResponse)
} }
list (args) { list (queries) {
// args.path: Path to list // args.path: Path to list
return this.get('/list', args).then(handleResponse); return this.get('list', queries).then(handleResponse)
} }
/** /**
* @param {Object} args Querystring arguments to include * @param {Object} args Querystring arguments to include
* @return {Promise} Fetch request promise * @return {Promise} Fetch request promise
*/ */
info (args) { info (queries) {
// args.sitename: sitename to get info on // args.sitename: sitename to get info on
return this.get('/info', args).then(handleResponse); return this.get('info', queries).then(handleResponse)
} }
}
export async function handleResponse (response) { deploy (folder) {
const contentType = response.headers.get('Content-Type'); throw new Error('NOT IMPLEMENTED')
const isJSON = contentType && contentType.match(/json/);
const data = isJSON ? await response.json() : await response.text();
if (response.ok) return data;
else {
return isJSON
? Promise.reject(new JSONHTTPError(response, data))
: Promise.reject(new TextHTTPError(response, data));
}
}
export class HTTPError extends Error {
constructor (response) {
super(response.statusText);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = new Error(response.statusText).stack;
}
this.status = response.status;
}
}
export class TextHTTPError extends HTTPError {
constructor (response, data) {
super(response);
this.data = data;
}
}
export class JSONHTTPError extends HTTPError {
constructor (response, json) {
super(response);
this.json = json;
} }
} }
module.exports = { NeocitiesAPIClient }

View File

@ -1,4 +0,0 @@
// ESM syntax is supported.
import { NeocitiesAPIClient } from './lib/client.js';
export { NeocitiesAPIClient };

View File

@ -3,17 +3,13 @@
"version": "0.0.0", "version": "0.0.0",
"description": "Github Action to deplpoy a folder to Neocities.org", "description": "Github Action to deplpoy a folder to Neocities.org",
"main": "index.js", "main": "index.js",
"module": "main.js",
"private": true, "private": true,
"scripts": { "scripts": {
"test": "run-s test:*", "test": "run-s test:*",
"test-skip:deps": "dependency-check . --no-dev --no-peer", "test-skip:deps": "dependency-check . --no-dev --no-peer",
"test:standard": "semistandard", "test:standard": "standard",
"test:tape": "tape -r esm test.js", "test:tape": "tap",
"prepare": "run-s build", "clean": "rimraf dist && mkdirp dist"
"clean": "rimraf dist && mkdirp dist",
"build": "run-s clean build:*",
"build:browserify": "rollup --config"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,24 +25,21 @@
"devDependencies": { "devDependencies": {
"builtin-modules": "^3.1.0", "builtin-modules": "^3.1.0",
"dependency-check": "^4.1.0", "dependency-check": "^4.1.0",
"esm": "^3.2.25",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"rimraf": "^3.0.0", "rimraf": "^3.0.0",
"rollup": "^1.26.5", "standard": "^14.3.1",
"rollup-plugin-commonjs": "^10.1.0", "tap": "^14.10.5"
"rollup-plugin-node-resolve": "^5.2.0",
"semistandard": "^14.2.0",
"tape": "^4.11.0",
"tape-promise": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.2.0", "@actions/core": "^1.2.0",
"@actions/github": "^1.1.0", "@actions/github": "^1.1.0",
"fetch-errors": "^1.0.1",
"form-data": "^3.0.0",
"nanoassert": "^2.0.0", "nanoassert": "^2.0.0",
"qs": "^6.9.1" "qs": "^6.9.1"
}, },
"semistandard": { "standard": {
"ignore": [ "ignore": [
"dist" "dist"
] ]

View File

@ -1,21 +0,0 @@
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import builtins from 'builtin-modules';
export default [
{
input: 'main.js',
output: [
{ file: 'dist/bundle.cjs.js', format: 'cjs' }
],
plugins: [
resolve({
browser: false,
preferBuiltins: true
}),
commonjs()
],
external: builtins
}
];

102
test.js
View File

@ -1,44 +1,82 @@
import tape from 'tape'; const tap = require('tap')
import ptape from 'tape-promise';
import { readFileSync } from 'fs';
import { resolve } from 'path';
import { NeocitiesAPIClient } from './lib/client.js';
const test = ptape(tape);
let token = process.env.NEOCITIES_API_TOKEN; const { readFileSync } = require('fs')
const { resolve } = require('path')
const { NeocitiesAPIClient } = require('./lib/client')
let token = process.env.NEOCITIES_API_TOKEN
if (!token) { if (!token) {
try { try {
const config = JSON.parse(readFileSync(resolve(__dirname, 'config.json'))); const config = JSON.parse(readFileSync(resolve(__dirname, 'config.json')))
token = config.token; token = config.token
} catch (e) { } catch (e) {
console.warn('error loading config.json'); console.warn('error loading config.json')
console.warn(e); console.warn(e)
} }
} }
if (token) { tap.test('token loaded', async t => {
test('token loaded', async t => { t.ok(token)
t.ok(token); })
});
test('basic client api', async t => { tap.test('basic client api', async t => {
const client = new NeocitiesAPIClient(token); const client = new NeocitiesAPIClient(token)
t.ok(client.info, 'info method available'); t.ok(client.info, 'info method available')
t.ok(client.list, 'list method available'); t.ok(client.list, 'list method available')
t.ok(client.get, 'get method available'); t.ok(client.get, 'get method available')
t.ok(client.post, 'post method available'); t.ok(client.post, 'post method available')
}); })
test('can get info about site', async t => { tap.test('can get info about site', async t => {
const client = new NeocitiesAPIClient(token); const client = new NeocitiesAPIClient(token)
const info = await client.info(); const info = await client.info()
console.log(info); console.log(info)
const list = await client.list(); t.equal(info.result, 'success', 'info requesst successfull')
console.log(list); const list = await client.list()
}); console.log(list)
} else { t.equal(list.result, 'success', 'list result successfull')
console.warn('No token set, live tests disabled'); })
}
// test('form data works the way I think', t => {
// const form = new FormData();
// const p = resolve(__dirname, 'package.json');
// form.append('package.json', next => next(createReadStream(p)));
//
// const concatStream = concat((data) => {
// console.log(data);
// t.end();
// });
//
// form.on('error', (err) => {
// t.error(err);
// });
// form.pipe(concatStream);
// });
tap.test('can upload and delete files', async t => {
const client = new NeocitiesAPIClient(token)
const uploadResults = await client.upload([
{
name: 'toot.gif',
path: resolve(__dirname, 'fixtures/toot.gif')
},
{
name: 'img/tootzzz.png',
path: resolve(__dirname, 'fixtures/tootzzz.png')
}
])
console.log(uploadResults)
t.equal(uploadResults.result, 'success', 'list result successfull')
const deleteResults = await client.delete([
'toot.gif',
'img/tootzzz.png'
])
console.log(deleteResults)
t.equal(deleteResults.result, 'success', 'list result successfull')
})