@kollors/deep-json-server 1.0.0-rc.6 → 1.0.0-rc.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 (82) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/MIGRATION.md +187 -25
  3. package/MIGRATION.ru.md +211 -0
  4. package/README.md +48 -33
  5. package/README.ru.md +50 -35
  6. package/dist/index.d.ts +1 -1
  7. package/dist/package.json +104 -0
  8. package/dist/src/auth/contract.d.ts +8 -0
  9. package/dist/src/auth/contract.js.map +1 -1
  10. package/dist/src/auth/public.d.ts +1 -1
  11. package/dist/src/auth/service.d.ts +7 -16
  12. package/dist/src/auth/service.js +40 -48
  13. package/dist/src/auth/service.js.map +1 -1
  14. package/dist/src/auth/store.d.ts +11 -5
  15. package/dist/src/auth/store.js +37 -19
  16. package/dist/src/auth/store.js.map +1 -1
  17. package/dist/src/cli/index.js +2 -2
  18. package/dist/src/cli/index.js.map +1 -1
  19. package/dist/src/core/constants.d.ts +1 -1
  20. package/dist/src/core/constants.js +2 -1
  21. package/dist/src/core/constants.js.map +1 -1
  22. package/dist/src/core/engine.d.ts +2 -1
  23. package/dist/src/core/engine.js +7 -3
  24. package/dist/src/core/engine.js.map +1 -1
  25. package/dist/src/core/model/infer.js +8 -5
  26. package/dist/src/core/model/infer.js.map +1 -1
  27. package/dist/src/core/model/load.js +1 -1
  28. package/dist/src/core/model/load.js.map +1 -1
  29. package/dist/src/core/mutations/write.d.ts +3 -3
  30. package/dist/src/core/mutations/write.js +10 -5
  31. package/dist/src/core/mutations/write.js.map +1 -1
  32. package/dist/src/core/paths.d.ts +4 -0
  33. package/dist/src/core/paths.js +7 -0
  34. package/dist/src/core/paths.js.map +1 -1
  35. package/dist/src/core/query/budget.d.ts +24 -0
  36. package/dist/src/core/query/budget.js +69 -0
  37. package/dist/src/core/query/budget.js.map +1 -0
  38. package/dist/src/core/query/execute.d.ts +2 -1
  39. package/dist/src/core/query/execute.js +5 -2
  40. package/dist/src/core/query/execute.js.map +1 -1
  41. package/dist/src/core/query/filter.d.ts +2 -1
  42. package/dist/src/core/query/filter.js +27 -9
  43. package/dist/src/core/query/filter.js.map +1 -1
  44. package/dist/src/core/records.d.ts +2 -0
  45. package/dist/src/core/records.js +15 -4
  46. package/dist/src/core/records.js.map +1 -1
  47. package/dist/src/files/contract.js +1 -0
  48. package/dist/src/files/contract.js.map +1 -1
  49. package/dist/src/files/disk-store.js +7 -5
  50. package/dist/src/files/disk-store.js.map +1 -1
  51. package/dist/src/graphql/preflight.d.ts +11 -2
  52. package/dist/src/graphql/preflight.js +48 -2
  53. package/dist/src/graphql/preflight.js.map +1 -1
  54. package/dist/src/graphql/resolvers.d.ts +3 -0
  55. package/dist/src/graphql/resolvers.js +47 -8
  56. package/dist/src/graphql/resolvers.js.map +1 -1
  57. package/dist/src/graphql/routes.d.ts +1 -1
  58. package/dist/src/graphql/routes.js +16 -0
  59. package/dist/src/graphql/routes.js.map +1 -1
  60. package/dist/src/graphql/schema.js +6 -4
  61. package/dist/src/graphql/schema.js.map +1 -1
  62. package/dist/src/openapi/document.js +8 -2
  63. package/dist/src/openapi/document.js.map +1 -1
  64. package/dist/src/rest/options.d.ts +2 -1
  65. package/dist/src/rest/options.js +5 -3
  66. package/dist/src/rest/options.js.map +1 -1
  67. package/dist/src/rest/projection.d.ts +4 -3
  68. package/dist/src/rest/projection.js +31 -12
  69. package/dist/src/rest/projection.js.map +1 -1
  70. package/dist/src/rest/routes.js +13 -7
  71. package/dist/src/rest/routes.js.map +1 -1
  72. package/dist/src/server/bootstrap.js +15 -7
  73. package/dist/src/server/bootstrap.js.map +1 -1
  74. package/dist/src/server/input-paths.d.ts +14 -1
  75. package/dist/src/server/input-paths.js +18 -2
  76. package/dist/src/server/input-paths.js.map +1 -1
  77. package/dist/src/server/storage-lock.d.ts +7 -1
  78. package/dist/src/server/storage-lock.js +103 -99
  79. package/dist/src/server/storage-lock.js.map +1 -1
  80. package/examples/database.json +2 -14
  81. package/examples/schema.json +0 -15
  82. package/package.json +3 -1
