@kollors/deep-json-server 0.3.1 → 0.3.2

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 CHANGED
@@ -106,7 +106,7 @@ PATCH /movies/:id
106
106
  DELETE /movies/:id
107
107
  ```
108
108
 
109
- `POST` generates a string ID, while `PUT` and `PATCH` preserve the stored ID type. All write operations — `POST`, `PUT`, `PATCH` and `DELETE` — persist their changes in the JSON file. The database file must exist before startup and contain a JSON object whose resources are arrays. Top-level metadata keys prefixed with `$`, such as `$schema`, may contain non-array values.
109
+ `POST` generates a string ID, while `PUT` and `PATCH` preserve the stored ID type. All write operations — `POST`, `PUT`, `PATCH` and `DELETE` — persist their changes in the JSON file. The database file must exist before startup and contain a JSON object whose every top-level property is an array of resource records.
110
110
 
111
111
  ## Pagination and sorting
112
112
 
package/README.ru.md CHANGED
@@ -106,7 +106,7 @@ PATCH /movies/:id
106
106
  DELETE /movies/:id
107
107
  ```
108
108
 
109
- `POST` генерирует строковый ID, а `PUT` и `PATCH` сохраняют исходный тип ID. Все операции записи — `POST`, `PUT`, `PATCH` и `DELETE` — сохраняют изменения в JSON-файле. Файл базы должен существовать до запуска и содержать JSON-объект, ресурсы которого являются массивами. Служебные ключи верхнего уровня с префиксом `$`, например `$schema`, могут содержать значения других типов.
109
+ `POST` генерирует строковый ID, а `PUT` и `PATCH` сохраняют исходный тип ID. Все операции записи — `POST`, `PUT`, `PATCH` и `DELETE` — сохраняют изменения в JSON-файле. Файл базы должен существовать до запуска и содержать JSON-объект, каждое свойство верхнего уровня которого является массивом записей отдельного ресурса.
110
110
 
111
111
  ## Пагинация и сортировка
112
112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kollors/deep-json-server",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "JSON mock server with deep filters and recursive relationship embedding",
5
5
  "type": "module",
6
6
  "bin": {
package/src/openapi.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import { dirname, resolve } from 'node:path';
3
3
  import { stringify } from 'yaml';
4
- import { getResourceNames, isObject, singularize, toPascalCase } from './utils.js';
4
+ import { getResourceNames, isObject, singularize, toPascalCase, validateDatabase } from './utils.js';
5
5
 
6
6
  const readJson = async(path, label) => {
7
7
  const value = JSON.parse(await readFile(resolve(path), 'utf8'));
@@ -450,8 +450,10 @@ const validateGeneratedNames = (resources, componentNames) => {
450
450
  };
451
451
 
452
452
  export function createOpenApiDocument(database, schemaConfig = {}, { host = '127.0.0.1', port = 4001 } = {}) {
453
- if (!isObject(database) || !isObject(schemaConfig)) {
454
- throw new Error('База данных и её схема должны содержать JSON-объекты');
453
+ validateDatabase(database);
454
+
455
+ if (!isObject(schemaConfig)) {
456
+ throw new Error('Схема базы данных должна содержать JSON-объект');
455
457
  }
456
458
 
457
459
  const resources = getResourceNames(database);
package/src/server.js CHANGED
@@ -4,7 +4,7 @@ import { randomBytes } from 'node:crypto';
4
4
  import { readFile } from 'node:fs/promises';
5
5
  import { matchesWhere, paginateItems, parsePagination, parseWhere, sortItems, validateWhere } from './query.js';
6
6
  import { embedItem, parseEmbedPaths } from './relations.js';
7
- import { createHttpError, getResourceNames, isObject, isSafeKey, resolveDatabasePath } from './utils.js';
7
+ import { createHttpError, getResourceNames, isObject, isSafeKey, resolveDatabasePath, validateDatabase } from './utils.js';
8
8
 
9
9
  const CORS_HEADERS = {
10
10
  'Access-Control-Allow-Headers': 'Content-Type',
@@ -32,18 +32,6 @@ const getRequestBody = (body) => {
32
32
 
33
33
  const findItem = (collection, id) => collection.find((item) => isObject(item) && String(item.id) === id);
34
34
 
35
- const validateDatabase = (data) => {
36
- if (!isObject(data)) {
37
- throw new Error('База данных должна содержать JSON-объект');
38
- }
39
-
40
- const invalidResource = Object.entries(data).find(([key, value]) => !key.startsWith('$') && !Array.isArray(value));
41
-
42
- if (invalidResource != null) {
43
- throw new Error(`Ресурс «${invalidResource[0]}» должен содержать JSON-массив`);
44
- }
45
- };
46
-
47
35
  const readDatabaseFile = async(databasePath) => {
48
36
  let source;
49
37
 
@@ -59,9 +47,7 @@ const readDatabaseFile = async(databasePath) => {
59
47
 
60
48
  const data = JSON.parse(source);
61
49
 
62
- validateDatabase(data);
63
-
64
- return data;
50
+ return validateDatabase(data);
65
51
  };
66
52
 
67
53
  export async function createServer({ databasePath, logger = true } = {}) {
package/src/utils.js CHANGED
@@ -13,12 +13,26 @@ export const createHttpError = (statusCode, message) => {
13
13
  return error;
14
14
  };
15
15
 
16
- export const getResourceNames = (data) => Object.entries(data).filter(([, value]) => Array.isArray(value)).map(([resource]) => resource);
16
+ export const getResourceNames = (data) => Object.keys(data);
17
17
  export const isMainModule = (filePath, moduleUrl) => filePath != null && realpathSync(resolve(filePath)) === fileURLToPath(moduleUrl);
18
18
  export const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
19
19
  export const isSafeKey = (key) => !UNSAFE_KEYS.has(key);
20
20
  export const toArray = (value) => (Array.isArray(value) ? value : [value]);
21
21
 
22
+ export const validateDatabase = (data) => {
23
+ if (!isObject(data)) {
24
+ throw new Error('База данных должна содержать JSON-объект');
25
+ }
26
+
27
+ const invalidResource = Object.entries(data).find(([, value]) => !Array.isArray(value));
28
+
29
+ if (invalidResource != null) {
30
+ throw new Error(`Ресурс «${invalidResource[0]}» должен содержать JSON-массив`);
31
+ }
32
+
33
+ return data;
34
+ };
35
+
22
36
  export const isEqual = (left, right) => {
23
37
  if (Object.is(left, right)) {
24
38
  return true;