@kollors/deep-json-server 1.0.0-rc.7 → 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.
- package/CHANGELOG.md +13 -0
- package/MIGRATION.md +6 -6
- package/MIGRATION.ru.md +6 -6
- package/README.md +23 -11
- package/README.ru.md +23 -11
- package/dist/index.d.ts +1 -1
- package/dist/package.json +104 -0
- package/dist/src/auth/contract.d.ts +8 -0
- package/dist/src/auth/contract.js.map +1 -1
- package/dist/src/auth/public.d.ts +1 -1
- package/dist/src/auth/service.d.ts +7 -16
- package/dist/src/auth/service.js +40 -48
- package/dist/src/auth/service.js.map +1 -1
- package/dist/src/auth/store.d.ts +11 -5
- package/dist/src/auth/store.js +37 -19
- package/dist/src/auth/store.js.map +1 -1
- package/dist/src/cli/index.js +2 -2
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/constants.d.ts +1 -1
- package/dist/src/core/constants.js +2 -1
- package/dist/src/core/constants.js.map +1 -1
- package/dist/src/core/engine.d.ts +2 -1
- package/dist/src/core/engine.js +7 -3
- package/dist/src/core/engine.js.map +1 -1
- package/dist/src/core/model/infer.js +8 -5
- package/dist/src/core/model/infer.js.map +1 -1
- package/dist/src/core/mutations/write.js +5 -2
- package/dist/src/core/mutations/write.js.map +1 -1
- package/dist/src/core/paths.d.ts +4 -0
- package/dist/src/core/paths.js +7 -0
- package/dist/src/core/paths.js.map +1 -1
- package/dist/src/core/query/budget.d.ts +24 -0
- package/dist/src/core/query/budget.js +69 -0
- package/dist/src/core/query/budget.js.map +1 -0
- package/dist/src/core/query/execute.d.ts +2 -1
- package/dist/src/core/query/execute.js +5 -2
- package/dist/src/core/query/execute.js.map +1 -1
- package/dist/src/core/query/filter.d.ts +2 -1
- package/dist/src/core/query/filter.js +27 -9
- package/dist/src/core/query/filter.js.map +1 -1
- package/dist/src/core/records.d.ts +2 -0
- package/dist/src/core/records.js +15 -4
- package/dist/src/core/records.js.map +1 -1
- package/dist/src/files/contract.js +1 -0
- package/dist/src/files/contract.js.map +1 -1
- package/dist/src/files/disk-store.js +7 -5
- package/dist/src/files/disk-store.js.map +1 -1
- package/dist/src/graphql/preflight.d.ts +11 -2
- package/dist/src/graphql/preflight.js +48 -2
- package/dist/src/graphql/preflight.js.map +1 -1
- package/dist/src/graphql/resolvers.d.ts +3 -0
- package/dist/src/graphql/resolvers.js +47 -8
- package/dist/src/graphql/resolvers.js.map +1 -1
- package/dist/src/graphql/routes.d.ts +1 -1
- package/dist/src/graphql/routes.js +16 -0
- package/dist/src/graphql/routes.js.map +1 -1
- package/dist/src/graphql/schema.js +5 -3
- package/dist/src/graphql/schema.js.map +1 -1
- package/dist/src/rest/options.d.ts +2 -1
- package/dist/src/rest/options.js +5 -3
- package/dist/src/rest/options.js.map +1 -1
- package/dist/src/rest/projection.d.ts +4 -3
- package/dist/src/rest/projection.js +31 -12
- package/dist/src/rest/projection.js.map +1 -1
- package/dist/src/rest/routes.js +13 -7
- package/dist/src/rest/routes.js.map +1 -1
- package/dist/src/server/bootstrap.js +15 -7
- package/dist/src/server/bootstrap.js.map +1 -1
- package/dist/src/server/input-paths.d.ts +14 -1
- package/dist/src/server/input-paths.js +18 -2
- package/dist/src/server/input-paths.js.map +1 -1
- package/dist/src/server/storage-lock.d.ts +7 -1
- package/dist/src/server/storage-lock.js +103 -99
- package/dist/src/server/storage-lock.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projection.js","sourceRoot":"","sources":["../../../src/rest/projection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAY,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEnE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAgC,QAAQ,EAAmB,aAAa,EAAE,MAAM,cAAc,CAAC;AAE9H;;GAEG;AACH,SAAS,aAAa,CAAC,IAAsB,EAAE,KAAc;IAC3D,OAAO,CACL,CAAC,IAAI,EAAE,SAAS;QAChB,CAAC,IAAI,EAAE,QAAQ;QACf,CAAC,IAAI,EAAE,QAAQ;QACf,CAAC,IAAI,EAAE,WAAW;QAClB,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAC/D,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC,CAC3E,CAAC;AACJ,CAAC;AAMD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,MAAc,EAAE,OAAoB,EAAE,IAAI,GAAG,KAAK;
|
|
1
|
+
{"version":3,"file":"projection.js","sourceRoot":"","sources":["../../../src/rest/projection.ts"],"names":[],"mappings":"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"}
|
package/dist/src/rest/routes.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { domainError } from '../core/errors.js';
|
|
2
2
|
import { MUTATIONS } from '../core/operations.js';
|
|
3
|
+
import { QueryBudget } from '../core/query/budget.js';
|
|
3
4
|
import { parseRestOptions } from './options.js';
|
|
4
5
|
import { listScope, project, validateRest } from './projection.js';
|
|
5
6
|
/** Возвращает актуальную сущность из снимка модели или сообщает об исчезнувшем ресурсе.
|
|
@@ -20,36 +21,41 @@ export function registerRestRoutes(server, engine, authenticate) {
|
|
|
20
21
|
const path = `/${initial.collection}`;
|
|
21
22
|
const itemPath = `${path}/:${initial.primary}`;
|
|
22
23
|
server.get(path, async (request) => {
|
|
24
|
+
const budget = new QueryBudget();
|
|
23
25
|
const actor = authenticate && request.headers.authorization !== undefined ? authenticate(request.headers.authorization) : undefined;
|
|
24
26
|
const context = await engine.context();
|
|
27
|
+
context.budget = budget;
|
|
25
28
|
const entity = entityFor(engine, initial.collection);
|
|
26
29
|
const options = parseRestOptions(request.query);
|
|
27
|
-
const { scope, plans } = validateRest(engine, entity, options, true);
|
|
28
|
-
const page = listScope(engine, engine.records(context, entity), entity.root, scope, plans);
|
|
29
|
-
return { data: page.data.map((entry) => project(engine, entry.ref, entry.scope, plans, actor)), total: page.total };
|
|
30
|
+
const { scope, plans } = validateRest(engine, entity, options, true, budget);
|
|
31
|
+
const page = listScope(engine, engine.records(context, entity), entity.root, scope, plans, undefined, budget);
|
|
32
|
+
return { data: page.data.map((entry) => project(engine, entry.ref, entry.scope, plans, actor, budget)), total: page.total };
|
|
30
33
|
});
|
|
31
34
|
server.get(itemPath, async (request) => {
|
|
35
|
+
const budget = new QueryBudget();
|
|
32
36
|
const actor = authenticate && request.headers.authorization !== undefined ? authenticate(request.headers.authorization) : undefined;
|
|
33
37
|
const context = await engine.context();
|
|
38
|
+
context.budget = budget;
|
|
34
39
|
const entity = entityFor(engine, initial.collection);
|
|
35
40
|
const options = parseRestOptions(request.query);
|
|
36
|
-
const { scope, plans } = validateRest(engine, entity, options);
|
|
41
|
+
const { scope, plans } = validateRest(engine, entity, options, false, budget);
|
|
37
42
|
const ref = engine.find(context, entity, request.params[entity.primary]);
|
|
38
43
|
if (!ref)
|
|
39
44
|
throw domainError('NOT_FOUND', 'Record not found');
|
|
40
|
-
return project(engine, ref, scope, plans, actor);
|
|
45
|
+
return project(engine, ref, scope, plans, actor, budget);
|
|
41
46
|
});
|
|
42
47
|
for (const { method, mode, hasKey, status } of MUTATIONS) {
|
|
43
48
|
server.route({
|
|
44
49
|
method,
|
|
45
50
|
url: hasKey ? itemPath : path,
|
|
46
51
|
handler: async (request, reply) => {
|
|
52
|
+
const budget = new QueryBudget();
|
|
47
53
|
const actor = authenticate ? () => authenticate(request.headers.authorization) : undefined;
|
|
48
54
|
actor?.();
|
|
49
55
|
const options = parseRestOptions(request.query);
|
|
50
56
|
const result = await engine.mutate(initial, mode, request.params[initial.primary], request.body, (ref) => {
|
|
51
|
-
const { scope, plans } = validateRest(engine, ref.entity, options);
|
|
52
|
-
return project(engine, ref, scope, plans, actor?.());
|
|
57
|
+
const { scope, plans } = validateRest(engine, ref.entity, options, false, budget);
|
|
58
|
+
return project(engine, ref, scope, plans, actor?.(), budget);
|
|
53
59
|
}, actor);
|
|
54
60
|
return reply.code(status).send(result);
|
|
55
61
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/rest/routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnE;;GAEG;AACH,SAAS,SAAS,CAAC,MAAc,EAAE,UAAkB;IACnD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM;QAAE,MAAM,WAAW,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC;AAChB,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAuB,EAAE,MAAc,EAAE,YAA2B;IACrG,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IACvJ,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACjC,MAAM,KAAK,GAAG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACpI,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAChD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/rest/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,24 @@
|
|
|
1
|
+
import { mkdir } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
1
3
|
import { AUTH_PATHS } from '../auth/contract.js';
|
|
2
4
|
import { configSourcePath } from './config.js';
|
|
3
5
|
import { validateEndpoints } from './features.js';
|
|
4
|
-
import { inputPaths } from './input-paths.js';
|
|
5
|
-
import {
|
|
6
|
+
import { inputPaths, writablePaths } from './input-paths.js';
|
|
7
|
+
import { acquireStorageLocks } from './storage-lock.js';
|
|
6
8
|
/** Подключает к HTTP-серверу хранилище записей и включённые прикладные модули.
|
|
7
9
|
* @example Конфигурация только с базой → REST-маршруты без auth, files и API-экспортов.
|
|
8
10
|
*/
|
|
9
11
|
export async function registerConfiguredModules(app, config, explicitModel, openapi) {
|
|
10
|
-
|
|
12
|
+
if (config.storage === 'file' && config.files) {
|
|
13
|
+
await mkdir(config.files.source, { recursive: true });
|
|
14
|
+
if (config.files.metadata)
|
|
15
|
+
await mkdir(dirname(config.files.metadata), { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
const sources = writablePaths(config);
|
|
18
|
+
const locks = await acquireStorageLocks(sources, inputPaths(config, '.', configSourcePath(config), false));
|
|
19
|
+
const { release } = locks;
|
|
11
20
|
try {
|
|
21
|
+
app.addHook('onClose', release);
|
|
12
22
|
const enabled = { auth: config.auth !== undefined, files: config.files !== undefined };
|
|
13
23
|
const recordSettings = { auth: enabled.auth };
|
|
14
24
|
const keys = explicitModel ? new Map(explicitModel.entities.map((entity) => [entity.collection, entity.primary])) : undefined;
|
|
@@ -49,14 +59,12 @@ export async function registerConfiguredModules(app, config, explicitModel, open
|
|
|
49
59
|
}
|
|
50
60
|
if (enabled.files && config.files) {
|
|
51
61
|
const { createFileStore, registerFileRoutes } = await import('../files/index.js');
|
|
52
|
-
const protectedPaths = inputPaths({ database: config.database, auth: config.auth, package: config.package }, '.', configSourcePath(config));
|
|
62
|
+
const protectedPaths = [...inputPaths({ database: config.database, auth: config.auth, package: config.package }, '.', configSourcePath(config)), ...locks.paths];
|
|
53
63
|
registerFileRoutes(app, { getStore: () => createFileStore(config.files, protectedPaths), maxFileSize: config.server.maxFileSize });
|
|
54
64
|
}
|
|
55
|
-
if (release)
|
|
56
|
-
app.addHook('onClose', release);
|
|
57
65
|
}
|
|
58
66
|
catch (error) {
|
|
59
|
-
await release
|
|
67
|
+
await release();
|
|
60
68
|
throw error;
|
|
61
69
|
}
|
|
62
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/server/bootstrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/server/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** Возвращает дисковые источники, совместное использование которых требует блокировки. */
|
|
2
|
+
export declare function writablePaths(config: {
|
|
3
|
+
database?: unknown;
|
|
4
|
+
files?: unknown;
|
|
5
|
+
auth?: unknown;
|
|
6
|
+
}, directory?: string): string[];
|
|
1
7
|
/** Собирает пути входных файлов, счётчиков и временных файлов записи без чтения диска.
|
|
2
8
|
* @example auth.source = '/tmp/users.json' → среди защищённых путей '/tmp/users.json' и '/tmp/.users.json.tmp'.
|
|
3
9
|
*/
|
|
@@ -6,4 +12,11 @@ export declare function inputPaths(config: {
|
|
|
6
12
|
files?: unknown;
|
|
7
13
|
auth?: unknown;
|
|
8
14
|
package?: unknown;
|
|
9
|
-
}, directory?: string, sourcePath?: string): string[];
|
|
15
|
+
}, directory?: string, sourcePath?: string, includeLocks?: boolean): string[];
|
|
16
|
+
/** Дополняет защиту экспорта файлами блокировок целей символических ссылок. */
|
|
17
|
+
export declare function protectedInputPaths(config: {
|
|
18
|
+
database?: unknown;
|
|
19
|
+
files?: unknown;
|
|
20
|
+
auth?: unknown;
|
|
21
|
+
package?: unknown;
|
|
22
|
+
}, directory?: string, sourcePath?: string): Promise<string[]>;
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { basename, dirname, resolve } from 'node:path';
|
|
2
|
+
import { canonicalEntryPath, canonicalPath } from '../core/paths.js';
|
|
2
3
|
import { isObject } from '../core/utils.js';
|
|
3
4
|
import { databaseLockPath } from './storage-lock.js';
|
|
5
|
+
/** Возвращает дисковые источники, совместное использование которых требует блокировки. */
|
|
6
|
+
export function writablePaths(config, directory = '.') {
|
|
7
|
+
const database = isObject(config.database) ? config.database : {};
|
|
8
|
+
const files = isObject(config.files) ? config.files : {};
|
|
9
|
+
const auth = isObject(config.auth) ? config.auth : {};
|
|
10
|
+
return [database.source, auth.source, files.source, files.metadata ?? (typeof files.source === 'string' ? resolve(directory, files.source, '.files.json') : undefined)]
|
|
11
|
+
.filter((path) => typeof path === 'string')
|
|
12
|
+
.map((path) => resolve(directory, path));
|
|
13
|
+
}
|
|
4
14
|
/** Собирает пути входных файлов, счётчиков и временных файлов записи без чтения диска.
|
|
5
15
|
* @example auth.source = '/tmp/users.json' → среди защищённых путей '/tmp/users.json' и '/tmp/.users.json.tmp'.
|
|
6
16
|
*/
|
|
7
|
-
export function inputPaths(config, directory = '.', sourcePath) {
|
|
17
|
+
export function inputPaths(config, directory = '.', sourcePath, includeLocks = true) {
|
|
8
18
|
const database = isObject(config.database) ? config.database : {};
|
|
9
19
|
const files = isObject(config.files) ? config.files : {};
|
|
10
20
|
const auth = isObject(config.auth) ? config.auth : {};
|
|
@@ -19,12 +29,18 @@ export function inputPaths(config, directory = '.', sourcePath) {
|
|
|
19
29
|
].filter((path) => typeof path === 'string');
|
|
20
30
|
if (typeof database.source === 'string') {
|
|
21
31
|
paths.push(`${database.source}.counters.json`);
|
|
22
|
-
paths.push(databaseLockPath(database.source), `${databaseLockPath(database.source)}.recovery`);
|
|
23
32
|
}
|
|
33
|
+
if (includeLocks)
|
|
34
|
+
paths.push(...writablePaths(config, directory).map(databaseLockPath));
|
|
24
35
|
// JSONFile использует эти соседние файлы при записи; они тоже содержат защищённые данные.
|
|
25
36
|
for (const path of [database.source, typeof database.source === 'string' ? `${database.source}.counters.json` : undefined, auth.source])
|
|
26
37
|
if (typeof path === 'string')
|
|
27
38
|
paths.push(resolve(directory, dirname(path), `.${basename(path)}.tmp`));
|
|
28
39
|
return paths.map((path) => resolve(directory, path));
|
|
29
40
|
}
|
|
41
|
+
/** Дополняет защиту экспорта файлами блокировок целей символических ссылок. */
|
|
42
|
+
export async function protectedInputPaths(config, directory = '.', sourcePath) {
|
|
43
|
+
const sources = await Promise.all(writablePaths(config, directory).map((path) => Promise.all([canonicalEntryPath(path), canonicalPath(path)])));
|
|
44
|
+
return [...inputPaths(config, directory, sourcePath), ...sources.flat().map(databaseLockPath)];
|
|
45
|
+
}
|
|
30
46
|
//# sourceMappingURL=input-paths.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-paths.js","sourceRoot":"","sources":["../../../src/server/input-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"input-paths.js","sourceRoot":"","sources":["../../../src/server/input-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** Имя одного файла блокировки рядом с источником: /data/catalog.json → /data/catalog-lock.json. */
|
|
1
2
|
export declare const databaseLockPath: (path: string) => string;
|
|
2
|
-
/**
|
|
3
|
+
/** Блокирует все записываемые источники и освобождает уже полученные блокировки при ошибке. */
|
|
4
|
+
export declare function acquireStorageLocks(sources: string[], inputs?: string[]): Promise<{
|
|
5
|
+
paths: string[];
|
|
6
|
+
release: () => Promise<void>;
|
|
7
|
+
}>;
|
|
8
|
+
/** Блокирует дисковую базу, включая путь ссылки, который заменяется атомарной записью. */
|
|
3
9
|
export declare function acquireDatabaseLock(databasePath: string): Promise<() => Promise<void>>;
|
|
@@ -1,116 +1,120 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
28
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"storage-lock.js","sourceRoot":"","sources":["../../../src/server/storage-lock.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kollors/deep-json-server",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
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",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"ajv": "^8.20.0",
|
|
60
60
|
"ajv-formats": "^3.0.1",
|
|
61
61
|
"fastify": "^5.12.3",
|
|
62
|
+
"fs-native-extensions": "^1.5.1",
|
|
62
63
|
"graphql": "^16.14.2",
|
|
63
64
|
"lowdb": "^7.0.1",
|
|
64
65
|
"mercurius": "^16.10.0",
|