@@ -1,116 +1,120 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { mkdir, readFile, rmdir, stat, unlink, writeFile } from 'node:fs/promises';
3
- import { canonicalPath } from '../core/paths.js';
4
- import { isSystemError } from '../core/utils.js';
5
- const INCOMPLETE_LOCK_GRACE_MS = 2000;
6
- export const databaseLockPath = (path) => `${path}.deep-json-server.lock`;
2
+ import { constants } from 'node:fs';
3
+ import { lstat, open, unlink } from 'node:fs/promises';
4
+ import { createRequire } from 'node:module';
5
+ import { basename, dirname, extname, join } from 'node:path';
6
+ import { canonicalEntryPath, canonicalPath, validateExportPaths } from '../core/paths.js';
7
+ import { isObject, isSystemError } from '../core/utils.js';
8
+ /** Имя одного файла блокировки рядом с источником: /data/catalog.json → /data/catalog-lock.json. */
9
+ export const databaseLockPath = (path) => join(dirname(path), `${basename(path, extname(path))}-lock.json`);
10
+ const LOCK_TYPE = 'deep-json-server-lock';
11
+ const LOCK_PREFIX = `{"type":"${LOCK_TYPE}",`;
12
+ const sameFile = (left, right) => left.dev === right.dev && left.ino === right.ino;
7
13
  const missing = (error) => isSystemError(error) && error.code === 'ENOENT';
