HATEOAS-first backend framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
3.7 KiB

  1. import {describe, it, expect, beforeAll, afterAll} from 'vitest';
  2. import {App, app, DataSource, Endpoint, endpoint, Operation, operation, validation as v} from '../src/common';
  3. import {server} from '../src/extenders/http/backend';
  4. import {Backend, backend, Server} from '../src/backend';
  5. import {Client} from '../src/client';
  6. import {client} from '../src/extenders/http/client';
  7. const op = operation({
  8. name: 'create' as const,
  9. method: 'POST' as const,
  10. });
  11. const e = endpoint({
  12. name: 'e' as const,
  13. schema: v.object({}),
  14. })
  15. .can('create');
  16. const a = app({
  17. name: 'foo' as const,
  18. })
  19. .operation(op)
  20. .endpoint(e);
  21. describe('app', () => {
  22. let theApp: App;
  23. let theBackend: Backend;
  24. let theClient: Client;
  25. let theDataSource: DataSource;
  26. let theEndpoint: Endpoint;
  27. let theServer: Server;
  28. let theOperation: Operation;
  29. beforeAll(async () => {
  30. theOperation = operation({
  31. name: 'fetch' as const,
  32. });
  33. theEndpoint = endpoint({
  34. name: 'users' as const,
  35. schema: v.object({
  36. username: v.string()
  37. }),
  38. })
  39. .param('resourceId')
  40. .can('fetch');
  41. theApp = app({
  42. name: 'foo' as const
  43. })
  44. .operation(theOperation)
  45. .endpoint(theEndpoint);
  46. theBackend = backend({
  47. app: theApp
  48. });
  49. // add recipes function that will wrap app and backend to add operations and implement them, and will return a set
  50. // of operations.
  51. //
  52. // recipes should have a backend and client counterpart.
  53. theBackend.implementOperation('fetch', (params) => {
  54. // noop
  55. });
  56. theServer = server({
  57. backend: theBackend
  58. });
  59. const connectionParams = {
  60. port: 3000,
  61. };
  62. await theServer.serve(connectionParams);
  63. theClient = client({
  64. app: theApp
  65. })
  66. .connect(connectionParams);
  67. });
  68. afterAll(() => {
  69. theServer.close();
  70. });
  71. it('works', async () => {
  72. const response = await theClient
  73. .at(theEndpoint, { resourceId: 3 })
  74. .makeRequest(theOperation);
  75. expect(response).toHaveProperty('status', 200);
  76. });
  77. });
  78. // const theEndpoint = endpoint({
  79. // schema: v.object({
  80. // username: v.string(),
  81. // }),
  82. // })
  83. // .can('patch')
  84. // .can('query');
  85. //
  86. // const canPatch = operation({
  87. // name: 'patch' as const,
  88. // args: [
  89. // 'merge',
  90. // 'delta',
  91. // ] as const,
  92. // // TODO define resource-specific stuff, like defining URL params, etc.
  93. // });
  94. //
  95. // const canFetch = operation({
  96. // name: 'fetch' as const,
  97. // args: [
  98. // 'item',
  99. // 'default',
  100. // ] as const,
  101. // });
  102. //
  103. // const canQuery = operation({
  104. // name: 'query' as const,
  105. // });
  106. //
  107. // const canCreate = operation({
  108. // name: 'create' as const,
  109. // });
  110. //
  111. // const canEmplace = operation({
  112. // name: 'emplace' as const,
  113. // });
  114. //
  115. // const canDelete = operation({
  116. // name: 'delete' as const,
  117. // });
  118. //
  119. // export const theApp = app({
  120. // name: 'foo' as const,
  121. // })
  122. // .operation(canQuery)
  123. // .operation(canPatch)
  124. // .operation(canFetch)
  125. // .operation(canCreate)
  126. // .operation(canEmplace)
  127. // .operation(canDelete)
  128. // .endpoint(theEndpoint);
  129. // //
  130. // // const bootstrap = async (theApp: App) => {
  131. // // if (typeof window === 'undefined') {
  132. // // const { backend } = await import('./backend');
  133. // // const theBackend = backend({
  134. // // app: theApp
  135. // // });
  136. // // }
  137. // // };
  138. //
  139. // const b = backend({
  140. // app: theApp,
  141. // })
  142. // .implementOperation({
  143. // operation: 'fetch' as const,
  144. // implementation: ({
  145. // endpoint,
  146. // arg
  147. // }) => {
  148. // switch (arg) {
  149. // case 'default': {
  150. //
  151. // }
  152. // }
  153. // },
  154. // });
  155. //
  156. // const s = server({
  157. // backend: b,
  158. // })
  159. // .serve({
  160. // host: '0.0.0.0',
  161. // port: 3000,
  162. // basePath: '/api'
  163. // });