diff --git a/README.md b/README.md index 60bed84..136ea72 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,15 @@ new Server({ }); ``` +or jsut use `autoconfig`. + +```javascript +const { server } = require('objective-http').server.autoconfig; +const { env } = require('ndoe:process'); + +server({ env, endpoints }); +``` + `MyEndpoint` class example: ```javascript diff --git a/package-lock.json b/package-lock.json index bb80e27..d236d65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "objective-http", - "version": "2.1.2", + "version": "2.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "objective-http", - "version": "2.1.2", + "version": "2.1.3", "license": "LGPL-3.0-only", "devDependencies": { "@dotenvx/dotenvx": "^1.60.2", diff --git a/package.json b/package.json index 5376169..2bf4d3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "objective-http", - "version": "2.1.2", + "version": "2.1.3", "description": "Proxy classes for creating a http server", "keywords": [ "web", @@ -20,7 +20,7 @@ "license": "LGPL-3.0-only", "scripts": { "lint": "eslint", - "test": "node --test --experimental-test-coverage --test-reporter=spec src/test/*.js src/test/**/*.js", + "test": "node --test --experimental-test-coverage --test-reporter=spec test/*.js test/**/*.js", "test:coverage": "node scripts/coverage.js", "release": "release-it --config release-it.config.mjs", "release:no-increment": "release-it --ci --config release-it.config.mjs --no-increment --no-git", diff --git a/src/test/e2e/client/client.js b/src/test/e2e/client/client.js deleted file mode 100644 index c604b99..0000000 --- a/src/test/e2e/client/client.js +++ /dev/null @@ -1,241 +0,0 @@ -/* node:coverage disable */ - -const { describe, it, before, after } = require('node:test'); -const assert = require('node:assert'); - -const http = require('node:http'); -const { - request: { - chunk: { JsonClientRequest, ChunkClientRequest }, - }, - response: { - chunk: { JsonClientResponse, ChunkClientResponse }, - }, -} = require('../../../js').client; -const { - Server, - handler: { - endpoint: { - EndpointHandler, - EndpointsHandler, - EndpointHandlers, - EndpointRequiredHandler, - }, - error: { - LogErrorHandler, - UnexpectedErrorHandler, - InvalidRequestErrorHandler, - HandlerNotFoundErrorHandler, - }, - }, - request: { - chunk: { JsonServerRequest, ChunkServerRequest }, - }, - response: { - chunk: { JsonServerResponse, ChunkServerResponse }, - }, -} = require('../../../js').server; - -const serverConfig = new Server({ - handler: new UnexpectedErrorHandler({ - origin: new LogErrorHandler({ - origin: new InvalidRequestErrorHandler({ - origin: new HandlerNotFoundErrorHandler({ - origin: new EndpointRequiredHandler({ - origin: new EndpointHandlers({ - handlers: [ - new EndpointHandler({ - endpoint: { - route: { - method: 'GET', - path: '/error', - }, - - handle() { - throw new Error('WTF'); - }, - }, - request: new ChunkServerRequest({}), - response: new ChunkServerResponse({}), - }), - new EndpointHandler({ - endpoint: { - route: { - method: 'GET', - path: '/test', - }, - - handle() { - return { - status: 200, - body: 'success', - }; - }, - }, - request: new ChunkServerRequest({}), - response: new ChunkServerResponse({}), - }), - new EndpointsHandler({ - endpoints: [ - { - route: { - method: 'GET', - path: '/json/test', - }, - - handle(request) { - return { - status: 200, - body: request.query, - }; - }, - }, - { - route: { - method: 'POST', - path: '/json/test', - }, - - handle(request) { - return { - status: 201, - body: request.body, - }; - }, - }, - ], - request: new JsonServerRequest({ - origin: new ChunkServerRequest({}), - }), - response: new JsonServerResponse({ - origin: new ChunkServerResponse({}), - }), - }), - ], - }), - }), - response: new ChunkServerResponse({}), - }), - response: new ChunkServerResponse({}), - }), - logger: console, - }), - response: new ChunkServerResponse({}), - }), - - options: { port: 8090 }, - http, -}); -const request = new ChunkClientRequest({ - http: http, - response: new ChunkClientResponse({}), -}); -const jsonRequest = new JsonClientRequest({ - origin: request.with({ - response: new JsonClientResponse({ - origin: request.response, - }), - }), -}); -describe('client', async () => { - let serverInstance; - before(async () => { - serverInstance = await serverConfig.start(); - }); - after(async () => { - await serverInstance.stop(); - }); - - await it('should be started', async () => { - await assert.doesNotReject( - () => - request - .with({ - options: { - host: 'localhost', - port: 8090, - method: 'GET', - }, - }) - .send(), - { message: 'fetch failed' }, - ); - - try { - await request - .with({ - options: { - host: 'localhost', - port: 8091, - method: 'GET', - }, - }) - .send(); - } catch (e) { - assert.strictEqual(e.cause.code, 'REQUEST_ERROR'); - } - }); - - await it('should return 500', async () => { - const response = await request - .with({ - options: { - host: 'localhost', - port: 8090, - method: 'GET', - path: '/error', - }, - }) - .send(); - - assert.strictEqual(response.status, 500); - }); - - await it('should return 501', async () => { - const response = await request - .with({ - options: { - host: 'localhost', - port: 8090, - method: 'GET', - path: '/not_a_test', - }, - }) - .send(); - - assert.strictEqual(response.status, 501); - }); - - await it('should return 200 and query as body', async () => { - const response = await jsonRequest - .with({ - options: { - host: 'localhost', - port: 8090, - method: 'GET', - path: '/json/test?x=x0', - }, - }) - .send(); - - assert.strictEqual(response.status, 200); - assert.deepEqual(response.body, { x: 'x0' }); - }); - - await it('should return 201 and sended body', async () => { - const response = await jsonRequest - .with({ - options: { - host: 'localhost', - port: 8090, - method: 'POST', - path: '/json/test', - }, - body: { y: 'y0' }, - }) - .send(); - - assert.strictEqual(response.status, 201); - assert.deepEqual(response.body, { y: 'y0' }); - }); -}); diff --git a/src/test/e2e/server/server.js b/src/test/e2e/server/server.js deleted file mode 100644 index d51ab4a..0000000 --- a/src/test/e2e/server/server.js +++ /dev/null @@ -1,216 +0,0 @@ -/* node:coverage disable */ - -const { describe, it, before, after } = require('node:test'); -const assert = require('node:assert'); - -const http = require('node:http'); -const console = require('node:console'); -const { - Server, - handler: { - endpoint: { - EndpointHandler, - EndpointsHandler, - EndpointHandlers, - EndpointRequiredHandler, - }, - error: { - LogErrorHandler, - UnexpectedErrorHandler, - InvalidRequestErrorHandler, - HandlerNotFoundErrorHandler, - }, - }, - request: { - chunk: { JsonServerRequest, ChunkServerRequest }, - }, - response: { - chunk: { JsonServerResponse, ChunkServerResponse }, - }, -} = require('../../../js').server; - -const serverConfig = new Server({ - handler: new UnexpectedErrorHandler({ - origin: new LogErrorHandler({ - origin: new InvalidRequestErrorHandler({ - origin: new HandlerNotFoundErrorHandler({ - origin: new EndpointRequiredHandler({ - origin: new EndpointHandlers({ - handlers: [ - new EndpointHandler({ - endpoint: { - route: { - method: 'GET', - path: '/error', - }, - - handle() { - throw new Error('WTF', { - cause: { - error: new Error('1', { - cause: { - error: new Error( - '2', - { - cause: { - error: new TypeError(), - code: '2', - }, - }, - ), - code: '1', - }, - }), - code: 'MAIN', - }, - }); - }, - }, - request: new ChunkServerRequest({}), - response: new ChunkServerResponse({}), - }), - new EndpointHandler({ - endpoint: { - route: { - method: 'GET', - path: '/test', - }, - - handle() { - return { - status: 200, - body: 'success', - }; - }, - }, - request: new ChunkServerRequest({}), - response: new ChunkServerResponse({}), - }), - new EndpointsHandler({ - endpoints: [ - { - route: { - method: 'GET', - path: '/json/test', - }, - - handle(request) { - return { - status: 200, - body: request.query, - }; - }, - }, - { - route: { - method: 'POST', - path: '/json/test', - }, - - handle(request) { - return { - status: 201, - body: request.body, - }; - }, - }, - { - route: { - method: 'POST', - path: '/not/a/json/test', - }, - - handle(request) { - return { - status: 200, - body: request.body.toString(), - }; - }, - }, - ], - request: new JsonServerRequest({ - origin: new ChunkServerRequest({}), - }), - response: new JsonServerResponse({ - origin: new ChunkServerResponse({}), - }), - }), - ], - }), - }), - response: new ChunkServerResponse({}), - }), - response: new ChunkServerResponse({}), - }), - logger: console, - }), - response: new ChunkServerResponse({}), - }), - - options: { port: 8080 }, - http, -}); - -describe('server', async () => { - let serverInstance; - before(async () => { - serverInstance = await serverConfig.start(); - }); - after(async () => await serverInstance.stop()); - - await it('should be started', async () => { - await assert.doesNotReject(() => fetch('http://localhost:8080'), { - message: 'fetch failed', - }); - }); - - await it('should return 501', async () => { - const response = await fetch('http://localhost:8080/not/a/test', { - method: 'GET', - }); - - assert.strictEqual(response.status, 501); - }); - - await it('should return 500', async () => { - const response = await fetch('http://localhost:8080/error', { - method: 'GET', - }); - - assert.strictEqual(response.status, 500); - }); - - await it('should return 200 and query in body', async () => { - const response = await fetch('http://localhost:8080/json/test?x=x0', { - method: 'GET', - }); - const body = await (await response.blob()).text(); - - assert.strictEqual(response.status, 200); - assert.strictEqual(body, JSON.stringify({ x: 'x0' })); - }); - - await it('should return 400 cause not a json body', async () => { - const response = await fetch( - 'http://localhost:8080/not/a/json/test?x=x0', - { - method: 'POST', - body: 'not a real json', - }, - ); - - assert.strictEqual(response.status, 400); - }); - - await it('should return 201 and test body', async () => { - const testBody = { x: 'x0', y: 'y0' }; - const response = await fetch('http://localhost:8080/json/test?z=z', { - method: 'POST', - body: JSON.stringify(testBody), - }); - const body = await (await response.blob()).text(); - - assert.strictEqual(response.status, 201); - assert.strictEqual(body, JSON.stringify(testBody)); - }); -}); diff --git a/test/e2e/client.js b/test/e2e/client.js new file mode 100644 index 0000000..d44a7de --- /dev/null +++ b/test/e2e/client.js @@ -0,0 +1,188 @@ +/* node:coverage disable */ + +const { describe, it, before, after } = require('node:test'); +const assert = require('node:assert'); + +const http = require('node:http'); +const { + request: { + chunk: { JsonClientRequest, ChunkClientRequest }, + }, + response: { + chunk: { JsonClientResponse, ChunkClientResponse }, + }, +} = require('../../src/js/index').client; + +const { server } = require('../../src/js/index').server.autoconfig; + +const endpoints = [ + { + route: { + method: 'GET', + path: '/error', + }, + + handle() { + throw new Error('WTF'); + }, + }, + { + route: { + method: 'GET', + path: '/test', + }, + + handle() { + return { + status: 200, + body: 'success', + }; + }, + }, + [ + { + route: { + method: 'GET', + path: '/json/test', + }, + + handle(request) { + return { + status: 200, + body: request.query, + }; + }, + }, + { + route: { + method: 'POST', + path: '/json/test', + }, + + handle(request) { + return { + status: 201, + body: request.body, + }; + }, + }, + ], +]; + +const serverConfig = server({ + endpoints, + env: { SERVER_PORT: 8090, SERVER_LOG_ENABLE: true }, +}); +const request = new ChunkClientRequest({ + http: http, + response: new ChunkClientResponse({}), +}); +const jsonRequest = new JsonClientRequest({ + origin: request.with({ + response: new JsonClientResponse({ + origin: request.response, + }), + }), +}); +describe('client', async () => { + let serverInstance; + before(async () => { + serverInstance = await serverConfig.start(); + }); + after(async () => { + await serverInstance.stop(); + }); + + await it('should be started', async () => { + await assert.doesNotReject( + () => + request + .with({ + options: { + host: 'localhost', + port: 8090, + method: 'GET', + }, + }) + .send(), + { message: 'fetch failed' }, + ); + + try { + await request + .with({ + options: { + host: 'localhost', + port: 8091, + method: 'GET', + }, + }) + .send(); + } catch (e) { + assert.strictEqual(e.cause.code, 'REQUEST_ERROR'); + } + }); + + await it('should return 500', async () => { + const response = await request + .with({ + options: { + host: 'localhost', + port: 8090, + method: 'GET', + path: '/error', + }, + }) + .send(); + + assert.strictEqual(response.status, 500); + }); + + await it('should return 501', async () => { + const response = await request + .with({ + options: { + host: 'localhost', + port: 8090, + method: 'GET', + path: '/not_a_test', + }, + }) + .send(); + + assert.strictEqual(response.status, 501); + }); + + await it('should return 200 and query as body', async () => { + const response = await jsonRequest + .with({ + options: { + host: 'localhost', + port: 8090, + method: 'GET', + path: '/json/test?x=x0', + }, + }) + .send(); + + assert.strictEqual(response.status, 200); + assert.deepEqual(response.body, { x: 'x0' }); + }); + + await it('should return 201 and sended body', async () => { + const response = await jsonRequest + .with({ + options: { + host: 'localhost', + port: 8090, + method: 'POST', + path: '/json/test', + }, + body: { y: 'y0' }, + }) + .send(); + + assert.strictEqual(response.status, 201); + assert.deepEqual(response.body, { y: 'y0' }); + }); +}); diff --git a/test/e2e/server.js b/test/e2e/server.js new file mode 100644 index 0000000..3a43060 --- /dev/null +++ b/test/e2e/server.js @@ -0,0 +1,142 @@ +/* node:coverage disable */ + +const { describe, it, before, after } = require('node:test'); +const assert = require('node:assert'); + +const { server } = require('../../src/js/index').server.autoconfig; + +const endpoints = [ + { + route: { + method: 'GET', + path: '/error', + }, + + handle() { + throw new Error('WTF'); + }, + }, + { + route: { + method: 'GET', + path: '/test', + }, + + handle() { + return { + status: 200, + body: 'success', + }; + }, + }, + [ + { + route: { + method: 'GET', + path: '/json/test', + }, + + handle(request) { + return { + status: 200, + body: request.query, + }; + }, + }, + { + route: { + method: 'POST', + path: '/json/test', + }, + + handle(request) { + return { + status: 201, + body: request.body, + }; + }, + }, + { + route: { + method: 'POST', + path: '/not/a/json/test', + }, + + handle(request) { + return { + status: 200, + body: request.body.toString(), + }; + }, + }, + ], +]; + +const serverConfig = server({ + endpoints, + env: { SERVER_PORT: 8080, SERVER_ERROR_LOG: true }, +}); + +describe('server', async () => { + let serverInstance; + before(async () => { + serverInstance = await serverConfig.start(); + }); + after(async () => await serverInstance.stop()); + + await it('should be started', async () => { + await assert.doesNotReject(() => fetch('http://localhost:8080'), { + message: 'fetch failed', + }); + }); + + await it('should return 501', async () => { + const response = await fetch('http://localhost:8080/not/a/test', { + method: 'GET', + }); + + assert.strictEqual(response.status, 501); + }); + + await it('should return 500', async () => { + const response = await fetch('http://localhost:8080/error', { + method: 'GET', + }); + + assert.strictEqual(response.status, 500); + }); + + await it('should return 200 and query in body', async () => { + const response = await fetch('http://localhost:8080/json/test?x=x0', { + method: 'GET', + }); + const body = await (await response.blob()).text(); + + assert.strictEqual(response.status, 200); + assert.strictEqual(body, JSON.stringify({ x: 'x0' })); + }); + + await it('should return 400 cause not a json body', async () => { + const response = await fetch( + 'http://localhost:8080/not/a/json/test?x=x0', + { + method: 'POST', + body: 'not a real json', + }, + ); + + assert.strictEqual(response.status, 400); + }); + + await it('should return 201 and test body', async () => { + const testBody = { x: 'x0', y: 'y0' }; + const response = await fetch('http://localhost:8080/json/test?z=z', { + method: 'POST', + body: JSON.stringify(testBody), + }); + const body = await (await response.blob()).text(); + + assert.strictEqual(response.status, 201); + assert.strictEqual(body, JSON.stringify(testBody)); + }); +});