@kollors/deep-json-server 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +12 -9
  2. package/README.ru.md +12 -9
  3. package/dist/bin/deep-json-server.d.ts +2 -0
  4. package/dist/bin/deep-json-server.js +11 -0
  5. package/dist/bin/deep-json-server.js.map +1 -0
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.js +2 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/src/cli.d.ts +4 -0
  10. package/dist/src/cli.js +80 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/config.d.ts +54 -0
  13. package/dist/src/config.js +145 -0
  14. package/dist/src/config.js.map +1 -0
  15. package/{src → dist/src}/constants.js +1 -0
  16. package/dist/src/constants.js.map +1 -0
  17. package/dist/src/database.d.ts +20 -0
  18. package/dist/src/database.js +136 -0
  19. package/dist/src/database.js.map +1 -0
  20. package/dist/src/files/contract.d.ts +67 -0
  21. package/dist/src/files/contract.js +106 -0
  22. package/dist/src/files/contract.js.map +1 -0
  23. package/dist/src/files/disk-store.d.ts +5 -0
  24. package/dist/src/files/disk-store.js +313 -0
  25. package/dist/src/files/disk-store.js.map +1 -0
  26. package/dist/src/files/index.d.ts +5 -0
  27. package/dist/src/files/index.js +6 -0
  28. package/dist/src/files/index.js.map +1 -0
  29. package/dist/src/files/memory-store.d.ts +3 -0
  30. package/dist/src/files/memory-store.js +80 -0
  31. package/dist/src/files/memory-store.js.map +1 -0
  32. package/dist/src/files/routes.d.ts +6 -0
  33. package/dist/src/files/routes.js +77 -0
  34. package/dist/src/files/routes.js.map +1 -0
  35. package/dist/src/openapi/config.d.ts +11 -0
  36. package/dist/src/openapi/config.js +204 -0
  37. package/dist/src/openapi/config.js.map +1 -0
  38. package/dist/src/openapi/document.d.ts +9 -0
  39. package/dist/src/openapi/document.js +338 -0
  40. package/dist/src/openapi/document.js.map +1 -0
  41. package/dist/src/openapi/index.d.ts +10 -0
  42. package/dist/src/openapi/index.js +27 -0
  43. package/dist/src/openapi/index.js.map +1 -0
  44. package/dist/src/openapi/inference.d.ts +14 -0
  45. package/dist/src/openapi/inference.js +145 -0
  46. package/dist/src/openapi/inference.js.map +1 -0
  47. package/dist/src/query/filter.d.ts +6 -0
  48. package/dist/src/query/filter.js +248 -0
  49. package/dist/src/query/filter.js.map +1 -0
  50. package/{src → dist/src}/query/index.js +1 -0
  51. package/dist/src/query/index.js.map +1 -0
  52. package/dist/src/query/pagination.d.ts +11 -0
  53. package/dist/src/query/pagination.js +28 -0
  54. package/dist/src/query/pagination.js.map +1 -0
  55. package/dist/src/query/sort.d.ts +1 -0
  56. package/dist/src/query/sort.js +54 -0
  57. package/dist/src/query/sort.js.map +1 -0
  58. package/dist/src/relation-metadata.d.ts +10 -0
  59. package/dist/src/relation-metadata.js +32 -0
  60. package/dist/src/relation-metadata.js.map +1 -0
  61. package/dist/src/relations.d.ts +12 -0
  62. package/dist/src/relations.js +155 -0
  63. package/dist/src/relations.js.map +1 -0
  64. package/dist/src/server.d.ts +13 -0
  65. package/dist/src/server.js +188 -0
  66. package/dist/src/server.js.map +1 -0
  67. package/dist/src/types.d.ts +52 -0
  68. package/dist/src/types.js +2 -0
  69. package/dist/src/types.js.map +1 -0
  70. package/dist/src/utils.d.ts +20 -0
  71. package/dist/src/utils.js +63 -0
  72. package/dist/src/utils.js.map +1 -0
  73. package/package.json +16 -15
  74. package/bin/deep-json-server.js +0 -11
  75. package/index.js +0 -12
  76. package/src/cli.js +0 -91
  77. package/src/config.js +0 -203
  78. package/src/database.js +0 -148
  79. package/src/files.js +0 -633
  80. package/src/openapi/config.js +0 -124
  81. package/src/openapi/document.js +0 -394
  82. package/src/openapi/index.js +0 -36
  83. package/src/openapi/inference.js +0 -187
  84. package/src/query/filter.js +0 -283
  85. package/src/query/pagination.js +0 -44
  86. package/src/query/sort.js +0 -63
  87. package/src/relation-metadata.js +0 -41
  88. package/src/relations.js +0 -173
  89. package/src/server.js +0 -250
  90. package/src/utils.js +0 -84
  91. package/types/index.d.ts +0 -21
  92. package/types/src/config.d.ts +0 -73
  93. package/types/src/database.d.ts +0 -33
  94. package/types/src/files.d.ts +0 -64
  95. package/types/src/openapi/config.d.ts +0 -3
  96. package/types/src/openapi/document.d.ts +0 -11
  97. package/types/src/openapi/index.d.ts +0 -9
  98. package/types/src/openapi/inference.d.ts +0 -9
  99. package/types/src/query/filter.d.ts +0 -3
  100. package/types/src/query/pagination.d.ts +0 -8
  101. package/types/src/query/sort.d.ts +0 -1
  102. package/types/src/relation-metadata.d.ts +0 -9
  103. package/types/src/relations.d.ts +0 -3
  104. package/types/src/server.d.ts +0 -14
  105. package/types/src/utils.d.ts +0 -18
  106. /package/{types → dist}/src/constants.d.ts +0 -0
  107. /package/{types → dist}/src/query/index.d.ts +0 -0
