@kollors/deep-json-server 1.0.0-alpha.6 → 1.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/README.md +373 -230
  2. package/README.ru.md +370 -227
  3. package/dist/bin/deep-json-server.js +1 -1
  4. package/dist/bin/deep-json-server.js.map +1 -1
  5. package/dist/index.d.ts +10 -8
  6. package/dist/index.js +3 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/src/auth/contract.d.ts +6 -2
  9. package/dist/src/auth/contract.js +8 -1
  10. package/dist/src/auth/contract.js.map +1 -1
  11. package/dist/src/auth/input.d.ts +18 -0
  12. package/dist/src/auth/input.js +34 -0
  13. package/dist/src/auth/input.js.map +1 -0
  14. package/dist/src/auth/password.d.ts +13 -0
  15. package/dist/src/auth/password.js +17 -1
  16. package/dist/src/auth/password.js.map +1 -1
  17. package/dist/src/auth/routes.d.ts +3 -0
  18. package/dist/src/auth/routes.js +6 -0
  19. package/dist/src/auth/routes.js.map +1 -1
  20. package/dist/src/auth/service.d.ts +64 -4
  21. package/dist/src/auth/service.js +167 -61
  22. package/dist/src/auth/service.js.map +1 -1
  23. package/dist/src/auth/store.d.ts +26 -0
  24. package/dist/src/auth/store.js +82 -0
  25. package/dist/src/auth/store.js.map +1 -0
  26. package/dist/src/cli/index.d.ts +7 -0
  27. package/dist/src/{cli.js → cli/index.js} +31 -15
  28. package/dist/src/cli/index.js.map +1 -0
  29. package/dist/src/core/config-values.d.ts +28 -0
  30. package/dist/src/core/config-values.js +53 -0
  31. package/dist/src/core/config-values.js.map +1 -0
  32. package/dist/src/{constants.d.ts → core/constants.d.ts} +1 -1
  33. package/dist/src/{constants.js → core/constants.js} +1 -1
  34. package/dist/src/core/constants.js.map +1 -0
  35. package/dist/src/core/database.d.ts +53 -0
  36. package/dist/src/{database.js → core/database.js} +23 -3
  37. package/dist/src/core/database.js.map +1 -0
  38. package/dist/src/core/engine.d.ts +65 -0
  39. package/dist/src/{engine.js → core/engine.js} +114 -59
  40. package/dist/src/core/engine.js.map +1 -0
  41. package/dist/src/{errors.d.ts → core/errors.d.ts} +4 -1
  42. package/dist/src/core/errors.js +12 -0
  43. package/dist/src/core/errors.js.map +1 -0
  44. package/dist/src/core/http-errors.d.ts +9 -0
  45. package/dist/src/core/http-errors.js +15 -0
  46. package/dist/src/core/http-errors.js.map +1 -0
  47. package/dist/src/core/lifecycle/mutation.d.ts +49 -0
  48. package/dist/src/core/lifecycle/mutation.js +170 -0
  49. package/dist/src/core/lifecycle/mutation.js.map +1 -0
  50. package/dist/src/core/lifecycle/options.d.ts +21 -0
  51. package/dist/src/core/lifecycle/options.js +19 -0
  52. package/dist/src/core/lifecycle/options.js.map +1 -0
  53. package/dist/src/core/model.d.ts +131 -0
  54. package/dist/src/{model.js → core/model.js} +106 -10
  55. package/dist/src/core/model.js.map +1 -0
  56. package/dist/src/{mutations → core/mutations}/write.d.ts +4 -4
  57. package/dist/src/{mutations → core/mutations}/write.js +14 -4
  58. package/dist/src/core/mutations/write.js.map +1 -0
  59. package/dist/src/core/operations.d.ts +33 -0
  60. package/dist/src/core/operations.js +10 -0
  61. package/dist/src/core/operations.js.map +1 -0
  62. package/dist/src/core/pagination.d.ts +10 -0
  63. package/dist/src/core/pagination.js +13 -0
  64. package/dist/src/core/pagination.js.map +1 -0
  65. package/dist/src/core/paths.d.ts +16 -0
  66. package/dist/src/{paths.js → core/paths.js} +16 -0
  67. package/dist/src/core/paths.js.map +1 -0
  68. package/dist/src/core/query/contract.d.ts +6 -0
  69. package/dist/src/{query → core/query}/contract.js +3 -0
  70. package/dist/src/core/query/contract.js.map +1 -0
  71. package/dist/src/core/query/filter.d.ts +6 -0
  72. package/dist/src/{query → core/query}/filter.js +18 -4
  73. package/dist/src/core/query/filter.js.map +1 -0
  74. package/dist/src/core/query/options.d.ts +30 -0
  75. package/dist/src/{query → core/query}/options.js +12 -0
  76. package/dist/src/core/query/options.js.map +1 -0
  77. package/dist/src/core/records.d.ts +46 -0
  78. package/dist/src/{records.js → core/records.js} +24 -3
  79. package/dist/src/core/records.js.map +1 -0
  80. package/dist/src/core/relation-metadata.d.ts +15 -0
  81. package/dist/src/{relation-metadata.js → core/relation-metadata.js} +7 -1
  82. package/dist/src/core/relation-metadata.js.map +1 -0
  83. package/dist/src/core/types.d.ts +10 -0
  84. package/dist/src/{types.js.map → core/types.js.map} +1 -1
  85. package/dist/src/core/utils.d.ts +56 -0
  86. package/dist/src/core/utils.js +102 -0
  87. package/dist/src/core/utils.js.map +1 -0
  88. package/dist/src/files/contract.d.ts +33 -0
  89. package/dist/src/files/contract.js +25 -3
  90. package/dist/src/files/contract.js.map +1 -1
  91. package/dist/src/files/disk-store.d.ts +3 -0
  92. package/dist/src/files/disk-store.js +25 -18
  93. package/dist/src/files/disk-store.js.map +1 -1
  94. package/dist/src/files/http.d.ts +8 -3
  95. package/dist/src/files/http.js +9 -0
  96. package/dist/src/files/http.js.map +1 -1
  97. package/dist/src/files/index.d.ts +4 -3
  98. package/dist/src/files/index.js +3 -1
  99. package/dist/src/files/index.js.map +1 -1
  100. package/dist/src/files/memory-store.d.ts +4 -1
  101. package/dist/src/files/memory-store.js +21 -15
  102. package/dist/src/files/memory-store.js.map +1 -1
  103. package/dist/src/files/routes.d.ts +3 -0
  104. package/dist/src/files/routes.js +25 -1
  105. package/dist/src/files/routes.js.map +1 -1
  106. package/dist/src/files/streams.d.ts +5 -0
  107. package/dist/src/files/streams.js +20 -0
  108. package/dist/src/files/streams.js.map +1 -0
  109. package/dist/src/graphql/entry.d.ts +12 -3
  110. package/dist/src/graphql/entry.js +12 -2
  111. package/dist/src/graphql/entry.js.map +1 -1
  112. package/dist/src/graphql/generate.d.ts +11 -0
  113. package/dist/src/graphql/generate.js +17 -0
  114. package/dist/src/graphql/generate.js.map +1 -0
  115. package/dist/src/graphql/preflight.d.ts +4 -1
  116. package/dist/src/graphql/preflight.js +3 -0
  117. package/dist/src/graphql/preflight.js.map +1 -1
  118. package/dist/src/graphql/resolvers.d.ts +10 -2
  119. package/dist/src/graphql/resolvers.js +8 -2
  120. package/dist/src/graphql/resolvers.js.map +1 -1
  121. package/dist/src/graphql/routes.d.ts +6 -2
  122. package/dist/src/graphql/routes.js +6 -3
  123. package/dist/src/graphql/routes.js.map +1 -1
  124. package/dist/src/graphql/schema.d.ts +6 -0
  125. package/dist/src/{graphql.js → graphql/schema.js} +20 -14
  126. package/dist/src/graphql/schema.js.map +1 -0
  127. package/dist/src/graphql/write.d.ts +3 -0
  128. package/dist/src/graphql/write.js +3 -0
  129. package/dist/src/graphql/write.js.map +1 -1
  130. package/dist/src/openapi/auth.d.ts +13 -0
  131. package/dist/src/openapi/auth.js +139 -0
  132. package/dist/src/openapi/auth.js.map +1 -0
  133. package/dist/src/openapi/document.d.ts +5 -2
  134. package/dist/src/openapi/document.js +41 -42
  135. package/dist/src/openapi/document.js.map +1 -1
  136. package/dist/src/openapi/entry.d.ts +14 -3
  137. package/dist/src/openapi/entry.js +12 -1
  138. package/dist/src/openapi/entry.js.map +1 -1
  139. package/dist/src/openapi/files.d.ts +6 -0
  140. package/dist/src/{files/openapi.js → openapi/files.js} +6 -3
  141. package/dist/src/openapi/files.js.map +1 -0
  142. package/dist/src/openapi/generate.d.ts +19 -0
  143. package/dist/src/openapi/generate.js +39 -0
  144. package/dist/src/openapi/generate.js.map +1 -0
  145. package/dist/src/openapi/helpers.d.ts +10 -1
  146. package/dist/src/openapi/helpers.js +9 -0
  147. package/dist/src/openapi/helpers.js.map +1 -1
  148. package/dist/src/openapi/options.d.ts +20 -0
  149. package/dist/src/openapi/options.js +13 -0
  150. package/dist/src/openapi/options.js.map +1 -0
  151. package/dist/src/{types.d.ts → openapi/types.d.ts} +1 -10
  152. package/dist/src/openapi/types.js +2 -0
  153. package/dist/src/openapi/types.js.map +1 -0
  154. package/dist/src/openapi/write.d.ts +5 -0
  155. package/dist/src/openapi/write.js +12 -0
  156. package/dist/src/openapi/write.js.map +1 -0
  157. package/dist/src/rest/options.d.ts +11 -2
  158. package/dist/src/rest/options.js +12 -3
  159. package/dist/src/rest/options.js.map +1 -1
  160. package/dist/src/rest/projection.d.ts +10 -4
  161. package/dist/src/rest/projection.js +10 -4
  162. package/dist/src/rest/projection.js.map +1 -1
  163. package/dist/src/rest/routes.d.ts +6 -2
  164. package/dist/src/rest/routes.js +12 -11
  165. package/dist/src/rest/routes.js.map +1 -1
  166. package/dist/src/server/config.d.ts +76 -0
  167. package/dist/src/{config.js → server/config.js} +71 -74
  168. package/dist/src/server/config.js.map +1 -0
  169. package/dist/src/server/create.d.ts +18 -0
  170. package/dist/src/{server.js → server/create.js} +33 -28
  171. package/dist/src/server/create.js.map +1 -0
  172. package/dist/src/server/features.d.ts +15 -0
  173. package/dist/src/{features.js → server/features.js} +8 -2
  174. package/dist/src/server/features.js.map +1 -0
  175. package/dist/src/server/public.d.ts +3 -3
  176. package/dist/src/server/public.js +1 -1
  177. package/dist/src/server/public.js.map +1 -1
  178. package/package.json +1 -1
  179. package/dist/src/auth/openapi.d.ts +0 -10
  180. package/dist/src/auth/openapi.js +0 -62
  181. package/dist/src/auth/openapi.js.map +0 -1
  182. package/dist/src/cli.d.ts +0 -4
  183. package/dist/src/cli.js.map +0 -1
  184. package/dist/src/config.d.ts +0 -86
  185. package/dist/src/config.js.map +0 -1
  186. package/dist/src/constants.js.map +0 -1
  187. package/dist/src/database.d.ts +0 -20
  188. package/dist/src/database.js.map +0 -1
  189. package/dist/src/engine.d.ts +0 -36
  190. package/dist/src/engine.js.map +0 -1
  191. package/dist/src/errors.js +0 -9
  192. package/dist/src/errors.js.map +0 -1
  193. package/dist/src/features.d.ts +0 -9
  194. package/dist/src/features.js.map +0 -1
  195. package/dist/src/files/openapi.d.ts +0 -3
  196. package/dist/src/files/openapi.js.map +0 -1
  197. package/dist/src/graphql/public.d.ts +0 -3
  198. package/dist/src/graphql/public.js +0 -11
  199. package/dist/src/graphql/public.js.map +0 -1
  200. package/dist/src/graphql.d.ts +0 -3
  201. package/dist/src/graphql.js.map +0 -1
  202. package/dist/src/http/errors.d.ts +0 -6
  203. package/dist/src/http/errors.js +0 -3
  204. package/dist/src/http/errors.js.map +0 -1
  205. package/dist/src/model.d.ts +0 -72
  206. package/dist/src/model.js.map +0 -1
  207. package/dist/src/mutations/write.js.map +0 -1
  208. package/dist/src/openapi/index.d.ts +0 -7
  209. package/dist/src/openapi/index.js +0 -28
  210. package/dist/src/openapi/index.js.map +0 -1
  211. package/dist/src/openapi/public.d.ts +0 -18
  212. package/dist/src/openapi/public.js +0 -20
  213. package/dist/src/openapi/public.js.map +0 -1
  214. package/dist/src/pagination.d.ts +0 -7
  215. package/dist/src/pagination.js +0 -12
  216. package/dist/src/pagination.js.map +0 -1
  217. package/dist/src/paths.d.ts +0 -7
  218. package/dist/src/paths.js.map +0 -1
  219. package/dist/src/query/contract.d.ts +0 -3
  220. package/dist/src/query/contract.js.map +0 -1
  221. package/dist/src/query/filter.d.ts +0 -3
  222. package/dist/src/query/filter.js.map +0 -1
  223. package/dist/src/query/options.d.ts +0 -18
  224. package/dist/src/query/options.js.map +0 -1
  225. package/dist/src/records.d.ts +0 -25
  226. package/dist/src/records.js.map +0 -1
  227. package/dist/src/relation-metadata.d.ts +0 -9
  228. package/dist/src/relation-metadata.js.map +0 -1
  229. package/dist/src/schema.d.ts +0 -8
  230. package/dist/src/schema.js +0 -13
  231. package/dist/src/schema.js.map +0 -1
  232. package/dist/src/server.d.ts +0 -12
  233. package/dist/src/server.js.map +0 -1
  234. package/dist/src/utils.d.ts +0 -12
  235. package/dist/src/utils.js +0 -58
  236. package/dist/src/utils.js.map +0 -1
  237. /package/dist/src/{types.js → core/types.js} +0 -0
