@kollors/deep-json-server 0.3.1 → 0.4.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 +14 -8
- package/README.ru.md +14 -8
- package/bin/deep-json-server.js +11 -0
- package/index.js +1 -11
- package/package.json +22 -5
- package/src/cli.js +19 -15
- package/src/constants.js +4 -0
- package/src/database.js +128 -0
- package/src/openapi/config.js +110 -0
- package/src/openapi/document.js +287 -0
- package/src/openapi/index.js +25 -0
- package/src/openapi/inference.js +187 -0
- package/src/{query.js → query/filter.js} +23 -113
- package/src/query/index.js +3 -0
- package/src/query/pagination.js +50 -0
- package/src/query/sort.js +63 -0
- package/src/relation-metadata.js +40 -0
- package/src/relations.js +62 -24
- package/src/server.js +108 -114
- package/src/utils.js +8 -5
- package/types/index.d.ts +2 -0
- package/types/src/constants.d.ts +4 -0
- package/types/src/database.d.ts +8 -0
- package/types/src/openapi/config.d.ts +3 -0
- package/types/src/openapi/document.d.ts +11 -0
- package/types/src/openapi/index.d.ts +13 -0
- package/types/src/openapi/inference.d.ts +9 -0
- package/types/src/query/filter.d.ts +3 -0
- package/types/src/query/index.d.ts +3 -0
- package/types/src/query/pagination.d.ts +13 -0
- package/types/src/query/sort.d.ts +1 -0
- package/types/src/relation-metadata.d.ts +9 -0
- package/types/src/relations.d.ts +3 -0
- package/types/src/server.d.ts +24 -0
- package/types/src/utils.d.ts +10 -0
- package/src/openapi.js +0 -518
package/src/server.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Fastify from 'fastify';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { DEFAULT_HOST, DEFAULT_PORT, MAX_PAGE_SIZE } from './constants.js';
|
|
3
|
+
import { createDatabaseStore, createId, findItem, getCollection } from './database.js';
|
|
4
|
+
import { readSchemaConfig } from './openapi/config.js';
|
|
5
|
+
import { createOpenApiDocument } from './openapi/index.js';
|
|
6
|
+
import { matchesWhere, paginateItems, parsePagination, parseWhere, sortItems, validateWhere } from './query/index.js';
|
|
7
|
+
import { embedItem, parseEmbedPaths, validateEmbedPaths } from './relations.js';
|
|
8
|
+
import { createHttpError, getResourceNames, isObject, resolveDatabasePath } from './utils.js';
|
|
8
9
|
|
|
9
10
|
const CORS_HEADERS = {
|
|
10
11
|
'Access-Control-Allow-Headers': 'Content-Type',
|
|
@@ -12,16 +13,6 @@ const CORS_HEADERS = {
|
|
|
12
13
|
'Access-Control-Allow-Origin': '*',
|
|
13
14
|
};
|
|
14
15
|
|
|
15
|
-
const getCollection = (database, resource) => {
|
|
16
|
-
const collection = isSafeKey(resource) ? database.data[resource] : undefined;
|
|
17
|
-
|
|
18
|
-
if (!Array.isArray(collection)) {
|
|
19
|
-
throw createHttpError(404, 'Ресурс не найден');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return collection;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
16
|
const getRequestBody = (body) => {
|
|
26
17
|
if (!isObject(body)) {
|
|
27
18
|
throw createHttpError(400, 'Тело запроса должно быть JSON-объектом');
|
|
@@ -30,111 +21,66 @@ const getRequestBody = (body) => {
|
|
|
30
21
|
return body;
|
|
31
22
|
};
|
|
32
23
|
|
|
33
|
-
const
|
|
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
|
-
const readDatabaseFile = async(databasePath) => {
|
|
48
|
-
let source;
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
source = await readFile(databasePath, 'utf8');
|
|
52
|
-
} catch (error) {
|
|
53
|
-
if (error?.code === 'ENOENT') {
|
|
54
|
-
throw new Error(`Файл базы данных не найден: ${databasePath}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
throw error;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const data = JSON.parse(source);
|
|
61
|
-
|
|
62
|
-
validateDatabase(data);
|
|
63
|
-
|
|
64
|
-
return data;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export async function createServer({ databasePath, logger = true } = {}) {
|
|
68
|
-
const resolvedDatabasePath = resolveDatabasePath(databasePath);
|
|
69
|
-
const initialData = await readDatabaseFile(resolvedDatabasePath);
|
|
70
|
-
const database = await JSONFilePreset(resolvedDatabasePath, initialData);
|
|
71
|
-
const server = Fastify({ logger });
|
|
72
|
-
let databaseWriteQueue = Promise.resolve();
|
|
73
|
-
|
|
74
|
-
const readDatabase = async() => {
|
|
75
|
-
database.data = await readDatabaseFile(resolvedDatabasePath);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const updateDatabase = (update) => {
|
|
79
|
-
const operation = databaseWriteQueue.then(async() => {
|
|
80
|
-
await readDatabase();
|
|
81
|
-
|
|
82
|
-
const result = update();
|
|
83
|
-
|
|
84
|
-
await database.write();
|
|
85
|
-
|
|
86
|
-
return result;
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
databaseWriteQueue = operation.catch(() => undefined);
|
|
24
|
+
const getSchemaName = (reference) => reference.split('/').at(-1);
|
|
90
25
|
|
|
91
|
-
|
|
92
|
-
|
|
26
|
+
const addRequestSchemas = (server, document, resources) => {
|
|
27
|
+
const requestSchemaNames = new Set(
|
|
28
|
+
resources.flatMap((resource) => {
|
|
29
|
+
const resourcePath = document.paths[`/${resource}`];
|
|
30
|
+
const itemPath = document.paths[`/${resource}/{id}`];
|
|
93
31
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
32
|
+
return [getSchemaName(resourcePath.post.requestBody.content['application/json'].schema.$ref), getSchemaName(itemPath.patch.requestBody.content['application/json'].schema.$ref)];
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
97
35
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await readDatabase();
|
|
101
|
-
}
|
|
36
|
+
requestSchemaNames.forEach((schemaName) => {
|
|
37
|
+
server.addSchema({ $id: schemaName, ...document.components.schemas[schemaName] });
|
|
102
38
|
});
|
|
39
|
+
};
|
|
103
40
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
41
|
+
const registerResourceRoutes = (server, store, resource, document, maxPageSize) => {
|
|
42
|
+
const resourcePath = `/${resource}`;
|
|
43
|
+
const itemPath = `/${resource}/:id`;
|
|
44
|
+
const createSchemaName = getSchemaName(document.paths[resourcePath].post.requestBody.content['application/json'].schema.$ref);
|
|
45
|
+
const updateSchemaName = getSchemaName(document.paths[`/${resource}/{id}`].patch.requestBody.content['application/json'].schema.$ref);
|
|
107
46
|
|
|
108
|
-
server.get(
|
|
109
|
-
const collection = getCollection(database,
|
|
47
|
+
server.get(resourcePath, async (request) => {
|
|
48
|
+
const collection = getCollection(store.database, resource);
|
|
110
49
|
const where = parseWhere(request.query);
|
|
111
50
|
const embedPaths = parseEmbedPaths(request.query._embed);
|
|
51
|
+
const pagination = parsePagination(request.query, maxPageSize);
|
|
52
|
+
|
|
53
|
+
validateEmbedPaths(store.database, resource, collection, embedPaths);
|
|
54
|
+
|
|
112
55
|
const relationIndexes = new Map();
|
|
113
|
-
const embeddedItems = collection.map((item) => embedItem(database, item,
|
|
114
|
-
const pagination = parsePagination(request.query);
|
|
56
|
+
const embeddedItems = collection.map((item) => embedItem(store.database, item, resource, embedPaths, relationIndexes));
|
|
115
57
|
|
|
116
58
|
validateWhere(where, embeddedItems);
|
|
117
59
|
|
|
118
60
|
const filteredItems = embeddedItems.filter((item) => matchesWhere(item, where));
|
|
119
|
-
const sortedItems = sortItems(filteredItems, request.query._sort);
|
|
61
|
+
const sortedItems = sortItems(filteredItems, request.query._sort, embeddedItems);
|
|
120
62
|
|
|
121
63
|
return paginateItems(sortedItems, pagination.page, pagination.pageSize);
|
|
122
64
|
});
|
|
123
65
|
|
|
124
|
-
server.get(
|
|
125
|
-
const
|
|
66
|
+
server.get(itemPath, async (request) => {
|
|
67
|
+
const collection = getCollection(store.database, resource);
|
|
68
|
+
const item = findItem(collection, request.params.id);
|
|
69
|
+
const embedPaths = parseEmbedPaths(request.query._embed);
|
|
126
70
|
|
|
127
71
|
if (item == null) {
|
|
128
72
|
throw createHttpError(404, 'Запись не найдена');
|
|
129
73
|
}
|
|
130
74
|
|
|
131
|
-
|
|
75
|
+
validateEmbedPaths(store.database, resource, collection, embedPaths);
|
|
76
|
+
|
|
77
|
+
return embedItem(store.database, item, resource, embedPaths);
|
|
132
78
|
});
|
|
133
79
|
|
|
134
|
-
server.post(
|
|
135
|
-
const item = await
|
|
136
|
-
const collection = getCollection(database,
|
|
137
|
-
const createdItem = { ...getRequestBody(request.body), id:
|
|
80
|
+
server.post(resourcePath, { schema: { body: { $ref: `${createSchemaName}#` } } }, async (request, reply) => {
|
|
81
|
+
const item = await store.update((database) => {
|
|
82
|
+
const collection = getCollection(database, resource);
|
|
83
|
+
const createdItem = { ...getRequestBody(request.body), id: createId(collection) };
|
|
138
84
|
|
|
139
85
|
collection.push(createdItem);
|
|
140
86
|
|
|
@@ -144,9 +90,9 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
144
90
|
return reply.code(201).send(item);
|
|
145
91
|
});
|
|
146
92
|
|
|
147
|
-
server.put(
|
|
148
|
-
|
|
149
|
-
const collection = getCollection(database,
|
|
93
|
+
server.put(itemPath, { schema: { body: { $ref: `${createSchemaName}#` } } }, async (request) =>
|
|
94
|
+
store.update((database) => {
|
|
95
|
+
const collection = getCollection(database, resource);
|
|
150
96
|
const currentItem = findItem(collection, request.params.id);
|
|
151
97
|
|
|
152
98
|
if (currentItem == null) {
|
|
@@ -158,12 +104,12 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
158
104
|
collection.splice(collection.indexOf(currentItem), 1, item);
|
|
159
105
|
|
|
160
106
|
return item;
|
|
161
|
-
})
|
|
162
|
-
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
163
109
|
|
|
164
|
-
server.patch(
|
|
165
|
-
|
|
166
|
-
const collection = getCollection(database,
|
|
110
|
+
server.patch(itemPath, { schema: { body: { $ref: `${updateSchemaName}#` } } }, async (request) =>
|
|
111
|
+
store.update((database) => {
|
|
112
|
+
const collection = getCollection(database, resource);
|
|
167
113
|
const currentItem = findItem(collection, request.params.id);
|
|
168
114
|
|
|
169
115
|
if (currentItem == null) {
|
|
@@ -175,12 +121,12 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
175
121
|
collection.splice(collection.indexOf(currentItem), 1, item);
|
|
176
122
|
|
|
177
123
|
return item;
|
|
178
|
-
})
|
|
179
|
-
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
180
126
|
|
|
181
|
-
server.delete(
|
|
182
|
-
|
|
183
|
-
const collection = getCollection(database,
|
|
127
|
+
server.delete(itemPath, async (request) =>
|
|
128
|
+
store.update((database) => {
|
|
129
|
+
const collection = getCollection(database, resource);
|
|
184
130
|
const currentItem = findItem(collection, request.params.id);
|
|
185
131
|
|
|
186
132
|
if (currentItem == null) {
|
|
@@ -190,9 +136,50 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
190
136
|
collection.splice(collection.indexOf(currentItem), 1);
|
|
191
137
|
|
|
192
138
|
return currentItem;
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Creates a Fastify server without opening a network port.
|
|
145
|
+
* @param {{ databasePath: string, logger?: boolean | Record<string, unknown>, maxPageSize?: number, schemaPath?: string }} options Server options.
|
|
146
|
+
* @returns {Promise<import('fastify').FastifyInstance>} Fastify server.
|
|
147
|
+
*/
|
|
148
|
+
export async function createServer(options) {
|
|
149
|
+
const { databasePath, logger = true, maxPageSize = MAX_PAGE_SIZE, schemaPath } = options ?? {};
|
|
150
|
+
|
|
151
|
+
if (!Number.isInteger(maxPageSize) || maxPageSize < 1) {
|
|
152
|
+
throw new Error('Максимальный размер страницы должен быть положительным целым числом');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const store = await createDatabaseStore(databasePath);
|
|
156
|
+
const schemaConfig = await readSchemaConfig(schemaPath);
|
|
157
|
+
const document = createOpenApiDocument(store.database.data, schemaConfig);
|
|
158
|
+
const resources = getResourceNames(store.database.data);
|
|
159
|
+
const server = Fastify({ logger });
|
|
160
|
+
|
|
161
|
+
addRequestSchemas(server, document, resources);
|
|
162
|
+
|
|
163
|
+
server.addHook('onRequest', async (_request, reply) => {
|
|
164
|
+
Object.entries(CORS_HEADERS).forEach(([header, value]) => {
|
|
165
|
+
reply.header(header, value);
|
|
193
166
|
});
|
|
194
167
|
});
|
|
195
168
|
|
|
169
|
+
server.addHook('preHandler', async (request) => {
|
|
170
|
+
if (request.method === 'GET') {
|
|
171
|
+
await store.read();
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
server.options('/', async (_request, reply) => reply.code(204).send());
|
|
176
|
+
server.options('/*', async (_request, reply) => reply.code(204).send());
|
|
177
|
+
server.get('/', async () => ({ resources }));
|
|
178
|
+
|
|
179
|
+
resources.forEach((resource) => {
|
|
180
|
+
registerResourceRoutes(server, store, resource, document, maxPageSize);
|
|
181
|
+
});
|
|
182
|
+
|
|
196
183
|
server.setErrorHandler((error, request, reply) => {
|
|
197
184
|
const statusCode = Number.isInteger(error.statusCode) ? error.statusCode : 500;
|
|
198
185
|
|
|
@@ -206,13 +193,20 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
206
193
|
return server;
|
|
207
194
|
}
|
|
208
195
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Creates and starts a Fastify server.
|
|
198
|
+
* @param {{ databasePath: string, host?: string, logger?: boolean | Record<string, unknown>, maxPageSize?: number, port?: number, schemaPath?: string }} options Server options.
|
|
199
|
+
* @returns {Promise<import('fastify').FastifyInstance>} Listening Fastify server.
|
|
200
|
+
*/
|
|
201
|
+
export async function startServer(options) {
|
|
202
|
+
const { databasePath, host = DEFAULT_HOST, logger = true, maxPageSize = MAX_PAGE_SIZE, port = DEFAULT_PORT, schemaPath } = options ?? {};
|
|
203
|
+
|
|
204
|
+
if (!Number.isInteger(port) || port < 0 || port > 65_535) {
|
|
205
|
+
throw new Error('Порт должен быть целым числом от 0 до 65535');
|
|
212
206
|
}
|
|
213
207
|
|
|
214
208
|
const resolvedDatabasePath = resolveDatabasePath(databasePath);
|
|
215
|
-
const server = await createServer({ databasePath: resolvedDatabasePath, logger });
|
|
209
|
+
const server = await createServer({ databasePath: resolvedDatabasePath, logger, maxPageSize, schemaPath });
|
|
216
210
|
|
|
217
211
|
await server.listen({ host, port });
|
|
218
212
|
server.log.info({ database: resolvedDatabasePath }, 'Deep JSON Server запущен');
|
package/src/utils.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { realpathSync } from 'node:fs';
|
|
2
1
|
import { resolve } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
2
|
import pluralize from 'pluralize';
|
|
5
3
|
|
|
6
4
|
const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
@@ -13,8 +11,7 @@ export const createHttpError = (statusCode, message) => {
|
|
|
13
11
|
return error;
|
|
14
12
|
};
|
|
15
13
|
|
|
16
|
-
export const getResourceNames = (data) => Object.
|
|
17
|
-
export const isMainModule = (filePath, moduleUrl) => filePath != null && realpathSync(resolve(filePath)) === fileURLToPath(moduleUrl);
|
|
14
|
+
export const getResourceNames = (data) => Object.keys(data);
|
|
18
15
|
export const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
19
16
|
export const isSafeKey = (key) => !UNSAFE_KEYS.has(key);
|
|
20
17
|
export const toArray = (value) => (Array.isArray(value) ? value : [value]);
|
|
@@ -46,6 +43,12 @@ export const resolveDatabasePath = (databasePath) => {
|
|
|
46
43
|
return resolve(databasePath);
|
|
47
44
|
};
|
|
48
45
|
|
|
46
|
+
export const isIdEqual = (left, right) => left != null && right != null && String(left) === String(right);
|
|
49
47
|
export const singularize = (value) => pluralize.singular(value);
|
|
50
48
|
|
|
51
|
-
export const toPascalCase = (value) =>
|
|
49
|
+
export const toPascalCase = (value) =>
|
|
50
|
+
value
|
|
51
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
|
54
|
+
.join('');
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const validateDatabase: (data: any) => any;
|
|
2
|
+
export declare const readJsonObject: (path: any, label: any) => Promise<any>;
|
|
3
|
+
export declare const readDatabaseFile: (databasePath: any) => Promise<any>;
|
|
4
|
+
/** @returns {Promise<any>} Internal LowDB-backed store. */
|
|
5
|
+
export declare const createDatabaseStore: (databasePath: any) => Promise<any>;
|
|
6
|
+
export declare const getCollection: (database: any, resource: any) => any[];
|
|
7
|
+
export declare const findItem: (collection: any, id: any) => any;
|
|
8
|
+
export declare const createId: (collection: any) => any;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates an OpenAPI 3.0 document from a database and optional schema configuration.
|
|
3
|
+
* @param {Record<string, Array<Record<string, unknown>>>} database Database contents.
|
|
4
|
+
* @param {Record<string, unknown>} [schemaConfig] Schema configuration.
|
|
5
|
+
* @param {{ host?: string, port?: number }} [serverOptions] Server address used in the generated document.
|
|
6
|
+
* @returns {Record<string, unknown>} OpenAPI document.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createOpenApiDocument(database: Record<string, Array<Record<string, unknown>>>, schemaConfig?: Record<string, unknown>, { host, port }?: {
|
|
9
|
+
host?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
}): Record<string, unknown>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { createOpenApiDocument } from './document.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates an OpenAPI YAML file.
|
|
4
|
+
* @param {{ databasePath: string, host?: string, outputPath: string, port?: number, schemaPath: string }} options Generation options.
|
|
5
|
+
* @returns {Promise<Record<string, unknown>>} Generated OpenAPI document.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateOpenApi({ databasePath, host, outputPath, port, schemaPath }: {
|
|
8
|
+
databasePath: string;
|
|
9
|
+
host?: string;
|
|
10
|
+
outputPath: string;
|
|
11
|
+
port?: number;
|
|
12
|
+
schemaPath: string;
|
|
13
|
+
}): Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const mergeSchemas: (schemas: any) => any;
|
|
2
|
+
export declare const mergeSchemaOverrides: (schema: any, overrides: any) => any;
|
|
3
|
+
export declare const applyRequiredFields: (schema: any, path: any, requiredFields: any) => any;
|
|
4
|
+
export declare const inferSchema: (values: any) => any;
|
|
5
|
+
export declare function inferObjectSchema(values: any): any;
|
|
6
|
+
export declare const ensureGeneratedIdSchema: (schema: any) => any;
|
|
7
|
+
export declare const getSchemasAtPath: (schema: any, keys: any) => any;
|
|
8
|
+
export declare const updateSchemasAtPath: (schema: any, keys: any, update: any) => any;
|
|
9
|
+
export declare const omitId: (schema: any, keepRequired: any) => any;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const parsePagination: (query: any, maxPageSize?: number) => {
|
|
2
|
+
page: any;
|
|
3
|
+
pageSize: any;
|
|
4
|
+
};
|
|
5
|
+
export declare const paginateItems: (items: any, page: any, pageSize: any) => {
|
|
6
|
+
data: any;
|
|
7
|
+
first: number;
|
|
8
|
+
items: any;
|
|
9
|
+
last: number;
|
|
10
|
+
next: any;
|
|
11
|
+
pages: number;
|
|
12
|
+
prev: number | null;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sortItems: (items: any, sort: any, validationItems?: any) => any[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const getRelationKeys: (...names: any[]) => string[];
|
|
2
|
+
export declare const resolveRelationResource: (resourceNames: any, relation: any, sourceResource: any) => any;
|
|
3
|
+
export declare const getRelationMetadata: (key: any, resourceNames: any, sourceResource: any) => {
|
|
4
|
+
isMany: boolean;
|
|
5
|
+
relationName: any;
|
|
6
|
+
reverseRelationName: any;
|
|
7
|
+
sourceResource: any;
|
|
8
|
+
targetResource: any;
|
|
9
|
+
} | undefined;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const parseEmbedPaths: (embed: any) => any[];
|
|
2
|
+
export declare const validateEmbedPaths: (database: any, resource: any, items: any, embedPaths: any) => void;
|
|
3
|
+
export declare const embedItem: (database: any, item: any, resource: any, embedPaths: any, indexes?: Map<any, any>) => any;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a Fastify server without opening a network port.
|
|
3
|
+
* @param {{ databasePath: string, logger?: boolean | Record<string, unknown>, maxPageSize?: number, schemaPath?: string }} options Server options.
|
|
4
|
+
* @returns {Promise<import('fastify').FastifyInstance>} Fastify server.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createServer(options: {
|
|
7
|
+
databasePath: string;
|
|
8
|
+
logger?: boolean | Record<string, unknown>;
|
|
9
|
+
maxPageSize?: number;
|
|
10
|
+
schemaPath?: string;
|
|
11
|
+
}): Promise<import('fastify').FastifyInstance>;
|
|
12
|
+
/**
|
|
13
|
+
* Creates and starts a Fastify server.
|
|
14
|
+
* @param {{ databasePath: string, host?: string, logger?: boolean | Record<string, unknown>, maxPageSize?: number, port?: number, schemaPath?: string }} options Server options.
|
|
15
|
+
* @returns {Promise<import('fastify').FastifyInstance>} Listening Fastify server.
|
|
16
|
+
*/
|
|
17
|
+
export declare function startServer(options: {
|
|
18
|
+
databasePath: string;
|
|
19
|
+
host?: string;
|
|
20
|
+
logger?: boolean | Record<string, unknown>;
|
|
21
|
+
maxPageSize?: number;
|
|
22
|
+
port?: number;
|
|
23
|
+
schemaPath?: string;
|
|
24
|
+
}): Promise<import('fastify').FastifyInstance>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const createHttpError: (statusCode: any, message: any) => Error;
|
|
2
|
+
export declare const getResourceNames: (data: any) => string[];
|
|
3
|
+
export declare const isObject: (value: any) => boolean;
|
|
4
|
+
export declare const isSafeKey: (key: any) => boolean;
|
|
5
|
+
export declare const toArray: (value: any) => any[];
|
|
6
|
+
export declare const isEqual: (left: any, right: any) => any;
|
|
7
|
+
export declare const resolveDatabasePath: (databasePath: any) => any;
|
|
8
|
+
export declare const isIdEqual: (left: any, right: any) => boolean;
|
|
9
|
+
export declare const singularize: (value: any) => any;
|
|
10
|
+
export declare const toPascalCase: (value: any) => any;
|