@kollors/deep-json-server 1.0.0-alpha.1 → 1.0.0-alpha.11
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 +522 -179
- package/README.ru.md +525 -180
- package/dist/bin/deep-json-server.js +1 -1
- package/dist/bin/deep-json-server.js.map +1 -1
- package/dist/index.d.ts +13 -6
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/src/auth/contract.d.ts +31 -0
- package/dist/src/auth/contract.js +12 -0
- package/dist/src/auth/contract.js.map +1 -0
- package/dist/src/auth/input.d.ts +18 -0
- package/dist/src/auth/input.js +34 -0
- package/dist/src/auth/input.js.map +1 -0
- package/dist/src/auth/password.d.ts +17 -0
- package/dist/src/auth/password.js +41 -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 +18 -0
- package/dist/src/auth/routes.js.map +1 -0
- package/dist/src/auth/service.d.ts +78 -0
- package/dist/src/auth/service.js +218 -0
- package/dist/src/auth/service.js.map +1 -0
- package/dist/src/auth/store.d.ts +26 -0
- package/dist/src/auth/store.js +82 -0
- package/dist/src/auth/store.js.map +1 -0
- package/dist/src/cli/index.d.ts +7 -0
- package/dist/src/cli/index.js +113 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/core/config-values.d.ts +28 -0
- package/dist/src/core/config-values.js +53 -0
- package/dist/src/core/config-values.js.map +1 -0
- package/dist/src/{constants.d.ts → core/constants.d.ts} +1 -0
- package/dist/src/{constants.js → core/constants.js} +1 -0
- package/dist/src/core/constants.js.map +1 -0
- package/dist/src/core/database.d.ts +48 -0
- package/dist/src/{database.js → core/database.js} +36 -14
- package/dist/src/core/database.js.map +1 -0
- package/dist/src/core/engine.d.ts +53 -0
- package/dist/src/core/engine.js +249 -0
- 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 +21 -0
- package/dist/src/core/lifecycle/options.js +19 -0
- package/dist/src/core/lifecycle/options.js.map +1 -0
- package/dist/src/core/model.d.ts +145 -0
- package/dist/src/{model.js → core/model.js} +224 -33
- package/dist/src/core/model.js.map +1 -0
- package/dist/src/core/mutations/write.d.ts +26 -0
- package/dist/src/core/mutations/write.js +284 -0
- package/dist/src/core/mutations/write.js.map +1 -0
- package/dist/src/core/operations.d.ts +33 -0
- package/dist/src/core/operations.js +10 -0
- package/dist/src/core/operations.js.map +1 -0
- package/dist/src/core/pagination.d.ts +10 -0
- package/dist/src/core/pagination.js +13 -0
- package/dist/src/core/pagination.js.map +1 -0
- package/dist/src/core/paths.d.ts +16 -0
- package/dist/src/core/paths.js +64 -0
- package/dist/src/core/paths.js.map +1 -0
- package/dist/src/core/query/contract.d.ts +6 -0
- package/dist/src/core/query/contract.js +22 -0
- package/dist/src/core/query/contract.js.map +1 -0
- package/dist/src/core/query/execute.d.ts +25 -0
- package/dist/src/core/query/execute.js +82 -0
- package/dist/src/core/query/execute.js.map +1 -0
- package/dist/src/core/query/filter.d.ts +6 -0
- package/dist/src/core/query/filter.js +100 -0
- package/dist/src/core/query/filter.js.map +1 -0
- package/dist/src/core/query/options.d.ts +30 -0
- package/dist/src/core/query/options.js +44 -0
- package/dist/src/core/query/options.js.map +1 -0
- package/dist/src/core/records.d.ts +46 -0
- package/dist/src/core/records.js +69 -0
- 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 -2
- package/dist/src/core/relation-metadata.js.map +1 -0
- package/dist/src/core/storage.d.ts +2 -0
- package/dist/src/core/storage.js +2 -0
- package/dist/src/core/storage.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 +32 -30
- package/dist/src/files/contract.js +29 -48
- package/dist/src/files/contract.js.map +1 -1
- package/dist/src/files/disk-metadata.d.ts +9 -0
- package/dist/src/files/disk-metadata.js +44 -0
- package/dist/src/files/disk-metadata.js.map +1 -0
- package/dist/src/files/disk-paths.d.ts +15 -0
- package/dist/src/files/disk-paths.js +100 -0
- package/dist/src/files/disk-paths.js.map +1 -0
- package/dist/src/files/disk-store.d.ts +5 -1
- package/dist/src/files/disk-store.js +46 -173
- package/dist/src/files/disk-store.js.map +1 -1
- package/dist/src/files/http.d.ts +36 -0
- package/dist/src/files/http.js +53 -0
- package/dist/src/files/http.js.map +1 -0
- package/dist/src/files/index.d.ts +5 -4
- package/dist/src/files/index.js +7 -2
- 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 +29 -22
- 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 +27 -2
- package/dist/src/files/routes.js.map +1 -1
- package/dist/src/files/streams.d.ts +5 -0
- package/dist/src/files/streams.js +20 -0
- package/dist/src/files/streams.js.map +1 -0
- package/dist/src/graphql/entry.d.ts +12 -0
- package/dist/src/graphql/entry.js +13 -0
- package/dist/src/graphql/entry.js.map +1 -0
- package/dist/src/graphql/generate.d.ts +12 -0
- package/dist/src/graphql/generate.js +19 -0
- package/dist/src/graphql/generate.js.map +1 -0
- package/dist/src/graphql/preflight.d.ts +6 -0
- package/dist/src/graphql/preflight.js +44 -0
- package/dist/src/graphql/preflight.js.map +1 -0
- package/dist/src/graphql/resolvers.d.ts +17 -0
- package/dist/src/graphql/resolvers.js +44 -0
- package/dist/src/graphql/resolvers.js.map +1 -0
- package/dist/src/graphql/routes.d.ts +8 -0
- package/dist/src/graphql/routes.js +30 -0
- package/dist/src/graphql/routes.js.map +1 -0
- package/dist/src/graphql/schema.d.ts +6 -0
- package/dist/src/{graphql.js → graphql/schema.js} +59 -49
- package/dist/src/graphql/schema.js.map +1 -0
- package/dist/src/graphql/write.d.ts +4 -0
- package/dist/src/graphql/write.js +10 -0
- package/dist/src/graphql/write.js.map +1 -0
- package/dist/src/openapi/auth.d.ts +13 -0
- package/dist/src/openapi/auth.js +139 -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 +154 -103
- package/dist/src/openapi/document.js.map +1 -1
- package/dist/src/openapi/entry.d.ts +14 -0
- package/dist/src/openapi/entry.js +13 -0
- package/dist/src/openapi/entry.js.map +1 -0
- package/dist/src/openapi/files.d.ts +6 -0
- package/dist/src/{files/openapi.js → openapi/files.js} +6 -5
- package/dist/src/openapi/files.js.map +1 -0
- package/dist/src/openapi/generate.d.ts +19 -0
- package/dist/src/openapi/generate.js +41 -0
- package/dist/src/openapi/generate.js.map +1 -0
- package/dist/src/openapi/helpers.d.ts +26 -0
- package/dist/src/openapi/helpers.js +13 -0
- package/dist/src/openapi/helpers.js.map +1 -0
- package/dist/src/openapi/options.d.ts +18 -0
- package/dist/src/openapi/options.js +13 -0
- package/dist/src/openapi/options.js.map +1 -0
- package/dist/src/openapi/registry.d.ts +11 -0
- package/dist/src/openapi/registry.js +20 -0
- package/dist/src/openapi/registry.js.map +1 -0
- 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/openapi/write.d.ts +5 -0
- package/dist/src/openapi/write.js +12 -0
- package/dist/src/openapi/write.js.map +1 -0
- package/dist/src/rest/options.d.ts +22 -0
- package/dist/src/rest/options.js +65 -0
- package/dist/src/rest/options.js.map +1 -0
- package/dist/src/rest/projection.d.ts +13 -0
- package/dist/src/rest/projection.js +61 -0
- package/dist/src/rest/projection.js.map +1 -0
- package/dist/src/rest/routes.d.ts +7 -0
- package/dist/src/rest/routes.js +58 -0
- package/dist/src/rest/routes.js.map +1 -0
- package/dist/src/server/bootstrap.d.ts +7 -0
- package/dist/src/server/bootstrap.js +48 -0
- package/dist/src/server/bootstrap.js.map +1 -0
- package/dist/src/server/config.d.ts +74 -0
- package/dist/src/server/config.js +142 -0
- package/dist/src/server/config.js.map +1 -0
- package/dist/src/server/create.d.ts +16 -0
- package/dist/src/server/create.js +59 -0
- package/dist/src/server/create.js.map +1 -0
- package/dist/src/server/features.d.ts +4 -0
- package/dist/src/server/features.js +11 -0
- package/dist/src/server/features.js.map +1 -0
- package/dist/src/server/http.d.ts +12 -0
- package/dist/src/server/http.js +40 -0
- package/dist/src/server/http.js.map +1 -0
- package/dist/src/server/model.d.ts +6 -0
- package/dist/src/server/model.js +14 -0
- package/dist/src/server/model.js.map +1 -0
- package/dist/src/server/openapi-options.d.ts +6 -0
- package/dist/src/server/openapi-options.js +15 -0
- package/dist/src/server/openapi-options.js.map +1 -0
- package/dist/src/server/public.d.ts +2 -0
- package/dist/src/server/public.js +2 -0
- package/dist/src/server/public.js.map +1 -0
- package/package.json +19 -3
- package/dist/src/cli.d.ts +0 -4
- package/dist/src/cli.js +0 -67
- package/dist/src/cli.js.map +0 -1
- package/dist/src/config.d.ts +0 -68
- package/dist/src/config.js +0 -161
- package/dist/src/config.js.map +0 -1
- package/dist/src/constants.js.map +0 -1
- package/dist/src/database.d.ts +0 -21
- package/dist/src/database.js.map +0 -1
- package/dist/src/engine.d.ts +0 -47
- package/dist/src/engine.js +0 -438
- package/dist/src/engine.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 -4
- package/dist/src/graphql.js.map +0 -1
- package/dist/src/model.d.ts +0 -67
- package/dist/src/model.js.map +0 -1
- package/dist/src/openapi/index.d.ts +0 -7
- package/dist/src/openapi/index.js +0 -26
- package/dist/src/openapi/index.js.map +0 -1
- package/dist/src/query/filter.d.ts +0 -1
- package/dist/src/query/filter.js +0 -84
- package/dist/src/query/filter.js.map +0 -1
- package/dist/src/query/options.d.ts +0 -31
- package/dist/src/query/options.js +0 -135
- package/dist/src/query/options.js.map +0 -1
- package/dist/src/relation-metadata.d.ts +0 -10
- package/dist/src/relation-metadata.js.map +0 -1
- package/dist/src/server.d.ts +0 -14
- package/dist/src/server.js +0 -166
- package/dist/src/server.js.map +0 -1
- package/dist/src/utils.d.ts +0 -19
- package/dist/src/utils.js +0 -62
- package/dist/src/utils.js.map +0 -1
- /package/dist/src/{types.js → core/types.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../../src/core/query/execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Node } from '../model.js';
|
|
2
|
+
export type Predicate = (value: unknown) => boolean;
|
|
3
|
+
/** Компилирует условия объекта в предикат; учитывает логические операторы и фильтрацию удалённых записей.
|
|
4
|
+
* @example Для числового age: compileWhere(node, { age: { gte: 18 } })({ age: 20 }) → true.
|
|
5
|
+
*/
|
|
6
|
+
export declare function compileWhere(node: Node, input: unknown, depth?: number, defaults?: boolean): Predicate;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { mentionsDeletedAt } from '../lifecycle/options.js';
|
|
2
|
+
import { isEqual, isObject } from '../utils.js';
|
|
3
|
+
import { operatorsFor } from './contract.js';
|
|
4
|
+
import { badQuery, childrenOf } from './options.js';
|
|
5
|
+
const comparable = (value) => typeof value === 'string' || typeof value === 'number';
|
|
6
|
+
const equal = (left, right) => isEqual(left, right);
|
|
7
|
+
/** Компилирует условие поля в предикат, проверяя операторы и их аргументы.
|
|
8
|
+
* @example Для строкового узла condition(node, { contains: 'ан' }, 0)('Анна') → true.
|
|
9
|
+
*/
|
|
10
|
+
function condition(node, input, depth) {
|
|
11
|
+
if (!isObject(input) || depth > 32)
|
|
12
|
+
badQuery('Field filter must contain operators with depth at most 32');
|
|
13
|
+
if (!node.many && (node.relation || node.base === 'object'))
|
|
14
|
+
return compileWhere(node, input, depth);
|
|
15
|
+
const operators = operatorsFor(node);
|
|
16
|
+
const predicates = Object.entries(input).map(([operator, value]) => {
|
|
17
|
+
const operand = operators[operator];
|
|
18
|
+
if (!Object.hasOwn(operators, operator))
|
|
19
|
+
badQuery(`Invalid operator ${operator} for ${node.type}`);
|
|
20
|
+
if (operand === 'condition') {
|
|
21
|
+
const nested = condition(node, value, depth + 1);
|
|
22
|
+
return (field) => !nested(field);
|
|
23
|
+
}
|
|
24
|
+
if (operand === 'element') {
|
|
25
|
+
const nested = condition({ ...node, many: false }, value, depth + 1);
|
|
26
|
+
return (field) => {
|
|
27
|
+
if (!Array.isArray(field))
|
|
28
|
+
return false;
|
|
29
|
+
const values = node.relation?.softDelete && !mentionsDeletedAt(value) ? field.filter((item) => isObject(item) && item.deletedAt == null) : field;
|
|
30
|
+
return operator === 'every' ? values.every(nested) : operator === 'none' ? !values.some(nested) : values.some(nested);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const values = operand === 'values' ? value : [value];
|
|
34
|
+
if (!Array.isArray(values))
|
|
35
|
+
badQuery(`Invalid value for ${operator}`);
|
|
36
|
+
const nullable = ['eq', 'ne', 'in'].includes(operator);
|
|
37
|
+
for (const candidate of values) {
|
|
38
|
+
if (candidate === null && nullable)
|
|
39
|
+
continue;
|
|
40
|
+
const base = operand === 'text' ? 'string' : node.base;
|
|
41
|
+
if (typeof candidate !== base || (typeof candidate === 'number' && !Number.isFinite(candidate)))
|
|
42
|
+
badQuery(`Invalid value for ${operator}`);
|
|
43
|
+
if ((operand === 'value' || operand === 'values') && node.enum && !node.enum.some((v) => equal(v, candidate)))
|
|
44
|
+
badQuery(`Invalid enum value for ${operator}`);
|
|
45
|
+
}
|
|
46
|
+
switch (operator) {
|
|
47
|
+
case 'eq':
|
|
48
|
+
return (field) => equal(field, value);
|
|
49
|
+
case 'ne':
|
|
50
|
+
return (field) => !equal(field, value);
|
|
51
|
+
case 'in':
|
|
52
|
+
return (field) => (Array.isArray(field) ? field : [field]).some((item) => values.some((v) => equal(item, v)));
|
|
53
|
+
case 'contains':
|
|
54
|
+
return (field) => (typeof field === 'string' ? field.toLowerCase().includes(String(value).toLowerCase()) : Array.isArray(field) && field.some((v) => equal(v, value)));
|
|
55
|
+
case 'startsWith':
|
|
56
|
+
return (field) => typeof field === 'string' && field.toLowerCase().startsWith(String(value).toLowerCase());
|
|
57
|
+
case 'endsWith':
|
|
58
|
+
return (field) => typeof field === 'string' && field.toLowerCase().endsWith(String(value).toLowerCase());
|
|
59
|
+
case 'gt':
|
|
60
|
+
return (field) => comparable(field) && comparable(value) && field > value;
|
|
61
|
+
case 'gte':
|
|
62
|
+
return (field) => comparable(field) && comparable(value) && field >= value;
|
|
63
|
+
case 'lt':
|
|
64
|
+
return (field) => comparable(field) && comparable(value) && field < value;
|
|
65
|
+
default:
|
|
66
|
+
return (field) => comparable(field) && comparable(value) && field <= value;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return (value) => predicates.every((predicate) => predicate(value));
|
|
70
|
+
}
|
|
71
|
+
/** Компилирует условия объекта в предикат; учитывает логические операторы и фильтрацию удалённых записей.
|
|
72
|
+
* @example Для числового age: compileWhere(node, { age: { gte: 18 } })({ age: 20 }) → true.
|
|
73
|
+
*/
|
|
74
|
+
export function compileWhere(node, input, depth = 0, defaults = true) {
|
|
75
|
+
if (!isObject(input) || depth > 32)
|
|
76
|
+
badQuery('where must be an object with depth at most 32');
|
|
77
|
+
const predicates = Object.entries(input).map(([key, value]) => {
|
|
78
|
+
if (key === 'and' || key === 'or') {
|
|
79
|
+
if (!Array.isArray(value) || (key === 'or' && !value.length))
|
|
80
|
+
badQuery(`Invalid ${key}`);
|
|
81
|
+
const nested = value.map((item) => compileWhere(node, item, depth + 1, false));
|
|
82
|
+
return (field) => (key === 'and' ? nested.every((p) => p(field)) : nested.some((p) => p(field)));
|
|
83
|
+
}
|
|
84
|
+
if (key === 'not') {
|
|
85
|
+
const nested = compileWhere(node, value, depth + 1, false);
|
|
86
|
+
return (field) => !nested(field);
|
|
87
|
+
}
|
|
88
|
+
const child = childrenOf(node)[key];
|
|
89
|
+
if (!Object.hasOwn(childrenOf(node), key) || child.writeOnly)
|
|
90
|
+
badQuery(`Unknown or inaccessible filter field ${key}`);
|
|
91
|
+
if (child.mixed)
|
|
92
|
+
badQuery(`Field ${key} has inconsistent types; provide an explicit schema`);
|
|
93
|
+
const nested = condition(child, value, depth + 1);
|
|
94
|
+
return (field) => isObject(field) && nested(Object.hasOwn(field, key) ? field[key] : undefined);
|
|
95
|
+
});
|
|
96
|
+
if (defaults && (node.relation?.softDelete || node.softDelete) && !mentionsDeletedAt(input))
|
|
97
|
+
predicates.push((value) => isObject(value) && value.deletedAt == null);
|
|
98
|
+
return (value) => isObject(value) && predicates.every((predicate) => predicate(value));
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../../src/core/query/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Node } from '../model.js';
|
|
2
|
+
export interface Order {
|
|
3
|
+
field: string;
|
|
4
|
+
direction: 'ASC' | 'DESC';
|
|
5
|
+
}
|
|
6
|
+
export interface Pager {
|
|
7
|
+
page?: number;
|
|
8
|
+
pageSize?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ListOptions {
|
|
11
|
+
where?: Record<string, unknown>;
|
|
12
|
+
order?: Order[];
|
|
13
|
+
pager?: Pager;
|
|
14
|
+
}
|
|
15
|
+
/** Выбрасывает исключение с кодом неверного запроса.
|
|
16
|
+
* @example badQuery('Unknown field') → исключение с code = 'INVALID_QUERY'.
|
|
17
|
+
*/
|
|
18
|
+
export declare function badQuery(message: string): never;
|
|
19
|
+
/** Возвращает поля целевой сущности для связи или собственные дочерние поля узла.
|
|
20
|
+
* @example childrenOf({ children: { name: field }, … }) → { name: field }.
|
|
21
|
+
*/
|
|
22
|
+
export declare function childrenOf(node: Node): Record<string, Node>;
|
|
23
|
+
/** Находит узел по пути и проверяет доступность; режим scalarOnly запрещает связи и массивы.
|
|
24
|
+
* @example nodeAt(root, 'profile.name') → узел name; неизвестный путь → ошибка.
|
|
25
|
+
*/
|
|
26
|
+
export declare function nodeAt(node: Node, path: string, scalarOnly?: boolean): Node;
|
|
27
|
+
/** Собирает пути доступных скалярных полей, пропуская массивы, связи и скрытые поля.
|
|
28
|
+
* @example Для объекта profile с полем name → ['profile.name'].
|
|
29
|
+
*/
|
|
30
|
+
export declare function sortableFields(node: Node, prefix?: string): string[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { domainError } from '../errors.js';
|
|
2
|
+
import { pathParts } from '../model.js';
|
|
3
|
+
/** Выбрасывает исключение с кодом неверного запроса.
|
|
4
|
+
* @example badQuery('Unknown field') → исключение с code = 'INVALID_QUERY'.
|
|
5
|
+
*/
|
|
6
|
+
export function badQuery(message) {
|
|
7
|
+
throw domainError('INVALID_QUERY', message);
|
|
8
|
+
}
|
|
9
|
+
/** Возвращает поля целевой сущности для связи или собственные дочерние поля узла.
|
|
10
|
+
* @example childrenOf({ children: { name: field }, … }) → { name: field }.
|
|
11
|
+
*/
|
|
12
|
+
export function childrenOf(node) {
|
|
13
|
+
return node.relation?.root.children ?? node.children;
|
|
14
|
+
}
|
|
15
|
+
/** Находит узел по пути и проверяет доступность; режим scalarOnly запрещает связи и массивы.
|
|
16
|
+
* @example nodeAt(root, 'profile.name') → узел name; неизвестный путь → ошибка.
|
|
17
|
+
*/
|
|
18
|
+
export function nodeAt(node, path, scalarOnly = false) {
|
|
19
|
+
let current = node;
|
|
20
|
+
const parts = pathParts(path);
|
|
21
|
+
parts.forEach((part, index) => {
|
|
22
|
+
const child = childrenOf(current)[part];
|
|
23
|
+
if (!Object.hasOwn(childrenOf(current), part) || child.writeOnly)
|
|
24
|
+
badQuery(`Unknown or inaccessible field ${path}`);
|
|
25
|
+
if (child.mixed)
|
|
26
|
+
badQuery(`Field ${path} has inconsistent types; provide an explicit schema`);
|
|
27
|
+
if (scalarOnly && (child.many || child.relation || (index === parts.length - 1 && child.base === 'object')))
|
|
28
|
+
badQuery(`Cannot sort by ${path}`);
|
|
29
|
+
current = child;
|
|
30
|
+
});
|
|
31
|
+
return current;
|
|
32
|
+
}
|
|
33
|
+
/** Собирает пути доступных скалярных полей, пропуская массивы, связи и скрытые поля.
|
|
34
|
+
* @example Для объекта profile с полем name → ['profile.name'].
|
|
35
|
+
*/
|
|
36
|
+
export function sortableFields(node, prefix = '') {
|
|
37
|
+
return Object.entries(childrenOf(node)).flatMap(([key, child]) => {
|
|
38
|
+
if (child.writeOnly || child.mixed || child.many || child.relation)
|
|
39
|
+
return [];
|
|
40
|
+
const path = prefix + key;
|
|
41
|
+
return child.base === 'object' ? sortableFields(child, `${path}.`) : [path];
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../src/core/query/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAcxC;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,MAAM,WAAW,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC;AACvD,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,IAAU,EAAE,IAAY,EAAE,UAAU,GAAG,KAAK;IACjE,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,SAAS;YAAE,QAAQ,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;QACpH,IAAI,KAAK,CAAC,KAAK;YAAE,QAAQ,CAAC,SAAS,IAAI,qDAAqD,CAAC,CAAC;QAC9F,IAAI,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YAAE,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;QAChJ,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,MAAM,GAAG,EAAE;IACpD,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC/D,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QAC9E,MAAM,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;QAC1B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Entity, type Model, type Node } from './model.js';
|
|
2
|
+
import type { DatabaseData, JsonObject } from './types.js';
|
|
3
|
+
declare const REF: unique symbol;
|
|
4
|
+
export interface Ref {
|
|
5
|
+
[REF]: true;
|
|
6
|
+
entity: Entity;
|
|
7
|
+
node: Node;
|
|
8
|
+
value: JsonObject;
|
|
9
|
+
root: JsonObject;
|
|
10
|
+
bindings: Record<string, JsonObject>;
|
|
11
|
+
context: Context;
|
|
12
|
+
}
|
|
13
|
+
export interface Context {
|
|
14
|
+
data: DatabaseData;
|
|
15
|
+
model: Model;
|
|
16
|
+
indexes: Map<string, Map<string, JsonObject[]>>;
|
|
17
|
+
}
|
|
18
|
+
/** Создаёт контекст чтения с пустым кешем индексов; данные и модель передаются по ссылке.
|
|
19
|
+
* @example makeContext(data, model) → { data, model, indexes: Map(0) }.
|
|
20
|
+
*/
|
|
21
|
+
export declare const makeContext: (data: DatabaseData, model: Model) => Context;
|
|
22
|
+
/** Оборачивает запись ссылкой с контекстом и корневым узлом без копирования записи.
|
|
23
|
+
* @example rootRef(context, entity, row).value → row; .bindings → {}.
|
|
24
|
+
*/
|
|
25
|
+
export declare const rootRef: (context: Context, entity: Entity, value: JsonObject) => Ref;
|
|
26
|
+
/** Строит ключ скалярного значения с префиксом типа, различая числа и строки.
|
|
27
|
+
* @example keyOf(1) → 'number:1'; keyOf('1') → 'string:1'.
|
|
28
|
+
*/
|
|
29
|
+
export declare const keyOf: (value: unknown) => string;
|
|
30
|
+
/** Читает ключи связи из ближайшего вложенного объекта или из корневой записи.
|
|
31
|
+
* @example При source = 'authorId' и записи { authorId: 7 } → [7].
|
|
32
|
+
*/
|
|
33
|
+
export declare function sourceValues(ref: Ref, node: Node): unknown[];
|
|
34
|
+
/** Находит связанные записи по сопоставленным ключам и кеширует индекс в контексте; убирает повторы.
|
|
35
|
+
* @example Ключи [1, 1, 2] при двух совпавших записях → две ссылки на записи.
|
|
36
|
+
*/
|
|
37
|
+
export declare function related(ref: Ref, node: Node): Ref[];
|
|
38
|
+
/** Возвращает значение поля или ссылки на связанные объекты, учитывая отсутствующие и удалённые записи.
|
|
39
|
+
* @example Для обычного name в записи { name: 'Анна' } → 'Анна'; отсутствующая одиночная связь → null.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveField(ref: Ref, node: Node, includeDeleted?: boolean): unknown;
|
|
42
|
+
/** Проверяет наличие внутренней метки ссылки на запись.
|
|
43
|
+
* @example isRef({ id: '1' }) → false; isRef(rootRef(context, entity, row)) → true.
|
|
44
|
+
*/
|
|
45
|
+
export declare const isRef: (value: unknown) => value is Ref;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { bindingFor, childName, readPath } from './model.js';
|
|
2
|
+
import { isObject } from './utils.js';
|
|
3
|
+
const REF = Symbol('record reference');
|
|
4
|
+
/** Создаёт контекст чтения с пустым кешем индексов; данные и модель передаются по ссылке.
|
|
5
|
+
* @example makeContext(data, model) → { data, model, indexes: Map(0) }.
|
|
6
|
+
*/
|
|
7
|
+
export const makeContext = (data, model) => ({ data, model, indexes: new Map() });
|
|
8
|
+
/** Оборачивает запись ссылкой с контекстом и корневым узлом без копирования записи.
|
|
9
|
+
* @example rootRef(context, entity, row).value → row; .bindings → {}.
|
|
10
|
+
*/
|
|
11
|
+
export const rootRef = (context, entity, value) => ({ [REF]: true, context, entity, node: entity.root, value, root: value, bindings: {} });
|
|
12
|
+
/** Строит ключ скалярного значения с префиксом типа, различая числа и строки.
|
|
13
|
+
* @example keyOf(1) → 'number:1'; keyOf('1') → 'string:1'.
|
|
14
|
+
*/
|
|
15
|
+
export const keyOf = (value) => `${typeof value}:${String(value)}`;
|
|
16
|
+
/** Читает ключи связи из ближайшего вложенного объекта или из корневой записи.
|
|
17
|
+
* @example При source = 'authorId' и записи { authorId: 7 } → [7].
|
|
18
|
+
*/
|
|
19
|
+
export function sourceValues(ref, node) {
|
|
20
|
+
const path = node.source;
|
|
21
|
+
const binding = bindingFor(ref.bindings, path);
|
|
22
|
+
return binding ? readPath(ref.bindings[binding], path === binding ? [] : path.slice(binding.length + 1)) : readPath(ref.root, path);
|
|
23
|
+
}
|
|
24
|
+
/** Находит связанные записи по сопоставленным ключам и кеширует индекс в контексте; убирает повторы.
|
|
25
|
+
* @example Ключи [1, 1, 2] при двух совпавших записях → две ссылки на записи.
|
|
26
|
+
*/
|
|
27
|
+
export function related(ref, node) {
|
|
28
|
+
const entity = node.relation;
|
|
29
|
+
const indexKey = `${entity.collection}:${node.target}`;
|
|
30
|
+
let index = ref.context.indexes.get(indexKey);
|
|
31
|
+
if (!index) {
|
|
32
|
+
index = new Map();
|
|
33
|
+
for (const record of ref.context.data[entity.collection] ?? [])
|
|
34
|
+
for (const value of readPath(record, node.target)) {
|
|
35
|
+
const key = keyOf(value);
|
|
36
|
+
const bucket = index.get(key) ?? [];
|
|
37
|
+
bucket.push(record);
|
|
38
|
+
index.set(key, bucket);
|
|
39
|
+
}
|
|
40
|
+
ref.context.indexes.set(indexKey, index);
|
|
41
|
+
}
|
|
42
|
+
const found = new Set();
|
|
43
|
+
for (const value of sourceValues(ref, node))
|
|
44
|
+
for (const record of index.get(keyOf(value)) ?? [])
|
|
45
|
+
found.add(record);
|
|
46
|
+
return [...found].map((record) => rootRef(ref.context, entity, record));
|
|
47
|
+
}
|
|
48
|
+
/** Возвращает значение поля или ссылки на связанные объекты, учитывая отсутствующие и удалённые записи.
|
|
49
|
+
* @example Для обычного name в записи { name: 'Анна' } → 'Анна'; отсутствующая одиночная связь → null.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveField(ref, node, includeDeleted = false) {
|
|
52
|
+
if (node.relation) {
|
|
53
|
+
const records = related(ref, node).filter((record) => node.many || includeDeleted || !record.entity.softDelete || record.value.deletedAt == null);
|
|
54
|
+
return node.many ? records : (records[0] ?? null);
|
|
55
|
+
}
|
|
56
|
+
const key = childName(node);
|
|
57
|
+
const value = Object.hasOwn(ref.value, key) ? ref.value[key] : node.system && !node.internal ? null : undefined;
|
|
58
|
+
if ((ref.context.model.explicit && node.base !== 'object') || value == null)
|
|
59
|
+
return value;
|
|
60
|
+
const wrap = (object) => ({ ...ref, node, value: object, bindings: { ...ref.bindings, [node.path]: object } });
|
|
61
|
+
if (Array.isArray(value))
|
|
62
|
+
return value.map((item) => (isObject(item) ? wrap(item) : item));
|
|
63
|
+
return isObject(value) ? wrap(value) : value;
|
|
64
|
+
}
|
|
65
|
+
/** Проверяет наличие внутренней метки ссылки на запись.
|
|
66
|
+
* @example isRef({ id: '1' }) → false; isRef(rootRef(context, entity, row)) → true.
|
|
67
|
+
*/
|
|
68
|
+
export const isRef = (value) => isObject(value) && value[REF] === true;
|
|
69
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../../src/core/records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface RelationMetadata {
|
|
2
|
+
isMany: boolean;
|
|
3
|
+
relationName: string;
|
|
4
|
+
reverseRelationName: string;
|
|
5
|
+
sourceResource: string;
|
|
6
|
+
targetResource: string;
|
|
7
|
+
}
|
|
8
|
+
/** Находит коллекцию по точному имени, единственному числу или обозначению родительской связи.
|
|
9
|
+
* @example resolveRelationResource(['users'], 'user', 'posts') → 'users'.
|
|
10
|
+
*/
|
|
11
|
+
export declare const resolveRelationResource: (resourceNames: string[], relation: string, sourceResource: string) => string | undefined;
|
|
12
|
+
/** Выводит описание связи из суффикса Id или Ids и доступных имён коллекций.
|
|
13
|
+
* @example getRelationMetadata('userId', ['users', 'posts'], 'posts') → { isMany: false, relationName: 'user', reverseRelationName: 'posts', sourceResource: 'posts', targetResource: 'users' }.
|
|
14
|
+
*/
|
|
15
|
+
export declare const getRelationMetadata: (key: string, resourceNames: string[], sourceResource: string) => RelationMetadata | undefined;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { singularize } from './utils.js';
|
|
2
2
|
const SELF_RELATIONS = new Set(['child', 'children', 'parent', 'parents']);
|
|
3
|
-
|
|
3
|
+
/** Находит коллекцию по точному имени, единственному числу или обозначению родительской связи.
|
|
4
|
+
* @example resolveRelationResource(['users'], 'user', 'posts') → 'users'.
|
|
5
|
+
*/
|
|
4
6
|
export const resolveRelationResource = (resourceNames, relation, sourceResource) => {
|
|
5
7
|
const resource = resourceNames.find((resourceName) => resourceName === relation) ?? resourceNames.find((resourceName) => singularize(resourceName) === relation);
|
|
6
8
|
if (resource != null) {
|
|
@@ -8,8 +10,11 @@ export const resolveRelationResource = (resourceNames, relation, sourceResource)
|
|
|
8
10
|
}
|
|
9
11
|
return SELF_RELATIONS.has(relation) && resourceNames.includes(sourceResource) ? sourceResource : undefined;
|
|
10
12
|
};
|
|
13
|
+
/** Выводит описание связи из суффикса Id или Ids и доступных имён коллекций.
|
|
14
|
+
* @example getRelationMetadata('userId', ['users', 'posts'], 'posts') → { isMany: false, relationName: 'user', reverseRelationName: 'posts', sourceResource: 'posts', targetResource: 'users' }.
|
|
15
|
+
*/
|
|
11
16
|
export const getRelationMetadata = (key, resourceNames, sourceResource) => {
|
|
12
|
-
//
|
|
17
|
+
// Суффиксы Id и Ids обозначают одиночный ключ и массив ключей.
|
|
13
18
|
const match = key.match(/^(.+)(Id|Ids)$/);
|
|
14
19
|
if (match == null) {
|
|
15
20
|
return undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation-metadata.js","sourceRoot":"","sources":["../../../src/core/relation-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAU3E;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,aAAuB,EAAE,QAAgB,EAAE,cAAsB,EAAsB,EAAE;IAC/H,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,QAAQ,CAAC,CAAC;IAEjK,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QACrB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7G,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAW,EAAE,aAAuB,EAAE,cAAsB,EAAgC,EAAE;IAChI,+DAA+D;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAE1C,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,KAAK,KAAK,CAAC;IAChC,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClI,MAAM,cAAc,GAAG,uBAAuB,CAAC,aAAa,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;IAE5F,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,MAAM;QACN,YAAY;QACZ,mBAAmB,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc;QAC/F,cAAc;QACd,cAAc;KACf,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/storage.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type JsonPrimitive = boolean | number | string | null;
|
|
2
|
+
export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
3
|
+
export type JsonObject = {
|
|
4
|
+
[key: string]: JsonValue;
|
|
5
|
+
};
|
|
6
|
+
export type DatabaseId = number | string;
|
|
7
|
+
export type DatabaseRecord = JsonObject;
|
|
8
|
+
export type DatabaseData = Record<string, DatabaseRecord[]>;
|
|
9
|
+
export type QueryValue = string | string[] | undefined;
|
|
10
|
+
export type Query = Record<string, QueryValue>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Проверяет собственные ключи объекта; при неизвестном ключе выбрасывает исключение.
|
|
2
|
+
* @example assertKnownKeys({ x: 1 }, new Set(['x']), 'data') → undefined; { y: 1 } → ошибка.
|
|
3
|
+
*/
|
|
4
|
+
export declare const assertKnownKeys: (value: object, keys: Set<string>, path: string) => void;
|
|
5
|
+
/** Создаёт очередь асинхронных действий. Следующее действие запускается после завершения предыдущего, даже если оно завершилось ошибкой.
|
|
6
|
+
* @example const run = createSerialQueue(); await run(() => 2) → 2.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createSerialQueue: () => <T>(operation: () => Promise<T> | T) => Promise<T>;
|
|
9
|
+
/** Генерирует случайную строку и повторяет генерацию, пока проверка считает её занятой.
|
|
10
|
+
* @example createUniqueId(() => false) → строка из 11 символов; значение меняется при каждом вызове.
|
|
11
|
+
*/
|
|
12
|
+
export declare const createUniqueId: (isUsed: (id: string) => boolean) => string;
|
|
13
|
+
/** Проверяет, что значение является ненулевым объектом, кроме массива. Экземпляры классов тоже подходят.
|
|
14
|
+
* @example isObject({ x: 1 }) → true; isObject(null) → false; isObject([]) → false.
|
|
15
|
+
*/
|
|
16
|
+
export declare const isObject: (value: unknown) => value is Record<string, unknown>;
|
|
17
|
+
/** Исключает имена свойств, через которые можно изменить прототип объекта.
|
|
18
|
+
* @example isSafeKey('name') → true; isSafeKey('__proto__') → false.
|
|
19
|
+
*/
|
|
20
|
+
export declare const isSafeKey: (key: string) => boolean;
|
|
21
|
+
/** Распознаёт экземпляр Error с полем code; наличие поля не гарантирует конкретный код.
|
|
22
|
+
* @example isSystemError(Object.assign(new Error(), { code: 'ENOENT' })) → true.
|
|
23
|
+
*/
|
|
24
|
+
export declare const isSystemError: (error: unknown) => error is NodeJS.ErrnoException;
|
|
25
|
+
/** Рекурсивно сравнивает JSON-значения; порядок ключей объекта не важен, порядок элементов массива важен.
|
|
26
|
+
* @example isEqual({ a: [1] }, { a: [1] }) → true; isEqual([1, 2], [2, 1]) → false.
|
|
27
|
+
*/
|
|
28
|
+
export declare const isEqual: (left: unknown, right: unknown) => boolean;
|
|
29
|
+
/** Проверяет непустой путь и делает его абсолютным относительно рабочего каталога.
|
|
30
|
+
* @example При рабочем каталоге /tmp: resolveDatabasePath('data.json') → '/tmp/data.json'.
|
|
31
|
+
*/
|
|
32
|
+
export declare const resolveDatabasePath: (databasePath: string) => string;
|
|
33
|
+
/** Возвращает единственное число английского существительного.
|
|
34
|
+
* @example singularize('people') → 'person'; singularize('movies') → 'movie'.
|
|
35
|
+
*/
|
|
36
|
+
export declare const singularize: (value: string) => string;
|
|
37
|
+
/** Разбивает строку по символам вне латинских букв и цифр и объединяет части с заглавной буквы.
|
|
38
|
+
* @example toPascalCase('user-profile') → 'UserProfile'; toPascalCase('') → ''.
|
|
39
|
+
*/
|
|
40
|
+
export declare const toPascalCase: (value: string) => string;
|
|
41
|
+
/** Проверяет, что все собственные перечислимые ключи входят в разрешённый список.
|
|
42
|
+
* @example hasOnlyKeys({ name: 'Анна' }, ['name']) → true; hasOnlyKeys({ age: 2 }, ['name']) → false.
|
|
43
|
+
*/
|
|
44
|
+
export declare const hasOnlyKeys: (value: object, allowed: readonly string[]) => boolean;
|
|
45
|
+
/** Возвращает сообщение исключения или строковое представление другого значения.
|
|
46
|
+
* @example errorMessage(new Error('Нет файла')) → 'Нет файла'; errorMessage(404) → '404'.
|
|
47
|
+
*/
|
|
48
|
+
export declare const errorMessage: (value: unknown) => string;
|
|
49
|
+
/** Переводит первый символ в верхний регистр, сохраняя остальные символы.
|
|
50
|
+
* @example capitalize('helloWorld') → 'HelloWorld'; capitalize('') → ''.
|
|
51
|
+
*/
|
|
52
|
+
export declare const capitalize: (value: string) => string;
|
|
53
|
+
/** Проверяет целый номер порта; ноль допустим для автоматического выбора.
|
|
54
|
+
* @example isPortNumber(4001) → true; isPortNumber(65536) → false; isPortNumber('80') → false.
|
|
55
|
+
*/
|
|
56
|
+
export declare const isPortNumber: (value: unknown) => value is number;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import pluralize from 'pluralize';
|
|
4
|
+
const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
5
|
+
/** Проверяет собственные ключи объекта; при неизвестном ключе выбрасывает исключение.
|
|
6
|
+
* @example assertKnownKeys({ x: 1 }, new Set(['x']), 'data') → undefined; { y: 1 } → ошибка.
|
|
7
|
+
*/
|
|
8
|
+
export const assertKnownKeys = (value, keys, path) => {
|
|
9
|
+
const unknownKey = Object.keys(value).find((key) => !keys.has(key));
|
|
10
|
+
if (unknownKey != null) {
|
|
11
|
+
throw new Error(`Неизвестный ключ ${path}.${unknownKey}`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/** Создаёт очередь асинхронных действий. Следующее действие запускается после завершения предыдущего, даже если оно завершилось ошибкой.
|
|
15
|
+
* @example const run = createSerialQueue(); await run(() => 2) → 2.
|
|
16
|
+
*/
|
|
17
|
+
export const createSerialQueue = () => {
|
|
18
|
+
let queue = Promise.resolve();
|
|
19
|
+
return (operation) => {
|
|
20
|
+
const pendingOperation = queue.then(operation);
|
|
21
|
+
// После ошибки разрешаем запуск следующей операции.
|
|
22
|
+
queue = pendingOperation.catch(() => undefined);
|
|
23
|
+
return pendingOperation;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
/** Генерирует случайную строку и повторяет генерацию, пока проверка считает её занятой.
|
|
27
|
+
* @example createUniqueId(() => false) → строка из 11 символов; значение меняется при каждом вызове.
|
|
28
|
+
*/
|
|
29
|
+
export const createUniqueId = (isUsed) => {
|
|
30
|
+
let id;
|
|
31
|
+
do {
|
|
32
|
+
id = randomBytes(8).toString('base64url');
|
|
33
|
+
} while (isUsed(id));
|
|
34
|
+
return id;
|
|
35
|
+
};
|
|
36
|
+
/** Проверяет, что значение является ненулевым объектом, кроме массива. Экземпляры классов тоже подходят.
|
|
37
|
+
* @example isObject({ x: 1 }) → true; isObject(null) → false; isObject([]) → false.
|
|
38
|
+
*/
|
|
39
|
+
export const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
40
|
+
/** Исключает имена свойств, через которые можно изменить прототип объекта.
|
|
41
|
+
* @example isSafeKey('name') → true; isSafeKey('__proto__') → false.
|
|
42
|
+
*/
|
|
43
|
+
export const isSafeKey = (key) => !UNSAFE_KEYS.has(key);
|
|
44
|
+
/** Распознаёт экземпляр Error с полем code; наличие поля не гарантирует конкретный код.
|
|
45
|
+
* @example isSystemError(Object.assign(new Error(), { code: 'ENOENT' })) → true.
|
|
46
|
+
*/
|
|
47
|
+
export const isSystemError = (error) => error instanceof Error && 'code' in error;
|
|
48
|
+
/** Рекурсивно сравнивает JSON-значения; порядок ключей объекта не важен, порядок элементов массива важен.
|
|
49
|
+
* @example isEqual({ a: [1] }, { a: [1] }) → true; isEqual([1, 2], [2, 1]) → false.
|
|
50
|
+
*/
|
|
51
|
+
export const isEqual = (left, right) => {
|
|
52
|
+
if (Object.is(left, right)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
56
|
+
return left.length === right.length && left.every((value, index) => isEqual(value, right[index]));
|
|
57
|
+
}
|
|
58
|
+
if (isObject(left) && isObject(right)) {
|
|
59
|
+
const leftKeys = Object.keys(left);
|
|
60
|
+
const rightKeys = Object.keys(right);
|
|
61
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key) => isSafeKey(key) && Object.hasOwn(right, key) && isEqual(left[key], right[key]));
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
};
|
|
65
|
+
/** Проверяет непустой путь и делает его абсолютным относительно рабочего каталога.
|
|
66
|
+
* @example При рабочем каталоге /tmp: resolveDatabasePath('data.json') → '/tmp/data.json'.
|
|
67
|
+
*/
|
|
68
|
+
export const resolveDatabasePath = (databasePath) => {
|
|
69
|
+
if (typeof databasePath !== 'string' || databasePath === '') {
|
|
70
|
+
throw new Error('Укажите путь к JSON-базе данных');
|
|
71
|
+
}
|
|
72
|
+
return resolve(databasePath);
|
|
73
|
+
};
|
|
74
|
+
/** Возвращает единственное число английского существительного.
|
|
75
|
+
* @example singularize('people') → 'person'; singularize('movies') → 'movie'.
|
|
76
|
+
*/
|
|
77
|
+
export const singularize = (value) => pluralize.singular(value);
|
|
78
|
+
/** Разбивает строку по символам вне латинских букв и цифр и объединяет части с заглавной буквы.
|
|
79
|
+
* @example toPascalCase('user-profile') → 'UserProfile'; toPascalCase('') → ''.
|
|
80
|
+
*/
|
|
81
|
+
export const toPascalCase = (value) => value
|
|
82
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
83
|
+
.filter(Boolean)
|
|
84
|
+
.map(capitalize)
|
|
85
|
+
.join('');
|
|
86
|
+
/** Проверяет, что все собственные перечислимые ключи входят в разрешённый список.
|
|
87
|
+
* @example hasOnlyKeys({ name: 'Анна' }, ['name']) → true; hasOnlyKeys({ age: 2 }, ['name']) → false.
|
|
88
|
+
*/
|
|
89
|
+
export const hasOnlyKeys = (value, allowed) => Object.keys(value).every((key) => allowed.includes(key));
|
|
90
|
+
/** Возвращает сообщение исключения или строковое представление другого значения.
|
|
91
|
+
* @example errorMessage(new Error('Нет файла')) → 'Нет файла'; errorMessage(404) → '404'.
|
|
92
|
+
*/
|
|
93
|
+
export const errorMessage = (value) => (value instanceof Error ? value.message : String(value));
|
|
94
|
+
/** Переводит первый символ в верхний регистр, сохраняя остальные символы.
|
|
95
|
+
* @example capitalize('helloWorld') → 'HelloWorld'; capitalize('') → ''.
|
|
96
|
+
*/
|
|
97
|
+
export const capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
98
|
+
/** Проверяет целый номер порта; ноль допустим для автоматического выбора.
|
|
99
|
+
* @example isPortNumber(4001) → true; isPortNumber(65536) → false; isPortNumber('80') → false.
|
|
100
|
+
*/
|
|
101
|
+
export const isPortNumber = (value) => typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 65535;
|
|
102
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/core/utils.ts"],"names":[],"mappings":"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"}
|