@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.
- package/README.md +12 -9
- package/README.ru.md +12 -9
- package/dist/bin/deep-json-server.d.ts +2 -0
- package/dist/bin/deep-json-server.js +11 -0
- package/dist/bin/deep-json-server.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cli.d.ts +4 -0
- package/dist/src/cli.js +80 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +54 -0
- package/dist/src/config.js +145 -0
- package/dist/src/config.js.map +1 -0
- package/{src → dist/src}/constants.js +1 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/database.d.ts +20 -0
- package/dist/src/database.js +136 -0
- package/dist/src/database.js.map +1 -0
- package/dist/src/files/contract.d.ts +67 -0
- package/dist/src/files/contract.js +106 -0
- package/dist/src/files/contract.js.map +1 -0
- package/dist/src/files/disk-store.d.ts +5 -0
- package/dist/src/files/disk-store.js +313 -0
- package/dist/src/files/disk-store.js.map +1 -0
- package/dist/src/files/index.d.ts +5 -0
- package/dist/src/files/index.js +6 -0
- package/dist/src/files/index.js.map +1 -0
- package/dist/src/files/memory-store.d.ts +3 -0
- package/dist/src/files/memory-store.js +80 -0
- package/dist/src/files/memory-store.js.map +1 -0
- package/dist/src/files/routes.d.ts +6 -0
- package/dist/src/files/routes.js +77 -0
- package/dist/src/files/routes.js.map +1 -0
- package/dist/src/openapi/config.d.ts +11 -0
- package/dist/src/openapi/config.js +204 -0
- package/dist/src/openapi/config.js.map +1 -0
- package/dist/src/openapi/document.d.ts +9 -0
- package/dist/src/openapi/document.js +338 -0
- package/dist/src/openapi/document.js.map +1 -0
- package/dist/src/openapi/index.d.ts +10 -0
- package/dist/src/openapi/index.js +27 -0
- package/dist/src/openapi/index.js.map +1 -0
- package/dist/src/openapi/inference.d.ts +14 -0
- package/dist/src/openapi/inference.js +145 -0
- package/dist/src/openapi/inference.js.map +1 -0
- package/dist/src/query/filter.d.ts +6 -0
- package/dist/src/query/filter.js +248 -0
- package/dist/src/query/filter.js.map +1 -0
- package/{src → dist/src}/query/index.js +1 -0
- package/dist/src/query/index.js.map +1 -0
- package/dist/src/query/pagination.d.ts +11 -0
- package/dist/src/query/pagination.js +28 -0
- package/dist/src/query/pagination.js.map +1 -0
- package/dist/src/query/sort.d.ts +1 -0
- package/dist/src/query/sort.js +54 -0
- package/dist/src/query/sort.js.map +1 -0
- package/dist/src/relation-metadata.d.ts +10 -0
- package/dist/src/relation-metadata.js +32 -0
- package/dist/src/relation-metadata.js.map +1 -0
- package/dist/src/relations.d.ts +12 -0
- package/dist/src/relations.js +155 -0
- package/dist/src/relations.js.map +1 -0
- package/dist/src/server.d.ts +13 -0
- package/dist/src/server.js +188 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/types.d.ts +52 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils.d.ts +20 -0
- package/dist/src/utils.js +63 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +16 -15
- package/bin/deep-json-server.js +0 -11
- package/index.js +0 -12
- package/src/cli.js +0 -91
- package/src/config.js +0 -203
- package/src/database.js +0 -148
- package/src/files.js +0 -633
- package/src/openapi/config.js +0 -124
- package/src/openapi/document.js +0 -394
- package/src/openapi/index.js +0 -36
- package/src/openapi/inference.js +0 -187
- package/src/query/filter.js +0 -283
- package/src/query/pagination.js +0 -44
- package/src/query/sort.js +0 -63
- package/src/relation-metadata.js +0 -41
- package/src/relations.js +0 -173
- package/src/server.js +0 -250
- package/src/utils.js +0 -84
- package/types/index.d.ts +0 -21
- package/types/src/config.d.ts +0 -73
- package/types/src/database.d.ts +0 -33
- package/types/src/files.d.ts +0 -64
- package/types/src/openapi/config.d.ts +0 -3
- package/types/src/openapi/document.d.ts +0 -11
- package/types/src/openapi/index.d.ts +0 -9
- package/types/src/openapi/inference.d.ts +0 -9
- package/types/src/query/filter.d.ts +0 -3
- package/types/src/query/pagination.d.ts +0 -8
- package/types/src/query/sort.d.ts +0 -1
- package/types/src/relation-metadata.d.ts +0 -9
- package/types/src/relations.d.ts +0 -3
- package/types/src/server.d.ts +0 -14
- package/types/src/utils.d.ts +0 -18
- /package/{types → dist}/src/constants.d.ts +0 -0
- /package/{types → dist}/src/query/index.d.ts +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type FastifyInstance } from 'fastify';
|
|
2
|
+
import { type DeepJsonServerConfig } from './config.js';
|
|
3
|
+
import type { OpenapiDocument } from './types.js';
|
|
4
|
+
export interface ServerFacade {
|
|
5
|
+
fastify(): FastifyInstance;
|
|
6
|
+
openapi(): Promise<OpenapiDocument>;
|
|
7
|
+
}
|
|
8
|
+
interface ServerFeatures {
|
|
9
|
+
files?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Creates lazy Fastify and OpenAPI accessors from one configuration. */
|
|
12
|
+
export declare function createServer(config: DeepJsonServerConfig, features?: ServerFeatures): Promise<ServerFacade>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import Fastify from 'fastify';
|
|
2
|
+
import { normalizeServerConfig } from './config.js';
|
|
3
|
+
import { DEFAULT_HOST, DEFAULT_MAX_FILE_SIZE, DEFAULT_MAX_PAGE_SIZE, DEFAULT_PORT } from './constants.js';
|
|
4
|
+
import { createDatabaseStore, createId, findItemIndex, getCollection } from './database.js';
|
|
5
|
+
import { FILE_HEADERS } from './files/contract.js';
|
|
6
|
+
import { createFileStore, registerFileRoutes } from './files/index.js';
|
|
7
|
+
import { resolveSchemaConfig } from './openapi/config.js';
|
|
8
|
+
import { buildOpenapiDocument } from './openapi/document.js';
|
|
9
|
+
import { createOpenapi, writeOpenapi } from './openapi/index.js';
|
|
10
|
+
import { matchesWhere, paginateItems, parsePagination, parseWhere, sortItems, validateWhere } from './query/index.js';
|
|
11
|
+
import { createRelationContext, embedItem, parseEmbedPaths, validateEmbedPaths } from './relations.js';
|
|
12
|
+
import { createHttpError, getResourceNames, isObject } from './utils.js';
|
|
13
|
+
const CORS_HEADERS = {
|
|
14
|
+
'Access-Control-Allow-Headers': [...Object.values(FILE_HEADERS).map(({ name }) => name), 'Content-Type'].join(', '),
|
|
15
|
+
'Access-Control-Allow-Methods': 'DELETE, GET, OPTIONS, PATCH, POST, PUT',
|
|
16
|
+
'Access-Control-Allow-Origin': '*',
|
|
17
|
+
};
|
|
18
|
+
const getSchemaName = (reference) => reference.split('/').at(-1);
|
|
19
|
+
const addRequestSchemas = (fastify, document, resources) => {
|
|
20
|
+
const requestSchemaNames = new Set(resources.flatMap((resource) => {
|
|
21
|
+
const resourcePath = document.paths[`/${resource}`];
|
|
22
|
+
const itemPath = document.paths[`/${resource}/{id}`];
|
|
23
|
+
return [getSchemaName(resourcePath.post.requestBody.content['application/json'].schema.$ref), getSchemaName(itemPath.patch.requestBody.content['application/json'].schema.$ref)];
|
|
24
|
+
}));
|
|
25
|
+
requestSchemaNames.forEach((schemaName) => {
|
|
26
|
+
fastify.addSchema({ $id: schemaName, ...document.components.schemas[schemaName] });
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const getCollectionItem = (database, resource, id) => {
|
|
30
|
+
const collection = getCollection(database, resource);
|
|
31
|
+
const index = findItemIndex(collection, id);
|
|
32
|
+
if (index === -1) {
|
|
33
|
+
throw createHttpError(404, 'Запись не найдена');
|
|
34
|
+
}
|
|
35
|
+
return { collection, index, item: collection[index] };
|
|
36
|
+
};
|
|
37
|
+
const registerResourceRoutes = (fastify, store, resource, document, maxPageSize) => {
|
|
38
|
+
const resourcePath = `/${resource}`;
|
|
39
|
+
const itemPath = `/${resource}/:id`;
|
|
40
|
+
const createOperation = document.paths[resourcePath].post;
|
|
41
|
+
const updateOperation = document.paths[`/${resource}/{id}`].patch;
|
|
42
|
+
const createSchemaName = getSchemaName(createOperation.requestBody.content['application/json'].schema.$ref);
|
|
43
|
+
const updateSchemaName = getSchemaName(updateOperation.requestBody.content['application/json'].schema.$ref);
|
|
44
|
+
fastify.get(resourcePath, async (request) => {
|
|
45
|
+
await store.read();
|
|
46
|
+
const collection = getCollection(store.database, resource);
|
|
47
|
+
const query = request.query;
|
|
48
|
+
const where = parseWhere(query);
|
|
49
|
+
const embedPaths = parseEmbedPaths(query._embed);
|
|
50
|
+
const pagination = parsePagination(query, maxPageSize);
|
|
51
|
+
validateEmbedPaths(store.database, resource, collection, embedPaths);
|
|
52
|
+
const relationContext = createRelationContext(store.database);
|
|
53
|
+
const embeddedItems = collection.map((item) => embedItem(store.database, item, resource, embedPaths, relationContext));
|
|
54
|
+
validateWhere(where, embeddedItems);
|
|
55
|
+
const filteredItems = embeddedItems.filter((item) => matchesWhere(item, where));
|
|
56
|
+
const sortedItems = sortItems(filteredItems, query._sort, embeddedItems);
|
|
57
|
+
return paginateItems(sortedItems, pagination.page, pagination.pageSize);
|
|
58
|
+
});
|
|
59
|
+
fastify.get(itemPath, async (request) => {
|
|
60
|
+
await store.read();
|
|
61
|
+
const params = request.params;
|
|
62
|
+
const query = request.query;
|
|
63
|
+
const { collection, item } = getCollectionItem(store.database, resource, params.id);
|
|
64
|
+
const embedPaths = parseEmbedPaths(query._embed);
|
|
65
|
+
validateEmbedPaths(store.database, resource, collection, embedPaths);
|
|
66
|
+
return embedItem(store.database, item, resource, embedPaths);
|
|
67
|
+
});
|
|
68
|
+
fastify.post(resourcePath, { schema: { body: { $ref: `${createSchemaName}#` } } }, async (request, reply) => {
|
|
69
|
+
const item = await store.update((database) => {
|
|
70
|
+
const collection = getCollection(database, resource);
|
|
71
|
+
const createdItem = { ...request.body, id: createId(collection) };
|
|
72
|
+
collection.push(createdItem);
|
|
73
|
+
return createdItem;
|
|
74
|
+
});
|
|
75
|
+
return reply.code(201).send(item);
|
|
76
|
+
});
|
|
77
|
+
fastify.put(itemPath, { schema: { body: { $ref: `${createSchemaName}#` } } }, async (request) => store.update((database) => {
|
|
78
|
+
const { collection, index, item: currentItem } = getCollectionItem(database, resource, request.params.id);
|
|
79
|
+
const item = { ...request.body, id: currentItem.id };
|
|
80
|
+
collection.splice(index, 1, item);
|
|
81
|
+
return item;
|
|
82
|
+
}));
|
|
83
|
+
fastify.patch(itemPath, { schema: { body: { $ref: `${updateSchemaName}#` } } }, async (request) => store.update((database) => {
|
|
84
|
+
const { collection, index, item: currentItem } = getCollectionItem(database, resource, request.params.id);
|
|
85
|
+
const item = { ...currentItem, ...request.body, id: currentItem.id };
|
|
86
|
+
collection.splice(index, 1, item);
|
|
87
|
+
return item;
|
|
88
|
+
}));
|
|
89
|
+
fastify.delete(itemPath, async (request) => store.update((database) => {
|
|
90
|
+
const { collection, index, item } = getCollectionItem(database, resource, request.params.id);
|
|
91
|
+
collection.splice(index, 1);
|
|
92
|
+
return item;
|
|
93
|
+
}));
|
|
94
|
+
};
|
|
95
|
+
/** Creates lazy Fastify and OpenAPI accessors from one configuration. */
|
|
96
|
+
export async function createServer(config, features = {}) {
|
|
97
|
+
if (!isObject(features) || Object.keys(features).some((key) => key !== 'files') || (features.files != null && typeof features.files !== 'boolean')) {
|
|
98
|
+
throw new Error('Параметр features должен содержать только необязательный boolean-ключ files');
|
|
99
|
+
}
|
|
100
|
+
const normalizedConfig = normalizeServerConfig(config);
|
|
101
|
+
const filesEnabled = features.files ?? normalizedConfig.files != null;
|
|
102
|
+
const { cors = true, logger = true, maxFileSize = DEFAULT_MAX_FILE_SIZE, maxPageSize = DEFAULT_MAX_PAGE_SIZE } = normalizedConfig.server;
|
|
103
|
+
const store = await createDatabaseStore(normalizedConfig.database);
|
|
104
|
+
const schema = await resolveSchemaConfig(normalizedConfig.database.schema);
|
|
105
|
+
let fileStorePromise;
|
|
106
|
+
let fastifyInstance;
|
|
107
|
+
if (filesEnabled && normalizedConfig.files == null) {
|
|
108
|
+
throw new Error('Для файловых маршрутов укажите секцию config.files');
|
|
109
|
+
}
|
|
110
|
+
const getFileStore = () => (fileStorePromise ??= createFileStore(normalizedConfig.files));
|
|
111
|
+
if (filesEnabled && normalizedConfig.files?.data != null) {
|
|
112
|
+
await getFileStore();
|
|
113
|
+
}
|
|
114
|
+
const buildDocument = () => buildOpenapiDocument({
|
|
115
|
+
database: store.database.data,
|
|
116
|
+
files: filesEnabled,
|
|
117
|
+
maxPageSize,
|
|
118
|
+
schema,
|
|
119
|
+
});
|
|
120
|
+
const getFastify = () => {
|
|
121
|
+
if (fastifyInstance != null) {
|
|
122
|
+
return fastifyInstance;
|
|
123
|
+
}
|
|
124
|
+
const document = buildDocument();
|
|
125
|
+
const resources = getResourceNames(store.database.data);
|
|
126
|
+
const fastify = Fastify({ logger });
|
|
127
|
+
const originalListen = fastify.listen.bind(fastify);
|
|
128
|
+
// Calling fastify().listen() without arguments uses config defaults.
|
|
129
|
+
const defaultListenOptions = { host: normalizedConfig.server.host ?? DEFAULT_HOST, port: normalizedConfig.server.port ?? DEFAULT_PORT };
|
|
130
|
+
const listenWithDefaults = (optionsOrCallback, callback) => {
|
|
131
|
+
if (typeof optionsOrCallback === 'function') {
|
|
132
|
+
originalListen(defaultListenOptions, optionsOrCallback);
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
const options = optionsOrCallback ?? defaultListenOptions;
|
|
136
|
+
if (callback != null) {
|
|
137
|
+
originalListen(options, callback);
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
return originalListen(options);
|
|
141
|
+
};
|
|
142
|
+
fastify.listen = listenWithDefaults;
|
|
143
|
+
addRequestSchemas(fastify, document, resources);
|
|
144
|
+
if (cors) {
|
|
145
|
+
fastify.addHook('onRequest', async (_request, reply) => {
|
|
146
|
+
Object.entries(CORS_HEADERS).forEach(([header, value]) => {
|
|
147
|
+
reply.header(header, value);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
fastify.options('/', async (_request, reply) => reply.code(204).send());
|
|
151
|
+
fastify.options('/*', async (_request, reply) => reply.code(204).send());
|
|
152
|
+
}
|
|
153
|
+
fastify.get('/', async () => ({ resources }));
|
|
154
|
+
resources.forEach((resource) => {
|
|
155
|
+
registerResourceRoutes(fastify, store, resource, document, maxPageSize);
|
|
156
|
+
});
|
|
157
|
+
if (filesEnabled) {
|
|
158
|
+
registerFileRoutes(fastify, { getStore: getFileStore, maxFileSize });
|
|
159
|
+
}
|
|
160
|
+
fastify.setErrorHandler((error, request, reply) => {
|
|
161
|
+
const candidateStatusCode = typeof error === 'object' && error != null && 'statusCode' in error ? error.statusCode : undefined;
|
|
162
|
+
const statusCode = typeof candidateStatusCode === 'number' && Number.isInteger(candidateStatusCode) && candidateStatusCode >= 400 && candidateStatusCode <= 599 ? candidateStatusCode : 500;
|
|
163
|
+
if (statusCode === 500) {
|
|
164
|
+
request.log.error(error);
|
|
165
|
+
}
|
|
166
|
+
return reply.code(statusCode).send({ error: statusCode === 500 ? 'Внутренняя ошибка сервера' : error instanceof Error ? error.message : String(error) });
|
|
167
|
+
});
|
|
168
|
+
fastifyInstance = fastify;
|
|
169
|
+
return fastifyInstance;
|
|
170
|
+
};
|
|
171
|
+
const openapi = async () => {
|
|
172
|
+
await store.read();
|
|
173
|
+
const document = createOpenapi({
|
|
174
|
+
database: store.database.data,
|
|
175
|
+
files: filesEnabled,
|
|
176
|
+
host: normalizedConfig.server.host,
|
|
177
|
+
maxPageSize,
|
|
178
|
+
port: normalizedConfig.server.port,
|
|
179
|
+
schema,
|
|
180
|
+
});
|
|
181
|
+
if (normalizedConfig.openapi.path != null) {
|
|
182
|
+
await writeOpenapi(document, normalizedConfig.openapi.path);
|
|
183
|
+
}
|
|
184
|
+
return document;
|
|
185
|
+
};
|
|
186
|
+
return { fastify: getFastify, openapi };
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
id: DatabaseId;
|
|
9
|
+
};
|
|
10
|
+
export type DatabaseData = Record<string, DatabaseRecord[]>;
|
|
11
|
+
export type OpenapiType = 'array' | 'boolean' | 'integer' | 'number' | 'object' | 'string';
|
|
12
|
+
export interface OpenapiSchema {
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
additionalProperties?: boolean | OpenapiSchema;
|
|
15
|
+
allOf?: OpenapiSchema[];
|
|
16
|
+
anyOf?: OpenapiSchema[];
|
|
17
|
+
default?: JsonValue;
|
|
18
|
+
description?: string;
|
|
19
|
+
enum?: JsonValue[];
|
|
20
|
+
format?: string;
|
|
21
|
+
items?: OpenapiSchema;
|
|
22
|
+
maximum?: number;
|
|
23
|
+
maxItems?: number;
|
|
24
|
+
maxLength?: number;
|
|
25
|
+
minimum?: number;
|
|
26
|
+
minItems?: number;
|
|
27
|
+
minLength?: number;
|
|
28
|
+
not?: OpenapiSchema;
|
|
29
|
+
nullable?: boolean;
|
|
30
|
+
oneOf?: OpenapiSchema[];
|
|
31
|
+
pattern?: string;
|
|
32
|
+
properties?: Record<string, OpenapiSchema>;
|
|
33
|
+
required?: string[];
|
|
34
|
+
title?: string;
|
|
35
|
+
type?: OpenapiType;
|
|
36
|
+
uniqueItems?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface OpenapiDocument {
|
|
39
|
+
[key: string]: unknown;
|
|
40
|
+
components: {
|
|
41
|
+
parameters: Record<string, unknown>;
|
|
42
|
+
schemas: Record<string, OpenapiSchema>;
|
|
43
|
+
};
|
|
44
|
+
info: Record<string, unknown>;
|
|
45
|
+
openapi: string;
|
|
46
|
+
paths: Record<string, Record<string, unknown>>;
|
|
47
|
+
servers?: Array<{
|
|
48
|
+
url: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
export type QueryValue = string | string[] | undefined;
|
|
52
|
+
export type Query = Record<string, QueryValue>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface HttpError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
}
|
|
4
|
+
export declare const assertKnownKeys: (value: object, keys: Set<string>, path: string) => void;
|
|
5
|
+
export declare const createHttpError: (statusCode: number, message: string) => HttpError;
|
|
6
|
+
/** Creates a scheduler that runs mutations sequentially. */
|
|
7
|
+
export declare const createSerialQueue: () => <T>(operation: () => Promise<T> | T) => Promise<T>;
|
|
8
|
+
/** Creates a random ID that is not currently in use. */
|
|
9
|
+
export declare const createUniqueId: (isUsed: (id: string) => boolean) => string;
|
|
10
|
+
export declare const getResourceNames: (data: object) => string[];
|
|
11
|
+
export declare const isObject: (value: unknown) => value is Record<string, unknown>;
|
|
12
|
+
export declare const isSafeKey: (key: string) => boolean;
|
|
13
|
+
export declare const isSystemError: (error: unknown) => error is NodeJS.ErrnoException;
|
|
14
|
+
/** Converts a single value or an array to an array. */
|
|
15
|
+
export declare const toArray: <T>(value: T | T[]) => T[];
|
|
16
|
+
export declare const isEqual: (left: unknown, right: unknown) => boolean;
|
|
17
|
+
export declare const resolveDatabasePath: (databasePath: string) => string;
|
|
18
|
+
export declare const isIdEqual: (left: unknown, right: unknown) => boolean;
|
|
19
|
+
export declare const singularize: (value: string) => string;
|
|
20
|
+
export declare const toPascalCase: (value: string) => string;
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
export const assertKnownKeys = (value, keys, path) => {
|
|
6
|
+
const unknownKey = Object.keys(value).find((key) => !keys.has(key));
|
|
7
|
+
if (unknownKey != null) {
|
|
8
|
+
throw new Error(`Неизвестный ключ ${path}.${unknownKey}`);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const createHttpError = (statusCode, message) => Object.assign(new Error(message), { statusCode });
|
|
12
|
+
/** Creates a scheduler that runs mutations sequentially. */
|
|
13
|
+
export const createSerialQueue = () => {
|
|
14
|
+
let queue = Promise.resolve();
|
|
15
|
+
return (operation) => {
|
|
16
|
+
const pendingOperation = queue.then(operation);
|
|
17
|
+
// Keep the queue usable after a failed operation.
|
|
18
|
+
queue = pendingOperation.catch(() => undefined);
|
|
19
|
+
return pendingOperation;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/** Creates a random ID that is not currently in use. */
|
|
23
|
+
export const createUniqueId = (isUsed) => {
|
|
24
|
+
let id;
|
|
25
|
+
do {
|
|
26
|
+
id = randomBytes(8).toString('base64url');
|
|
27
|
+
} while (isUsed(id));
|
|
28
|
+
return id;
|
|
29
|
+
};
|
|
30
|
+
export const getResourceNames = (data) => Object.keys(data);
|
|
31
|
+
export const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
32
|
+
export const isSafeKey = (key) => !UNSAFE_KEYS.has(key);
|
|
33
|
+
export const isSystemError = (error) => error instanceof Error && 'code' in error;
|
|
34
|
+
/** Converts a single value or an array to an array. */
|
|
35
|
+
export const toArray = (value) => (Array.isArray(value) ? value : [value]);
|
|
36
|
+
export const isEqual = (left, right) => {
|
|
37
|
+
if (Object.is(left, right)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
41
|
+
return left.length === right.length && left.every((value, index) => isEqual(value, right[index]));
|
|
42
|
+
}
|
|
43
|
+
if (isObject(left) && isObject(right)) {
|
|
44
|
+
const leftKeys = Object.keys(left);
|
|
45
|
+
const rightKeys = Object.keys(right);
|
|
46
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key) => isSafeKey(key) && Object.hasOwn(right, key) && isEqual(left[key], right[key]));
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
export const resolveDatabasePath = (databasePath) => {
|
|
51
|
+
if (typeof databasePath !== 'string' || databasePath === '') {
|
|
52
|
+
throw new Error('Укажите путь к JSON-базе данных');
|
|
53
|
+
}
|
|
54
|
+
return resolve(databasePath);
|
|
55
|
+
};
|
|
56
|
+
export const isIdEqual = (left, right) => left != null && right != null && String(left) === String(right);
|
|
57
|
+
export const singularize = (value) => pluralize.singular(value);
|
|
58
|
+
export const toPascalCase = (value) => value
|
|
59
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
60
|
+
.filter(Boolean)
|
|
61
|
+
.map((part) => `${part[0].toUpperCase()}${part.slice(1)}`)
|
|
62
|
+
.join('');
|
|
63
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kollors/deep-json-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "JSON mock server with deep filters and recursive relationship embedding",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"bin": {
|
|
8
|
-
"deep-json-server": "bin/deep-json-server.js"
|
|
9
|
+
"deep-json-server": "dist/bin/deep-json-server.js"
|
|
9
10
|
},
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
12
|
-
"types": "./
|
|
13
|
-
"import": "./index.js"
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
|
-
"
|
|
18
|
-
"index.js",
|
|
19
|
-
"src",
|
|
20
|
-
"types",
|
|
18
|
+
"dist",
|
|
21
19
|
"LICENSE",
|
|
22
20
|
"README.md",
|
|
23
21
|
"README.ru.md"
|
|
24
22
|
],
|
|
25
23
|
"scripts": {
|
|
26
|
-
"
|
|
24
|
+
"build": "node scripts/clean-dist.js && tsc && node scripts/prepare-dist.js",
|
|
27
25
|
"lint": "biome check .",
|
|
28
26
|
"lint:fix": "biome check --write .",
|
|
29
|
-
"
|
|
27
|
+
"pack:check": "node scripts/check-package.js",
|
|
28
|
+
"prepack": "npm run build",
|
|
30
29
|
"prepublishOnly": "npm run verify",
|
|
31
|
-
"test": "node --test",
|
|
32
|
-
"test:coverage": "
|
|
33
|
-
"
|
|
34
|
-
"verify": "npm run
|
|
30
|
+
"test": "npm run build && node --test",
|
|
31
|
+
"test:coverage": "npm run build && node scripts/run-coverage.js",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"verify": "npm run typecheck && npm run lint && npm run test:coverage && npm run pack:check"
|
|
35
34
|
},
|
|
36
35
|
"engines": {
|
|
37
36
|
"node": ">=20"
|
|
@@ -72,6 +71,8 @@
|
|
|
72
71
|
},
|
|
73
72
|
"devDependencies": {
|
|
74
73
|
"@biomejs/biome": "^2.5.11",
|
|
74
|
+
"@types/node": "^24.10.0",
|
|
75
|
+
"@types/pluralize": "^0.0.33",
|
|
75
76
|
"typescript": "^7.0.2"
|
|
76
77
|
}
|
|
77
78
|
}
|
package/bin/deep-json-server.js
DELETED
package/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/** @typedef {import('./src/config.js').DeepJsonServerConfig} DeepJsonServerConfig */
|
|
2
|
-
/** @typedef {import('./src/config.js').DatabaseConfig} DatabaseConfig */
|
|
3
|
-
/** @typedef {import('./src/config.js').FilesConfig} FilesConfig */
|
|
4
|
-
/** @typedef {import('./src/config.js').MemoryFile} MemoryFile */
|
|
5
|
-
/** @typedef {import('./src/config.js').OpenapiConfig} OpenapiConfig */
|
|
6
|
-
/** @typedef {import('./src/config.js').ServerConfig} ServerConfig */
|
|
7
|
-
/** @typedef {import('./src/files.js').FileMetadata} FileMetadata */
|
|
8
|
-
/** @typedef {import('./src/files.js').FileUpdate} FileUpdate */
|
|
9
|
-
/** @typedef {import('./src/server.js').OpenapiDocument} OpenapiDocument */
|
|
10
|
-
/** @typedef {import('./src/server.js').ServerFacade} ServerFacade */
|
|
11
|
-
|
|
12
|
-
export { createServer } from './src/server.js';
|
package/src/cli.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import process from 'node:process';
|
|
2
|
-
import { readServerConfig } from './config.js';
|
|
3
|
-
import { DEFAULT_HOST, DEFAULT_PORT } from './constants.js';
|
|
4
|
-
import { createServer } from './server.js';
|
|
5
|
-
|
|
6
|
-
const HELP_TEXT = `Deep JSON Server
|
|
7
|
-
|
|
8
|
-
Использование:
|
|
9
|
-
deep-json-server [--files] [--openapi | --openapi-only] <server.config.js>
|
|
10
|
-
|
|
11
|
-
Параметры:
|
|
12
|
-
--files Добавить файловые маршруты в сервер и OpenAPI
|
|
13
|
-
--openapi Сгенерировать OpenAPI и запустить сервер
|
|
14
|
-
--openapi-only Сгенерировать OpenAPI и завершить работу
|
|
15
|
-
--help Показать справку`;
|
|
16
|
-
|
|
17
|
-
const parseArguments = (args) => {
|
|
18
|
-
const options = { files: false, openapiMode: 'none' };
|
|
19
|
-
let configPath;
|
|
20
|
-
|
|
21
|
-
args.forEach((argument) => {
|
|
22
|
-
if (argument === '--files') {
|
|
23
|
-
options.files = true;
|
|
24
|
-
} else if (argument === '--openapi') {
|
|
25
|
-
if (options.openapiMode !== 'none') {
|
|
26
|
-
throw new Error('Параметры --openapi и --openapi-only нельзя использовать одновременно');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
options.openapiMode = 'generate';
|
|
30
|
-
} else if (argument === '--openapi-only') {
|
|
31
|
-
if (options.openapiMode !== 'none') {
|
|
32
|
-
throw new Error('Параметры --openapi и --openapi-only нельзя использовать одновременно');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
options.openapiMode = 'only';
|
|
36
|
-
} else if (argument.startsWith('-')) {
|
|
37
|
-
throw new Error(`Неизвестный параметр: ${argument}`);
|
|
38
|
-
} else if (configPath == null) {
|
|
39
|
-
configPath = argument;
|
|
40
|
-
} else {
|
|
41
|
-
throw new Error('Можно указать только один файл конфигурации');
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
if (configPath == null) {
|
|
46
|
-
throw new Error('Укажите путь к файлу конфигурации');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return { configPath, ...options };
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const validateModeConfig = (config, { files, openapiMode }) => {
|
|
53
|
-
if (openapiMode !== 'none' && config.openapi.path == null) {
|
|
54
|
-
throw new Error(`Для --openapi${openapiMode === 'only' ? '-only' : ''} укажите ключ config.openapi.path`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (files && config.files == null) {
|
|
58
|
-
throw new Error('Для --files укажите секцию config.files');
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export async function runCli(args = process.argv.slice(2), services = { createServer }) {
|
|
63
|
-
if (args.includes('--help')) {
|
|
64
|
-
process.stdout.write(`${HELP_TEXT}\n`);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const { configPath, files, openapiMode } = parseArguments(args);
|
|
69
|
-
const config = await readServerConfig(configPath);
|
|
70
|
-
const host = config.server.host ?? process.env.HOST ?? DEFAULT_HOST;
|
|
71
|
-
const port = config.server.port ?? Number(process.env.PORT ?? DEFAULT_PORT);
|
|
72
|
-
|
|
73
|
-
validateModeConfig(config, { files, openapiMode });
|
|
74
|
-
|
|
75
|
-
const runtimeConfig = { ...config, server: { ...config.server, host, port } };
|
|
76
|
-
const serverFacade = await services.createServer(runtimeConfig, { files });
|
|
77
|
-
|
|
78
|
-
if (openapiMode !== 'none') {
|
|
79
|
-
await serverFacade.openapi();
|
|
80
|
-
process.stdout.write(`OpenAPI-схема сохранена в ${config.openapi.path}\n`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (openapiMode === 'only') {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const fastify = serverFacade.fastify();
|
|
88
|
-
|
|
89
|
-
await fastify.listen({ host, port });
|
|
90
|
-
fastify.log.info({ database: 'path' in config.database ? config.database.path : 'memory' }, 'Deep JSON Server запущен');
|
|
91
|
-
}
|