@@ -1,14 +1,22 @@
1
+ import { getBoolean, getObject, getPositiveInteger, getString, normalizeAddress } from '../core/config-values.js';
2
+ import { DEFAULT_MAX_FILE_SIZE } from '../core/constants.js';
3
+ import { recordOptions } from '../core/lifecycle/options.js';
4
+ import { errorMessage } from '../core/utils.js';
5
+ import { normalizeOpenapiInfo } from '../openapi/options.js';
1
6
  import { dirname, resolve } from 'node:path';
2
7
  import { pathToFileURL } from 'node:url';
3
- import { normalizePagination } from './pagination.js';
4
- import { assertKnownKeys, isObject } from './utils.js';
8
+ import { normalizePagination } from '../core/pagination.js';
9
+ import { assertKnownKeys, isObject } from '../core/utils.js';
5
10
  const CONFIG_KEYS = new Set(['database', 'files', 'openapi', 'graphql', 'server', 'auth']);
6
- const DATABASE_KEYS = new Set(['data', 'path', 'schema']);
11
+ const DATABASE_KEYS = new Set(['data', 'path', 'schema', 'timestamps', 'softDelete']);
7
12
  const FILES_KEYS = new Set(['data', 'directory', 'metadata']);
8
13
  const OPENAPI_KEYS = new Set(['path', 'info', 'enabled', 'endpoint']);