@@ -0,0 +1,248 @@
1
+ import { createHttpError, isEqual, isObject, isSafeKey, toArray } from '../utils.js';
2
+ const FIELD_OPERATORS = new Set(['contains', 'endsWith', 'eq', 'every', 'gt', 'gte', 'in', 'lt', 'lte', 'ne', 'none', 'not', 'some', 'startsWith']);
3
+ const RESERVED_QUERY_KEYS = new Set(['_embed', '_page', '_perPage', '_sort', '_where']);
4
+ const NUMBER_PATTERN = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
5
+ const isFilterEqual = (left, right) => {
6
+ if (isEqual(left, right)) {
7
+ return true;
8
+ }
9
+ if (typeof left === 'number' && typeof right === 'string' && NUMBER_PATTERN.test(right)) {
10
+ // Query parameters are strings, so numeric strings must match stored numbers.
11
+ return left === Number(right);
12
+ }
13
+ return typeof right === 'number' && typeof left === 'string' && NUMBER_PATTERN.test(left) && right === Number(left);
14
+ };
15
+ const validateLogicalConditions = (operator, value) => {
16
+ if (!Array.isArray(value) || (operator === 'or' && value.length === 0) || value.some((condition) => !isObject(condition))) {
17
+ throw createHttpError(400, `Оператор «${operator}» должен содержать ${operator === 'or' ? 'непустой ' : ''}массив JSON-объектов`);
18
+ }
19
+ return value;
20
+ };
21
+ const isComparable = (value) => typeof value === 'number' || typeof value === 'string';
22
+ const matchesOperator = (field, operator, expectedValue) => {
23
+ switch (operator) {
24
+ case 'contains':
25
+ return typeof field === 'string' ? field.toLowerCase().includes(String(expectedValue).toLowerCase()) : Array.isArray(field) && field.some((value) => isFilterEqual(value, expectedValue));
26
+ case 'endsWith':
27
+ return typeof field === 'string' && field.toLowerCase().endsWith(String(expectedValue).toLowerCase());
28
+ case 'eq':
29
+ return isFilterEqual(field, expectedValue);
30
+ case 'every':
31
+ return Array.isArray(field) && field.every((value) => matchesValue(value, expectedValue));
32
+ case 'gt':
33
+ return isComparable(field) && isComparable(expectedValue) && field > expectedValue;
34
+ case 'gte':
35
+ return isComparable(field) && isComparable(expectedValue) && field >= expectedValue;
36
+ case 'in': {
37
+ const expectedValues = toArray(expectedValue);
38
+ return Array.isArray(field)
39
+ ? field.some((value) => expectedValues.some((expectedItem) => isFilterEqual(value, expectedItem)))
40
+ : expectedValues.some((expectedItem) => isFilterEqual(field, expectedItem));
41
+ }
42
+ case 'lt':
43
+ return isComparable(field) && isComparable(expectedValue) && field < expectedValue;
44
+ case 'lte':
45
+ return isComparable(field) && isComparable(expectedValue) && field <= expectedValue;
46
+ case 'ne':
47
+ return !isFilterEqual(field, expectedValue);
48
+ case 'none':
49
+ return Array.isArray(field) && !field.some((value) => matchesValue(value, expectedValue));
50
+ case 'not':
51
+ return !matchesValue(field, expectedValue);
52
+ case 'some':
53
+ return Array.isArray(field) && field.some((value) => matchesValue(value, expectedValue));
54
+ case 'startsWith':
55
+ return typeof field === 'string' && field.toLowerCase().startsWith(String(expectedValue).toLowerCase());
56
+ default:
57
+ return false;
58
+ }
59
+ };
60
+ function matchesValue(field, condition) {
61
+ if (!isObject(condition)) {
62
+ return isFilterEqual(field, condition);
63
+ }
64
+ const conditionEntries = Object.entries(condition);
65
+ const operatorEntries = conditionEntries.filter((entry) => FIELD_OPERATORS.has(entry[0]));
66
+ const nestedEntries = conditionEntries.filter(([key]) => !FIELD_OPERATORS.has(key));
67
+ if (!operatorEntries.every(([operator, expectedValue]) => matchesOperator(field, operator, expectedValue))) {
68
+ return false;
69
+ }
70
+ return nestedEntries.length === 0 || (isObject(field) && matchesWhere(field, Object.fromEntries(nestedEntries)));
71
+ }
72
+ export function matchesWhere(value, where) {
73
+ if (!isObject(value) || !isObject(where)) {
74
+ return false;
75
+ }
76
+ return Object.entries(where).every(([key, condition]) => {
77
+ if (key === 'and') {
78
+ return Array.isArray(condition) && condition.every((nestedWhere) => matchesWhere(value, nestedWhere));
79
+ }
80
+ if (key === 'or') {
81
+ return Array.isArray(condition) && condition.length > 0 && condition.some((nestedWhere) => matchesWhere(value, nestedWhere));
82
+ }
83
+ if (key === 'not') {
84
+ return isObject(condition) && !matchesWhere(value, condition);
85
+ }
86
+ return isSafeKey(key) && matchesValue(value[key], condition);
87
+ });
88
+ }
89
+ const parsePrimitive = (value) => {
90
+ if (typeof value !== 'string') {
91
+ return value;
92
+ }
93
+ if (value === 'true') {
94
+ return true;
95
+ }
96
+ if (value === 'false') {
97
+ return false;
98
+ }
99
+ if (value === 'null') {
100
+ return null;
101
+ }
102
+ return NUMBER_PATTERN.test(value) && Number.isFinite(Number(value)) ? Number(value) : value;
103
+ };
104
+ const parseFilterKey = (key) => {
105
+ const colonIndex = key.lastIndexOf(':');
106
+ if (colonIndex !== -1) {
107
+ const path = key.slice(0, colonIndex);
108
+ const operator = key.slice(colonIndex + 1);
109
+ if (!FIELD_OPERATORS.has(operator)) {
110
+ throw createHttpError(400, `Неизвестный оператор «${operator}» в фильтре «${key}»`);
111
+ }
112
+ return { operator: operator, path };
113
+ }
114
+ return { operator: 'eq', path: key };
115
+ };
116
+ const setWhereOperator = (where, path, operator, value) => {
117
+ const keys = path.split('.');
118
+ if (keys.some((key) => key === '' || !isSafeKey(key))) {
119
+ throw createHttpError(400, `Недопустимый путь фильтра «${path}»`);
120
+ }
121
+ const fieldKey = keys.pop();
122
+ let currentValue = where;
123
+ keys.forEach((key) => {
124
+ currentValue[key] = isObject(currentValue[key]) ? currentValue[key] : {};
125
+ currentValue = currentValue[key];
126
+ });
127
+ currentValue[fieldKey] = isObject(currentValue[fieldKey]) ? currentValue[fieldKey] : {};
128
+ currentValue[fieldKey][operator] = operator === 'in' && typeof value === 'string' ? value.split(',').map((item) => parsePrimitive(item.trim())) : parsePrimitive(value);
129
+ };
130
+ export const parseWhere = (query) => {
131
+ const rawWhere = Array.isArray(query._where) ? query._where.at(-1) : query._where;
132
+ if (rawWhere != null) {
133
+ let where;
134
+ try {
135
+ where = JSON.parse(rawWhere);
136
+ }
137
+ catch {
138
+ throw createHttpError(400, 'Параметр _where должен содержать JSON-объект');
139
+ }
140
+ if (!isObject(where)) {
141
+ throw createHttpError(400, 'Параметр _where должен содержать JSON-объект');
142
+ }
143
+ return where;
144
+ }
145
+ const where = {};
146
+ Object.entries(query).forEach(([key, rawValue]) => {
147
+ if (!RESERVED_QUERY_KEYS.has(key)) {
148
+ const filterKey = parseFilterKey(key);
149
+ const values = toArray(rawValue);
150
+ if (filterKey.operator === 'eq' && values.length > 1) {
151
+ setWhereOperator(where, filterKey.path, 'in', values.map(parsePrimitive));
152
+ }
153
+ else {
154
+ values.forEach((value) => {
155
+ setWhereOperator(where, filterKey.path, filterKey.operator, value);
156
+ });
157
+ }
158
+ }
159
+ });
160
+ return where;
161
+ };
162
+ const validateExpectedValue = (operator, value, samples, path) => {
163
+ if (['startsWith', 'endsWith'].includes(operator) && typeof value !== 'string') {
164
+ throw createHttpError(400, `Оператор «${operator}» в фильтре «${path}» должен содержать строку`);
165
+ }
166
+ if (['gt', 'gte', 'lt', 'lte'].includes(operator) && !isComparable(value)) {
167
+ throw createHttpError(400, `Оператор «${operator}» в фильтре «${path}» должен содержать строку или число`);
168
+ }
169
+ if (operator === 'contains' && samples.some((sample) => typeof sample === 'string') && typeof value !== 'string') {
170
+ throw createHttpError(400, `Оператор «contains» в строковом фильтре «${path}» должен содержать строку`);
171
+ }
172
+ if (['every', 'none', 'some'].includes(operator) && isObject(value) && Object.keys(value).length === 0) {
173
+ throw createHttpError(400, `Оператор «${operator}» в фильтре «${path}» не должен содержать пустое условие`);
174
+ }
175
+ };
176
+ const validateCondition = (condition, samples, path) => {
177
+ if (!isObject(condition)) {
178
+ return;
179
+ }
180
+ Object.entries(condition).forEach(([key, value]) => {
181
+ if (key === 'and' || key === 'or') {
182
+ validateLogicalConditions(key, value).forEach((nestedWhere) => {
183
+ validateWhere(nestedWhere, samples, path);
184
+ });
185
+ return;
186
+ }
187
+ if (FIELD_OPERATORS.has(key)) {
188
+ const operator = key;
189
+ validateExpectedValue(operator, value, samples, path);
190
+ if (['every', 'none', 'some'].includes(key)) {
191
+ if (samples.length > 0 && !samples.some(Array.isArray)) {
192
+ throw createHttpError(400, `Оператор «${key}» в фильтре «${path}» можно применить только к массиву`);
193
+ }
194
+ validateCondition(value, samples.flatMap((sample) => (Array.isArray(sample) ? sample : [])), `${path}.${key}`);
195
+ }
196
+ else if (key === 'not') {
197
+ validateCondition(value, samples, `${path}.not`);
198
+ }
199
+ else if (['endsWith', 'startsWith'].includes(key) && samples.length > 0 && !samples.some((sample) => typeof sample === 'string')) {
200
+ throw createHttpError(400, `Оператор «${key}» в фильтре «${path}» можно применить только к строке`);
201
+ }
202
+ else if (key === 'contains' && samples.length > 0 && !samples.some((sample) => typeof sample === 'string' || Array.isArray(sample))) {
203
+ throw createHttpError(400, `Оператор «contains» в фильтре «${path}» можно применить только к строке или массиву`);
204
+ }
205
+ return;
206
+ }
207
+ if (!isSafeKey(key)) {
208
+ throw createHttpError(400, `Недопустимый путь фильтра «${path}.${key}»`);
209
+ }
210
+ const objectSamples = samples.filter(isObject);
211
+ if (samples.length > 0 && objectSamples.length === 0) {
212
+ throw createHttpError(400, `Неизвестный оператор или вложенное поле «${path}.${key}»`);
213
+ }
214
+ const nestedSamples = objectSamples.filter((sample) => Object.hasOwn(sample, key)).map((sample) => sample[key]);
215
+ if (objectSamples.length > 0 && nestedSamples.length === 0) {
216
+ throw createHttpError(400, `Неизвестное поле фильтра «${path}.${key}»`);
217
+ }
218
+ validateCondition(value, nestedSamples, `${path}.${key}`);
219
+ });
220
+ };
221
+ export const validateWhere = (where, items, path = '') => {
222
+ Object.entries(where).forEach(([key, condition]) => {
223
+ if (key === 'and' || key === 'or') {
224
+ validateLogicalConditions(key, condition).forEach((nestedWhere) => {
225
+ validateWhere(nestedWhere, items, path);
226
+ });
227
+ return;
228
+ }
229
+ if (key === 'not') {
230
+ if (!isObject(condition)) {
231
+ throw createHttpError(400, 'Оператор «not» должен содержать JSON-объект');
232
+ }
233
+ validateWhere(condition, items, path);
234
+ return;
235
+ }
236
+ if (!isSafeKey(key)) {
237
+ throw createHttpError(400, `Недопустимый путь фильтра «${path === '' ? key : `${path}.${key}`}»`);
238
+ }
239
+ const fieldPath = path === '' ? key : `${path}.${key}`;
240
+ const objectItems = items.filter(isObject);
241
+ const samples = objectItems.filter((item) => Object.hasOwn(item, key)).map((item) => item[key]);
242
+ if (objectItems.length > 0 && samples.length === 0) {
243
+ throw createHttpError(400, `Неизвестное поле фильтра «${fieldPath}»`);
244
+ }
245
+ validateCondition(condition, samples, fieldPath);
246
+ });
247
+ };
248
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/query/filter.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export { matchesWhere, parseWhere, validateWhere } from './filter.js';
2
2
  export { paginateItems, parsePagination } from './pagination.js';