8
- async function ownerOf(path) {
9
- try {
10
- const value = JSON.parse(await readFile(path, 'utf8'));
11
- if (typeof value === 'object' && value !== null && 'pid' in value && 'token' in value && Number.isSafeInteger(value.pid) && typeof value.token === 'string')
12
- return value;
13
- }
14
- catch (error) {
15
- if (!missing(error) && !(error instanceof SyntaxError))
16
- throw error;
17
- }
18
- return undefined;
19
- }
20
- function processExists(pid) {
21
- if (pid < 1)
22
- return false;
23
- try {
24
- process.kill(pid, 0);
14
+ /** Разрешает старые метаданные и незавершённую запись, но не перезаписывает посторонний JSON. */
15
+ function isLockContent(content) {
16
+ if (!content)
25
17
  return true;
18
+ try {
19
+ const value = JSON.parse(content);
20
+ return isObject(value) && value.type === LOCK_TYPE;
26
21
  }
27
- catch (error) {
28
- if (isSystemError(error) && error.code === 'ESRCH')
29
- return false;
30
- if (isSystemError(error) && error.code === 'EPERM')
31
- return true;
32
- throw error;
33
- }
34
- }
35
- async function removeOwnedLock(directory, token) {
36
- const ownerPath = `${directory}/owner.json`;
37
- const owner = await ownerOf(ownerPath);
38
- if (!owner) {
39
- try {
40
- await stat(directory);
41
- }
42
- catch (error) {
43
- if (missing(error))
44
- return;
45
- throw error;
46
- }
22
+ catch {
23
+ return LOCK_PREFIX.startsWith(content) || content.startsWith(LOCK_PREFIX);
47
24
  }
48
- if (owner?.token !== token)
49
- throw new Error(`Database lock was changed: ${directory}`);
50
- await unlink(ownerPath);
51
- await rmdir(directory);
52
25
  }
53
- /** Удерживает блокировку дисковой базы до закрытия сервера и восстанавливает её после остановки процесса. */
54
- export async function acquireDatabaseLock(databasePath) {
55
- const path = await canonicalPath(databasePath);
56
- const directory = databaseLockPath(path);
57
- const recovery = `${directory}.recovery`;
58
- const ownerPath = `${directory}/owner.json`;
59
- const busy = () => new Error(`Database is already in use by another server: ${path}`);
60
- for (let attempt = 0; attempt < 3; attempt++) {
26
+ /** Удерживает системную блокировку дескриптора; после аварии ОС освобождает её автоматически. */
27
+ async function acquireLock(path, source) {
28
+ // Нативный модуль нужен только дисковым серверам, а не генераторам схем или memory storage.
29
+ const { tryLock } = createRequire(import.meta.url)('fs-native-extensions');
30
+ const busy = () => new Error(`Storage is already in use by another server: ${source}`);
31
+ for (let attempt = 0; attempt < 5; attempt++) {
32
+ const handle = await open(path, constants.O_CREAT | constants.O_RDWR | (constants.O_NOFOLLOW ?? 0), 0o600);
33
+ let retained = false;
61
34
  try {
62
- await mkdir(directory);
63
- const token = randomUUID();
64
- try {
65
- await writeFile(ownerPath, JSON.stringify({ pid: process.pid, token }), { flag: 'wx' });
35
+ const identity = await handle.stat();
36
+ if (!identity.isFile() || identity.nlink > 1)
37
+ throw new Error(`Storage lock must be a regular file without hard links: ${path}`);
38
+ // LockFileEx запрещает чтение заблокированных байтов другим дескриптором: на Windows
39
+ // блокируем байт за метаданными, чтобы JSON владельца оставался доступен для чтения.
40
+ if (!(process.platform === 'win32' ? tryLock(handle.fd, 4096, 1) : tryLock(handle.fd)))
41
+ throw busy();
42
+ // Предыдущий владелец мог удалить файл после нашего open(), но до tryLock().
43
+ // Старый inode не защищает новый путь: в таком случае открываем файл заново.
44
+ const current = await lstat(path).catch((error) => {
45
+ if (missing(error))
46
+ return undefined;
47
+ throw error;
48
+ });
49
+ if (!current || !sameFile(identity, current))
50
+ continue;
51
+ if (current.size > 4096 || !isLockContent(await handle.readFile('utf8')))
52
+ throw new Error(`Storage lock path contains an unrelated file: ${path}`);
53
+ const content = Buffer.from(`${JSON.stringify({ type: LOCK_TYPE, pid: process.pid, token: randomUUID() })}\n`);
54
+ await handle.truncate(0);
55
+ for (let offset = 0; offset < content.length;) {
56
+ const { bytesWritten } = await handle.write(content, offset, content.length - offset, offset);
57
+ if (!bytesWritten)
58
+ throw new Error(`Cannot write storage lock: ${path}`);
59
+ offset += bytesWritten;
60
+ }
61
+ let closing;
62
+ retained = true;
63
+ return () => (closing ??= (async () => {
66
64
  try {
67
- await stat(recovery);
68
- await removeOwnedLock(directory, token);
69
- continue;
70
- }
71
- catch (error) {
72
- if (!missing(error))
65
+ const current = await lstat(path).catch((error) => {
66
+ if (missing(error))
67
+ return undefined;
73
68
  throw error;
69
+ });
70
+ if (current) {
71
+ if (!sameFile(identity, current))
72
+ throw new Error(`Storage lock was changed: ${path}`);
73
+ // Не снимаем блокировку до unlink; конкуренты проверяют inode после захвата.
74
+ await unlink(path);
75
+ }
74
76
  }
75
- return () => removeOwnedLock(directory, token);
76
- }
77
- catch (error) {
78
- if ((await ownerOf(ownerPath))?.token === token)
79
- await removeOwnedLock(directory, token);
80
- else
81
- await rmdir(directory).catch(() => undefined);
82
- throw error;
83
- }
84
- }
85
- catch (error) {
86
- if (!isSystemError(error) || error.code !== 'EEXIST')
87
- throw error;
88
- }
89
- const owner = await ownerOf(ownerPath);
90
- if (owner && processExists(owner.pid))
91
- throw busy();
92
- if (!owner && Date.now() - (await stat(directory)).mtimeMs < INCOMPLETE_LOCK_GRACE_MS)
93
- throw busy();
94
- try {
95
- await mkdir(recovery);
96
- }
97
- catch (error) {
98
- if (isSystemError(error) && error.code === 'EEXIST')
99
- throw busy();
100
- throw error;
101
- }
102
- try {
103
- const current = await ownerOf(ownerPath);
104
- if (current && processExists(current.pid))
105
- throw busy();
106
- if (current)
107
- await unlink(ownerPath);
108
- await rmdir(directory);
77
+ finally {
78
+ await handle.close();
79
+ }
80
+ })());
109
81
  }
110
82
  finally {
111
- await rmdir(recovery);
83
+ if (!retained)
84
+ await handle.close();
112
85
  }
113
86
  }
114
87
  throw busy();
115
88
  }
89
+ /** Блокирует все записываемые источники и освобождает уже полученные блокировки при ошибке. */
90
+ export async function acquireStorageLocks(sources, inputs = sources) {
91
+ const entries = await Promise.all(sources.map(async (source) => [await canonicalEntryPath(source), await canonicalPath(source)]));
92
+ const owners = new Map();
93
+ for (const entry of entries)
94
+ for (const source of entry)
95
+ owners.set(databaseLockPath(source), source);
96
+ const paths = [...owners.keys()].sort();
97
+ await validateExportPaths(paths, [...sources, ...inputs]);
98
+ const releases = [];
99
+ let closing;
100
+ const release = () => (closing ??= (async () => {
101
+ const results = await Promise.allSettled(releases.reverse().map((close) => close()));
102
+ const errors = results.filter((result) => result.status === 'rejected').map((result) => result.reason);
103
+ if (errors.length)
104
+ throw new AggregateError(errors, 'Cannot release storage locks');
105
+ })());
106
+ try {
107
+ for (const path of paths)
108
+ releases.push(await acquireLock(path, owners.get(path)));
109
+ }
110
+ catch (error) {
111
+ await release();
112
+ throw error;
113
+ }
114
+ return { paths, release };
115
+ }
116
+ /** Блокирует дисковую базу, включая путь ссылки, который заменяется атомарной записью. */
117
+ export async function acquireDatabaseLock(databasePath) {
118
+ return (await acquireStorageLocks([databasePath])).release;
119
+ }
116
120
  //# sourceMappingURL=storage-lock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage-lock.js","sourceRoot":"","sources":["../../../src/server/storage-lock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage-lock.js","sourceRoot":"","sources":["../../../src/server/storage-lock.ts"],"names":[],"mappings":"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"}
@@ -2,37 +2,31 @@
2
2
  "countries": [
3
3
  {
4
4
  "id": "1",
5
- "isArchived": false,
6
5
  "name": "Ardenia"
7
6
  },
8
7
  {
9
8
  "id": "2",
10
- "isArchived": false,
11
9
  "name": "Veloria"
12
10
  }
13
11
  ],
14
12
  "genres": [
15
13
  {
16
14
  "id": "1",
17
- "isArchived": false,
18
15
  "name": "Crime",
19
16
  "parentIds": []
20
17
  },
21
18
  {
22
19
  "id": "2",
23
- "isArchived": false,
24
20
  "name": "Gangster",
25
21
  "parentIds": ["1"]
26
22
  },
27
23
  {
28
24
  "id": "3",
29
- "isArchived": false,
30
25
  "name": "Drama",
31
26
  "parentIds": []
32
27
  },
33
28
  {
34
29
  "id": "4",
35
- "isArchived": false,
36
30
  "name": "Comedy",
37
31
  "parentIds": []
38
32
  }
@@ -54,7 +48,6 @@
54
48
  "coverSrc": "https://example.com/covers/shadows-of-ardenia.jpg",
55
49
  "description": "An heiress in a port city uncovers a plot involving two rival families.",
56
50
  "id": "1",
57
- "isArchived": false,
58
51
  "publisherIds": ["2"],
59
52
  "title": "Shadows of Ardenia"
60
53
  },
@@ -63,7 +56,6 @@
63
56
  "coverSrc": "https://example.com/covers/northern-star.jpg",
64
57
  "description": "A night clerk at an old hotel gets drawn into the search for a missing painting.",
65
58
  "id": "2",
66
- "isArchived": false,
67
59
  "publisherIds": ["1"],
68
60
  "title": "Midnight at the Northern Star"
69
61
  }
@@ -71,12 +63,10 @@
71
63
  "publishers": [
72
64
  {
73
65
  "id": "1",
74
- "isArchived": false,
75
66
  "name": "Northlight Studio"
76
67
  },
77
68
  {
78
69
  "id": "2",
79
- "isArchived": false,
80
70
  "name": "Aurora Pictures"
81
71
  }
82
72
  ],
@@ -85,15 +75,13 @@
85
75
  "bornAt": "1988-03-14",
86
76
  "countryId": "1",
87
77
  "fullName": "Mira Volkova",
88
- "id": "1",
89
- "isArchived": false
78
+ "id": "1"
90
79
  },
91
80
  {
92
81
  "bornAt": "1991-11-02",
93
82
  "countryId": "2",
94
83
  "fullName": "Leon Vetrov",
95
- "id": "2",
96
- "isArchived": false
84
+ "id": "2"
97
85
  }
98
86
  ]
99
87
  }
@@ -9,9 +9,6 @@
9
9
  "primary": true,
10
10
  "generated": "uuid"
11
11
  },
