@kollors/deep-json-server 1.0.0-alpha.5 → 1.0.0-alpha.7
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/README.md +346 -188
- package/README.ru.md +343 -185
- package/dist/bin/deep-json-server.js +1 -1
- package/dist/bin/deep-json-server.js.map +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/src/auth/contract.d.ts +27 -0
- package/dist/src/auth/contract.js +5 -0
- package/dist/src/auth/contract.js.map +1 -0
- package/dist/src/auth/password.d.ts +13 -0
- package/dist/src/auth/password.js +37 -0
- package/dist/src/auth/password.js.map +1 -0
- package/dist/src/auth/public.d.ts +3 -0
- package/dist/src/auth/public.js +5 -0
- package/dist/src/auth/public.js.map +1 -0
- package/dist/src/auth/routes.d.ts +6 -0
- package/dist/src/auth/routes.js +15 -0
- package/dist/src/auth/routes.js.map +1 -0
- package/dist/src/auth/service.d.ts +39 -0
- package/dist/src/auth/service.js +143 -0
- package/dist/src/auth/service.js.map +1 -0
- package/dist/src/cli/index.d.ts +7 -0
- package/dist/src/{cli.js → cli/index.js} +32 -12
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/{constants.d.ts → core/constants.d.ts} +1 -1
- package/dist/src/{constants.js → core/constants.js} +1 -1
- package/dist/src/core/constants.js.map +1 -0
- package/dist/src/core/database.d.ts +50 -0
- package/dist/src/{database.js → core/database.js} +21 -1
- package/dist/src/core/database.js.map +1 -0
- package/dist/src/core/engine.d.ts +64 -0
- package/dist/src/{engine.js → core/engine.js} +64 -18
- package/dist/src/core/engine.js.map +1 -0
- package/dist/src/core/errors.d.ts +9 -0
- package/dist/src/core/errors.js +12 -0
- package/dist/src/core/errors.js.map +1 -0
- package/dist/src/core/http-errors.d.ts +9 -0
- package/dist/src/core/http-errors.js +15 -0
- package/dist/src/core/http-errors.js.map +1 -0
- package/dist/src/core/lifecycle/mutation.d.ts +49 -0
- package/dist/src/core/lifecycle/mutation.js +170 -0
- package/dist/src/core/lifecycle/mutation.js.map +1 -0
- package/dist/src/core/lifecycle/options.d.ts +20 -0
- package/dist/src/core/lifecycle/options.js +21 -0
- package/dist/src/core/lifecycle/options.js.map +1 -0
- package/dist/src/core/model.d.ts +130 -0
- package/dist/src/{model.js → core/model.js} +106 -10
- package/dist/src/core/model.js.map +1 -0
- package/dist/src/{mutations → core/mutations}/write.d.ts +3 -2
- package/dist/src/{mutations → core/mutations}/write.js +14 -4
- package/dist/src/core/mutations/write.js.map +1 -0
- package/dist/src/core/pagination.d.ts +10 -0
- package/dist/src/{pagination.js → core/pagination.js} +3 -0
- package/dist/src/core/pagination.js.map +1 -0
- package/dist/src/core/paths.d.ts +16 -0
- package/dist/src/{paths.js → core/paths.js} +14 -1
- package/dist/src/core/paths.js.map +1 -0
- package/dist/src/core/query/contract.d.ts +6 -0
- package/dist/src/{query → core/query}/contract.js +3 -0
- package/dist/src/core/query/contract.js.map +1 -0
- package/dist/src/core/query/filter.d.ts +6 -0
- package/dist/src/{query → core/query}/filter.js +18 -4
- package/dist/src/core/query/filter.js.map +1 -0
- package/dist/src/core/query/options.d.ts +30 -0
- package/dist/src/{query → core/query}/options.js +12 -0
- package/dist/src/core/query/options.js.map +1 -0
- package/dist/src/core/records.d.ts +46 -0
- package/dist/src/{records.js → core/records.js} +24 -3
- package/dist/src/core/records.js.map +1 -0
- package/dist/src/core/relation-metadata.d.ts +15 -0
- package/dist/src/{relation-metadata.js → core/relation-metadata.js} +7 -1
- package/dist/src/core/relation-metadata.js.map +1 -0
- package/dist/src/core/types.d.ts +10 -0
- package/dist/src/{types.js.map → core/types.js.map} +1 -1
- package/dist/src/core/utils.d.ts +56 -0
- package/dist/src/core/utils.js +102 -0
- package/dist/src/core/utils.js.map +1 -0
- package/dist/src/files/contract.d.ts +33 -0
- package/dist/src/files/contract.js +25 -3
- package/dist/src/files/contract.js.map +1 -1
- package/dist/src/files/disk-store.d.ts +3 -0
- package/dist/src/files/disk-store.js +27 -3
- package/dist/src/files/disk-store.js.map +1 -1
- package/dist/src/files/http.d.ts +8 -3
- package/dist/src/files/http.js +9 -0
- package/dist/src/files/http.js.map +1 -1
- package/dist/src/files/index.d.ts +4 -3
- package/dist/src/files/index.js +3 -1
- package/dist/src/files/index.js.map +1 -1
- package/dist/src/files/memory-store.d.ts +4 -1
- package/dist/src/files/memory-store.js +8 -2
- package/dist/src/files/memory-store.js.map +1 -1
- package/dist/src/files/routes.d.ts +3 -0
- package/dist/src/files/routes.js +25 -1
- package/dist/src/files/routes.js.map +1 -1
- package/dist/src/graphql/entry.d.ts +2 -2
- package/dist/src/graphql/entry.js.map +1 -1
- package/dist/src/graphql/lazy.d.ts +10 -0
- package/dist/src/graphql/lazy.js +13 -0
- package/dist/src/graphql/lazy.js.map +1 -0
- package/dist/src/graphql/preflight.d.ts +4 -1
- package/dist/src/graphql/preflight.js +3 -0
- package/dist/src/graphql/preflight.js.map +1 -1
- package/dist/src/graphql/public.d.ts +10 -2
- package/dist/src/graphql/public.js +10 -4
- package/dist/src/graphql/public.js.map +1 -1
- package/dist/src/graphql/resolvers.d.ts +10 -2
- package/dist/src/graphql/resolvers.js +8 -2
- package/dist/src/graphql/resolvers.js.map +1 -1
- package/dist/src/graphql/routes.d.ts +6 -2
- package/dist/src/graphql/routes.js +6 -3
- package/dist/src/graphql/routes.js.map +1 -1
- package/dist/src/graphql/schema.d.ts +6 -0
- package/dist/src/{graphql.js → graphql/schema.js} +14 -11
- package/dist/src/graphql/schema.js.map +1 -0
- package/dist/src/graphql/write.d.ts +3 -0
- package/dist/src/graphql/write.js +3 -0
- package/dist/src/graphql/write.js.map +1 -1
- package/dist/src/openapi/auth.d.ts +13 -0
- package/dist/src/openapi/auth.js +72 -0
- package/dist/src/openapi/auth.js.map +1 -0
- package/dist/src/openapi/document.d.ts +7 -3
- package/dist/src/openapi/document.js +49 -34
- package/dist/src/openapi/document.js.map +1 -1
- package/dist/src/openapi/entry.d.ts +2 -2
- package/dist/src/openapi/entry.js.map +1 -1
- package/dist/src/openapi/files.d.ts +6 -0
- package/dist/src/{files/openapi.js → openapi/files.js} +6 -3
- package/dist/src/openapi/files.js.map +1 -0
- package/dist/src/openapi/helpers.d.ts +10 -1
- package/dist/src/openapi/helpers.js +9 -0
- package/dist/src/openapi/helpers.js.map +1 -1
- package/dist/src/openapi/index.d.ts +7 -1
- package/dist/src/openapi/index.js +14 -5
- package/dist/src/openapi/index.js.map +1 -1
- package/dist/src/openapi/lazy.d.ts +11 -0
- package/dist/src/openapi/lazy.js +13 -0
- package/dist/src/openapi/lazy.js.map +1 -0
- package/dist/src/openapi/public.d.ts +11 -2
- package/dist/src/openapi/public.js +12 -4
- package/dist/src/openapi/public.js.map +1 -1
- package/dist/src/{types.d.ts → openapi/types.d.ts} +2 -10
- package/dist/src/openapi/types.js +2 -0
- package/dist/src/openapi/types.js.map +1 -0
- package/dist/src/rest/options.d.ts +11 -2
- package/dist/src/rest/options.js +12 -3
- package/dist/src/rest/options.js.map +1 -1
- package/dist/src/rest/projection.d.ts +10 -4
- package/dist/src/rest/projection.js +10 -4
- package/dist/src/rest/projection.js.map +1 -1
- package/dist/src/rest/routes.d.ts +6 -2
- package/dist/src/rest/routes.js +7 -3
- package/dist/src/rest/routes.js.map +1 -1
- package/dist/src/server/config.d.ts +79 -0
- package/dist/src/{config.js → server/config.js} +73 -12
- package/dist/src/server/config.js.map +1 -0
- package/dist/src/server/create.d.ts +18 -0
- package/dist/src/{server.js → server/create.js} +39 -21
- package/dist/src/server/create.js.map +1 -0
- package/dist/src/server/features.d.ts +15 -0
- package/dist/src/server/features.js +31 -0
- package/dist/src/server/features.js.map +1 -0
- package/dist/src/server/public.d.ts +3 -3
- package/dist/src/server/public.js +1 -1
- package/dist/src/server/public.js.map +1 -1
- package/package.json +5 -1
- package/dist/src/cli.d.ts +0 -4
- package/dist/src/cli.js.map +0 -1
- package/dist/src/config.d.ts +0 -81
- package/dist/src/config.js.map +0 -1
- package/dist/src/constants.js.map +0 -1
- package/dist/src/database.d.ts +0 -20
- package/dist/src/database.js.map +0 -1
- package/dist/src/engine.d.ts +0 -36
- package/dist/src/engine.js.map +0 -1
- package/dist/src/errors.d.ts +0 -6
- package/dist/src/errors.js +0 -9
- package/dist/src/errors.js.map +0 -1
- package/dist/src/features.d.ts +0 -8
- package/dist/src/features.js +0 -18
- package/dist/src/features.js.map +0 -1
- package/dist/src/files/openapi.d.ts +0 -3
- package/dist/src/files/openapi.js.map +0 -1
- package/dist/src/graphql.d.ts +0 -3
- package/dist/src/graphql.js.map +0 -1
- package/dist/src/http/errors.d.ts +0 -6
- package/dist/src/http/errors.js +0 -3
- package/dist/src/http/errors.js.map +0 -1
- package/dist/src/model.d.ts +0 -72
- package/dist/src/model.js.map +0 -1
- package/dist/src/mutations/write.js.map +0 -1
- package/dist/src/pagination.d.ts +0 -7
- package/dist/src/pagination.js.map +0 -1
- package/dist/src/paths.d.ts +0 -6
- package/dist/src/paths.js.map +0 -1
- package/dist/src/query/contract.d.ts +0 -3
- package/dist/src/query/contract.js.map +0 -1
- package/dist/src/query/filter.d.ts +0 -3
- package/dist/src/query/filter.js.map +0 -1
- package/dist/src/query/options.d.ts +0 -18
- package/dist/src/query/options.js.map +0 -1
- package/dist/src/records.d.ts +0 -25
- package/dist/src/records.js.map +0 -1
- package/dist/src/relation-metadata.d.ts +0 -9
- package/dist/src/relation-metadata.js.map +0 -1
- package/dist/src/schema.d.ts +0 -8
- package/dist/src/schema.js +0 -13
- package/dist/src/schema.js.map +0 -1
- package/dist/src/server.d.ts +0 -12
- package/dist/src/server.js.map +0 -1
- package/dist/src/utils.d.ts +0 -12
- package/dist/src/utils.js +0 -58
- package/dist/src/utils.js.map +0 -1
- /package/dist/src/{types.js → core/types.js} +0 -0
|
@@ -5,6 +5,9 @@ import { JSONFile } from 'lowdb/node';
|
|
|
5
5
|
import { domainError } from './errors.js';
|
|
6
6
|
import { createSerialQueue, createUniqueId, isObject, isSafeKey, isSystemError, resolveDatabasePath } from './utils.js';
|
|
7
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
|
+
*/
|
|
8
11
|
export const validateJsonValue = (value, path, ancestors = new WeakSet()) => {
|
|
9
12
|
if (value === null || typeof value === 'string' || typeof value === 'boolean') {
|
|
10
13
|
return;
|
|
@@ -41,6 +44,9 @@ export const validateJsonValue = (value, path, ancestors = new WeakSet()) => {
|
|
|
41
44
|
}
|
|
42
45
|
ancestors.delete(value);
|
|
43
46
|
};
|
|
47
|
+
/** Проверяет объект коллекций, записи и уникальность ключей; возвращает исходный объект.
|
|
48
|
+
* @example validateDatabase({ notes: [{ id: '1' }] }) → тот же объект; повторный id → ошибка.
|
|
49
|
+
*/
|
|
44
50
|
export const validateDatabase = (data, primaryKeys) => {
|
|
45
51
|
if (!isObject(data)) {
|
|
46
52
|
throw new Error('База данных должна содержать JSON-объект');
|
|
@@ -74,6 +80,9 @@ export const validateDatabase = (data, primaryKeys) => {
|
|
|
74
80
|
});
|
|
75
81
|
return data;
|
|
76
82
|
};
|
|
83
|
+
/** Читает UTF-8 JSON-файл и проверяет, что верхний уровень является объектом.
|
|
84
|
+
* @example Файл с {"a":1} → Promise<{ a: 1 }>; файл с [] → ошибка.
|
|
85
|
+
*/
|
|
77
86
|
export const readJsonObjectFile = async (path, label) => {
|
|
78
87
|
const resolvedPath = resolve(path);
|
|
79
88
|
let source;
|
|
@@ -92,6 +101,9 @@ export const readJsonObjectFile = async (path, label) => {
|
|
|
92
101
|
}
|
|
93
102
|
return value;
|
|
94
103
|
};
|
|
104
|
+
/** Читает файл и проверяет коллекции и первичные ключи.
|
|
105
|
+
* @example Файл с {"notes":[]} → Promise<{ notes: [] }>.
|
|
106
|
+
*/
|
|
95
107
|
export const readDatabaseFile = async (databasePath, keys) => validateDatabase(await readJsonObjectFile(databasePath, 'Файл базы данных'), keys);
|
|
96
108
|
const validateDraft = (data, keys) => {
|
|
97
109
|
try {
|
|
@@ -144,8 +156,16 @@ const createMemoryDatabaseStore = (sourceData, keys) => {
|
|
|
144
156
|
});
|
|
145
157
|
return { database, read, update };
|
|
146
158
|
};
|
|
147
|
-
/**
|
|
159
|
+
/** Создаёт дисковое хранилище или хранилище в памяти по настройкам.
|
|
160
|
+
* @example createDatabaseStore({ data: { notes: [] } }) → Promise<DatabaseStore>.
|
|
161
|
+
*/
|
|
148
162
|
export const createDatabaseStore = async (config, keys) => config.data != null ? createMemoryDatabaseStore(config.data, keys) : createDiskDatabaseStore(config.path, keys);
|
|
163
|
+
/** Ищет индекс записи, сравнивая строковые представления id.
|
|
164
|
+
* @example findItemIndex([{ id: 1 }], '1') → 0; пустой массив → -1.
|
|
165
|
+
*/
|
|
149
166
|
export const findItemIndex = (collection, id) => collection.findIndex((item) => String(item.id) === String(id));
|
|
167
|
+
/** Генерирует случайный строковый id, отсутствующий в переданной коллекции.
|
|
168
|
+
* @example createId([]) → строка из 11 символов; конкретное значение зависит от генератора случайных чисел.
|
|
169
|
+
*/
|
|
150
170
|
export const createId = (collection) => createUniqueId((id) => findItemIndex(collection, id) !== -1);
|
|
151
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,64 @@
|
|
|
1
|
+
import type { DatabaseStore } from './database.js';
|
|
2
|
+
import type { Actor } from './lifecycle/options.js';
|
|
3
|
+
import { type Entity, type Model, type Node } from './model.js';
|
|
4
|
+
import { type Predicate } from './query/filter.js';
|
|
5
|
+
import { type ListOptions } from './query/options.js';
|
|
6
|
+
import { type Context, type Ref } from './records.js';
|
|
7
|
+
import type { DatabaseData } from './types.js';
|
|
8
|
+
export interface PreparedList {
|
|
9
|
+
page: number;
|
|
10
|
+
pageSize: number;
|
|
11
|
+
predicate?: Predicate;
|
|
12
|
+
rules: Array<{
|
|
13
|
+
direction: 'ASC' | 'DESC';
|
|
14
|
+
keys: string[];
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export interface Page {
|
|
18
|
+
data: Ref[];
|
|
19
|
+
total: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class Engine {
|
|
22
|
+
readonly store: DatabaseStore;
|
|
23
|
+
model: Model;
|
|
24
|
+
readonly pageSize: number;
|
|
25
|
+
readonly maxPageSize: number;
|
|
26
|
+
private inferredModels;
|
|
27
|
+
constructor(store: DatabaseStore, model: Model, pageSize?: number, maxPageSize?: number);
|
|
28
|
+
/** Возвращает явную модель или кешированное описание, выведенное из переданного снимка данных.
|
|
29
|
+
* @example Повторный вызов с тем же объектом data → тот же объект Model.
|
|
30
|
+
*/
|
|
31
|
+
private modelFor;
|
|
32
|
+
/** Читает актуальный снимок хранилища и создаёт контекст с пустым кешем индексов.
|
|
33
|
+
* @example context() → Promise<Context>; при ошибке чтения хранилища → отклонённый Promise.
|
|
34
|
+
*/
|
|
35
|
+
context(): Promise<Context>;
|
|
36
|
+
/** Оборачивает все записи выбранной коллекции ссылками с контекстом.
|
|
37
|
+
* @example Пустая коллекция → []; две записи → две ссылки Ref.
|
|
38
|
+
*/
|
|
39
|
+
records(context: Context, entity: Entity): Ref[];
|
|
40
|
+
/** Ищет запись по строковому представлению первичного ключа, включая удалённые записи.
|
|
41
|
+
* @example Ключ '1' находит запись с числовым ключом 1; отсутствующий ключ → undefined.
|
|
42
|
+
*/
|
|
43
|
+
find(context: Context, entity: Entity, key: unknown): Ref | undefined;
|
|
44
|
+
/** Проверяет аргументы списка и подготавливает предикат, пути сортировки и размеры страницы.
|
|
45
|
+
* @example pager: { page: 2, pageSize: 5 } → план с page: 2 и pageSize: 5; page: 0 → ошибка.
|
|
46
|
+
*/
|
|
47
|
+
prepareOptions(node: Node, options?: ListOptions): PreparedList;
|
|
48
|
+
/** Фильтрует, сортирует и возвращает страницу, не меняя порядок исходного массива.
|
|
49
|
+
* @example Три подходящие записи, page: 2, pageSize: 2 → { data: [третья запись], total: 3 }.
|
|
50
|
+
*/
|
|
51
|
+
list(records: Ref[], node: Node, options?: ListOptions, prepared?: PreparedList): Page;
|
|
52
|
+
/** Проверяет коллекции, значения полей и целостность активных связей.
|
|
53
|
+
* @example Согласованные записи → undefined; обязательная связь без цели → исключение.
|
|
54
|
+
*/
|
|
55
|
+
validateData(data: DatabaseData): void;
|
|
56
|
+
/** Выполняет одну операцию записи в транзакции, включая связи, права и подготовку ответа.
|
|
57
|
+
* @example Режим update с { name: 'Анна' } → обновлённая запись; ошибка проверки → прежние данные.
|
|
58
|
+
*/
|
|
59
|
+
mutate<T = Ref>(entity: Entity, mode: 'create' | 'replace' | 'update' | 'delete', key?: unknown, body?: unknown, prepare?: (ref: Ref) => T, actor?: Actor): Promise<T>;
|
|
60
|
+
/** Вычисляет каскад удаления, проверяет запрещающие связи и меняет только черновик данных.
|
|
61
|
+
* @example Удаление родителя при cascade → удалённые зависимые записи; restrict → исключение.
|
|
62
|
+
*/
|
|
63
|
+
private cascade;
|
|
64
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { DEFAULT_MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE } from './constants.js';
|
|
2
2
|
import { domainError } from './errors.js';
|
|
3
|
+
import { RecordMutation } from './lifecycle/mutation.js';
|
|
3
4
|
import { inferModel, isReverseRelation, pathParts, readPath, validateRecord } from './model.js';
|
|
4
5
|
import { MutationWriter } from './mutations/write.js';
|
|
5
6
|
import { compileWhere } from './query/filter.js';
|
|
6
7
|
import { badQuery, childrenOf, nodeAt } from './query/options.js';
|
|
7
8
|
import { isRef, keyOf, makeContext, related, resolveField, rootRef, sourceValues } from './records.js';
|
|
8
|
-
import { isObject } from './utils.js';
|
|
9
|
+
import { hasOnlyKeys, isObject } from './utils.js';
|
|
9
10
|
function filterView(ref) {
|
|
10
11
|
const value = {};
|
|
11
12
|
for (const [name, node] of Object.entries(childrenOf(ref.node)))
|
|
@@ -13,7 +14,7 @@ function filterView(ref) {
|
|
|
13
14
|
Object.defineProperty(value, name, {
|
|
14
15
|
enumerable: true,
|
|
15
16
|
get: () => {
|
|
16
|
-
const field = resolveField(ref, node);
|
|
17
|
+
const field = resolveField(ref, node, true);
|
|
17
18
|
return isRef(field) ? filterView(field) : Array.isArray(field) ? field.map((v) => (isRef(v) ? filterView(v) : v)) : field;
|
|
18
19
|
},
|
|
19
20
|
});
|
|
@@ -33,41 +34,56 @@ export class Engine {
|
|
|
33
34
|
this.maxPageSize = maxPageSize;
|
|
34
35
|
this.inferredModels.set(store.database.data, model);
|
|
35
36
|
}
|
|
37
|
+
/** Возвращает явную модель или кешированное описание, выведенное из переданного снимка данных.
|
|
38
|
+
* @example Повторный вызов с тем же объектом data → тот же объект Model.
|
|
39
|
+
*/
|
|
36
40
|
modelFor(data) {
|
|
37
41
|
if (this.model.explicit)
|
|
38
42
|
return this.model;
|
|
39
43
|
let model = this.inferredModels.get(data);
|
|
40
44
|
if (!model) {
|
|
41
|
-
model = inferModel(data);
|
|
45
|
+
model = inferModel(data, this.model.options);
|
|
42
46
|
this.inferredModels.set(data, model);
|
|
43
47
|
}
|
|
44
48
|
return model;
|
|
45
49
|
}
|
|
50
|
+
/** Читает актуальный снимок хранилища и создаёт контекст с пустым кешем индексов.
|
|
51
|
+
* @example context() → Promise<Context>; при ошибке чтения хранилища → отклонённый Promise.
|
|
52
|
+
*/
|
|
46
53
|
async context() {
|
|
47
54
|
const data = await this.store.read();
|
|
48
55
|
if (!this.model.explicit)
|
|
49
56
|
this.model = this.modelFor(data);
|
|
50
57
|
return makeContext(data, this.model);
|
|
51
58
|
}
|
|
59
|
+
/** Оборачивает все записи выбранной коллекции ссылками с контекстом.
|
|
60
|
+
* @example Пустая коллекция → []; две записи → две ссылки Ref.
|
|
61
|
+
*/
|
|
52
62
|
records(context, entity) {
|
|
53
63
|
return (context.data[entity.collection] ?? []).map((value) => rootRef(context, entity, value));
|
|
54
64
|
}
|
|
65
|
+
/** Ищет запись по строковому представлению первичного ключа, включая удалённые записи.
|
|
66
|
+
* @example Ключ '1' находит запись с числовым ключом 1; отсутствующий ключ → undefined.
|
|
67
|
+
*/
|
|
55
68
|
find(context, entity, key) {
|
|
56
69
|
const value = (context.data[entity.collection] ?? []).find((record) => String(record[entity.primary]) === String(key));
|
|
57
70
|
return value ? rootRef(context, entity, value) : undefined;
|
|
58
71
|
}
|
|
72
|
+
/** Проверяет аргументы списка и подготавливает предикат, пути сортировки и размеры страницы.
|
|
73
|
+
* @example pager: { page: 2, pageSize: 5 } → план с page: 2 и pageSize: 5; page: 0 → ошибка.
|
|
74
|
+
*/
|
|
59
75
|
prepareOptions(node, options = {}) {
|
|
60
|
-
const predicate = options.where !== undefined ? compileWhere(node, options.where) : undefined;
|
|
76
|
+
const predicate = options.where !== undefined || node.softDelete || node.relation?.softDelete ? compileWhere(node, options.where ?? {}) : undefined;
|
|
61
77
|
if (options.order !== undefined) {
|
|
62
78
|
if (!Array.isArray(options.order))
|
|
63
79
|
badQuery('order must be an array');
|
|
64
80
|
for (const rule of options.order) {
|
|
65
|
-
if (!isObject(rule) ||
|
|
81
|
+
if (!isObject(rule) || !hasOnlyKeys(rule, ['field', 'direction']) || typeof rule.field !== 'string' || !['ASC', 'DESC'].includes(rule.direction))
|
|
66
82
|
badQuery('Invalid order rule');
|
|
67
83
|
nodeAt(node, rule.field, true);
|
|
68
84
|
}
|
|
69
85
|
}
|
|
70
|
-
if (options.pager !== undefined && (!isObject(options.pager) ||
|
|
86
|
+
if (options.pager !== undefined && (!isObject(options.pager) || !hasOnlyKeys(options.pager, ['page', 'pageSize'])))
|
|
71
87
|
badQuery('Invalid pager');
|
|
72
88
|
const page = options.pager?.page ?? 1;
|
|
73
89
|
const pageSize = options.pager?.pageSize ?? this.pageSize;
|
|
@@ -82,6 +98,9 @@ export class Engine {
|
|
|
82
98
|
badQuery(`Invalid pager; pageSize must be 1..${this.maxPageSize}`);
|
|
83
99
|
return { page, pageSize, predicate, rules: (options.order ?? []).map((rule) => ({ direction: rule.direction, keys: pathParts(rule.field) })) };
|
|
84
100
|
}
|
|
101
|
+
/** Фильтрует, сортирует и возвращает страницу, не меняя порядок исходного массива.
|
|
102
|
+
* @example Три подходящие записи, page: 2, pageSize: 2 → { data: [третья запись], total: 3 }.
|
|
103
|
+
*/
|
|
85
104
|
list(records, node, options = {}, prepared = this.prepareOptions(node, options)) {
|
|
86
105
|
const { page, pageSize, predicate, rules } = prepared;
|
|
87
106
|
const data = predicate ? records.filter((ref) => predicate(filterView(ref))) : [...records];
|
|
@@ -106,6 +125,9 @@ export class Engine {
|
|
|
106
125
|
});
|
|
107
126
|
return { data: data.slice((page - 1) * pageSize, page * pageSize), total: data.length };
|
|
108
127
|
}
|
|
128
|
+
/** Проверяет коллекции, значения полей и целостность активных связей.
|
|
129
|
+
* @example Согласованные записи → undefined; обязательная связь без цели → исключение.
|
|
130
|
+
*/
|
|
109
131
|
validateData(data) {
|
|
110
132
|
if (!this.model.explicit)
|
|
111
133
|
return;
|
|
@@ -116,7 +138,7 @@ export class Engine {
|
|
|
116
138
|
const visit = (ref) => {
|
|
117
139
|
for (const node of Object.values(ref.node.children)) {
|
|
118
140
|
if (node.relation) {
|
|
119
|
-
const matches = related(ref, node);
|
|
141
|
+
const matches = related(ref, node).filter((match) => !match.entity.softDelete || match.value.deletedAt == null);
|
|
120
142
|
if (!node.many && matches.length > 1)
|
|
121
143
|
throw domainError('INVALID_INPUT', `Multiple targets for ${ref.entity.name}.${node.path}`);
|
|
122
144
|
if (node.required && !matches.length)
|
|
@@ -139,10 +161,16 @@ export class Engine {
|
|
|
139
161
|
for (const entity of this.model.entities)
|
|
140
162
|
for (const record of data[entity.collection] ?? []) {
|
|
141
163
|
validateRecord(entity, record, 'stored');
|
|
142
|
-
|
|
164
|
+
if (!entity.softDelete || record.deletedAt == null)
|
|
165
|
+
visit(rootRef(context, entity, record));
|
|
143
166
|
}
|
|
144
167
|
}
|
|
145
|
-
|
|
168
|
+
/** Выполняет одну операцию записи в транзакции, включая связи, права и подготовку ответа.
|
|
169
|
+
* @example Режим update с { name: 'Анна' } → обновлённая запись; ошибка проверки → прежние данные.
|
|
170
|
+
*/
|
|
171
|
+
async mutate(entity, mode, key, body, prepare, actor) {
|
|
172
|
+
if (this.model.options.auth && !actor)
|
|
173
|
+
throw domainError('UNAUTHENTICATED', 'Authentication required');
|
|
146
174
|
if (mode !== 'delete') {
|
|
147
175
|
if (!isObject(body))
|
|
148
176
|
throw domainError('INVALID_INPUT', 'Request body must be an object');
|
|
@@ -150,6 +178,7 @@ export class Engine {
|
|
|
150
178
|
throw domainError('INVALID_INPUT', 'id is generated and immutable');
|
|
151
179
|
}
|
|
152
180
|
const outcome = await this.store.update((database) => {
|
|
181
|
+
const lifecycle = new RecordMutation(database.data, this.model, actor);
|
|
153
182
|
const finish = (data, record) => {
|
|
154
183
|
const model = this.modelFor(data);
|
|
155
184
|
const currentEntity = model.byCollection.get(entity.collection);
|
|
@@ -175,23 +204,35 @@ export class Engine {
|
|
|
175
204
|
if (!current)
|
|
176
205
|
throw domainError('NOT_FOUND', 'Record not found');
|
|
177
206
|
const snapshot = structuredClone(database.data);
|
|
178
|
-
|
|
207
|
+
lifecycle.check(entity, current.value);
|
|
208
|
+
if (entity.softDelete && current.value.deletedAt != null)
|
|
209
|
+
return finish(database.data, current.value);
|
|
210
|
+
this.cascade(context, current, lifecycle);
|
|
211
|
+
lifecycle.finish();
|
|
179
212
|
this.validateData(database.data);
|
|
180
|
-
return finish(snapshot, current.value);
|
|
213
|
+
return finish(entity.softDelete ? database.data : snapshot, current.value);
|
|
181
214
|
}
|
|
182
|
-
const writer = new MutationWriter(database, this.model, mode === 'replace' ? 'replace' : 'update');
|
|
215
|
+
const writer = new MutationWriter(database, this.model, mode === 'replace' ? 'replace' : 'update', (owner, record) => lifecycle.write(owner, record));
|
|
183
216
|
const record = writer.write(entity, mode, key, body);
|
|
184
217
|
writer.validateRelations();
|
|
218
|
+
lifecycle.finish();
|
|
185
219
|
this.validateData(database.data);
|
|
186
220
|
return finish(database.data, record);
|
|
187
221
|
});
|
|
188
222
|
this.model = outcome.model;
|
|
189
223
|
return outcome.output;
|
|
190
224
|
}
|
|
191
|
-
|
|
225
|
+
/** Вычисляет каскад удаления, проверяет запрещающие связи и меняет только черновик данных.
|
|
226
|
+
* @example Удаление родителя при cascade → удалённые зависимые записи; restrict → исключение.
|
|
227
|
+
*/
|
|
228
|
+
cascade(context, initial, lifecycle) {
|
|
192
229
|
if (!this.model.explicit) {
|
|
193
|
-
|
|
194
|
-
|
|
230
|
+
lifecycle.deleteGroup(initial, new Set([initial.value]));
|
|
231
|
+
if (!initial.entity.softDelete) {
|
|
232
|
+
const rows = context.data[initial.entity.collection];
|
|
233
|
+
rows.splice(rows.indexOf(initial.value), 1);
|
|
234
|
+
}
|
|
235
|
+
lifecycle.capturePruned(initial);
|
|
195
236
|
return;
|
|
196
237
|
}
|
|
197
238
|
const deleted = new Set([initial.value]);
|
|
@@ -214,7 +255,9 @@ export class Engine {
|
|
|
214
255
|
}
|
|
215
256
|
};
|
|
216
257
|
for (const entity of this.model.entities)
|
|
217
|
-
this.records(context, entity)
|
|
258
|
+
this.records(context, entity)
|
|
259
|
+
.filter((ref) => !entity.softDelete || ref.value.deletedAt == null)
|
|
260
|
+
.forEach(collect);
|
|
218
261
|
let changed = true;
|
|
219
262
|
while (changed) {
|
|
220
263
|
changed = false;
|
|
@@ -231,6 +274,7 @@ export class Engine {
|
|
|
231
274
|
blocked.push({ owner: ref.value, root: ref.root, node });
|
|
232
275
|
if (blocked.length)
|
|
233
276
|
throw domainError('CONFLICT', `Delete restricted by ${blocked[0].node.path}`);
|
|
277
|
+
lifecycle.deleteGroup(initial, deleted);
|
|
234
278
|
const prune = (node, record) => {
|
|
235
279
|
for (const [key, child] of Object.entries(node.children))
|
|
236
280
|
if (!child.relation && child.base === 'object' && record[key] != null) {
|
|
@@ -247,11 +291,13 @@ export class Engine {
|
|
|
247
291
|
}
|
|
248
292
|
};
|
|
249
293
|
for (const entity of this.model.entities) {
|
|
250
|
-
context.data[entity.collection] = (context.data[entity.collection] ?? []).filter((record) => !deleted.has(record));
|
|
294
|
+
context.data[entity.collection] = (context.data[entity.collection] ?? []).filter((record) => entity.softDelete || !deleted.has(record));
|
|
251
295
|
context.data[entity.collection].forEach((record) => {
|
|
252
|
-
|
|
296
|
+
if (!deleted.has(record))
|
|
297
|
+
prune(entity.root, record);
|
|
253
298
|
});
|
|
254
299
|
}
|
|
300
|
+
lifecycle.capturePruned(initial);
|
|
255
301
|
}
|
|
256
302
|
}
|
|
257
303
|
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/core/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ErrorCode = 'INVALID_INPUT' | 'INVALID_QUERY' | 'NOT_FOUND' | 'CONFLICT' | 'PAYLOAD_TOO_LARGE' | 'UNAUTHENTICATED' | 'TOO_MANY_REQUESTS' | 'FORBIDDEN';
|
|
2
|
+
export declare class DomainError extends Error {
|
|
3
|
+
readonly code: ErrorCode;
|
|
4
|
+
constructor(code: ErrorCode, message: string);
|
|
5
|
+
}
|
|
6
|
+
/** Создаёт исключение с отдельным кодом и сообщением.
|
|
7
|
+
* @example domainError('NOT_FOUND', 'Нет записи') → Error с code = 'NOT_FOUND' и message = 'Нет записи'.
|
|
8
|
+
*/
|
|
9
|
+
export declare const domainError: (code: ErrorCode, message: string) => DomainError;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class DomainError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(code, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
/** Создаёт исключение с отдельным кодом и сообщением.
|
|
9
|
+
* @example domainError('NOT_FOUND', 'Нет записи') → Error с code = 'NOT_FOUND' и message = 'Нет записи'.
|
|
10
|
+
*/
|
|
11
|
+
export const domainError = (code, message) => new DomainError(code, message);
|
|
12
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AACA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAEzB,IAAI;IADf,YACW,IAAe,EACxB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;oBAHN,IAAI;IAIf,CAAC;CACF;AACD;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAe,EAAE,OAAe,EAAe,EAAE,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ErrorCode } from './errors.js';
|
|
2
|
+
export declare const domainStatus: Record<ErrorCode, number>;
|
|
3
|
+
export interface HttpError extends Error {
|
|
4
|
+
statusCode: number;
|
|
5
|
+
}
|
|
6
|
+
/** Создаёт исключение с HTTP-статусом и сообщением.
|
|
7
|
+
* @example createHttpError(404, 'Нет файла') → Error с statusCode = 404 и message = 'Нет файла'.
|
|
8
|
+
*/
|
|
9
|
+
export declare const createHttpError: (statusCode: number, message: string) => HttpError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const domainStatus = {
|
|
2
|
+
INVALID_INPUT: 400,
|
|
3
|
+
INVALID_QUERY: 400,
|
|
4
|
+
NOT_FOUND: 404,
|
|
5
|
+
CONFLICT: 409,
|
|
6
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
7
|
+
UNAUTHENTICATED: 401,
|
|
8
|
+
FORBIDDEN: 403,
|
|
9
|
+
TOO_MANY_REQUESTS: 429,
|
|
10
|
+
};
|
|
11
|
+
/** Создаёт исключение с HTTP-статусом и сообщением.
|
|
12
|
+
* @example createHttpError(404, 'Нет файла') → Error с statusCode = 404 и message = 'Нет файла'.
|
|
13
|
+
*/
|
|
14
|
+
export const createHttpError = (statusCode, message) => Object.assign(new Error(message), { statusCode });
|
|
15
|
+
//# sourceMappingURL=http-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-errors.js","sourceRoot":"","sources":["../../../src/core/http-errors.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,YAAY,GAA8B;IACrD,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,GAAG;IAClB,SAAS,EAAE,GAAG;IACd,QAAQ,EAAE,GAAG;IACb,iBAAiB,EAAE,GAAG;IACtB,eAAe,EAAE,GAAG;IACpB,SAAS,EAAE,GAAG;IACd,iBAAiB,EAAE,GAAG;CACvB,CAAC;AAIF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAkB,EAAE,OAAe,EAAa,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Entity, Model } from '../model.js';
|
|
2
|
+
import type { DatabaseData, JsonObject } from '../types.js';
|
|
3
|
+
import { type Actor } from './options.js';
|
|
4
|
+
/** Проверяет владельцев и заполняет поля дат и авторов внутри транзакции. */
|
|
5
|
+
export declare class RecordMutation {
|
|
6
|
+
private data;
|
|
7
|
+
private model;
|
|
8
|
+
private actor?;
|
|
9
|
+
readonly before: DatabaseData;
|
|
10
|
+
readonly now: string;
|
|
11
|
+
private originals;
|
|
12
|
+
private touched;
|
|
13
|
+
private enabled;
|
|
14
|
+
constructor(data: DatabaseData, model: Model, actor?: Actor | undefined);
|
|
15
|
+
/** Проверяет владельца исходной записи или права администратора; данные не меняет.
|
|
16
|
+
* @example Совпадающие createdById и actor.id → undefined; чужая запись без прав администратора → FORBIDDEN.
|
|
17
|
+
*/
|
|
18
|
+
check(entity: Entity, record: JsonObject): void;
|
|
19
|
+
/** Отмечает запись изменённой и при необходимости восстанавливает её каскад в черновике.
|
|
20
|
+
* @example Удалённая запись после успешного вызова → deletedAt: null; конфликт восстановления → ошибка.
|
|
21
|
+
*/
|
|
22
|
+
write(entity: Entity, record: JsonObject): void;
|
|
23
|
+
/** Очищает признаки удаления и служебные сведения восстановления, отмечая запись изменённой.
|
|
24
|
+
* @example Запись с deletedAt и сведениями каскада → deletedAt: null без служебных сведений; результат undefined.
|
|
25
|
+
*/
|
|
26
|
+
private clear;
|
|
27
|
+
/** Помечает выбранные записи временем удаления и общим случайным идентификатором операции.
|
|
28
|
+
* @example Две записи с включённым мягким удалением → одинаковые дата и идентификатор каскада.
|
|
29
|
+
*/
|
|
30
|
+
deleteGroup(initial: {
|
|
31
|
+
entity: Entity;
|
|
32
|
+
value: JsonObject;
|
|
33
|
+
}, deleted: Set<JsonObject>): void;
|
|
34
|
+
/** Сохраняет изменения вложенных объектов для последующего восстановления каскада.
|
|
35
|
+
* @example Поле actors изменилось с [a, b] на [b] → в сведениях удаления сохранены оба состояния.
|
|
36
|
+
*/
|
|
37
|
+
capturePruned(initial: {
|
|
38
|
+
entity: Entity;
|
|
39
|
+
value: JsonObject;
|
|
40
|
+
}): void;
|
|
41
|
+
/** Проверяет права на все изменения и проставляет даты и авторов в черновике.
|
|
42
|
+
* @example Новая запись при включённых флагах → createdAt = updatedAt и createdById = updatedById.
|
|
43
|
+
*/
|
|
44
|
+
finish(): void;
|
|
45
|
+
/** Разбирает и проверяет внутреннюю JSON-строку сведений об удалении.
|
|
46
|
+
* @example Отсутствующие сведения → undefined; корректная строка → объект; повреждённая строка → ошибка.
|
|
47
|
+
*/
|
|
48
|
+
private deletion;
|
|
49
|
+
}
|