Initial commit

This commit is contained in:
abrendan
2023-11-30 14:15:19 +00:00
commit e4599df811
5457 changed files with 500139 additions and 0 deletions

7
node_modules/server/router/del.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
// Import the generic REST handler
const generic = require('./generic');
// Defined the actual method
module.exports = (...middle) => {
return generic('DELETE', ...middle);
};

25
node_modules/server/router/error.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
const join = require('../src/join');
const parse = require('./parse');
const params = require('./path-to-regexp-wrap')();
module.exports = (...all) => {
// Extracted or otherwise it'd shift once per call; also more performant
const { path, middle } = parse(all);
const match = params(path || '');
const generic = () => {};
generic.error = async ctx => {
// Only do this if the correct path
ctx.error.code = ctx.error.code || '';
ctx.error.params = match(ctx.error.code);
// Add an extra-allowing initial matching
if (!ctx.error.params && ctx.error.code.slice(0, path.length) !== path) return;
const ret = await middle[0](ctx);
delete ctx.error;
return ret;
};
return generic;
};

8
node_modules/server/router/errors.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
// YOU MIGHT BE LOOKING FOR 'error.js' (without the "s")
const error = require('../error')('/server/test/');
error.router = 'This is a demo error';
error.simplerouter = ({ text }) => `Simple message: ${text}`;
module.exports = error;

31
node_modules/server/router/generic.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
const join = require('../src/join');
const parse = require('./parse');
const params = require('./path-to-regexp-wrap')();
// Generic request handler
module.exports = (method, ...all) => {
// Extracted or otherwise it'd shift once per call; also more performant
const { path, middle } = parse(all);
const match = params(path || '');
return async ctx => {
// A route should be solved only once per request
if (ctx.req.solved) return;
// Only for the correct method
if (method !== ctx.req.method) return;
// Only do this if the correct path
ctx.req.params = match(ctx.req.path);
if (!ctx.req.params) return;
ctx.params = ctx.req.params;
// Perform this promise chain
await join(middle)(ctx);
ctx.req.solved = true;
};
};

7
node_modules/server/router/get.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
// Import the generic REST handler
const generic = require('./generic');
// Defined the actual method
module.exports = (...middle) => {
return generic('GET', ...middle);
};

21
node_modules/server/router/index.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// Define the router methods that are available to use as middleware
// Each of these is available through:
// const { get } = require('server').router;
// const { get } = require('server/router');
// const get = require('server/router/get');
// Perform the routing required
module.exports = {
// REST
get : require('./get'),
post : require('./post'),
put : require('./put'),
del : require('./del'),
// Special cases
sub : require('./sub'),
error : require('./error'),
join : require('../src/join'),
socket : require('../plugins/socket').router
};

219
node_modules/server/router/integration.test.js generated vendored Normal file
View File

