@kollors/deep-json-server 1.0.0-alpha.1 → 1.0.0-alpha.10

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 (223) hide show
  1. package/README.md +522 -179
  2. package/README.ru.md +525 -180
  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 +13 -6
  6. package/dist/index.js +4 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/src/auth/contract.d.ts +31 -0
  9. package/dist/src/auth/contract.js +12 -0
  10. package/dist/src/auth/contract.js.map +1 -0
  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 +17 -0
  15. package/dist/src/auth/password.js +41 -0
  16. package/dist/src/auth/password.js.map +1 -0
  17. package/dist/src/auth/public.d.ts +3 -0
  18. package/dist/src/auth/public.js +5 -0
  19. package/dist/src/auth/public.js.map +1 -0
  20. package/dist/src/auth/routes.d.ts +6 -0
  21. package/dist/src/auth/routes.js +18 -0
  22. package/dist/src/auth/routes.js.map +1 -0
  23. package/dist/src/auth/service.d.ts +78 -0
  24. package/dist/src/auth/service.js +218 -0
  25. package/dist/src/auth/service.js.map +1 -0
  26. package/dist/src/auth/store.d.ts +26 -0
  27. package/dist/src/auth/store.js +82 -0
  28. package/dist/src/auth/store.js.map +1 -0
  29. package/dist/src/cli/index.d.ts +7 -0
  30. package/dist/src/cli/index.js +122 -0
  31. package/dist/src/cli/index.js.map +1 -0
  32. package/dist/src/core/config-values.d.ts +28 -0
  33. package/dist/src/core/config-values.js +53 -0
  34. package/dist/src/core/config-values.js.map +1 -0
  35. package/dist/src/{constants.d.ts → core/constants.d.ts} +1 -0
  36. package/dist/src/{constants.js → core/constants.js} +1 -0
  37. package/dist/src/core/constants.js.map +1 -0
  38. package/dist/src/core/database.d.ts +48 -0
  39. package/dist/src/{database.js → core/database.js} +36 -14
  40. package/dist/src/core/database.js.map +1 -0
  41. package/dist/src/core/engine.d.ts +65 -0
  42. package/dist/src/core/engine.js +312 -0
  43. package/dist/src/core/engine.js.map +1 -0
  44. package/dist/src/core/errors.d.ts +9 -0
  45. package/dist/src/core/errors.js +12 -0
  46. package/dist/src/core/errors.js.map +1 -0
  47. package/dist/src/core/http-errors.d.ts +9 -0
  48. package/dist/src/core/http-errors.js +15 -0
  49. package/dist/src/core/http-errors.js.map +1 -0
  50. package/dist/src/core/lifecycle/mutation.d.ts +49 -0
  51. package/dist/src/core/lifecycle/mutation.js +170 -0
  52. package/dist/src/core/lifecycle/mutation.js.map +1 -0
  53. package/dist/src/core/lifecycle/options.d.ts +21 -0
  54. package/dist/src/core/lifecycle/options.js +19 -0
  55. package/dist/src/core/lifecycle/options.js.map +1 -0
  56. package/dist/src/core/model.d.ts +145 -0
  57. package/dist/src/{model.js → core/model.js} +224 -33
  58. package/dist/src/core/model.js.map +1 -0
  59. package/dist/src/core/mutations/write.d.ts +26 -0
  60. package/dist/src/core/mutations/write.js +284 -0
  61. package/dist/src/core/mutations/write.js.map +1 -0
  62. package/dist/src/core/operations.d.ts +33 -0
  63. package/dist/src/core/operations.js +10 -0
  64. package/dist/src/core/operations.js.map +1 -0
  65. package/dist/src/core/pagination.d.ts +10 -0
  66. package/dist/src/core/pagination.js +13 -0
  67. package/dist/src/core/pagination.js.map +1 -0
  68. package/dist/src/core/paths.d.ts +16 -0
  69. package/dist/src/core/paths.js +64 -0
  70. package/dist/src/core/paths.js.map +1 -0
  71. package/dist/src/core/query/contract.d.ts +6 -0
  72. package/dist/src/core/query/contract.js +22 -0
  73. package/dist/src/core/query/contract.js.map +1 -0
  74. package/dist/src/core/query/filter.d.ts +6 -0
  75. package/dist/src/core/query/filter.js +100 -0
  76. package/dist/src/core/query/filter.js.map +1 -0
  77. package/dist/src/core/query/options.d.ts +30 -0
  78. package/dist/src/core/query/options.js +44 -0
  79. package/dist/src/core/query/options.js.map +1 -0
  80. package/dist/src/core/records.d.ts +46 -0
  81. package/dist/src/core/records.js +69 -0
  82. package/dist/src/core/records.js.map +1 -0
  83. package/dist/src/core/relation-metadata.d.ts +15 -0
  84. package/dist/src/{relation-metadata.js → core/relation-metadata.js} +7 -2
  85. package/dist/src/core/relation-metadata.js.map +1 -0
  86. package/dist/src/core/storage.d.ts +2 -0
  87. package/dist/src/core/storage.js +2 -0
  88. package/dist/src/core/storage.js.map +1 -0
  89. package/dist/src/core/types.d.ts +10 -0
  90. package/dist/src/{types.js.map → core/types.js.map} +1 -1
  91. package/dist/src/core/utils.d.ts +56 -0
  92. package/dist/src/core/utils.js +102 -0
  93. package/dist/src/core/utils.js.map +1 -0
  94. package/dist/src/files/contract.d.ts +32 -30
  95. package/dist/src/files/contract.js +29 -48
  96. package/dist/src/files/contract.js.map +1 -1
  97. package/dist/src/files/disk-store.d.ts +5 -1
  98. package/dist/src/files/disk-store.js +49 -32
  99. package/dist/src/files/disk-store.js.map +1 -1
  100. package/dist/src/files/http.d.ts +36 -0
  101. package/dist/src/files/http.js +53 -0
  102. package/dist/src/files/http.js.map +1 -0
  103. package/dist/src/files/index.d.ts +5 -4
  104. package/dist/src/files/index.js +7 -2
  105. package/dist/src/files/index.js.map +1 -1
  106. package/dist/src/files/memory-store.d.ts +4 -1
  107. package/dist/src/files/memory-store.js +29 -22
  108. package/dist/src/files/memory-store.js.map +1 -1
  109. package/dist/src/files/routes.d.ts +3 -0
  110. package/dist/src/files/routes.js +27 -2
  111. package/dist/src/files/routes.js.map +1 -1
  112. package/dist/src/files/streams.d.ts +5 -0
  113. package/dist/src/files/streams.js +20 -0
  114. package/dist/src/files/streams.js.map +1 -0
  115. package/dist/src/graphql/entry.d.ts +12 -0
  116. package/dist/src/graphql/entry.js +13 -0
  117. package/dist/src/graphql/entry.js.map +1 -0
  118. package/dist/src/graphql/generate.d.ts +12 -0
  119. package/dist/src/graphql/generate.js +19 -0
  120. package/dist/src/graphql/generate.js.map +1 -0
  121. package/dist/src/graphql/preflight.d.ts +6 -0
  122. package/dist/src/graphql/preflight.js +42 -0
  123. package/dist/src/graphql/preflight.js.map +1 -0
  124. package/dist/src/graphql/resolvers.d.ts +17 -0
  125. package/dist/src/graphql/resolvers.js +44 -0
  126. package/dist/src/graphql/resolvers.js.map +1 -0
  127. package/dist/src/graphql/routes.d.ts +8 -0
  128. package/dist/src/graphql/routes.js +30 -0
  129. package/dist/src/graphql/routes.js.map +1 -0
  130. package/dist/src/graphql/schema.d.ts +6 -0
  131. package/dist/src/{graphql.js → graphql/schema.js} +57 -50
  132. package/dist/src/graphql/schema.js.map +1 -0
  133. package/dist/src/graphql/write.d.ts +4 -0
  134. package/dist/src/graphql/write.js +10 -0
  135. package/dist/src/graphql/write.js.map +1 -0
  136. package/dist/src/openapi/auth.d.ts +13 -0
  137. package/dist/src/openapi/auth.js +139 -0
  138. package/dist/src/openapi/auth.js.map +1 -0
  139. package/dist/src/openapi/document.d.ts +7 -3
  140. package/dist/src/openapi/document.js +147 -92
  141. package/dist/src/openapi/document.js.map +1 -1
  142. package/dist/src/openapi/entry.d.ts +14 -0
  143. package/dist/src/openapi/entry.js +13 -0
  144. package/dist/src/openapi/entry.js.map +1 -0
  145. package/dist/src/openapi/files.d.ts +6 -0
  146. package/dist/src/{files/openapi.js → openapi/files.js} +6 -5
  147. package/dist/src/openapi/files.js.map +1 -0
  148. package/dist/src/openapi/generate.d.ts +19 -0
  149. package/dist/src/openapi/generate.js +41 -0
  150. package/dist/src/openapi/generate.js.map +1 -0
  151. package/dist/src/openapi/helpers.d.ts +26 -0
  152. package/dist/src/openapi/helpers.js +13 -0
  153. package/dist/src/openapi/helpers.js.map +1 -0
  154. package/dist/src/openapi/options.d.ts +18 -0
  155. package/dist/src/openapi/options.js +13 -0
  156. package/dist/src/openapi/options.js.map +1 -0
  157. package/dist/src/{types.d.ts → openapi/types.d.ts} +2 -10
  158. package/dist/src/openapi/types.js +2 -0
  159. package/dist/src/openapi/types.js.map +1 -0
  160. package/dist/src/openapi/write.d.ts +5 -0
  161. package/dist/src/openapi/write.js +12 -0
  162. package/dist/src/openapi/write.js.map +1 -0
  163. package/dist/src/rest/options.d.ts +22 -0
  164. package/dist/src/rest/options.js +65 -0
  165. package/dist/src/rest/options.js.map +1 -0
  166. package/dist/src/rest/projection.d.ts +13 -0
  167. package/dist/src/rest/projection.js +61 -0
  168. package/dist/src/rest/projection.js.map +1 -0
  169. package/dist/src/rest/routes.d.ts +7 -0
  170. package/dist/src/rest/routes.js +49 -0
  171. package/dist/src/rest/routes.js.map +1 -0
  172. package/dist/src/server/config.d.ts +74 -0
  173. package/dist/src/server/config.js +142 -0
  174. package/dist/src/server/config.js.map +1 -0
  175. package/dist/src/server/create.d.ts +16 -0
  176. package/dist/src/server/create.js +133 -0
  177. package/dist/src/server/create.js.map +1 -0
  178. package/dist/src/server/features.d.ts +4 -0
  179. package/dist/src/server/features.js +11 -0
  180. package/dist/src/server/features.js.map +1 -0
  181. package/dist/src/server/model.d.ts +6 -0
  182. package/dist/src/server/model.js +14 -0
  183. package/dist/src/server/model.js.map +1 -0
  184. package/dist/src/server/public.d.ts +2 -0
  185. package/dist/src/server/public.js +2 -0
  186. package/dist/src/server/public.js.map +1 -0
  187. package/package.json +17 -1
  188. package/dist/src/cli.d.ts +0 -4
  189. package/dist/src/cli.js +0 -67
  190. package/dist/src/cli.js.map +0 -1
  191. package/dist/src/config.d.ts +0 -68
  192. package/dist/src/config.js +0 -161
  193. package/dist/src/config.js.map +0 -1
  194. package/dist/src/constants.js.map +0 -1
  195. package/dist/src/database.d.ts +0 -21
  196. package/dist/src/database.js.map +0 -1
  197. package/dist/src/engine.d.ts +0 -47
  198. package/dist/src/engine.js +0 -438
  199. package/dist/src/engine.js.map +0 -1
  200. package/dist/src/files/openapi.d.ts +0 -3
  201. package/dist/src/files/openapi.js.map +0 -1
  202. package/dist/src/graphql.d.ts +0 -4
  203. package/dist/src/graphql.js.map +0 -1
  204. package/dist/src/model.d.ts +0 -67
  205. package/dist/src/model.js.map +0 -1
  206. package/dist/src/openapi/index.d.ts +0 -7
  207. package/dist/src/openapi/index.js +0 -26
  208. package/dist/src/openapi/index.js.map +0 -1
  209. package/dist/src/query/filter.d.ts +0 -1
  210. package/dist/src/query/filter.js +0 -84
  211. package/dist/src/query/filter.js.map +0 -1
  212. package/dist/src/query/options.d.ts +0 -31
  213. package/dist/src/query/options.js +0 -135
  214. package/dist/src/query/options.js.map +0 -1
  215. package/dist/src/relation-metadata.d.ts +0 -10
  216. package/dist/src/relation-metadata.js.map +0 -1
  217. package/dist/src/server.d.ts +0 -14
  218. package/dist/src/server.js +0 -166
  219. package/dist/src/server.js.map +0 -1
  220. package/dist/src/utils.d.ts +0 -19
  221. package/dist/src/utils.js +0 -62
  222. package/dist/src/utils.js.map +0 -1
  223. /package/dist/src/{types.js → core/types.js} +0 -0
