import {describe, it, expect, beforeAll, afterAll} from 'vitest'; import { App, app, Endpoint, endpoint, Operation, operation, statusCodes, validation as v, } from '../src/common'; import {Backend, backend, DataSource, Server} from '../src/backend'; import {Client} from '../src/client'; import {server} from '../src/extenders/http/backend'; import {client} from '../src/extenders/http/client'; const op = operation({ name: 'create' as const, method: 'POST' as const, }); const e = endpoint({ name: 'e' as const, schema: v.object({}), }) .can('create'); const a = app({ name: 'foo' as const, }) .operation(op) .endpoint(e); describe('app', () => { let theApp: App; let theBackend: Backend; let theClient: Client; let theDataSource: DataSource; let theEndpoint: Endpoint; let theServer: Server; let theOperation: Operation; beforeAll(async () => { theOperation = operation({ name: 'fetch' as const, }); theEndpoint = endpoint({ name: 'users' as const, schema: v.object({ username: v.string() }), }) .param('resourceId') .can('fetch'); theApp = app({ name: 'foo' as const }) .operation(theOperation) .endpoint(theEndpoint); theBackend = backend({ app: theApp }); // add recipes function that will wrap app and backend to add operations and implement them, and will return a set // of operations. // // recipes should have a backend and client counterpart. theBackend.implementOperation('fetch', async (ctx) => { // noop }); theServer = server({ backend: theBackend }); const connectionParams = { port: 3000, }; await theServer.serve(connectionParams); theClient = client({ app: theApp }); await theClient.connect(connectionParams); }); afterAll(async () => { await theClient.disconnect(); await theServer.close(); }); it('works', async () => { const response = await theClient .at(theEndpoint, { resourceId: 3 }) .makeRequest(theOperation); expect(response).toHaveProperty('status', statusCodes.HTTP_STATUS_UNPROCESSABLE_ENTITY); }); }); // const theEndpoint = endpoint({ // schema: v.object({ // username: v.string(), // }), // }) // .can('patch') // .can('query'); // // const canPatch = operation({ // name: 'patch' as const, // args: [ // 'merge', // 'delta', // ] as const, // // TODO define resource-specific stuff, like defining URL params, etc. // }); // // const canFetch = operation({ // name: 'fetch' as const, // args: [ // 'item', // 'default', // ] as const, // }); // // const canQuery = operation({ // name: 'query' as const, // }); // // const canCreate = operation({ // name: 'create' as const, // }); // // const canEmplace = operation({ // name: 'emplace' as const, // }); // // const canDelete = operation({ // name: 'delete' as const, // }); // // export const theApp = app({ // name: 'foo' as const, // }) // .operation(canQuery) // .operation(canPatch) // .operation(canFetch) // .operation(canCreate) // .operation(canEmplace) // .operation(canDelete) // .endpoint(theEndpoint); // // // // const bootstrap = async (theApp: App) => { // // if (typeof window === 'undefined') { // // const { backend } = await import('./backend'); // // const theBackend = backend({ // // app: theApp // // }); // // } // // }; // // const b = backend({ // app: theApp, // }) // .implementOperation({ // operation: 'fetch' as const, // implementation: ({ // endpoint, // arg // }) => { // switch (arg) { // case 'default': { // // } // } // }, // }); // // const s = server({ // backend: b, // }) // .serve({ // host: '0.0.0.0', // port: 3000, // basePath: '/api' // });