12
- "isArchived": {
13
- "type": "boolean"
14
- },
15
12
  "name": {
16
13
  "type": "string"
17
14
  },
@@ -29,9 +26,6 @@
29
26
  "primary": true,
30
27
  "generated": "uuid"
31
28
  },
32
- "isArchived": {
33
- "type": "boolean"
34
- },
35
29
  "name": {
36
30
  "type": "string"
37
31
  },
@@ -68,9 +62,6 @@
68
62
  "description": {
69
63
  "type": "string"
70
64
  },
71
- "isArchived": {
72
- "type": "boolean"
73
- },
74
65
  "title": {
75
66
  "type": "string",
76
67
  "required": true
@@ -118,9 +109,6 @@
118
109
  "primary": true,
119
110
  "generated": "uuid"
120
111
  },
121
- "isArchived": {
122
- "type": "boolean"
123
- },
124
112
  "name": {
125
113
  "type": "string"
126
114
  },
@@ -147,9 +135,6 @@
147
135
  "type": "string",
148
136
  "required": true
149
137
  },
150
- "isArchived": {
151
- "type": "boolean"
152
- },
153
138
  "avatarSrc": {
154
139
  "type": "string",
155
140
  "format": "uri"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kollors/deep-json-server",
3
- "version": "1.0.0-rc.6",
3
+ "version": "1.0.0-rc.8",
4
4
  "description": "JSON mock server with schema-driven REST, GraphQL, OpenAPI generation and file uploads",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,6 +37,7 @@
37
37
  "README.ru.md",
38
38
  "CHANGELOG.md",
39
39
  "MIGRATION.md",
40
+ "MIGRATION.ru.md",
40
41
  "examples"
41
42
  ],
42
43
  "scripts": {
@@ -58,6 +59,7 @@
58
59
  "ajv": "^8.20.0",
59
60
  "ajv-formats": "^3.0.1",
60
61
  "fastify": "^5.12.3",
62
+ "fs-native-extensions": "^1.5.1",
61
63
  "graphql": "^16.14.2",
62
64
  "lowdb": "^7.0.1",
63
65
  "mercurius": "^16.10.0",