@@ -0,0 +1,82 @@
1
+ import { JSONFile } from 'lowdb/node';
2
+ import { domainError } from '../core/errors.js';
3
+ import { createSerialQueue, hasOnlyKeys, isObject } from '../core/utils.js';
4
+ import { MAX_USERNAME_LENGTH } from './contract.js';
5
+ import { validPasswordHash } from './password.js';
6
+ /** Проверяет записи и строит индексы по двум уникальным строковым ключам.
7
+ * @example Две записи с разными id и username → два индекса; повторяющийся ключ → ошибка.
8
+ */
9
+ function indexUsers(records) {
10
+ if (!Array.isArray(records))
11
+ throw new Error('Auth users must be an array');
12
+ const byId = new Map();
13
+ const byUsername = new Map();
14
+ for (const record of records) {
15
+ if (!isObject(record) ||
16
+ !hasOnlyKeys(record, ['id', 'username', 'passwordHash', 'isAdmin']) ||
17
+ typeof record.id !== 'string' ||
18
+ !record.id.trim() ||
19
+ typeof record.username !== 'string' ||
20
+ !record.username.trim() ||
21
+ record.username.length > MAX_USERNAME_LENGTH ||
22
+ !validPasswordHash(record.passwordHash) ||
23
+ (record.isAdmin !== undefined && typeof record.isAdmin !== 'boolean'))
24
+ throw new Error('Auth users require id, username and a valid passwordHash');
25
+ if (byId.has(record.id) || byUsername.has(record.username))
26
+ throw new Error('Auth user ids and usernames must be unique');
27
+ const user = Object.freeze({ id: record.id, username: record.username, passwordHash: record.passwordHash, isAdmin: record.isAdmin ?? false });
28
+ byId.set(user.id, user);
29
+ byUsername.set(user.username, user);
30
+ }
31
+ return { byId, byUsername };
32
+ }
33
+ /** Хранит подтверждённые записи и последовательно сохраняет изменения одного пользователя. */
34
+ export class AuthStore {
35
+ users;
36
+ file;
37
+ schedule = createSerialQueue();
38
+ constructor(users, file) {
39
+ this.users = users;
40
+ this.file = file;
41
+ }
42
+ /** Возвращает индексы последнего успешно сохранённого состояния.
43
+ * @example Во время записи нового пароля read() ещё возвращает запись с прежним хешем.
44
+ */
45
+ read() {
46
+ return this.users;
47
+ }
48
+ /** Проверяет изменение внутри очереди и публикует его после записи; обработчик подтверждения вызывается синхронно.
49
+ * @example Успешная запись → новый пользователь; ошибка файла → прежние индексы, обработчик не вызван.
50
+ */
51
+ update(operation, committed) {
52
+ return this.schedule(async () => {
53
+ const user = Object.freeze(operation(this.users));
54
+ const owner = this.users.byUsername.get(user.username);
55
+ if (owner && owner.id !== user.id)
56
+ throw domainError('CONFLICT', 'Username already exists');
57
+ const byId = new Map(this.users.byId);
58
+ const byUsername = new Map(this.users.byUsername);
59
+ const previous = byId.get(user.id);
60
+ if (previous)
61
+ byUsername.delete(previous.username);
62
+ byId.set(user.id, user);
63
+ byUsername.set(user.username, user);
64
+ if (this.file)
65
+ await this.file.write([...byId.values()]);
66
+ this.users = { byId, byUsername };
67
+ committed?.();
68
+ return user;
69
+ });
70
+ }
71
+ }
72
+ /** Загружает массив из файла или памяти и подключает запись в тот же источник.
73
+ * @example Массив → хранилище в памяти; 'users.json' → чтение и сохранение JSON-массива через JSONFile.
74
+ */
75
+ export async function createAuthStore(source) {
76
+ const file = typeof source === 'string' ? new JSONFile(source) : undefined;
77
+ const records = file ? await file.read() : source;
78
+ if (file && records === null)
79
+ throw new Error(`Auth users file not found: ${source}`);
80
+ return new AuthStore(indexUsers(records), file);
81
+ }
82
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/auth/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { createConfiguredServer } from '../server/create.js';
2
+ /** Разбирает флаги, выполняет экспорт по секциям конфигурации и при необходимости запускает сервер.
3
+ * @example runCli(['--generate-only', 'config.mjs']) → файлы схем без открытия порта.
4
+ */
5
+ export declare function runCli(args?: string[], services?: {
6
+ createServer: typeof createConfiguredServer;
7
+ }): Promise<void>;
@@ -0,0 +1,122 @@
1
+ import process from 'node:process';
2
+ import { DEFAULT_HOST, DEFAULT_PORT, VERSION } from '../core/constants.js';
3
+ import { inputPaths, validateExportPaths } from '../core/paths.js';
4
+ import { isObject } from '../core/utils.js';
5
+ import { writeGraphql } from '../graphql/entry.js';
6
+ import { writeOpenapi } from '../openapi/entry.js';
7
+ import { configure, readConfigModule } from '../server/config.js';
8
+ import { createConfiguredServer } from '../server/create.js';
9
+ import { configuredModel } from '../server/model.js';
10
+ const HELP_TEXT = `Deep JSON Server
11
+
12
+ Usage:
13
+ deep-json-server [options] <server.config.js>
14
+
15
+ --generate Export configured schemas, then start the server
16
+ --generate-only Export configured schemas and exit
17
+ --host <host> Server address
18
+ --port <port> Server port
19
+ --help, -h Show help
20
+ --version, -v Show version
21
+
22
+ Modules and export formats are selected by configuration sections.
23
+ Generate flags are mutually exclusive and require output targets.`;
24
+ /** Проверяет все назначения, строит обе схемы и только затем сохраняет файлы.
25
+ * @example Секции openapi и graphql с target → два файла; нет target → ошибка до записи.
26
+ */
27
+ async function generate(config, source, directory, sourcePath) {
28
+ if (!config.openapi && !config.graphql)
29
+ throw new Error('Generation requires an openapi or graphql section');
30
+ const outputs = [];
31
+ for (const format of ['openapi', 'graphql']) {
32
+ if (!config[format])
33
+ continue;
34
+ const target = config[format].target;
35
+ if (!target)
36
+ throw new Error(`Укажите config.${format}.target`);
37
+ outputs.push(target);
38
+ }
39
+ await validateExportPaths(outputs, inputPaths(source, directory, sourcePath));
40
+ const model = await configuredModel(config);
41
+ const openapi = config.openapi
42
+ ? (await import('../openapi/generate.js')).openapiFromModel(model, {
43
+ files: config.files !== undefined,
44
+ auth: config.auth !== undefined,
45
+ host: config.server.host,
46
+ port: config.server.port,
47
+ pageSize: config.server.pageSize,
48
+ maxPageSize: config.server.maxPageSize,
49
+ info: config.openapi.info,
50
+ })
51
+ : undefined;
52
+ const graphql = config.graphql ? (await import('../graphql/generate.js')).graphqlFromModel(model) : undefined;
53
+ if (openapi && config.openapi?.target) {
54
+ await writeOpenapi(openapi, config.openapi.target);
55
+ process.stdout.write(`OpenAPI: ${config.openapi.target}\n`);
56
+ }
57
+ if (graphql && config.graphql?.target) {
58
+ await writeGraphql(graphql, config.graphql.target);
59
+ process.stdout.write(`GraphQL: ${config.graphql.target}\n`);
60
+ }
61
+ }
62
+ /** Разбирает флаги, выполняет экспорт по секциям конфигурации и при необходимости запускает сервер.
63
+ * @example runCli(['--generate-only', 'config.mjs']) → файлы схем без открытия порта.
64
+ */
65
+ export async function runCli(args = process.argv.slice(2), services = { createServer: createConfiguredServer }) {
66
+ if (args.includes('--help') || args.includes('-h')) {
67
+ process.stdout.write(`${HELP_TEXT}\n`);
68
+ return;
69
+ }
70
+ if (args.includes('--version') || args.includes('-v')) {
71
+ process.stdout.write(`${VERSION}\n`);
72
+ return;
73
+ }
74
+ const positional = [];
75
+ const seen = new Set();
76
+ let host;
77
+ let port;
78
+ for (let index = 0; index < args.length; index++) {
79
+ const arg = args[index];
80
+ if (!arg.startsWith('-')) {
81
+ positional.push(arg);
82
+ continue;
83
+ }
84
+ if (!['--generate', '--generate-only', '--host', '--port'].includes(arg) || seen.has(arg))
85
+ throw new Error(`Неизвестный параметр или повтор: ${arg}`);
86
+ seen.add(arg);
87
+ if (arg === '--host' || arg === '--port') {
88
+ const value = args[++index];
89
+ if (!value || value.startsWith('-'))
90
+ throw new Error(`Укажите значение ${arg}`);
91
+ if (arg === '--host')
92
+ host = value;
93
+ else {
94
+ if (!/^\d+$/.test(value))
95
+ throw new Error('Invalid --port');
96
+ port = Number(value);
97
+ }
98
+ }
99
+ }
100
+ if (seen.has('--generate') && seen.has('--generate-only'))
101
+ throw new Error('--generate and --generate-only are mutually exclusive');
102
+ if (!positional.length)
103
+ throw new Error('Укажите путь к файлу конфигурации');
104
+ if (positional.length !== 1)
105
+ throw new Error('Можно указать только один файл конфигурации');
106
+ const source = await readConfigModule(positional[0]);
107
+ const server = source.config.server ?? {};
108
+ if (!isObject(server))
109
+ throw new Error('config.server must be an object');
110
+ const config = configure({
111
+ ...source.config,
112
+ server: { ...server, host: host ?? server.host ?? process.env.HOST ?? DEFAULT_HOST, port: port ?? server.port ?? Number(process.env.PORT ?? DEFAULT_PORT) },
113
+ }, source.directory, source.path);
114
+ if (seen.has('--generate') || seen.has('--generate-only'))
115
+ await generate(config, source.config, source.directory, source.path);
116
+ if (seen.has('--generate-only'))
117
+ return;
118
+ const app = (await services.createServer(config)).fastify();
119
+ await app.listen();
120
+ app.log.info('Deep JSON Server started');
121
+ }
122
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /** Проверяет объект и обязательность значения; необязательные null и undefined пропускает.
2
+ * @example getObject(undefined, 'data') → undefined; getObject([], 'data', true) → ошибка.
3
+ */
4
+ export declare function getObject(value: unknown, path: string, required: true): Record<string, unknown>;
5
+ export declare function getObject(value: unknown, path: string, required?: false): Record<string, unknown> | undefined;
6
+ /** Проверяет непустую строку, не обрезая её; необязательные null и undefined пропускает.
7
+ * @example getString(' a ', 'name') → ' a '; getString('', 'name') → ошибка.
8
+ */
9
+ export declare function getString(value: unknown, path: string, required: true): string;
10
+ export declare function getString(value: unknown, path: string, required?: false): string | undefined;
11
+ /** Принимает положительное безопасное целое число или отсутствие значения.
12
+ * @example getPositiveInteger(2, 'size') → 2; getPositiveInteger(0, 'size') → ошибка.
13
+ */
14
+ export declare const getPositiveInteger: (value: unknown, path: string) => number | undefined;
15
+ /** Проверяет необязательный логический флаг, не преобразуя строки в boolean.
16
+ * @example getBoolean(false, 'flag') → false; getBoolean('false', 'flag') → ошибка.
17
+ */
18
+ export declare function getBoolean(value: unknown, path: string): boolean | undefined;
19
+ /** Проверяет адрес и порт и подставляет значения по умолчанию.
20
+ * @example normalizeAddress({ port: 0 }) → { host: '127.0.0.1', port: 0 }.
21
+ */
22
+ export declare function normalizeAddress(options: {
23
+ host?: unknown;
24
+ port?: unknown;
25
+ }): {
26
+ host: string;
27
+ port: number;
28
+ };
@@ -0,0 +1,53 @@
1
+ import { DEFAULT_HOST, DEFAULT_PORT } from './constants.js';
2
+ import { isObject, isPortNumber } from './utils.js';
3
+ export function getObject(value, path, required = false) {
4
+ if (value == null && !required) {
5
+ return undefined;
6
+ }
7
+ if (!isObject(value)) {
8
+ throw new Error(`Ключ ${path} должен быть JSON-объектом`);
9
+ }
10
+ return value;
11
+ }
12
+ export function getString(value, path, required = false) {
13
+ if (value == null && !required) {
14
+ return undefined;
15
+ }
16
+ if (typeof value !== 'string' || value.trim() === '') {
17
+ throw new Error(`Ключ ${path} должен содержать непустую строку`);
18
+ }
19
+ return value;
20
+ }
21
+ /** Принимает положительное безопасное целое число или отсутствие значения.
22
+ * @example getPositiveInteger(2, 'size') → 2; getPositiveInteger(0, 'size') → ошибка.
23
+ */
24
+ export const getPositiveInteger = (value, path) => {
25
+ if (value == null) {
26
+ return undefined;
27
+ }
28
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 1) {
29
+ throw new Error(`Ключ ${path} должен быть положительным целым числом`);
30
+ }
31
+ return value;
32
+ };
33
+ /** Проверяет необязательный логический флаг, не преобразуя строки в boolean.
34
+ * @example getBoolean(false, 'flag') → false; getBoolean('false', 'flag') → ошибка.
35
+ */
36
+ export function getBoolean(value, path) {
37
+ if (value === undefined)
38
+ return undefined;
39
+ if (typeof value !== 'boolean')
40
+ throw new Error(`${path} must be boolean`);
41
+ return value;
42
+ }
43
+ /** Проверяет адрес и порт и подставляет значения по умолчанию.
44
+ * @example normalizeAddress({ port: 0 }) → { host: '127.0.0.1', port: 0 }.
45
+ */
46
+ export function normalizeAddress(options) {
47
+ const host = getString(options.host, 'config.server.host') ?? DEFAULT_HOST;
48
+ const port = options.port ?? DEFAULT_PORT;
49
+ if (!isPortNumber(port))
50
+ throw new Error('Ключ config.server.port должен быть целым числом от 0 до 65535');
51
+ return { host, port };
52
+ }
53
+ //# sourceMappingURL=config-values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-values.js","sourceRoot":"","sources":["../../../src/core/config-values.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAOpD,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,IAAY,EAAE,QAAQ,GAAG,KAAK;IACtE,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,4BAA4B,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAOD,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,IAAY,EAAE,QAAQ,GAAG,KAAK;IACtE,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAAE,IAAY,EAAsB,EAAE;IACrF,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,yCAAyC,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,IAAY;IACrD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,kBAAkB,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA2C;IAC1E,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,IAAI,YAAY,CAAC;IAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC;IAC1C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAC3G,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
@@ -3,3 +3,4 @@ export declare const DEFAULT_MAX_FILE_SIZE: number;
3
3
  export declare const DEFAULT_MAX_PAGE_SIZE = 100;
