@kollors/deep-json-server 0.3.2 → 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 -100
- package/src/utils.js +7 -18
- 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 -520
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,97 +21,66 @@ const getRequestBody = (body) => {
|
|
|
30
21
|
return body;
|
|
31
22
|
};
|
|
32
23
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const readDatabaseFile = async(databasePath) => {
|
|
36
|
-
let source;
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
source = await readFile(databasePath, 'utf8');
|
|
40
|
-
} catch (error) {
|
|
41
|
-
if (error?.code === 'ENOENT') {
|
|
42
|
-
throw new Error(`Файл базы данных не найден: ${databasePath}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
throw error;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const data = JSON.parse(source);
|
|
49
|
-
|
|
50
|
-
return validateDatabase(data);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export async function createServer({ databasePath, logger = true } = {}) {
|
|
54
|
-
const resolvedDatabasePath = resolveDatabasePath(databasePath);
|
|
55
|
-
const initialData = await readDatabaseFile(resolvedDatabasePath);
|
|
56
|
-
const database = await JSONFilePreset(resolvedDatabasePath, initialData);
|
|
57
|
-
const server = Fastify({ logger });
|
|
58
|
-
let databaseWriteQueue = Promise.resolve();
|
|
59
|
-
|
|
60
|
-
const readDatabase = async() => {
|
|
61
|
-
database.data = await readDatabaseFile(resolvedDatabasePath);
|
|
62
|
-
};
|
|
24
|
+
const getSchemaName = (reference) => reference.split('/').at(-1);
|
|
63
25
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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}`];
|
|
67
31
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return result;
|
|
73
|
-
});
|
|
32
|
+
return [getSchemaName(resourcePath.post.requestBody.content['application/json'].schema.$ref), getSchemaName(itemPath.patch.requestBody.content['application/json'].schema.$ref)];
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
74
35
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return operation;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
server.addHook('onRequest', async(_request, reply) => {
|
|
81
|
-
Object.entries(CORS_HEADERS).forEach(([header, value]) => reply.header(header, value));
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
server.addHook('preHandler', async(request) => {
|
|
85
|
-
if (request.method === 'GET') {
|
|
86
|
-
await readDatabase();
|
|
87
|
-
}
|
|
36
|
+
requestSchemaNames.forEach((schemaName) => {
|
|
37
|
+
server.addSchema({ $id: schemaName, ...document.components.schemas[schemaName] });
|
|
88
38
|
});
|
|
39
|
+
};
|
|
89
40
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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);
|
|
93
46
|
|
|
94
|
-
server.get(
|
|
95
|
-
const collection = getCollection(database,
|
|
47
|
+
server.get(resourcePath, async (request) => {
|
|
48
|
+
const collection = getCollection(store.database, resource);
|
|
96
49
|
const where = parseWhere(request.query);
|
|
97
50
|
const embedPaths = parseEmbedPaths(request.query._embed);
|
|
51
|
+
const pagination = parsePagination(request.query, maxPageSize);
|
|
52
|
+
|
|
53
|
+
validateEmbedPaths(store.database, resource, collection, embedPaths);
|
|
54
|
+
|
|
98
55
|
const relationIndexes = new Map();
|
|
99
|
-
const embeddedItems = collection.map((item) => embedItem(database, item,
|
|
100
|
-
const pagination = parsePagination(request.query);
|
|
56
|
+
const embeddedItems = collection.map((item) => embedItem(store.database, item, resource, embedPaths, relationIndexes));
|
|
101
57
|
|
|
102
58
|
validateWhere(where, embeddedItems);
|
|
103
59
|
|
|
104
60
|
const filteredItems = embeddedItems.filter((item) => matchesWhere(item, where));
|
|
105
|
-
const sortedItems = sortItems(filteredItems, request.query._sort);
|
|
61
|
+
const sortedItems = sortItems(filteredItems, request.query._sort, embeddedItems);
|
|
106
62
|
|
|
107
63
|
return paginateItems(sortedItems, pagination.page, pagination.pageSize);
|
|
108
64
|
});
|
|
109
65
|
|
|
110
|
-
server.get(
|
|
111
|
-
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);
|
|
112
70
|
|
|
113
71
|
if (item == null) {
|
|
114
72
|
throw createHttpError(404, 'Запись не найдена');
|
|
115
73
|
}
|
|
116
74
|
|
|
117
|
-
|
|
75
|
+
validateEmbedPaths(store.database, resource, collection, embedPaths);
|
|
76
|
+
|
|
77
|
+
return embedItem(store.database, item, resource, embedPaths);
|
|
118
78
|
});
|
|
119
79
|
|
|
120
|
-
server.post(
|
|
121
|
-
const item = await
|
|
122
|
-
const collection = getCollection(database,
|
|
123
|
-
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) };
|
|
124
84
|
|
|
125
85
|
collection.push(createdItem);
|
|
126
86
|
|
|
@@ -130,9 +90,9 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
130
90
|
return reply.code(201).send(item);
|
|
131
91
|
});
|
|
132
92
|
|
|
133
|
-
server.put(
|
|
134
|
-
|
|
135
|
-
const collection = getCollection(database,
|
|
93
|
+
server.put(itemPath, { schema: { body: { $ref: `${createSchemaName}#` } } }, async (request) =>
|
|
94
|
+
store.update((database) => {
|
|
95
|
+
const collection = getCollection(database, resource);
|
|
136
96
|
const currentItem = findItem(collection, request.params.id);
|
|
137
97
|
|
|
138
98
|
if (currentItem == null) {
|
|
@@ -144,12 +104,12 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
144
104
|
collection.splice(collection.indexOf(currentItem), 1, item);
|
|
145
105
|
|
|
146
106
|
return item;
|
|
147
|
-
})
|
|
148
|
-
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
149
109
|
|
|
150
|
-
server.patch(
|
|
151
|
-
|
|
152
|
-
const collection = getCollection(database,
|
|
110
|
+
server.patch(itemPath, { schema: { body: { $ref: `${updateSchemaName}#` } } }, async (request) =>
|
|
111
|
+
store.update((database) => {
|
|
112
|
+
const collection = getCollection(database, resource);
|
|
153
113
|
const currentItem = findItem(collection, request.params.id);
|
|
154
114
|
|
|
155
115
|
if (currentItem == null) {
|
|
@@ -161,12 +121,12 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
161
121
|
collection.splice(collection.indexOf(currentItem), 1, item);
|
|
162
122
|
|
|
163
123
|
return item;
|
|
164
|
-
})
|
|
165
|
-
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
166
126
|
|
|
167
|
-
server.delete(
|
|
168
|
-
|
|
169
|
-
const collection = getCollection(database,
|
|
127
|
+
server.delete(itemPath, async (request) =>
|
|
128
|
+
store.update((database) => {
|
|
129
|
+
const collection = getCollection(database, resource);
|
|
170
130
|
const currentItem = findItem(collection, request.params.id);
|
|
171
131
|
|
|
172
132
|
if (currentItem == null) {
|
|
@@ -176,9 +136,50 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
176
136
|
collection.splice(collection.indexOf(currentItem), 1);
|
|
177
137
|
|
|
178
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);
|
|
179
166
|
});
|
|
180
167
|
});
|
|
181
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
|
+
|
|
182
183
|
server.setErrorHandler((error, request, reply) => {
|
|
183
184
|
const statusCode = Number.isInteger(error.statusCode) ? error.statusCode : 500;
|
|
184
185
|
|
|
@@ -192,13 +193,20 @@ export async function createServer({ databasePath, logger = true } = {}) {
|
|
|
192
193
|
return server;
|
|
193
194
|
}
|
|
194
195
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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');
|
|
198
206
|
}
|
|
199
207
|
|
|
200
208
|
const resolvedDatabasePath = resolveDatabasePath(databasePath);
|
|
201
|
-
const server = await createServer({ databasePath: resolvedDatabasePath, logger });
|
|
209
|
+
const server = await createServer({ databasePath: resolvedDatabasePath, logger, maxPageSize, schemaPath });
|
|
202
210
|
|
|
203
211
|
await server.listen({ host, port });
|
|
204
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']);
|
|
@@ -14,25 +12,10 @@ export const createHttpError = (statusCode, message) => {
|
|
|
14
12
|
};
|
|
15
13
|
|
|
16
14
|
export const getResourceNames = (data) => Object.keys(data);
|
|
17
|
-
export const isMainModule = (filePath, moduleUrl) => filePath != null && realpathSync(resolve(filePath)) === fileURLToPath(moduleUrl);
|
|
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]);
|
|
21
18
|
|
|
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
|
-
|
|
36
19
|
export const isEqual = (left, right) => {
|
|
37
20
|
if (Object.is(left, right)) {
|
|
38
21
|
return true;
|
|
@@ -60,6 +43,12 @@ export const resolveDatabasePath = (databasePath) => {
|
|
|
60
43
|
return resolve(databasePath);
|
|
61
44
|
};
|
|
62
45
|
|
|
46
|
+
export const isIdEqual = (left, right) => left != null && right != null && String(left) === String(right);
|
|
63
47
|
export const singularize = (value) => pluralize.singular(value);
|
|
64
48
|
|
|
65
|
-
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;
|