mirror of
https://github.com/bcomnes/deploy-to-neocities.git
synced 2026-01-16 22:56:28 +00:00
Implement easy parts of client
This commit is contained in:
parent
b3281ddda5
commit
364b8fc2ed
29
.github/workflows/example.yml
vendored
Normal file
29
.github/workflows/example.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
name: Example usage
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: sudo apt-get install xvfb
|
||||
- name: npm install, build, and test
|
||||
run: |
|
||||
npm i
|
||||
xvfb-run --auto-servernum node example.js
|
||||
env:
|
||||
CI: true
|
||||
- name: Cleanup xvfb pidx
|
||||
uses: bcomnes/cleanup-xvfb@v1
|
||||
|
||||
26
.github/workflows/test.yml
vendored
Normal file
26
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Tests
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install, build, and test
|
||||
run: |
|
||||
npm i
|
||||
npm test
|
||||
env:
|
||||
CI: true
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -59,3 +59,4 @@ typings/
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
config.json
|
||||
|
||||
@ -10,4 +10,4 @@ inputs:
|
||||
outputs: # none
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'dist/bundle.js'
|
||||
main: 'dist/bundle.cjs.js'
|
||||
|
||||
1676
dist/bundle.cjs.js
vendored
1676
dist/bundle.cjs.js
vendored
File diff suppressed because it is too large
Load Diff
4
index.js
4
index.js
@ -1,4 +1,4 @@
|
||||
// Set options as a parameter, environment variable, or rc file.
|
||||
// eslint-disable-next-line no-global-assign
|
||||
require = require('esm')(module/* , options */)
|
||||
module.exports = require('./main.js')
|
||||
require = require('esm')(module/* , options */);
|
||||
module.exports = require('./main.js');
|
||||
|
||||
134
lib/client.js
134
lib/client.js
@ -0,0 +1,134 @@
|
||||
import assert from 'nanoassert';
|
||||
import fetch from 'node-fetch';
|
||||
import { URL } from 'url';
|
||||
import qs from 'qs';
|
||||
import pkg from '../package.json';
|
||||
import os from 'os';
|
||||
|
||||
const defaultURL = 'https://neocities.org/api';
|
||||
|
||||
export 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({
|
||||
url: defaultURL
|
||||
}, opts);
|
||||
|
||||
return fetch();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
request (endpoint, args, opts) {
|
||||
assert(endpoint, 'must pass endpoint as first argument');
|
||||
opts = Object.assign({}, opts);
|
||||
opts.headers = Object.assign({
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
Accept: 'application/json',
|
||||
'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) {
|
||||
opts = Object.assign({
|
||||
method: 'GET'
|
||||
}, opts);
|
||||
return this.request(endpoint, args, opts);
|
||||
}
|
||||
|
||||
post (endpoint, args, opts) {
|
||||
opts = Object.assign({
|
||||
method: 'POST'
|
||||
}, opts);
|
||||
return this.request(endpoint, args, opts);
|
||||
}
|
||||
|
||||
upload (files) {
|
||||
throw new Error('NOT IMPLEMENTED');
|
||||
}
|
||||
|
||||
deploy (folder) {
|
||||
throw new Error('NOT IMPLEMENTED');
|
||||
}
|
||||
|
||||
delete (filenames) {
|
||||
const args = {
|
||||
filenames
|
||||
};
|
||||
|
||||
return this.post('/delete', args);
|
||||
}
|
||||
|
||||
list (args) {
|
||||
// args.path: Path to list
|
||||
return this.get('/list', args).then(handleResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args Querystring arguments to include
|
||||
* @return {Promise} Fetch request promise
|
||||
*/
|
||||
info (args) {
|
||||
// args.sitename: sitename to get info on
|
||||
return this.get('/info', args).then(handleResponse);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleResponse (response) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
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;
|
||||
}
|
||||
}
|
||||
9
main.js
9
main.js
@ -1,9 +1,4 @@
|
||||
// ESM syntax is supported.
|
||||
const thing = { foo: 'bar' }
|
||||
export {
|
||||
thing
|
||||
}
|
||||
import { NeocitiesAPIClient } from './lib/client.js';
|
||||
|
||||
console.log(thing)
|
||||
|
||||
console.log(process)
|
||||
export { NeocitiesAPIClient };
|
||||
|
||||
16
package.json
16
package.json
@ -7,8 +7,8 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "run-s test:*",
|
||||
"test:deps": "dependency-check . --no-dev --no-peer",
|
||||
"test:standard": "standard",
|
||||
"test-skip:deps": "dependency-check . --no-dev --no-peer",
|
||||
"test:standard": "semistandard",
|
||||
"test:tape": "tape -r esm test.js",
|
||||
"prepare": "run-s build",
|
||||
"clean": "rimraf dist && mkdirp dist",
|
||||
@ -27,6 +27,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/bcomnes/deploy-to-neocities#readme",
|
||||
"devDependencies": {
|
||||
"builtin-modules": "^3.1.0",
|
||||
"dependency-check": "^4.1.0",
|
||||
"esm": "^3.2.25",
|
||||
"mkdirp": "^0.5.1",
|
||||
@ -35,12 +36,19 @@
|
||||
"rollup": "^1.26.5",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"standard": "^13.1.0",
|
||||
"semistandard": "^14.2.0",
|
||||
"tape": "^4.11.0",
|
||||
"tape-promise": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.0",
|
||||
"@actions/github": "^1.1.0"
|
||||
"@actions/github": "^1.1.0",
|
||||
"nanoassert": "^2.0.0",
|
||||
"qs": "^6.9.1"
|
||||
},
|
||||
"semistandard": {
|
||||
"ignore": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import builtins from 'builtin-modules';
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -14,6 +15,7 @@ export default [
|
||||
preferBuiltins: true
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
],
|
||||
external: builtins
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
51
test.js
51
test.js
@ -1,9 +1,44 @@
|
||||
import tape from 'tape'
|
||||
import ptape from 'tape-promise'
|
||||
import { thing } from './main'
|
||||
const test = ptape(tape)
|
||||
import tape from 'tape';
|
||||
import ptape from 'tape-promise';
|
||||
import { readFileSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { NeocitiesAPIClient } from './lib/client.js';
|
||||
const test = ptape(tape);
|
||||
|
||||
test('a test', async t => {
|
||||
console.log(thing)
|
||||
t.ok('pass')
|
||||
})
|
||||
let token = process.env.NEOCITIES_API_TOKEN;
|
||||
|
||||
if (!token) {
|
||||
try {
|
||||
const config = JSON.parse(readFileSync(resolve(__dirname, 'config.json')));
|
||||
token = config.token;
|
||||
} catch (e) {
|
||||
console.warn('error loading config.json');
|
||||
console.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (token) {
|
||||
test('token loaded', async t => {
|
||||
t.ok(token);
|
||||
});
|
||||
|
||||
test('basic client api', async t => {
|
||||
const client = new NeocitiesAPIClient(token);
|
||||
|
||||
t.ok(client.info, 'info method available');
|
||||
t.ok(client.list, 'list method available');
|
||||
t.ok(client.get, 'get method available');
|
||||
t.ok(client.post, 'post method available');
|
||||
});
|
||||
|
||||
test('can get info about site', async t => {
|
||||
const client = new NeocitiesAPIClient(token);
|
||||
|
||||
const info = await client.info();
|
||||
console.log(info);
|
||||
const list = await client.list();
|
||||
console.log(list);
|
||||
});
|
||||
} else {
|
||||
console.warn('No token set, live tests disabled');
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user