4
4
  export declare const DEFAULT_PAGE_SIZE = 10;
5
5
  export declare const DEFAULT_PORT = 4001;
6
+ export declare const VERSION = "1.0.0-alpha.10";
@@ -3,4 +3,5 @@ export const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;
3
3
  export const DEFAULT_MAX_PAGE_SIZE = 100;
4
4
  export const DEFAULT_PAGE_SIZE = 10;
5
5
  export const DEFAULT_PORT = 4001;
6
+ export const VERSION = '1.0.0-alpha.10';
6
7
  //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AACxC,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AACvD,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { ModelSchema } from './model.js';
2
+ import type { Source, Storage } from './storage.js';
3
+ import type { DatabaseData, DatabaseRecord } from './types.js';
4
+ export interface DatabaseConfig<S extends Storage = Storage> {
5
+ source: Source<S, DatabaseData>;
6
+ schema?: Source<S, ModelSchema>;
7
+ }
8
+ export interface DatabaseContainer {
9
+ data: DatabaseData;
10
+ counters?: Record<string, number>;
11
+ }
12
+ export interface DatabaseStore {
13
+ database: DatabaseContainer;
14
+ path?: string;
15
+ read(): Promise<DatabaseData>;
16
+ /** Передаёт изменяемый черновик и исходные данные только для чтения; сохраняет черновик после проверки.
17
+ * @example update((draft, before) => { draft.data.notes = []; return before.notes.length; }) → прежнее число записей.
18
+ */
19
+ update<T>(operation: (database: DatabaseContainer, before: Readonly<DatabaseData>) => T): Promise<T>;
20
+ }
21
+ /** Проверяет сериализуемое JSON-значение; отвергает циклы, разреженные массивы, NaN и бесконечности.
22
+ * @example validateJsonValue({ a: [1, null] }, 'data') → undefined; NaN → ошибка.
23
+ */
24
+ export declare const validateJsonValue: (value: unknown, path: string, ancestors?: WeakSet<object>) => void;
25
+ /** Проверяет объект коллекций, записи и уникальность ключей; возвращает исходный объект.
26
+ * @example validateDatabase({ notes: [{ id: '1' }] }) → тот же объект; повторный id → ошибка.
27
+ */
28
+ export declare const validateDatabase: (data: unknown, primaryKeys?: Map<string, string>) => DatabaseData;
29
+ /** Читает UTF-8 JSON-файл и проверяет, что верхний уровень является объектом.
30
+ * @example Файл с {"a":1} → Promise<{ a: 1 }>; файл с [] → ошибка.
31
+ */
32
+ export declare const readJsonObjectFile: (path: string, label: string) => Promise<Record<string, unknown>>;
33
+ /** Читает файл и проверяет коллекции и первичные ключи.
34
+ * @example Файл с {"notes":[]} → Promise<{ notes: [] }>.
35
+ */
36
+ export declare const readDatabaseFile: (databasePath: string, keys?: Map<string, string>) => Promise<DatabaseData>;
37
+ /** Создаёт дисковое хранилище или хранилище в памяти по настройкам.
38
+ * @example createDatabaseStore({ source: { notes: [] } }) → Promise<DatabaseStore>.
39
+ */
40
+ export declare const createDatabaseStore: (config: DatabaseConfig, keys?: Map<string, string>) => Promise<DatabaseStore>;
41
+ /** Ищет индекс записи, сравнивая строковые представления id.
42
+ * @example findItemIndex([{ id: 1 }], '1') → 0; пустой массив → -1.
43
+ */
44
+ export declare const findItemIndex: (collection: DatabaseRecord[], id: unknown) => number;
45
+ /** Генерирует случайный строковый id, отсутствующий в переданной коллекции.
46
+ * @example createId([]) → строка из 11 символов; конкретное значение зависит от генератора случайных чисел.
47
+ */
48
+ export declare const createId: (collection: DatabaseRecord[]) => string;
@@ -2,8 +2,12 @@ import { readFile } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  import { Low } from 'lowdb';
4
4
  import { JSONFile } from 'lowdb/node';
