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.

159 lines
3.4 KiB

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