3
3
  export { sortItems } from './sort.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/query/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Query } from '../types.js';
2
+ export interface Pagination {
3
+ page: number;
4
+ pageSize: number;
5
+ }
6
+ export interface Page<T> {
7
+ data: T[];
8
+ total: number;
9
+ }
10
+ export declare const parsePagination: (query: Query, maxPageSize?: number) => Pagination;
11
+ export declare const paginateItems: <T>(items: T[], page: number, pageSize: number) => Page<T>;
@@ -0,0 +1,28 @@
1
+ import { DEFAULT_MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE } from '../constants.js';
2
+ import { createHttpError } from '../utils.js';
3
+ const parsePositiveInteger = (value, name, defaultValue) => {
4
+ if (value == null) {
5
+ return defaultValue;
6
+ }
7
+ const number = Number(value);
8
+ if (Array.isArray(value) || !/^[1-9]\d*$/.test(String(value)) || !Number.isSafeInteger(number)) {
9
+ throw createHttpError(400, `Параметр ${name} должен быть положительным целым числом`);
10
+ }
11
+ return number;
12
+ };
13
+ export const parsePagination = (query, maxPageSize = DEFAULT_MAX_PAGE_SIZE) => {
14
+ const page = parsePositiveInteger(query._page, '_page', 1);
15
+ const pageSize = parsePositiveInteger(query._perPage, '_perPage', DEFAULT_PAGE_SIZE);
16
+ if (pageSize > maxPageSize) {
17
+ throw createHttpError(400, `Параметр _perPage не должен превышать ${maxPageSize}`);
18
+ }
19
+ return { page, pageSize };
20
+ };
21
+ export const paginateItems = (items, page, pageSize) => {
22
+ const offset = (page - 1) * pageSize;
23
+ return {
24
+ data: items.slice(offset, offset + pageSize),
25
+ total: items.length,
26
+ };
27
+ };
28
+ //# sourceMappingURL=pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../../src/query/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE3E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAY9C,MAAM,oBAAoB,GAAG,CAAC,KAAoB,EAAE,IAAY,EAAE,YAAoB,EAAU,EAAE;IAChG,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/F,MAAM,eAAe,CAAC,GAAG,EAAE,YAAY,IAAI,yCAAyC,CAAC,CAAC;IACxF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAY,EAAE,WAAW,GAAG,qBAAqB,EAAc,EAAE;IAC/F,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;IAErF,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC3B,MAAM,eAAe,CAAC,GAAG,EAAE,yCAAyC,WAAW,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAI,KAAU,EAAE,IAAY,EAAE,QAAgB,EAAW,EAAE;IACtF,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAErC,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;QAC5C,KAAK,EAAE,KAAK,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const sortItems: <T>(items: T[], sort: unknown, validationItems?: unknown[]) => T[];
@@ -0,0 +1,54 @@
1
+ import { createHttpError, isObject, isSafeKey } from '../utils.js';
2
+ const collator = new Intl.Collator('en', { numeric: true, sensitivity: 'base' });
3
+ const compareValues = (left, right) => {
4
+ if (Object.is(left, right)) {
5
+ return 0;
6
+ }
7
+ if (left == null) {
8
+ return 1;
9
+ }
10
+ if (right == null) {
11
+ return -1;
12
+ }
13
+ return typeof left === 'number' && typeof right === 'number' ? left - right : collator.compare(String(left), String(right));
14
+ };
15
+ const getValueByPath = (value, path) => path.split('.').reduce((currentValue, key) => (isObject(currentValue) && isSafeKey(key) ? currentValue[key] : undefined), value);
16
+ const parseSortRules = (sort, items) => {
17
+ if (sort == null || sort === '') {
18
+ return [];
19
+ }
20
+ if (typeof sort !== 'string') {
21
+ throw createHttpError(400, 'Параметр _sort должен содержать строку');
22
+ }
23
+ return sort.split(',').map((sortRule) => {
24
+ const isDescending = sortRule.startsWith('-');
25
+ const path = isDescending ? sortRule.slice(1) : sortRule;
26
+ const keys = path.split('.');
27
+ if (keys.some((key) => key === '' || !isSafeKey(key))) {
28
+ throw createHttpError(400, `Недопустимое поле сортировки «${path}»`);
29
+ }
30
+ const samples = items.map((item) => getValueByPath(item, path)).filter((value) => value !== undefined);
31
+ if (items.length > 0 && samples.length === 0) {
32
+ throw createHttpError(400, `Неизвестное поле сортировки «${path}»`);
33
+ }
34
+ if (samples.some((value) => isObject(value) || Array.isArray(value))) {
35
+ throw createHttpError(400, `Поле сортировки «${path}» должно содержать примитивные значения`);
36
+ }
37
+ return { isDescending, path };
38
+ });
39
+ };
40
+ export const sortItems = (items, sort, validationItems = items) => {
41
+ const sortRules = parseSortRules(sort, validationItems);
42
+ return sortRules.length === 0
43
+ ? [...items]
44
+ : [...items].sort((left, right) => {
45
+ for (const { isDescending, path } of sortRules) {
46
+ const comparison = compareValues(getValueByPath(left, path), getValueByPath(right, path));
47
+ if (comparison !== 0) {
48
+ return isDescending ? -comparison : comparison;
49
+ }
50
+ }
51
+ return 0;
52
+ });
53
+ };
54
+ //# sourceMappingURL=sort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort.js","sourceRoot":"","sources":["../../../src/query/sort.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface RelationMetadata {
2
+ isMany: boolean;
3
+ relationName: string;
4
+ reverseRelationName: string;
5
+ sourceResource: string;
6
+ targetResource: string;
7
+ }
8
+ export declare const getRelationKeys: (...names: string[]) => string[];
9
+ export declare const resolveRelationResource: (resourceNames: string[], relation: string, sourceResource: string) => string | undefined;
10
+ export declare const getRelationMetadata: (key: string, resourceNames: string[], sourceResource: string) => RelationMetadata | undefined;
@@ -0,0 +1,32 @@
1
+ import { singularize } from './utils.js';
2
+ const SELF_RELATIONS = new Set(['child', 'children', 'parent', 'parents']);
3
+ export const getRelationKeys = (...names) => [...new Set(names.flatMap((name) => [`${name}Id`, `${name}Ids`]))];
4
+ export const resolveRelationResource = (resourceNames, relation, sourceResource) => {
5
+ const resource = resourceNames.find((resourceName) => resourceName === relation) ?? resourceNames.find((resourceName) => singularize(resourceName) === relation);
6
+ if (resource != null) {
7
+ return resource;
8
+ }
9
+ return SELF_RELATIONS.has(relation) && resourceNames.includes(sourceResource) ? sourceResource : undefined;
10
+ };
11
+ export const getRelationMetadata = (key, resourceNames, sourceResource) => {
12
+ // Relation fields follow the <resource>Id and <resource>Ids conventions.
13
+ const match = key.match(/^(.+)(Id|Ids)$/);
14
+ if (match == null) {
15
+ return undefined;
16
+ }
17
+ const [, relation, suffix] = match;
18
+ const isMany = suffix === 'Ids';
19
+ const relationName = isMany ? (resourceNames.find((resource) => singularize(resource) === relation) ?? `${relation}s`) : relation;
20
+ const targetResource = resolveRelationResource(resourceNames, relationName, sourceResource);
21
+ if (targetResource == null) {
22
+ return undefined;
23
+ }
24
+ return {
25
+ isMany,
26
+ relationName,
27
+ reverseRelationName: ['parent', 'parents'].includes(relationName) ? 'children' : sourceResource,
28
+ sourceResource,
29
+ targetResource,
30
+ };
31
+ };
32
+ //# sourceMappingURL=relation-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-metadata.js","sourceRoot":"","sources":["../../src/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,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,KAAe,EAAY,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpI,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,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAW,EAAE,aAAuB,EAAE,cAAsB,EAAgC,EAAE;IAChI,yEAAyE;IACzE,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,12 @@
1
+ import type { DatabaseContainer } from './database.js';
2
+ import type { DatabaseRecord } from './types.js';
3
+ interface RelationContext {
4
+ forwardIndexes: Map<string, Map<string, DatabaseRecord>>;
5
+ resourceNames: string[];
6
+ reverseIndexes: Map<string, Map<string, DatabaseRecord[]>>;
7
+ }
8
+ export declare const createRelationContext: (database: DatabaseContainer) => RelationContext;
9
+ export declare const parseEmbedPaths: (embed: unknown) => string[][];
10
+ export declare const validateEmbedPaths: (database: DatabaseContainer, resource: string, items: DatabaseRecord[], embedPaths: string[][]) => void;
11
+ export declare const embedItem: (database: DatabaseContainer, item: DatabaseRecord, resource: string, embedPaths: string[][], context?: RelationContext) => DatabaseRecord;
12
+ export {};
@@ -0,0 +1,155 @@
1
+ import { getRelationKeys, resolveRelationResource } from './relation-metadata.js';
2
+ import { createHttpError, getResourceNames, isObject, isSafeKey, singularize, toArray } from './utils.js';
3
+ export const createRelationContext = (database) => ({
4
+ forwardIndexes: new Map(),
5
+ resourceNames: getResourceNames(database.data),
6
+ reverseIndexes: new Map(),
7
+ });
8
+ const findLocalRelation = (item, relation, targetResource) => {
9
+ const relationKey = getRelationKeys(relation, singularize(relation), targetResource, singularize(targetResource)).find((key) => Object.hasOwn(item, key));
10
+ if (relationKey == null) {
11
+ return undefined;
12
+ }
13
+ return { ids: toArray(item[relationKey]).filter((id) => id != null), isMany: relationKey.endsWith('Ids') || Array.isArray(item[relationKey]) };
14
+ };
15
+ const collectReferences = (value, relationKeys, references) => {
16
+ if (Array.isArray(value)) {
17
+ value.forEach((item) => {
18
+ collectReferences(item, relationKeys, references);
19
+ });
20
+ return;
21
+ }
22
+ if (!isObject(value)) {
23
+ return;
24
+ }
25
+ Object.entries(value).forEach(([key, nestedValue]) => {
26
+ if (!isSafeKey(key)) {
27
+ return;
28
+ }
29
+ if (relationKeys.includes(key)) {
30
+ toArray(nestedValue).forEach((id) => {
31
+ if (id != null) {
32
+ references.add(String(id));
33
+ }
34
+ });
35
+ return;
36
+ }
37
+ collectReferences(nestedValue, relationKeys, references);
38
+ });
39
+ };
40
+ const getResourceIndex = (database, resource, context) => {
41
+ if (!context.forwardIndexes.has(resource)) {
42
+ context.forwardIndexes.set(resource, new Map(database.data[resource].map((item) => [String(item.id), item])));
43
+ }
44
+ return context.forwardIndexes.get(resource);
45
+ };
46
+ const getReverseIndex = (database, targetResource, relationKeys, context) => {
47
+ const cacheKey = `${targetResource}:${[...relationKeys].sort().join(',')}`;
48
+ const cachedIndex = context.reverseIndexes.get(cacheKey);
49
+ if (cachedIndex != null) {
50
+ return cachedIndex;
51
+ }
52
+ const index = new Map();
53
+ database.data[targetResource].forEach((item) => {
54
+ const references = new Set();
55
+ collectReferences(item, relationKeys, references);
56
+ references.forEach((id) => {
57
+ index.set(id, [...(index.get(id) ?? []), item]);
58
+ });
59
+ });
60
+ context.reverseIndexes.set(cacheKey, index);
61
+ return index;
62
+ };
63
+ const findRelatedValue = (database, item, sourceResource, relation, targetResource, context) => {
64
+ const localRelation = findLocalRelation(item, relation, targetResource);
65
+ if (localRelation != null) {
66
+ const targetIndex = getResourceIndex(database, targetResource, context);
67
+ const relatedItems = localRelation.ids.map((id) => targetIndex.get(String(id))).filter((targetItem) => targetItem != null);
68
+ return localRelation.isMany ? relatedItems : (relatedItems[0] ?? null);
69
+ }
70
+ if (item.id == null) {
71
+ return undefined;
72
+ }
73
+ const reverseRelationKeys = getRelationKeys(singularize(sourceResource));
74
+ if (relation === 'child' || relation === 'children') {
75
+ reverseRelationKeys.push('parentId', 'parentIds');
76
+ }
77
+ return getReverseIndex(database, targetResource, reverseRelationKeys, context).get(String(item.id)) ?? [];
78
+ };
79
+ const embedPath = (database, item, sourceResource, relations, context) => {
80
+ const [relation, ...nestedRelations] = relations;
81
+ if (relation == null || !isSafeKey(relation)) {
82
+ return item;
83
+ }
84
+ const currentValue = item[relation];
85
+ const targetResource = resolveRelationResource(context.resourceNames, relation, sourceResource);
86
+ const nestedSourceResource = targetResource ?? relation;
87
+ const localRelation = targetResource == null ? undefined : findLocalRelation(item, relation, targetResource);
88
+ if (localRelation == null) {
89
+ if (Array.isArray(currentValue)) {
90
+ return nestedRelations.length === 0
91
+ ? item
92
+ : { ...item, [relation]: currentValue.map((value) => (isObject(value) ? embedPath(database, value, nestedSourceResource, nestedRelations, context) : value)) };
93
+ }
94
+ if (isObject(currentValue)) {
95
+ return nestedRelations.length === 0 ? item : { ...item, [relation]: embedPath(database, currentValue, nestedSourceResource, nestedRelations, context) };
96
+ }
97
+ }
98
+ if (targetResource == null) {
99
+ return item;
100
+ }
101
+ const relatedValue = findRelatedValue(database, item, sourceResource, relation, targetResource, context);
102
+ if (relatedValue == null || nestedRelations.length === 0) {
103
+ return relatedValue === undefined ? item : { ...item, [relation]: relatedValue };
104
+ }
105
+ return {
106
+ ...item,
107
+ [relation]: Array.isArray(relatedValue)
108
+ ? relatedValue.map((value) => embedPath(database, value, targetResource, nestedRelations, context))
109
+ : embedPath(database, relatedValue, targetResource, nestedRelations, context),
110
+ };
111
+ };
112
+ export const parseEmbedPaths = (embed) => {
113
+ if (embed == null) {
114
+ return [];
115
+ }
116
+ const values = toArray(embed);
117
+ if (values.some((value) => typeof value !== 'string')) {
118
+ throw createHttpError(400, 'Параметр _embed должен содержать строковые пути связей');
119
+ }
120
+ return values
121
+ .flatMap((value) => value.split(','))
122
+ .map((path) => {
123
+ const keys = path.split('.');
124
+ if (keys.some((key) => key === '' || !isSafeKey(key))) {
125
+ throw createHttpError(400, `Недопустимый путь связи «${path}»`);
126
+ }
127
+ return keys;
128
+ });
129
+ };
130
+ const getNestedSamples = (samples, relation) => samples.flatMap((sample) => {
131
+ if (!isObject(sample) || !Object.hasOwn(sample, relation)) {
132
+ return [];
133
+ }
134
+ return toArray(sample[relation]).filter(isObject);
135
+ });
136
+ const validateEmbedPath = (database, sourceResource, samples, relations, path = '', resourceNames = getResourceNames(database.data)) => {
137
+ const [relation, ...nestedRelations] = relations;
138
+ const relationPath = path === '' ? relation : `${path}.${relation}`;
139
+ const targetResource = resolveRelationResource(resourceNames, relation, sourceResource);
140
+ const nestedSamples = targetResource == null ? getNestedSamples(samples, relation) : database.data[targetResource];
141
+ if (targetResource == null && nestedSamples.length === 0) {
142
+ throw createHttpError(400, `Неизвестный путь связи «${relationPath}»`);
143
+ }
144
+ if (nestedRelations.length > 0) {
145
+ validateEmbedPath(database, targetResource ?? relation, nestedSamples, nestedRelations, relationPath, resourceNames);
146
+ }
147
+ };
148
+ export const validateEmbedPaths = (database, resource, items, embedPaths) => {
149
+ const resourceNames = getResourceNames(database.data);
150
+ embedPaths.forEach((path) => {
151
+ validateEmbedPath(database, resource, items, path, '', resourceNames);
152
+ });
153
+ };
154
+ export const embedItem = (database, item, resource, embedPaths, context = createRelationContext(database)) => embedPaths.reduce((embeddedItem, path) => embedPath(database, embeddedItem, resource, path, context), item);
155
+ //# sourceMappingURL=relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/relations.ts"],"names":[],"mappings":"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"}