@@ -0,0 +1,219 @@
// Integration - test the router within the whole server functionality
const server = require('server');
const run = require('server/test/run');
const { get, post, put, del, sub, error } = server.router;
// Mock middlewares and data:
const question = { answer: 42 };
const mirror = ctx => ctx.data;
const hello = () => 'Hello 世界';
const throwError = () => {
const err = new Error('MockError');
err.code = 'test';
throw err;
};
// CSRF validation is checked in another place; disable it for these tests
run.options = { security: false };
describe('Basic router types', () => {
it('can do a GET request', async () => {
const mid = get('/', hello);
const res = await run(mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('can do a POST request', async () => {
const mid = post('/', ctx => ctx.data);
const res = await run(mid).post('/', { body: question });
expect(res.body).toEqual({ answer: 42 });
expect(res.status).toBe(200);
});
it('can do a PUT request', async () => {
const mid = post('/', ctx => ctx.data);
const res = await run(mid).post('/', { body: question });
expect(res.body).toEqual({ answer: 42 });
expect(res.status).toBe(200);
});
it('can do a DELETE request', async () => {
const mid = del('/', ctx => 'Hello 世界');
const res = await run(mid).del('/', { body: question });
expect(res.body).toEqual('Hello 世界');
expect(res.status).toBe(200);
});
});
describe('Generic paths', () => {
it('can do a GET request', async () => {
const mid = get(hello);
const res = await run(mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('can do a GET request', async () => {
const mid = get('*', hello);
const res = await run(mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
// it('can do a POST request', async () => {
// const mid = post('/', ctx => ctx.data);
//
// const res = await run(mid).post('/', { body: question });
// expect(res.body).toEqual({ answer: 42 });
// expect(res.status).toBe(200);
// });
//
// it('can do a PUT request', async () => {
// const mid = post('/', ctx => ctx.data);
//
// const res = await run(mid).post('/', { body: question });
// expect(res.body).toEqual({ answer: 42 });
// expect(res.status).toBe(200);
// });
//
// it('can do a DELETE request', async () => {
// const mid = del('/', ctx => 'Hello 世界');
//
// const res = await run(mid).del('/', { body: question });
// expect(res.body).toEqual('Hello 世界');
// expect(res.status).toBe(200);
// });
});
describe('Subdomain router', () => {
it('can do a request to a subdomain', async () => {
const mid = sub('api', get('/', hello));
const res = await run((ctx) => {
ctx.headers.host = 'api.example.com';
}, mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('can handle regex', async () => {
const mid = sub(/^api$/, get('/', hello));
const res = await run((ctx) => {
ctx.headers.host = 'api.example.com';
}, mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('does not do partial match', async () => {
const mid = sub(/^api$/, get('/', hello));
const res = await run((ctx) => {
ctx.headers.host = 'bla.api.example.com';
}, mid, () => 'Did not match').get('/');
expect(res).toMatchObject({ status: 200, body: 'Did not match' });
});
it('can do a request to a multi-level subdomain', async () => {
const mid = sub('api.local', get('/', hello));
const res = await run((ctx) => {
ctx.headers.host = 'api.local.example.com';
}, mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
});
describe('Ends where it should end', () => {
it('uses the matching method', async () => {
const mid = [
post('/', throwError),
put('/', throwError),
del('/', throwError),
get('/', hello)
];
const res = await run(mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('uses the matching path', async () => {
const mid = [
get('/bla', throwError),
get('/:id', throwError),
get('/', hello)
];
const res = await run(mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('uses a route only once', async () => {
const mid = [
get('/', hello),
get('/', throwError)
];
const res = await run(mid).get('/');
expect(res).toMatchObject({ status: 200, body: 'Hello 世界' });
});
it('parses params correctly', async () => {
const mid = get('/:id', ctx => ctx.params.id);
const res = await run(mid).get('/42?ignored=true');
expect(res.body).toBe('42');
});
// A bug shifted the router's middleware on each request so now we test for
// multiple request to make sure the middleware remains the same
it('does not modify the router', async () => {
const inst = run(get('/', hello)).alive(async api => {
for (let url of [0, 1, 2]) {
const res = await api.get('/');
expect(res.body).toBe('Hello 世界');
}
});
});
it('does generic error matching', async () => {
let err;
const res = await run(throwError, error(ctx => {
err = ctx.error;
return 'Hello world';
})).get('/');
expect(res.body).toBe('Hello world');
expect(err.message).toMatch(/MockError/);
});
it('does path error matching', async () => {
let err;
const res = await run(throwError, error('test', ctx => {
err = ctx.error;
return 'Hello world';
})).get('/');
expect(res.body).toBe('Hello world');
expect(err.message).toMatch(/MockError/);
});
it('does empty error matching', async () => {
let err;
const res = await run(throwError).get('/');
expect(res.status).toBe(500);
});
});

5
node_modules/server/router/parse.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// Parse the request parameters
module.exports = middle => {
const path = typeof middle[0] === 'string' ? middle.shift() : '*';
return { path, middle };
};

57
node_modules/server/router/path-to-regexp-wrap.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
// This comes from https://github.com/teologov/path-to-regexp-wrap
// because of this bug: https://github.com/franciscop/server/issues/43
/**
* Path to regexp lib wrapper
* @author Andrey Teologov <teologov.and@gmail.com>
* @date 16.04.14
*/
"use strict";
const path = require('path-to-regexp');
/**
* Routes lib
* @type {exports}
*/
module.exports = function(options) {
options = options || {};
/**
* String decoder
* @param {String} str
* @returns {*}
*/
function decodeUri(str) {
try {
str = decodeURIComponent(str);
} catch(e) {
throw new Error(`Cannot decodeURIComponent: ${str}` );
}
return str;
}
return function(route) {
const keys = [];
const reg = path.apply(this, [route, keys, options]);
return function(route, config) {
const res = reg.exec(route);
const params = config || {};
if (!res) {
return false;
}
for (let i = 1, l = res.length; i < l; i++) {
if (!res[i]) {
continue;
}
params[keys[i - 1].name] = decodeUri(res[i]);
}
return params;
}
}
};

7
node_modules/server/router/post.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
// Import the generic REST handler
const generic = require('./generic');
// Defined the actual method
module.exports = (...middle) => {
return generic('POST', ...middle);
};

7
node_modules/server/router/put.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
// Import the generic REST handler
const generic = require('./generic');
// Defined the actual method
module.exports = (...middle) => {
return generic('PUT', ...middle);
};

10
node_modules/server/router/sub.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
const join = require('../src/join');
module.exports = (path, ...middle) => async ctx => {
const full = ctx.req.subdomains.reverse().join('.');
if ((typeof path === 'string' && path === full) ||
(path instanceof RegExp && path.test(full))) {
await join(middle)(ctx);
ctx.req.solved = true;
}
};

146
node_modules/server/router/unit.test.js generated vendored Normal file
View File

@@ -0,0 +1,146 @@
// Unit - test the router on its own
const extend = require('extend');
const loadware = require('loadware');
const join = require('server/src/join');
const { get, error } = require('server/router');
const RouterError = require('./errors');
const run = require('server/test/run');
const createCtx = ({ url = '/', path = '/', method = 'GET' } = {}) => extend({
req: { url, path, method },
res: { send: () => {} },
options: {}
});
const router = require('.');
describe('server/router definition', () => {
it('loads the main router', () => {
expect(router).toEqual(require('server').router);
expect(router).toBe(require('server/router'));
});
it('has the right methods defined', () => {
expect(router.get ).toEqual(jasmine.any(Function));
expect(router.get ).toEqual(jasmine.any(Function));
expect(router.post ).toEqual(jasmine.any(Function));
expect(router.put ).toEqual(jasmine.any(Function));
expect(router.del ).toEqual(jasmine.any(Function));
expect(router.sub ).toEqual(jasmine.any(Function));
expect(router.error).toEqual(jasmine.any(Function));
});
it('can load all the methods manually', () => {
expect(require('server/router/get' )).toEqual(jasmine.any(Function));
expect(require('server/router/get' )).toEqual(jasmine.any(Function));
expect(require('server/router/post' )).toEqual(jasmine.any(Function));
expect(require('server/router/put' )).toEqual(jasmine.any(Function));
expect(require('server/router/del' )).toEqual(jasmine.any(Function));
expect(require('server/router/sub' )).toEqual(jasmine.any(Function));
expect(require('server/router/error')).toEqual(jasmine.any(Function));
});
});
describe('server/router works', () => {
it('works', async () => {
const mid = [
() => new Promise((resolve) => resolve()),
get('/aaa', () => { throw new Error(); }),
get('/', () => 'Hello 世界'),
get('/sth', () => { throw new Error(); }),
get('/', () => { throw new Error(); })
];
const ctx = createCtx();
await join(mid)(ctx);
expect(ctx.req.solved).toBe(true);
});
it('works even when wrapped with join() and loadware()', async () => {
const middles = [
() => new Promise((resolve) => resolve()),
get('/aaa', () => { throw new Error(); }),
join(loadware(get('/', () => 'Hello 世界'))),
get('/sth', () => { throw new Error(); }),
get('/', () => { throw new Error(); })
];
// Returns the promise to be handled async
const ctx = createCtx();
await join(middles)(ctx);
expect(ctx.req.solved).toBe(true);
});
it('works with parameters', async () => {
const ctx = createCtx({ path: '/test/francisco/presencia/bla' });
await get('/test/:name/:lastname/bla')(ctx);
expect(ctx.req.solved).toBe(true);
expect(ctx.req.params.name).toBe('francisco');
expect(ctx.req.params.lastname).toBe('presencia');
});
});
describe('Error routes', () => {
it('can catch errors', async () => {
const generate = () => { throw new Error('Should be caught'); };
const handle = error(() => 'Error 世界');
const res = await run([generate, handle]).get('/');
expect(res.body).toBe('Error 世界');
});
it('can catch errors with full path', async () => {
const generate = ctx => { throw new RouterError('router'); };
const handle = error('/server/test/router', ctx => {
return ctx.error.code;
});
const res = await run([generate, handle]).get('/');
expect(res.body).toBe('/server/test/router');
});
it('can catch errors with partial path', async () => {
const generate = ctx => { throw new RouterError('router'); };
const handle = error('/server/test', ctx => {
return ctx.error.code;
});
const res = await run([generate, handle]).get('/');
expect(res.body).toBe('/server/test/router');
});
const errors = {
'test:pre:1': new Error('Hi there 1'),
'test:pre:a': new Error('Hi there a'),
'test:pre:b': new Error('Hi there b'),
'test:pre:build': opts => new Error(`Hi there ${opts.name}`)
};
it('can generate errors', async () => {
const generate = ctx => {
throw new RouterError('router');
};
const handle = error('/server/test/router', ctx => {
return ctx.error.code;
});
const res = await run({ errors }, [generate, handle]).get('/');
expect(res.body).toBe('/server/test/router');
});
it('can generate errors with options', async () => {
const generate = ctx => {
throw new RouterError('simplerouter', { text: 'ABC' });
};
const handle = error('/server/test/simplerouter', ctx => {
return ctx.error.message;
});
const res = await run({ errors }, [generate, handle]).get('/');
expect(res.body).toBe(`Simple message: ABC`);
});
});