9
14
  const GRAPHQL_KEYS = new Set(['path', 'enabled', 'endpoint']);
10
15
  const SERVER_KEYS = new Set(['cors', 'host', 'logger', 'maxFileSize', 'maxPageSize', 'pageSize', 'port']);
11
16
  let configImportIndex = 0;
17
+ /** Глубоко копирует структурированные данные и оборачивает ошибку неподдерживаемого значения.
18
+ * @example copyInput({ a: [1] }) → независимая копия { a: [1] }; функция в значении → ошибка.
19
+ */
12
20
  const copyInput = (value) => {
13
21
  try {
14
22
  return structuredClone(value);
@@ -17,34 +25,13 @@ const copyInput = (value) => {
17
25
  throw new Error('Input must contain JSON data or binary file content', { cause: error });
18
26
  }
19
27
  };
20
- function getObject(value, path, required = false) {
21
- if (value == null && !required) {
22
- return undefined;
23
- }
24
- if (!isObject(value)) {
25
- throw new Error(`Ключ ${path} должен быть JSON-объектом`);
26
- }
27
- return value;
28
- }
29
- function getString(value, path, required = false) {
30
- if (value == null && !required) {
31
- return undefined;
32
- }
33
- if (typeof value !== 'string' || value.trim() === '') {
34
- throw new Error(`Ключ ${path} должен содержать непустую строку`);
35
- }
36
- return value;
37
- }
28
+ /** Делает заданный путь абсолютным относительно указанного каталога.
29
+ * @example resolveConfigPath('a.json', '/tmp') '/tmp/a.json'; undefined → undefined.
30
+ */
38
31
  const resolveConfigPath = (value, directoryPath) => (value == null ? undefined : resolve(directoryPath, value));
39
- const getPositiveInteger = (value, path) => {
40
- if (value == null) {
41
- return undefined;
42
- }
43
- if (typeof value !== 'number' || !Number.isInteger(value) || value < 1) {
44
- throw new Error(`Ключ ${path} должен быть положительным целым числом`);
45
- }
46
- return value;
47
- };
32
+ /** Принимает объект описания или разрешает путь к нему относительно каталога.
33
+ * @example normalizeSchema('schema.json', '/tmp') → '/tmp/schema.json'.
34
+ */
48
35
  const normalizeSchema = (schema, directoryPath) => {
49
36
  if (schema == null) {
50
37
  return undefined;
@@ -54,6 +41,9 @@ const normalizeSchema = (schema, directoryPath) => {
54
41
  }
55
42
  return getObject(schema, 'config.database.schema', true);
56
43
  };
44
+ /** Проверяет выбор между файлом и данными в памяти, разрешает пути и копирует данные.
45
+ * @example { path: 'db.json' } с каталогом /tmp → path: '/tmp/db.json'; одновременно data и path → ошибка.
46
+ */
57
47
  const normalizeDatabase = (value, directoryPath) => {
58
48
  const database = getObject(value, 'config.database', true);
59
49
  assertKnownKeys(database, DATABASE_KEYS, 'config.database');
@@ -63,11 +53,19 @@ const normalizeDatabase = (value, directoryPath) => {
63
53
  throw new Error('Укажите ровно один из ключей config.database.path и config.database.data');
64
54
  }
65
55
  const schema = normalizeSchema(database.schema, directoryPath);
56
+ recordOptions({ timestamps: database.timestamps, softDelete: database.softDelete });
57
+ const flags = {
58
+ ...(database.timestamps !== undefined ? { timestamps: database.timestamps } : {}),
59
+ ...(database.softDelete !== undefined ? { softDelete: database.softDelete } : {}),
60
+ };
66
61
  if (hasData) {
67
- return { data: copyInput(getObject(database.data, 'config.database.data', true)), schema };
62
+ return { data: copyInput(getObject(database.data, 'config.database.data', true)), schema, ...flags };
68
63
  }
69
- return { path: resolve(directoryPath, getString(database.path, 'config.database.path', true)), schema };
64
+ return { path: resolve(directoryPath, getString(database.path, 'config.database.path', true)), schema, ...flags };
70
65
  };
66
+ /** Проверяет выбор между файлами в памяти и дисковым хранилищем, разрешает пути.
67
+ * @example normalizeFiles(undefined, '/tmp') → undefined; { data: [] } → { data: [] }.
68
+ */
71
69
  const normalizeFiles = (value, directoryPath) => {
72
70
  const files = getObject(value, 'config.files');
73
71
  if (files == null) {
@@ -90,24 +88,27 @@ const normalizeFiles = (value, directoryPath) => {
90
88
  metadata: resolve(directoryPath, getString(files.metadata, 'config.files.metadata', true)),
91
89
  };
92
90
  };
91
+ /** Проверяет источник учётных записей и срок сессии; массив копирует, путь делает абсолютным.
92
+ * @example { users: 'users.json' } с каталогом /tmp → users: '/tmp/users.json'.
93
+ */
93
94
  const normalizeAuth = (value, directory) => {
94
95
  const auth = getObject(value, 'config.auth');
95
96
  if (!auth)
96
97
  return undefined;
97
- assertKnownKeys(auth, new Set(['enabled', 'users', 'expiresIn']), 'config.auth');
98
- if (auth.enabled !== undefined && typeof auth.enabled !== 'boolean')
99
- throw new Error('config.auth.enabled must be boolean');
98
+ assertKnownKeys(auth, new Set(['users', 'expiresIn']), 'config.auth');
100
99
  if (typeof auth.users !== 'string' && !Array.isArray(auth.users))
101
100
  throw new Error('config.auth.users must be a file path or user array');
102
101
  const expiresIn = getPositiveInteger(auth.expiresIn, 'config.auth.expiresIn');
103
102
  if (expiresIn !== undefined && expiresIn > 2147483647)
104
103
  throw new Error('config.auth.expiresIn must be at most 2147483647 seconds');
105
104
  return {
106
- enabled: auth.enabled,
107
105
  users: typeof auth.users === 'string' ? resolve(directory, getString(auth.users, 'config.auth.users', true)) : copyInput(auth.users),
108
106
  expiresIn,
109
107
  };
110
108
  };
109
+ /** Проверяет секции настроек и возвращает нормализованный объект с абсолютными путями.
110
+ * @example { database: { path: 'db.json' } } с каталогом /tmp → database.path: '/tmp/db.json'.
111
+ */
111
112
  const normalizeConfig = (config, directoryPath = '.') => {
112
113
  if (!isObject(config)) {
113
114
  throw new Error('Конфигурация сервера должна содержать JSON-объект');
@@ -120,74 +121,64 @@ const normalizeConfig = (config, directoryPath = '.') => {
120
121
  const server = getObject(config.server, 'config.server') ?? {};
121
122
  assertKnownKeys(openapi, OPENAPI_KEYS, 'config.openapi');
122
123
  assertKnownKeys(graphql, GRAPHQL_KEYS, 'config.graphql');
123
- if (openapi.enabled !== undefined && typeof openapi.enabled !== 'boolean')
124
- throw new Error('config.openapi.enabled must be boolean');
124
+ const openapiEnabled = getBoolean(openapi.enabled, 'config.openapi.enabled') ?? false;
125
125
  const openapiEndpoint = getString(openapi.endpoint, 'config.openapi.endpoint');
126
126
  if (openapiEndpoint && !/^\/[A-Za-z][A-Za-z0-9_./-]*$/.test(openapiEndpoint))
127
127
  throw new Error('Invalid OpenAPI endpoint');
128
- if (graphql.enabled !== undefined && typeof graphql.enabled !== 'boolean')
129
- throw new Error('config.graphql.enabled must be boolean');
128
+ const graphqlEnabled = getBoolean(graphql.enabled, 'config.graphql.enabled') ?? false;
130
129
  const endpoint = getString(graphql.endpoint, 'config.graphql.endpoint');
131
130
  if (endpoint && (!/^\/[A-Za-z][A-Za-z0-9_/-]*$/.test(endpoint) || endpoint === '/'))
132
131
  throw new Error('Invalid GraphQL endpoint');
133
- const info = getObject(openapi.info, 'config.openapi.info');
134
- if (info && (typeof info.title !== 'string' || typeof info.version !== 'string'))
135
- throw new Error('OpenAPI info requires title and version');
132
+ const info = normalizeOpenapiInfo(openapi.info);
136
133
  assertKnownKeys(server, SERVER_KEYS, 'config.server');
137
134
  const openapiPath = getString(openapi.path, 'config.openapi.path');
138
- const cors = server.cors;
139
- const host = getString(server.host, 'config.server.host');
135
+ const cors = getBoolean(server.cors ?? undefined, 'config.server.cors') ?? true;
136
+ const { host, port } = normalizeAddress(server);
140
137
  const logger = server.logger;
141
138
  const maxFileSize = getPositiveInteger(server.maxFileSize, 'config.server.maxFileSize');
142
- const maxPageSize = getPositiveInteger(server.maxPageSize, 'config.server.maxPageSize');
143
- const pageSize = getPositiveInteger(server.pageSize, 'config.server.pageSize');
144
- normalizePagination({ pageSize, maxPageSize });
145
- const port = server.port;
146
- if (port != null && (typeof port !== 'number' || !Number.isInteger(port) || port < 0 || port > 65_535)) {
147
- throw new Error('Ключ config.server.port должен быть целым числом от 0 до 65535');
148
- }
139
+ const pagination = normalizePagination(server);
149
140
  if (logger != null && typeof logger !== 'boolean' && !isObject(logger)) {
150
141
  throw new Error('Ключ config.server.logger должен содержать boolean или JSON-объект');
151
142
  }
152
- if (cors != null && typeof cors !== 'boolean') {
153
- throw new Error('Ключ config.server.cors должен содержать boolean');
154
- }
155
143
  return {
156
144
  database,
157
145
  files,
158
146
  auth: normalizeAuth(config.auth, directoryPath),
159
147
  openapi: {
160
- enabled: openapi.enabled,
161
- endpoint: openapiEndpoint,
148
+ enabled: openapiEnabled,
149
+ endpoint: openapiEndpoint ?? '/openapi.json',
162
150
  path: resolveConfigPath(openapiPath, directoryPath),
163
- ...(info && { info: copyInput(info) }),
151
+ ...(info && { info }),
164
152
  },
165
- graphql: { path: resolveConfigPath(getString(graphql.path, 'config.graphql.path'), directoryPath), enabled: graphql.enabled, endpoint },
153
+ graphql: { path: resolveConfigPath(getString(graphql.path, 'config.graphql.path'), directoryPath), enabled: graphqlEnabled, endpoint: endpoint ?? '/graphql' },
166
154
  server: {
167
- cors: cors,
155
+ cors,
168
156
  host,
169
- logger: logger,
170
- maxFileSize,
171
- maxPageSize,
172
- pageSize,
173
- port: port,
157
+ logger: (logger ?? true),
158
+ maxFileSize: maxFileSize ?? DEFAULT_MAX_FILE_SIZE,
159
+ ...pagination,
160
+ port,
174
161
  },
175
162
  };
176
163
  };
177
- /** Validates configuration and resolves relative paths. */
164
+ /** Проверяет настройки и разрешает относительные пути, не читая содержимое файлов.
165
+ * @example При directoryPath = '/tmp' путь './db.json' → '/tmp/db.json'.
166
+ */
178
167
  export const normalizeServerConfig = (config, directoryPath) => normalizeConfig(config, directoryPath);
179
- /** Loads an ES module config and resolves paths from its directory. */
168
+ /** Загружает default-экспорт ES-модуля, обходя кеш повторного импорта; выполняет код модуля.
169
+ * @example Файл /tmp/config.mjs с export default {} → { config: {}, directory: '/tmp', path: '/tmp/config.mjs' }.
170
+ */
180
171
  export async function readConfigModule(configPath) {
181
172
  const resolvedConfigPath = resolve(getString(configPath, 'config', true));
182
173
  let config;
183
174
  try {
184
175
  const configUrl = pathToFileURL(resolvedConfigPath);
185
- // Bypass the module cache so repeated reads use the latest config.
176
+ // Обходим кеш модуля, чтобы повторное чтение выполняло обновлённый файл.
186
177
  configUrl.searchParams.set('deep-json-server-import', String(configImportIndex++));
187
178
  config = (await import(configUrl.href)).default;
188
179
  }
189
180
  catch (error) {
190
- const message = error instanceof Error ? error.message : String(error);
181
+ const message = errorMessage(error);
191
182
  throw new Error(`Не удалось загрузить конфигурацию ${resolvedConfigPath}: ${message}`, { cause: error });
192
183
  }
193
184
  if (!isObject(config)) {
@@ -196,26 +187,32 @@ export async function readConfigModule(configPath) {
196
187
  return { config, directory: dirname(resolvedConfigPath), path: resolvedConfigPath };
197
188
  }
198
189
  const sourcePaths = new WeakMap();
190
+ /** Возвращает сохранённый путь исходного файла для данного объекта настроек.
191
+ * @example Для объекта без зарегистрированного источника → undefined.
192
+ */
199
193
  export const configSourcePath = (config) => sourcePaths.get(config);
194
+ /** Нормализует настройки и запоминает путь их источника во внутренней таблице.
195
+ * @example configure(config, '/tmp', '/tmp/config.mjs') → настройки; configSourcePath(result) → '/tmp/config.mjs'.
196
+ */
200
197
  export function configure(config, directory, sourcePath) {
201
198
  const normalized = normalizeConfig(config, directory);
202
199
  if (sourcePath)
203
200
  sourcePaths.set(normalized, sourcePath);
204
201
  return normalized;
205
202
  }
203
+ /** Выбирает настройки для указанных форматов экспорта и подставляет пустые данные вместо чтения базы.
204
+ * @example formats = ['graphql'] → настройки генерации GraphQL с database.data = {}.
205
+ */
206
206
  export function configureGeneration(source, formats, directory, sourcePath, overrides) {
207
207
  assertKnownKeys(source, CONFIG_KEYS, 'config');
208
208
  const database = getObject(source.database, 'config.database', true);
209
209
  if (database.schema === undefined)
210
210
  throw new Error('Generation requires an explicit model schema');
211
211
  const openapi = formats.includes('openapi');
212
- const auth = openapi ? getObject(source.auth, 'config.auth') : undefined;
213
- if (auth?.enabled !== undefined && typeof auth.enabled !== 'boolean')
214
- throw new Error('config.auth.enabled must be boolean');
215
212
  const server = openapi ? (getObject(source.server, 'config.server') ?? {}) : {};
216
213
  return configure({
217
- database: { data: {}, schema: database.schema },
218
- auth: openapi ? { users: [], enabled: overrides.auth ?? auth?.enabled ?? false } : undefined,
214
+ database: { data: {}, schema: database.schema, timestamps: overrides.timestamps ?? database.timestamps, softDelete: overrides.softDelete ?? database.softDelete },
215
+ auth: source.auth != null ? { users: [] } : undefined,
219
216
  openapi: openapi ? source.openapi : undefined,
220
217
  graphql: formats.includes('graphql') ? source.graphql : undefined,
221
218
  files: openapi && (overrides.files || source.files != null) ? { data: [] } : undefined,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { OpenapiDocument } from '../openapi/types.js';
3
+ import { type DeepJsonServerConfig, type NormalizedServerConfig } from './config.js';
4
+ import { type ServerFeatures } from './features.js';
5
+ export interface ServerFacade {
6
+ fastify(): FastifyInstance;
7
+ openapi(): Promise<OpenapiDocument>;
8
+ graphql(): Promise<string>;
9
+ }
10
+ export type { ServerFeatures } from './features.js';
11
+ /** Проверяет настройки и создаёт интерфейс запуска и генерации схем; сетевой порт ещё не открывает.
12
+ * @example await createServer({ database: { data: { notes: [] } } }) → объект с fastify(), openapi(), graphql().
13
+ */
14
+ export declare function createServer(config: DeepJsonServerConfig, features?: ServerFeatures): Promise<ServerFacade>;
15
+ /** Собирает сервер из нормализованных настроек; хранилища открываются при инициализации HTTP-экземпляра.
16
+ * @example Нормализованные настройки → Promise<ServerFacade>; listen() затем открывает сетевой порт.
17
+ */
18
+ export declare function createConfiguredServer(normalized: NormalizedServerConfig, features?: ServerFeatures): Promise<ServerFacade>;
@@ -1,37 +1,41 @@
1
- import { AUTH_PATHS } from './auth/contract.js';
1
+ import { AUTH_PATHS } from '../auth/contract.js';
2
+ import { DomainError } from '../core/errors.js';
3
+ import { domainStatus } from '../core/http-errors.js';
4
+ import { inputPaths } from '../core/paths.js';
5
+ import { errorMessage, isObject } from '../core/utils.js';
2
6
  import { configSourcePath, normalizeServerConfig } from './config.js';
3
- import { DEFAULT_HOST, DEFAULT_MAX_FILE_SIZE, DEFAULT_PORT } from './constants.js';
4
- import { DomainError } from './errors.js';
5
7
  import { resolveFeatures, validateEndpoints } from './features.js';
6
- import { domainStatus } from './http/errors.js';
7
- import { normalizePagination } from './pagination.js';
8
- import { inputPaths } from './paths.js';
9
- import { isObject } from './utils.js';
10
8
  const CORS_HEADERS = {
11
9
  'Access-Control-Allow-Headers': 'Content-Type',
12
10
  'Access-Control-Allow-Methods': 'DELETE, GET, OPTIONS, PATCH, POST, PUT',
13
11
  'Access-Control-Allow-Origin': '*',
14
12
  };
13
+ /** Проверяет настройки и создаёт интерфейс запуска и генерации схем; сетевой порт ещё не открывает.
14
+ * @example await createServer({ database: { data: { notes: [] } } }) → объект с fastify(), openapi(), graphql().
15
+ */
15
16
  export async function createServer(config, features = {}) {
16
17
  return createConfiguredServer(normalizeServerConfig(config), features);
17
18
  }
19
+ /** Собирает сервер из нормализованных настроек; хранилища открываются при инициализации HTTP-экземпляра.
20
+ * @example Нормализованные настройки → Promise<ServerFacade>; listen() затем открывает сетевой порт.
21
+ */
18
22
  export async function createConfiguredServer(normalized, features = {}) {
19
23
  const enabled = resolveFeatures(normalized, features);
20
- const { loadModel, inferModel } = await import('./model.js');
21
- const explicitModel = await loadModel(normalized.database.schema);
24
+ const { loadModel, inferModel } = await import('../core/model.js');
25
+ const recordSettings = { timestamps: normalized.database.timestamps, softDelete: normalized.database.softDelete, auth: enabled.auth };
26
+ const explicitModel = await loadModel(normalized.database.schema, recordSettings);
22
27
  const { default: Fastify } = await import('fastify');
23
28
  const corsHeaders = { ...CORS_HEADERS };
24
29
  if (enabled.files) {
25
- const { FILE_HEADERS } = await import('./files/http.js');
30
+ const { FILE_HEADERS } = await import('../files/http.js');
26
31
  corsHeaders['Access-Control-Allow-Headers'] = [...Object.values(FILE_HEADERS).map(({ name }) => name), 'Content-Type'].join(', ');
27
32
  }
28
33
  if (enabled.auth)
29
34
  corsHeaders['Access-Control-Allow-Headers'] += ', Authorization';
30
- const { cors = true, logger = true, maxFileSize = DEFAULT_MAX_FILE_SIZE } = normalized.server;
31
- const { pageSize, maxPageSize } = normalizePagination(normalized.server);
32
- const openapi = async () => (await import('./openapi/public.js')).openapiFromModel(explicitModel, {
35
+ const { cors, logger, maxFileSize, pageSize, maxPageSize } = normalized.server;
36
+ const openapi = async () => (await import('../openapi/generate.js')).openapiFromModel(explicitModel, {
33
37
  files: enabled.files,
34
- auth: enabled.auth,
38
+ ...recordSettings,
35
39
  pageSize,
36
40
  maxPageSize,
37
41
  info: normalized.openapi.info,
@@ -44,7 +48,7 @@ export async function createConfiguredServer(normalized, features = {}) {
44
48
  return instance;
45
49
  const server = Fastify({ ajv: { customOptions: { coerceTypes: false, removeAdditional: false } }, logger });
46
50
  const originalListen = server.listen.bind(server);
47
- const defaults = { host: normalized.server.host ?? DEFAULT_HOST, port: normalized.server.port ?? DEFAULT_PORT };
51
+ const defaults = { host: normalized.server.host, port: normalized.server.port };
48
52
  const listen = (optionsOrCallback, callback) => {
49
53
  if (typeof optionsOrCallback === 'function') {
50
54
  originalListen(defaults, optionsOrCallback);
@@ -62,7 +66,7 @@ export async function createConfiguredServer(normalized, features = {}) {
62
66
  const status = typeof candidate === 'number' && Number.isInteger(candidate) && candidate >= 400 && candidate <= 599 ? candidate : 500;
63
67
  if (status === 500)
64
68
  request.log.error(error);
65
- return reply.code(status).send({ error: status === 500 ? 'Внутренняя ошибка сервера' : error instanceof Error ? error.message : String(error) });
69
+ return reply.code(status).send({ error: status === 500 ? 'Внутренняя ошибка сервера' : errorMessage(error) });
66
70
  });
67
71
  if (cors) {
68
72
  server.addHook('onRequest', async (_request, reply) => {
@@ -73,25 +77,26 @@ export async function createConfiguredServer(normalized, features = {}) {
73
77
  server.options('/*', async (_request, reply) => reply.code(204).send());
74
78
  }
75
79
  server.register(async (app) => {
76
- const [{ createDatabaseStore }, { Engine }, { registerRestRoutes }] = await Promise.all([import('./database.js'), import('./engine.js'), import('./rest/routes.js')]);
80
+ const [{ createDatabaseStore }, { Engine }, { registerRestRoutes }] = await Promise.all([import('../core/database.js'), import('../core/engine.js'), import('../rest/routes.js')]);
77
81
  const keys = explicitModel ? new Map(explicitModel.entities.map((e) => [e.collection, e.primary])) : undefined;
78
82
  const store = await createDatabaseStore(normalized.database, keys);
79
- const model = explicitModel ?? inferModel(store.database.data);
83
+ const model = explicitModel ?? inferModel(store.database.data, recordSettings);
80
84
  const engine = new Engine(store, model, pageSize, maxPageSize);
81
85
  engine.validateData(store.database.data);
82
- const graphqlPath = normalized.graphql.endpoint ?? '/graphql';
83
- const openapiPath = normalized.openapi.endpoint ?? '/openapi.json';
86
+ const graphqlPath = normalized.graphql.endpoint;
87
+ const openapiPath = normalized.openapi.endpoint;
84
88
  validateEndpoints(model.entities.map((entity) => entity.collection), [...(enabled.graphql ? [graphqlPath] : []), ...(enabled.openapi ? [openapiPath] : []), ...(enabled.auth ? Object.values(AUTH_PATHS) : [])]);
85
- const auth = enabled.auth && normalized.auth ? await (await import('./auth/service.js')).createAuthService(normalized.auth) : undefined;
89
+ const auth = enabled.auth && normalized.auth ? await (await import('../auth/service.js')).createAuthService(normalized.auth) : undefined;
86
90
  if (auth) {
87
91
  app.addHook('onClose', async () => auth.close());
88
- const { registerAuthRoutes } = await import('./auth/routes.js');
92
+ const { registerAuthRoutes } = await import('../auth/routes.js');
89
93
  registerAuthRoutes(app, auth);
90
94
  }
91
- registerRestRoutes(app, engine);
95
+ const authenticate = auth ? (header) => auth.me(header) : undefined;
96
+ registerRestRoutes(app, engine, authenticate);
92
97
  if (enabled.graphql) {
93
- const [{ registerGraphqlRoutes }, { buildGraphql }] = await Promise.all([import('./graphql/routes.js'), import('./graphql.js')]);
94
- registerGraphqlRoutes(app, buildGraphql(model), engine, graphqlPath);
98
+ const [{ registerGraphqlRoutes }, { buildGraphql }] = await Promise.all([import('../graphql/routes.js'), import('../graphql/schema.js')]);
99
+ registerGraphqlRoutes(app, buildGraphql(model), engine, graphqlPath, authenticate);
95
100
  }
96
101
  if (enabled.openapi) {
97
102
  const document = await openapi();
@@ -100,7 +105,7 @@ export async function createConfiguredServer(normalized, features = {}) {
100
105
  }
101
106
  const files = normalized.files;
102
107
  if (enabled.files && files) {
103
- const { createFileStore, registerFileRoutes } = await import('./files/index.js');
108
+ const { createFileStore, registerFileRoutes } = await import('../files/index.js');
104
109
  const protectedPaths = inputPaths({ database: normalized.database, auth: normalized.auth }, '.', configSourcePath(normalized));
105
110
  registerFileRoutes(app, { getStore: () => createFileStore(files, protectedPaths), maxFileSize });
106
111
  }
@@ -112,8 +117,8 @@ export async function createConfiguredServer(normalized, features = {}) {
112
117
  fastify: getFastify,
113
118
  openapi,
114
119
  graphql: async () => {
115
- return (await import('./graphql/public.js')).graphqlFromModel(explicitModel);
120
+ return (await import('../graphql/generate.js')).graphqlFromModel(explicitModel);
116
121
  },
117
122
  };
118
123
  }
119
- //# sourceMappingURL=server.js.map
124
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/server/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { NormalizedServerConfig } from './config.js';
2
+ export interface ServerFeatures {
3
+ auth?: boolean;
4
+ files?: boolean;
5
+ graphql?: boolean;
6
+ openapi?: boolean;
7
+ }
8
+ /** Вычисляет включённые модули с учётом явных переопределений и проверяет обязательные настройки.
9
+ * @example Пустые секции и переопределение { graphql: true } → graphql: true, остальные флаги false.
10
+ */
11
+ export declare function resolveFeatures(config: NormalizedServerConfig, features?: ServerFeatures): Required<ServerFeatures>;
12
+ /** Проверяет, что пути не повторяются и не перекрывают коллекции или файловые маршруты.
13
+ * @example validateEndpoints(['users'], ['/users/1']) → ошибка; ['users'], ['/api'] → undefined.
14
+ */
15
+ export declare function validateEndpoints(collections: string[], endpoints: string[]): void;
@@ -1,10 +1,13 @@
1
- import { isObject } from './utils.js';
1
+ import { isObject } from '../core/utils.js';
2
+ /** Вычисляет включённые модули с учётом явных переопределений и проверяет обязательные настройки.
3
+ * @example Пустые секции и переопределение { graphql: true } → graphql: true, остальные флаги false.
4
+ */
2
5
  export function resolveFeatures(config, features = {}) {
3
6
  if (!isObject(features) || Object.entries(features).some(([key, value]) => !['files', 'graphql', 'openapi', 'auth'].includes(key) || typeof value !== 'boolean'))
4
7
  throw new Error('features supports boolean files, graphql, openapi and auth keys');
5
8
  const overrides = features;
6
9
  const resolved = {
7
- auth: overrides.auth ?? config.auth?.enabled ?? false,
10
+ auth: overrides.auth ?? config.auth != null,
8
11
  files: overrides.files ?? config.files != null,
9
12
  graphql: overrides.graphql ?? config.graphql.enabled ?? false,
10
13
  openapi: overrides.openapi ?? config.openapi.enabled ?? false,
@@ -15,6 +18,9 @@ export function resolveFeatures(config, features = {}) {
15
18
  throw new Error('Для файловых маршрутов укажите секцию config.files');
16
19
  return resolved;
17
20
  }
21
+ /** Проверяет, что пути не повторяются и не перекрывают коллекции или файловые маршруты.
22
+ * @example validateEndpoints(['users'], ['/users/1']) → ошибка; ['users'], ['/api'] → undefined.
23
+ */
18
24
  export function validateEndpoints(collections, endpoints) {
19
25
  if (new Set(endpoints).size !== endpoints.length)
20
26
  throw new Error('API endpoints conflict');
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../../src/server/features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAQ5C;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAA8B,EAAE,QAAQ,GAAmB,EAAE;IAC3F,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,KAAK,KAAK,SAAS,CAAC;QAC9J,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,MAAM,SAAS,GAAmB,QAAQ,CAAC;IAC3C,MAAM,QAAQ,GAAG;QACf,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI;QAC3C,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI;QAC9C,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK;QAC7D,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK;KAC9D,CAAC;IACF,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACnG,IAAI,QAAQ,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC3G,OAAO,QAAQ,CAAC;AAClB,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAqB,EAAE,SAAmB;IAC1E,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5F,KAAK,MAAM,QAAQ,IAAI,SAAS;QAC9B,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,QAAQ,KAAK,IAAI,UAAU,EAAE,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;YAC9I,MAAM,IAAI,KAAK,CAAC,iDAAiD,QAAQ,EAAE,CAAC,CAAC;AACnF,CAAC"}
@@ -1,3 +1,3 @@
1
- export type { AuthConfig, DatabaseConfig, DeepJsonServerConfig, FilesConfig, GraphqlConfig, MemoryFile, OpenapiConfig, ServerConfig } from '../config.js';
2
- export type { ServerFeatures } from '../features.js';
3
- export { createServer, type ServerFacade } from '../server.js';
1
+ export type { AuthConfig, DatabaseConfig, DeepJsonServerConfig, FilesConfig, GraphqlConfig, MemoryFile, OpenapiConfig, ServerConfig } from './config.js';
2
+ export { createServer, type ServerFacade } from './create.js';
3
+ export type { ServerFeatures } from './features.js';
@@ -1,2 +1,2 @@
1
- export { createServer } from '../server.js';
1
+ export { createServer } from './create.js';
2
2
  //# sourceMappingURL=public.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/server/public.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAqB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/server/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAqB,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kollors/deep-json-server",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "JSON mock server with schema-driven REST, GraphQL, nested queries and OpenAPI generation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,10 +0,0 @@
1
- import type { OpenapiDocument, OpenapiSchema } from '../types.js';
2
- export declare const AUTH_SCHEMAS: Record<string, OpenapiSchema>;
3
- export declare const AUTH_SECURITY_SCHEMES: {
4
- AuthBearer: {
5
- type: string;
6
- scheme: string;
7
- description: string;
8
- };
9
- };
10
- export declare function authOpenapiPaths(): OpenapiDocument['paths'];
@@ -1,62 +0,0 @@
1
- import { json, ref, response } from '../openapi/helpers.js';
2
- import { AUTH_PATHS, MAX_PASSWORD_LENGTH, MAX_USERNAME_LENGTH } from './contract.js';
3
- export const AUTH_SCHEMAS = {
4
- AuthUser: { type: 'object', additionalProperties: false, required: ['id', 'username'], properties: { id: { type: 'string' }, username: { type: 'string' } } },
5
- AuthLoginInput: {
6
- type: 'object',
7
- additionalProperties: false,
8
- required: ['username', 'password'],
9
- properties: {
10
- username: { type: 'string', minLength: 1, maxLength: MAX_USERNAME_LENGTH },
11
- password: { type: 'string', format: 'password', writeOnly: true, minLength: 1, maxLength: MAX_PASSWORD_LENGTH },
12
- },
13
- },
14
- AuthSession: {
15
- type: 'object',
16
- additionalProperties: false,
17
- required: ['accessToken', 'expiresIn', 'user'],
18
- properties: {
19
- accessToken: { type: 'string' },
20
- expiresIn: { type: 'integer', minimum: 1 },
21
- user: ref('AuthUser'),
22
- },
23
- },
24
- AuthLogoutResult: { type: 'object', additionalProperties: false, required: ['success'], properties: { success: { type: 'boolean' } } },
25
- };
26
- export const AUTH_SECURITY_SCHEMES = { AuthBearer: { type: 'http', scheme: 'bearer', description: 'Session token returned by POST /auth/login. Used only by GET /auth/me and POST /auth/logout.' } };
27
- export function authOpenapiPaths() {
28
- const unauthorized = response('Invalid credentials or expired session', ref('Error'));
29
- return {
30
- [AUTH_PATHS.login]: {
31
- post: {
32
- operationId: 'authLogin',
33
- tags: ['auth'],
34
- security: [],
35
- requestBody: { required: true, ...json(ref('AuthLoginInput')) },
36
- responses: {
37
- 200: response('Session created', ref('AuthSession')),
38
- 400: response('Invalid input', ref('Error')),
39
- 401: unauthorized,
40
- 429: response('Too many login attempts or sessions', ref('Error')),
41
- },
42
- },
43
- },
44
- [AUTH_PATHS.me]: {
45
- get: {
46
- operationId: 'authMe',
47
- tags: ['auth'],
48
- security: [{ AuthBearer: [] }],
49
- responses: { 200: response('Current auth user', ref('AuthUser')), 401: unauthorized },
50
- },
51
- },
52
- [AUTH_PATHS.logout]: {
53
- post: {
54
- operationId: 'authLogout',
55
- tags: ['auth'],
56
- security: [{ AuthBearer: [] }],
57
- responses: { 200: response('Session revoked', ref('AuthLogoutResult')), 401: unauthorized },
58
- },
59
- },
60
- };
61
- }
62
- //# sourceMappingURL=openapi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../../src/auth/openapi.ts"],"names":[],"mappings":"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"}