5
- import { createHttpError, createSerialQueue, createUniqueId, isObject, isSafeKey, isSystemError, resolveDatabasePath } from './utils.js';
5
+ import { domainError } from './errors.js';
6
+ import { createSerialQueue, createUniqueId, isObject, isSafeKey, isSystemError, resolveDatabasePath } from './utils.js';
6
7
  const RESOURCE_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;
8
+ /** Проверяет сериализуемое JSON-значение; отвергает циклы, разреженные массивы, NaN и бесконечности.
9
+ * @example validateJsonValue({ a: [1, null] }, 'data') → undefined; NaN → ошибка.
10
+ */
7
11
  export const validateJsonValue = (value, path, ancestors = new WeakSet()) => {
8
12
  if (value === null || typeof value === 'string' || typeof value === 'boolean') {
9
13
  return;
@@ -40,6 +44,9 @@ export const validateJsonValue = (value, path, ancestors = new WeakSet()) => {
40
44
  }
41
45
  ancestors.delete(value);
42
46
  };
47
+ /** Проверяет объект коллекций, записи и уникальность ключей; возвращает исходный объект.
48
+ * @example validateDatabase({ notes: [{ id: '1' }] }) → тот же объект; повторный id → ошибка.
49
+ */
43
50
  export const validateDatabase = (data, primaryKeys) => {
44
51
  if (!isObject(data)) {
45
52
  throw new Error('База данных должна содержать JSON-объект');
@@ -73,6 +80,9 @@ export const validateDatabase = (data, primaryKeys) => {
73
80
  });
74
81
  return data;
75
82
  };
83
+ /** Читает UTF-8 JSON-файл и проверяет, что верхний уровень является объектом.
84
+ * @example Файл с {"a":1} → Promise<{ a: 1 }>; файл с [] → ошибка.
85
+ */
76
86
  export const readJsonObjectFile = async (path, label) => {
77
87
  const resolvedPath = resolve(path);
78
88
  let source;
@@ -91,7 +101,18 @@ export const readJsonObjectFile = async (path, label) => {
91
101
  }
92
102
  return value;
93
103
  };
104
+ /** Читает файл и проверяет коллекции и первичные ключи.
105
+ * @example Файл с {"notes":[]} → Promise<{ notes: [] }>.
106
+ */
94
107
  export const readDatabaseFile = async (databasePath, keys) => validateDatabase(await readJsonObjectFile(databasePath, 'Файл базы данных'), keys);
108
+ const validateDraft = (data, keys) => {
109
+ try {
110
+ validateDatabase(data, keys);
111
+ }
112
+ catch (error) {
113
+ throw domainError('INVALID_INPUT', error.message);
114
+ }
115
+ };
95
116
  const createDiskDatabaseStore = async (databasePath, keys) => {
96
117
  const resolvedDatabasePath = resolveDatabasePath(databasePath);
97
118
  const initialData = await readDatabaseFile(resolvedDatabasePath, keys);
@@ -107,8 +128,8 @@ const createDiskDatabaseStore = async (databasePath, keys) => {
107
128
  await read();
108
129
  await counterStore.read();
109
130
  const draft = { data: structuredClone(database.data), counters: structuredClone(counterStore.data) };
110
- const result = operation(draft);
111
- validateDatabase(draft.data, keys);
131
+ const result = operation(draft, database.data);
132
+ validateDraft(draft.data, keys);
112
133
  // Reserve generated numbers first: failed data writes may leave gaps, never reused IDs.
113
134
  if (JSON.stringify(draft.counters) !== JSON.stringify(counterStore.data)) {
114
135
  counterStore.data = draft.counters;
@@ -127,23 +148,24 @@ const createMemoryDatabaseStore = (sourceData, keys) => {
127
148
  const read = async () => database.data;
128
149
  const update = (operation) => schedule(() => {
129
150
  const draft = structuredClone(database);
130
- const result = operation(draft);
131
- validateDatabase(draft.data, keys);
151
+ const result = operation(draft, database.data);
152
+ validateDraft(draft.data, keys);
132
153
  database.data = draft.data;
133
154
  database.counters = draft.counters;
134
155
  return result;
135
156
  });
136
157
  return { database, read, update };
137
158
  };
138
- /** Creates a disk- or memory-backed database with serialized updates. */
139
- export const createDatabaseStore = async (config, keys) => config.data != null ? createMemoryDatabaseStore(config.data, keys) : createDiskDatabaseStore(config.path, keys);
140
- export const getCollection = (database, resource) => {
141
- const collection = isSafeKey(resource) ? database.data[resource] : undefined;
142
- if (!Array.isArray(collection)) {
143
- throw createHttpError(404, 'Ресурс не найден');
144
- }
145
- return collection;
146
- };
159
+ /** Создаёт дисковое хранилище или хранилище в памяти по настройкам.
160
+ * @example createDatabaseStore({ source: { notes: [] } }) Promise<DatabaseStore>.
161
+ */
162
+ export const createDatabaseStore = async (config, keys) => typeof config.source === 'string' ? createDiskDatabaseStore(config.source, keys) : createMemoryDatabaseStore(config.source, keys);
163
+ /** Ищет индекс записи, сравнивая строковые представления id.
164
+ * @example findItemIndex([{ id: 1 }], '1') 0; пустой массив → -1.
165
+ */
147
166
  export const findItemIndex = (collection, id) => collection.findIndex((item) => String(item.id) === String(id));
167
+ /** Генерирует случайный строковый id, отсутствующий в переданной коллекции.
168
+ * @example createId([]) → строка из 11 символов; конкретное значение зависит от генератора случайных чисел.
169
+ */
148
170
  export const createId = (collection) => createUniqueId((id) => findItemIndex(collection, id) !== -1);
149
171
  //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/core/database.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { DatabaseStore } from './database.js';
2
+ import type { ActorSource } from './lifecycle/options.js';
3
+ import { type Entity, type Model, type Node } from './model.js';
4
+ import type { MutationMode } from './operations.js';
5
+ import { type Predicate } from './query/filter.js';
6
+ import { type ListOptions } from './query/options.js';
7
+ import { type Context, type Ref } from './records.js';
8
+ import type { DatabaseData } from './types.js';
9
+ export interface PreparedList {
10
+ page: number;
11
+ pageSize: number;
12
+ predicate?: Predicate;
13
+ rules: Array<{
14
+ direction: 'ASC' | 'DESC';
15
+ keys: string[];
16
+ }>;
17
+ }
18
+ export interface Page {
19
+ data: Ref[];
20
+ total: number;
21
+ }
22
+ export declare class Engine {
23
+ readonly store: DatabaseStore;
24
+ model: Model;
25
+ readonly pageSize: number;
26
+ readonly maxPageSize: number;
27
+ private inferredModels;
28
+ constructor(store: DatabaseStore, model: Model, pageSize?: number, maxPageSize?: number);
29
+ /** Возвращает явную модель или кешированное описание, выведенное из переданного снимка данных.
30
+ * @example Повторный вызов с тем же объектом data → тот же объект Model.
31
+ */
32
+ private modelFor;
33
+ /** Читает актуальный снимок хранилища и создаёт контекст с пустым кешем индексов.
34
+ * @example context() → Promise<Context>; при ошибке чтения хранилища → отклонённый Promise.
35
+ */
36
+ context(): Promise<Context>;
37
+ /** Оборачивает все записи выбранной коллекции ссылками с контекстом.
38
+ * @example Пустая коллекция → []; две записи → две ссылки Ref.
39
+ */
40
+ records(context: Context, entity: Entity): Ref[];
41
+ /** Ищет запись по строковому представлению первичного ключа, включая удалённые записи.
42
+ * @example Ключ '1' находит запись с числовым ключом 1; отсутствующий ключ → undefined.
43
+ */
44
+ find(context: Context, entity: Entity, key: unknown): Ref | undefined;
45
+ /** Проверяет аргументы списка и подготавливает предикат, пути сортировки и размеры страницы.
46
+ * @example pager: { page: 2, pageSize: 5 } → план с page: 2 и pageSize: 5; page: 0 → ошибка.
47
+ */
48
+ prepareOptions(node: Node, options?: ListOptions): PreparedList;
49
+ /** Фильтрует, сортирует и возвращает страницу, не меняя порядок исходного массива.
50
+ * @example Три подходящие записи, page: 2, pageSize: 2 → { data: [третья запись], total: 3 }.
51
+ */
52
+ list(records: Ref[], node: Node, options?: ListOptions, prepared?: PreparedList): Page;
53
+ /** Проверяет коллекции, значения полей и целостность активных связей.
54
+ * @example Согласованные записи → undefined; обязательная связь без цели → исключение.
55
+ */
56
+ validateData(data: DatabaseData): void;
57
+ /** Выполняет одну операцию записи в транзакции, включая связи, права и подготовку ответа.
58
+ * @example Режим update с { name: 'Анна' } → обновлённая запись; ошибка проверки → прежние данные.
59
+ */
60
+ mutate<T = Ref>(entity: Entity, mode: MutationMode, key?: unknown, body?: unknown, prepare?: (ref: Ref) => T, actor?: ActorSource): Promise<T>;
61
+ /** Вычисляет каскад удаления, проверяет запрещающие связи и меняет только черновик данных.
62
+ * @example Удаление родителя при cascade → удалённые зависимые записи; restrict → исключение.
63
+ */
64
+ private cascade;
65
+ }