New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mock-config-server

Package Overview
Dependencies
Maintainers
0
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mock-config-server - npm Package Compare versions

Comparing version 3.7.1 to 4.0.0

dist/bin/runFlatConfig.d.ts

2

dist/bin/bin.js

@@ -6,3 +6,3 @@ #!/usr/bin/env node

});
const pleaseUpgradeNode = require('please-upgrade-node');
/* eslint-disable ts/no-require-imports */ const pleaseUpgradeNode = require('please-upgrade-node');
const packageJson = require('../../package.json');

@@ -9,0 +9,0 @@ pleaseUpgradeNode(packageJson);

import type { MockServerConfigArgv } from '../src/utils/types';
export declare const build: (argv: MockServerConfigArgv) => Promise<void>;
export declare const build: (argv: MockServerConfigArgv) => Promise<(import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> & {
destroy: import("http").Server["close"];
}) | undefined>;

@@ -14,2 +14,3 @@ "use strict";

const _run = require("./run");
const _runFlatConfig = require("./runFlatConfig");
const build = async (argv)=>{

@@ -45,2 +46,7 @@ const configFilePath = (0, _helpers.resolveConfigFilePath)(argv.config);

const mockConfig = (0, _helpers.resolveConfigFile)(result.outputFiles[0].text);
const isFlatConfig = Array.isArray(mockConfig);
if (isFlatConfig) {
instance = (0, _runFlatConfig.runFlatConfig)(mockConfig, argv);
return;
}
instance = (0, _run.run)(mockConfig, argv);

@@ -58,3 +64,7 @@ }

const mockConfig = (0, _helpers.resolveConfigFile)(outputFiles[0].text);
const isFlatConfig = Array.isArray(mockConfig);
if (isFlatConfig) {
return (0, _runFlatConfig.runFlatConfig)(mockConfig, argv);
}
(0, _run.run)(mockConfig, argv);
};
interface CreateTemplateOptions {
withTypescript: boolean;
apiType: 'full' | 'graphql' | 'rest';
baseUrl: string;
port: number;
staticPath: string;
port: number;
apiType: 'rest' | 'graphql' | 'full';
withTypescript: boolean;
}
export declare const createTemplate: (options: CreateTemplateOptions) => void;
export {};

@@ -28,3 +28,3 @@ "use strict";

if (options.staticPath !== '/') {
mockServerConfig = mockServerConfig.replace(`port: ${_constants.DEFAULT.PORT}`, `port: ${_constants.DEFAULT.PORT},\n staticPath: '${options.staticPath}'`);
mockServerConfig = mockServerConfig.replace(`port: ${_constants.DEFAULT.PORT}`, `port: ${_constants.DEFAULT.PORT},\n\u0020\u0020\u0020\u0020staticPath: '${options.staticPath}'`);
}

@@ -31,0 +31,0 @@ mockServerConfig = mockServerConfig.replace(`port: ${_constants.DEFAULT.PORT}`, `port: ${options.port.toString()}`);

export * from './createTemplate';
export * from './getMostSpecificPathFromError';
export * from './getValidationMessageFromPath';
export * from './isOnlyRequestedDataResolvingPropertyExists';
export * from './resolveConfigFile';
export * from './resolveConfigFilePath';
export * from './resolveExportsFromSourceCode';

@@ -6,5 +6,2 @@ "use strict";

_export_star(require("./createTemplate"), exports);
_export_star(require("./getMostSpecificPathFromError"), exports);
_export_star(require("./getValidationMessageFromPath"), exports);
_export_star(require("./isOnlyRequestedDataResolvingPropertyExists"), exports);
_export_star(require("./resolveConfigFile"), exports);

@@ -11,0 +8,0 @@ _export_star(require("./resolveConfigFilePath"), exports);

@@ -1,2 +0,2 @@

import type { MockServerConfig } from '../../src/utils/types';
export declare const resolveConfigFile: (configSourceCode: string) => MockServerConfig;
import type { FlatMockServerConfig, MockServerConfig } from '../../src/utils/types';
export declare const resolveConfigFile: (configSourceCode: string) => FlatMockServerConfig | MockServerConfig;

@@ -22,6 +22,6 @@ "use strict";

}
if (!(0, _helpers.isPlainObject)(mockServerConfig)) {
throw new Error('configuration should be plain object; see our doc (https://www.npmjs.com/package/mock-config-server) for more information');
if (!(0, _helpers.isPlainObject)(mockServerConfig) && !Array.isArray(mockServerConfig)) {
throw new Error('configuration should be plain object or array; see our doc (https://www.npmjs.com/package/mock-config-server) for more information');
}
return mockServerConfig;
};

@@ -11,4 +11,4 @@ "use strict";

});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
function _interop_require_default(obj) {

@@ -21,5 +21,5 @@ return obj && obj.__esModule ? obj : {

const appPath = process.cwd();
if (cliConfigFilePath) return _path.default.resolve(appPath, cliConfigFilePath);
if (cliConfigFilePath) return _nodepath.default.resolve(appPath, cliConfigFilePath);
const configFileNameRegex = /mock-server.config.(?:ts|mts|cts|js|mjs|cjs)/;
return _fs.default.readdirSync(appPath).find((fileName)=>configFileNameRegex.test(fileName));
return _nodefs.default.readdirSync(appPath).find((fileName)=>configFileNameRegex.test(fileName));
};

@@ -12,7 +12,6 @@ "use strict";

const resolveExportsFromSourceCode = (sourceCode)=>{
// @ts-ignore
// @ts-expect-error: module is constructed
const moduleInstance = new module.constructor();
// eslint-disable-next-line no-underscore-dangle
moduleInstance._compile(sourceCode, '');
return moduleInstance.exports;
};

@@ -13,5 +13,3 @@ "use strict";

const _prompts = /*#__PURE__*/ _interop_require_default(require("prompts"));
const _baseUrlSchema = require("./validateMockServerConfig/baseUrlSchema/baseUrlSchema");
const _portSchema = require("./validateMockServerConfig/portSchema/portSchema");
const _staticPathSchema = require("./validateMockServerConfig/staticPathSchema/staticPathSchema");
const _validate = require("../src/utils/validate");
const _helpers = require("./helpers");

@@ -64,3 +62,3 @@ function _interop_require_default(obj) {

try {
_baseUrlSchema.baseUrlSchema.parse(baseUrl);
_validate.baseUrlSchema.parse(baseUrl);
return true;

@@ -79,5 +77,5 @@ } catch {

try {
_portSchema.portSchema.parse(+port);
_validate.portSchema.parse(+port);
return true;
} catch (error) {
} catch {
return 'Invalid port value';

@@ -94,3 +92,3 @@ }

try {
_staticPathSchema.staticPathSchema.parse(staticPath);
_validate.staticPathSchema.parse(staticPath);
return true;

@@ -113,3 +111,2 @@ } catch {

const userAgent = (_process_env_npm_config_user_agent = process.env.npm_config_user_agent) !== null && _process_env_npm_config_user_agent !== void 0 ? _process_env_npm_config_user_agent : '';
// eslint-disable-next-line no-nested-ternary
const packageManager = /pnpm/.test(userAgent) ? 'pnpm' : /yarn/.test(userAgent) ? 'yarn' : 'npx';

@@ -116,0 +113,0 @@ console.log('\n');

#!/usr/bin/env node
/// <reference types="node" />
import type { MockServerConfig, MockServerConfigArgv } from '../src';
export declare const run: (mockConfig: MockServerConfig, { baseUrl, port, staticPath }: MockServerConfigArgv) => (import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> & {
destroy: (callback?: ((err?: Error | undefined) => void) | undefined) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
destroy: import("http").Server["close"];
}) | undefined;

@@ -14,5 +14,4 @@ #!/usr/bin/env node

const _helpers = require("../src/utils/helpers");
const _validateApiMockServerConfig = require("./validateMockServerConfig/validateApiMockServerConfig");
const _validateMockServerConfig = require("./validateMockServerConfig/validateMockServerConfig");
const run = (mockConfig, { baseUrl, port, staticPath })=>{
console.warn(`**DEPRECATION WARNING**\nThe old mock config format is deprecated and will be removed in the next major version. Please use new format of config (flat config); see our doc (https://github.com/siberiacancode/mock-config-server) for more information`);
try {

@@ -34,13 +33,9 @@ const mergedMockServerConfig = {

if (Array.isArray(mergedApiMockServerConfig.configs) && (0, _helpers.isPlainObject)(mergedApiMockServerConfig.configs[0]) && 'path' in mergedApiMockServerConfig.configs[0]) {
(0, _validateApiMockServerConfig.validateApiMockServerConfig)(mergedApiMockServerConfig, 'rest');
return (0, _server.startRestMockServer)(mergedApiMockServerConfig);
}
if (Array.isArray(mergedApiMockServerConfig.configs) && (0, _helpers.isPlainObject)(mergedApiMockServerConfig.configs[0]) && ('query' in mergedApiMockServerConfig.configs[0] || 'operationName' in mergedApiMockServerConfig.configs[0])) {
(0, _validateApiMockServerConfig.validateApiMockServerConfig)(mergedApiMockServerConfig, 'graphql');
return (0, _server.startGraphQLMockServer)(mergedApiMockServerConfig);
}
(0, _validateApiMockServerConfig.validateApiMockServerConfig)(mergedApiMockServerConfig, 'rest');
return (0, _server.startRestMockServer)(mergedApiMockServerConfig);
}
(0, _validateMockServerConfig.validateMockServerConfig)(mergedMockServerConfig);
return (0, _server.startMockServer)(mergedMockServerConfig);

@@ -47,0 +42,0 @@ } catch (error) {

import { createUserMutation, getUserQuery, getUsersQuery } from './mock-requests/graphql';
import { getUserRequest, getUsersRequest, postUserRequest } from './mock-requests/rest';
const mockServerConfig = {
port: 31299,
baseUrl: '/',
rest: {
const mockServerConfig = [
{
port: 31299,
baseUrl: '/'
},
{
name: 'rest',
configs: [getUserRequest, getUsersRequest, postUserRequest]
},
graphql: {
baseUrl: '/graphql',
{
name: 'graphql',
configs: [getUserQuery, getUsersQuery, createUserMutation]
}
};
];
export default mockServerConfig;
import { createUserMutation, getUserQuery, getUsersQuery } from './mock-requests';
const restMockServerConfig = {
port: 31299,
baseUrl: '/',
configs: [getUserQuery, getUsersQuery, createUserMutation]
};
const mockServerConfig = [
{
port: 31299,
baseUrl: '/graphql'
},
{
name: 'graphql',
configs: [getUserQuery, getUsersQuery, createUserMutation]
}
];
export default restMockServerConfig;
export default mockServerConfig;
import { getUserRequest, getUsersRequest, postUserRequest } from './mock-requests';
const restMockServerConfig = {
port: 31299,
baseUrl: '/',
configs: [getUserRequest, getUsersRequest, postUserRequest]
};
const mockServerConfig = [
{
port: 31299,
baseUrl: '/'
},
{
name: 'rest',
configs: [getUserRequest, getUsersRequest, postUserRequest]
}
];
export default restMockServerConfig;
export default mockServerConfig;

@@ -1,2 +0,2 @@

import type { MockServerConfig } from 'mock-config-server';
import type { FlatMockServerConfig } from 'mock-config-server';

@@ -6,14 +6,17 @@ import { createUserMutation, getUserQuery, getUsersQuery } from './mock-requests/graphql';

const mockServerConfig: MockServerConfig = {
port: 31299,
baseUrl: '/',
rest: {
const mockServerConfig: FlatMockServerConfig = [
{
port: 31299,
baseUrl: '/'
},
{
name: 'rest',
configs: [getUserRequest, getUsersRequest, postUserRequest]
},
graphql: {
baseUrl: '/graphql',
{
name: 'graphql',
configs: [getUserQuery, getUsersQuery, createUserMutation]
}
};
];
export default mockServerConfig;

@@ -1,11 +0,16 @@

import type { GraphQLMockServerConfig } from 'mock-config-server';
import type { FlatMockServerConfig } from 'mock-config-server';
import { createUserMutation, getUserQuery, getUsersQuery } from './mock-requests';
const restMockServerConfig: GraphQLMockServerConfig = {
port: 31299,
baseUrl: '/',
configs: [getUserQuery, getUsersQuery, createUserMutation]
};
const mockServerConfig: FlatMockServerConfig = [
{
port: 31299,
baseUrl: '/graphql'
},
{
name: 'graphql',
configs: [getUserQuery, getUsersQuery, createUserMutation]
}
];
export default restMockServerConfig;
export default mockServerConfig;

@@ -1,11 +0,16 @@

import type { RestMockServerConfig } from 'mock-config-server';
import type { FlatMockServerConfig } from 'mock-config-server';
import { getUserRequest, getUsersRequest, postUserRequest } from './mock-requests';
const restMockServerConfig: RestMockServerConfig = {
port: 31299,
baseUrl: '/',
configs: [getUserRequest, getUsersRequest, postUserRequest]
};
const mockServerConfig: FlatMockServerConfig = [
{
port: 31299,
baseUrl: '/'
},
{
name: 'rest',
configs: [getUserRequest, getUsersRequest, postUserRequest]
}
];
export default restMockServerConfig;
export default mockServerConfig;

@@ -11,2 +11,3 @@ "use strict";

});
const _createStorage = require("../createStorage/createStorage");
const _helpers = require("./helpers");

@@ -17,3 +18,3 @@ const _storages = require("./storages");

if (routes) {
const storage = isVariableJsonFile(routes) ? new _storages.FileStorage(routes) : new _storages.MemoryStorage(routes);
const storage = (0, _createStorage.createStorage)(routes);
(0, _helpers.createRewrittenDatabaseRoutes)(router, storage.read());

@@ -20,0 +21,0 @@ router.route('/__routes').get((_request, response)=>{

@@ -90,8 +90,7 @@ "use strict";

});
router.route(itemPath).get((request, response)=>{
router.route(itemPath).get((request, response, next)=>{
const currentResourceCollection = storage.read(key);
const currentResourceIndex = (0, _array.findIndexById)(currentResourceCollection, request.params.id);
if (currentResourceIndex === -1) {
response.status(404).end();
return;
return next();
}

@@ -107,8 +106,7 @@ // ✅ important:

});
router.route(itemPath).put((request, response)=>{
router.route(itemPath).put((request, response, next)=>{
const currentResourceCollection = storage.read(key);
const currentResourceIndex = (0, _array.findIndexById)(currentResourceCollection, request.params.id);
if (currentResourceIndex === -1) {
response.status(404).end();
return;
return next();
}

@@ -129,8 +127,7 @@ const currentResource = storage.read([

});
router.route(itemPath).patch((request, response)=>{
router.route(itemPath).patch((request, response, next)=>{
const currentResourceCollection = storage.read(key);
const currentResourceIndex = (0, _array.findIndexById)(currentResourceCollection, request.params.id);
if (currentResourceIndex === -1) {
response.status(404).end();
return;
return next();
}

@@ -152,8 +149,7 @@ const currentResource = storage.read([

});
router.route(itemPath).delete((request, response)=>{
router.route(itemPath).delete((request, response, next)=>{
const currentResourceCollection = storage.read(key);
const currentResourceIndex = (0, _array.findIndexById)(currentResourceCollection, request.params.id);
if (currentResourceIndex === -1) {
response.status(404).end();
return;
return next();
}

@@ -160,0 +156,0 @@ storage.delete([

@@ -1,3 +0,2 @@

/// <reference types="node" />
import type { ParsedUrlQuery } from 'node:querystring';
export declare const filter: (array: any[], filters: ParsedUrlQuery) => any[];

@@ -1,2 +0,1 @@

/// <reference types="node" />
import type { ParsedUrlQuery } from 'node:querystring';

@@ -3,0 +2,0 @@ export declare const pagination: (array: any[], queries: ParsedUrlQuery) => any[] | {

@@ -1,4 +0,3 @@

/// <reference types="node" />
import type { ParsedUrlQuery } from 'node:querystring';
export declare const searchInNestedObjects: (obj: any, searchText: string) => boolean;
export declare const search: (array: any[], searchText: ParsedUrlQuery) => any[];

@@ -1,3 +0,2 @@

/// <reference types="node" />
import type { ParsedUrlQuery } from 'node:querystring';
export declare const sort: (array: any[], queries: ParsedUrlQuery) => any[];
import type { DatabaseConfig, NestedDatabase, ShallowDatabase } from '../../../../../utils/types';
export declare const splitDatabaseByNesting: (data: DatabaseConfig['data']) => {
export declare const splitDatabaseByNesting: (data: DatabaseConfig["data"]) => {
shallowDatabase: ShallowDatabase;
nestedDatabase: NestedDatabase;
};

@@ -1,10 +0,9 @@

type Index = string | number;
export declare class FileStorage<T extends Record<Index, any> = Record<Index, any>> {
import type { Storage, StorageIndex } from '../../../../../utils/types';
export declare class FileStorage<Data extends Record<StorageIndex, any> = Record<StorageIndex, any>> implements Storage {
private readonly fileWriter;
private readonly data;
constructor(fileName: string);
read(key?: Index | Index[]): any;
write(key: Index | Index[], value: unknown): void;
delete(key: Index | Index[]): void;
read(key?: StorageIndex | StorageIndex[]): any;
write(key: StorageIndex | StorageIndex[], value: unknown): void;
delete(key: StorageIndex | StorageIndex[]): void;
}
export {};

@@ -11,4 +11,4 @@ "use strict";

});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
const _constants = require("../../../../../utils/constants");

@@ -26,5 +26,5 @@ const _helpers = require("../../helpers");

constructor(fileName){
const filePath = _path.default.resolve(_constants.APP_PATH, fileName);
const filePath = _nodepath.default.resolve(_constants.APP_PATH, fileName);
this.fileWriter = new _FileWriter.FileWriter(filePath);
this.data = JSON.parse(_fs.default.readFileSync(filePath, 'utf-8'));
this.data = JSON.parse(_nodefs.default.readFileSync(filePath, 'utf-8'));
}

@@ -31,0 +31,0 @@ read(key) {

@@ -11,3 +11,3 @@ "use strict";

});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
function _interop_require_default(obj) {

@@ -42,3 +42,3 @@ return obj && obj.__esModule ? obj : {

this.writeIsLocked = true;
await _fs.default.promises.writeFile(this.filePath, data, 'utf-8');
await _nodefs.default.promises.writeFile(this.filePath, data, 'utf-8');
this.writeIsLocked = false;

@@ -45,0 +45,0 @@ // ✅ important:

@@ -1,9 +0,8 @@

type Index = string | number;
export declare class MemoryStorage<T extends Record<Index, any> = Record<Index, any>> {
import type { Storage, StorageIndex } from '../../../../../utils/types';
export declare class MemoryStorage<Data extends Record<StorageIndex, any> = Record<StorageIndex, any>> implements Storage {
private readonly data;
constructor(initialData: T);
read(key?: Index | Index[]): any;
write(key: Index | Index[], value: unknown): void;
delete(key: Index | Index[]): void;
constructor(initialData: Data);
read(key?: StorageIndex | StorageIndex[]): any;
write(key: StorageIndex | StorageIndex[], value: unknown): void;
delete(key: StorageIndex | StorageIndex[]): void;
}
export {};
export * from './createDatabaseRoutes/createDatabaseRoutes';
export * from './createOrm/createOrm';
export * from './createStorage/createStorage';

@@ -6,2 +6,4 @@ "use strict";

_export_star(require("./createDatabaseRoutes/createDatabaseRoutes"), exports);
_export_star(require("./createOrm/createOrm"), exports);
_export_star(require("./createStorage/createStorage"), exports);
function _export_star(from, to) {

@@ -8,0 +10,0 @@ Object.keys(from).forEach(function(k) {

import type { IRouter } from 'express';
import type { GraphqlConfig, Interceptors } from '../../../utils/types';
interface CreateGraphQLRoutesParams {
graphqlConfig: GraphqlConfig;
router: IRouter;
graphqlConfig: GraphqlConfig;
serverResponseInterceptor?: Interceptors<'graphql'>['response'];

@@ -7,0 +7,0 @@ }

@@ -33,7 +33,6 @@ "use strict";

if (requestConfig.operationType !== query.operationType) return false;
if ('query' in requestConfig && requestConfig.query.replace(/\s+/gi, ' ') !== ((_graphQLInput_query = graphQLInput.query) === null || _graphQLInput_query === void 0 ? void 0 : _graphQLInput_query.replace(/\s+/gi, ' '))) return false;
if ('query' in requestConfig && requestConfig.query.replace(/\s+/g, '') !== ((_graphQLInput_query = graphQLInput.query) === null || _graphQLInput_query === void 0 ? void 0 : _graphQLInput_query.replace(/\s+/g, ''))) return false;
if ('operationName' in requestConfig) {
if (!query.operationName) return false;
if (requestConfig.operationName instanceof RegExp) return new RegExp(requestConfig.operationName).test(query.operationName);
return requestConfig.operationName === query.operationName;
return requestConfig.operationName instanceof RegExp ? new RegExp(requestConfig.operationName).test(query.operationName) : requestConfig.operationName === query.operationName;
}

@@ -53,20 +52,43 @@ return true;

if (!entities) return true;
const entries = Object.entries(entities);
return entries.every(([entityName, entityDescriptorOrValue])=>{
const { checkMode, value: entityDescriptorValue } = (0, _helpers.convertToEntityDescriptor)(entityDescriptorOrValue);
// ✅ important: check whole variables as plain value strictly if descriptor used for variables
const entityEntries = Object.entries(entities);
return entityEntries.every(([entityName, entityDescriptorOrValue])=>{
// ✅ important:
// check whole variables as plain value strictly if descriptor used for variables
const isEntityVariablesByTopLevelDescriptor = entityName === 'variables' && (0, _helpers.isEntityDescriptor)(entityDescriptorOrValue);
if (isEntityVariablesByTopLevelDescriptor) {
return (0, _helpers.resolveEntityValues)(checkMode, graphQLInput.variables, entityDescriptorValue);
const variablesDescriptor = entityDescriptorOrValue;
if (variablesDescriptor.checkMode === 'exists' || variablesDescriptor.checkMode === 'notExists') {
return (0, _helpers.resolveEntityValues)({
actualValue: graphQLInput.variables,
checkMode: variablesDescriptor.checkMode
});
}
var _variablesDescriptor_oneOf;
return (0, _helpers.resolveEntityValues)({
actualValue: graphQLInput.variables,
descriptorValue: variablesDescriptor.value,
checkMode: variablesDescriptor.checkMode,
oneOf: (_variablesDescriptor_oneOf = variablesDescriptor.oneOf) !== null && _variablesDescriptor_oneOf !== void 0 ? _variablesDescriptor_oneOf : false
});
}
const isEntityVariablesByTopLevelArray = entityName === 'variables' && Array.isArray(entityDescriptorOrValue);
if (isEntityVariablesByTopLevelArray) {
return entityDescriptorOrValue.some((entityDescriptorOrValueElement)=>(0, _helpers.resolveEntityValues)(checkMode, graphQLInput.variables, entityDescriptorOrValueElement));
}
const recordOrArrayEntries = Object.entries(entityDescriptorOrValue);
return recordOrArrayEntries.every(([entityKey, entityValue])=>{
const { checkMode, value: descriptorValue } = (0, _helpers.convertToEntityDescriptor)(entityValue);
const flattenEntity = (0, _flat.flatten)(entityName === 'variables' ? graphQLInput.variables : request[entityName]);
const actualEntity = (0, _flat.flatten)(entityName === 'variables' ? graphQLInput.variables : request[entityName]);
const entityValueEntries = Object.entries(entityDescriptorOrValue);
return entityValueEntries.every(([entityPropertyKey, entityPropertyDescriptorOrValue])=>{
const entityPropertyDescriptor = (0, _helpers.convertToEntityDescriptor)(entityPropertyDescriptorOrValue);
// ✅ important: transform header keys to lower case because browsers send headers in lowercase
return (0, _helpers.resolveEntityValues)(checkMode, flattenEntity[entityName === 'headers' ? entityKey.toLowerCase() : entityKey], descriptorValue);
const actualPropertyKey = entityName === 'headers' ? entityPropertyKey.toLowerCase() : entityPropertyKey;
const actualPropertyValue = actualEntity[actualPropertyKey];
if (entityPropertyDescriptor.checkMode === 'exists' || entityPropertyDescriptor.checkMode === 'notExists') {
return (0, _helpers.resolveEntityValues)({
actualValue: actualPropertyValue,
checkMode: entityPropertyDescriptor.checkMode
});
}
var _entityPropertyDescriptor_oneOf;
return (0, _helpers.resolveEntityValues)({
actualValue: actualPropertyValue,
descriptorValue: entityPropertyDescriptor.value,
checkMode: entityPropertyDescriptor.checkMode,
oneOf: (_entityPropertyDescriptor_oneOf = entityPropertyDescriptor.oneOf) !== null && _entityPropertyDescriptor_oneOf !== void 0 ? _entityPropertyDescriptor_oneOf : false
});
});

@@ -73,0 +95,0 @@ });

@@ -21,3 +21,3 @@ "use strict";

if (variables) {
if ((0, _helpers.isPlainObject)(variables) && variables.checkMode) {
if (variables.checkMode) {
// ✅ important:

@@ -32,3 +32,3 @@ // check that actual value check modes does not have `value` for compare

}
routeConfigWeight += (0, _helpers.isPlainObject)(variables) ? Object.keys(variables).length : 1;
routeConfigWeight += Object.keys(variables).length;
}

@@ -35,0 +35,0 @@ return routeConfigWeight;

import type { Express } from 'express';
import type { GraphQLEntity, GraphQLOperationName, GraphQLOperationType } from '../../../utils/types';
import type { GraphQLEntity, GraphQLOperationName, GraphQLOperationType, MockServerConfig } from '../../../utils/types';
declare global {

@@ -17,2 +17,2 @@ namespace Express {

}
export declare const contextMiddleware: (server: Express) => void;
export declare const contextMiddleware: (server: Express, { database }: Pick<MockServerConfig, "database">) => void;

@@ -11,5 +11,14 @@ "use strict";

});
const _database = require("../../database");
const _helpers = require("../../../utils/helpers");
const contextMiddleware = (server)=>{
const contextMiddleware = (server, { database })=>{
let requestId = 0;
const context = {
orm: {}
};
if (database) {
const storage = (0, _database.createStorage)(database.data);
const orm = (0, _database.createOrm)(storage);
context.orm = orm;
}
server.use((request, _response, next)=>{

@@ -34,4 +43,5 @@ requestId += 1;

request.graphQL = null;
request.context = context;
return next();
});
};

@@ -1,3 +0,2 @@

/// <reference types="node" />
import type { Server } from 'http';
import type { Server } from 'node:http';
type ServerWithDestroyer = Server & {

@@ -4,0 +3,0 @@ destroy: Server['close'];

@@ -7,4 +7,3 @@ export * from './contextMiddleware/contextMiddleware';

export * from './noCorsMiddleware/noCorsMiddleware';
export * from './notFoundMiddleware/notFoundMiddleware';
export * from './requestInterceptorMiddleware/requestInterceptorMiddleware';
export * from './staticMiddleware/staticMiddleware';

@@ -11,3 +11,2 @@ "use strict";

_export_star(require("./noCorsMiddleware/noCorsMiddleware"), exports);
_export_star(require("./notFoundMiddleware/notFoundMiddleware"), exports);
_export_star(require("./requestInterceptorMiddleware/requestInterceptorMiddleware"), exports);

@@ -14,0 +13,0 @@ _export_star(require("./staticMiddleware/staticMiddleware"), exports);

import type { Express } from 'express';
import type { RequestInterceptor } from '../../../utils/types';
interface RequestInterceptorMiddlewareParams {
interceptor: RequestInterceptor;
path?: string;
server: Express;
path?: string;
interceptor: RequestInterceptor;
}
export declare const requestInterceptorMiddleware: ({ server, path, interceptor }: RequestInterceptorMiddlewareParams) => void;
export {};
import type { IRouter } from 'express';
import type { Interceptors, RestConfig } from '../../../utils/types';
interface CreateRestRoutesParams {
restConfig: RestConfig;
router: IRouter;
restConfig: RestConfig;
serverResponseInterceptor?: Interceptors<'rest'>['response'];

@@ -7,0 +7,0 @@ }

@@ -12,3 +12,4 @@ "use strict";

const _flat = require("flat");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
const _helpers = require("../../../utils/helpers");

@@ -33,5 +34,4 @@ const _helpers1 = require("./helpers");

if (!entities) return true;
const entries = Object.entries(entities);
return entries.every(([entityName, entityDescriptorOrValue])=>{
const { checkMode, value: descriptorValue } = (0, _helpers.convertToEntityDescriptor)(entityDescriptorOrValue);
const entityEntries = Object.entries(entities);
return entityEntries.every(([entityName, entityDescriptorOrValue])=>{
// ✅ important:

@@ -41,18 +41,46 @@ // check whole body as plain value strictly if descriptor used for body

if (isEntityBodyByTopLevelDescriptor) {
// ✅ important:
// bodyParser sets body to empty object if body not sent or invalid, so assume {} as undefined
return (0, _helpers.resolveEntityValues)(checkMode, Object.keys(request.body).length ? request.body : undefined, descriptorValue);
const bodyDescriptor = entityDescriptorOrValue;
if (bodyDescriptor.checkMode === 'exists' || bodyDescriptor.checkMode === 'notExists') {
return (0, _helpers.resolveEntityValues)({
actualValue: request.body,
checkMode: bodyDescriptor.checkMode
});
}
var _bodyDescriptor_oneOf;
return (0, _helpers.resolveEntityValues)({
actualValue: request.body,
descriptorValue: bodyDescriptor.value,
checkMode: bodyDescriptor.checkMode,
oneOf: (_bodyDescriptor_oneOf = bodyDescriptor.oneOf) !== null && _bodyDescriptor_oneOf !== void 0 ? _bodyDescriptor_oneOf : false
});
}
const isEntityBodyByTopLevelArray = entityName === 'body' && Array.isArray(entityDescriptorOrValue);
if (isEntityBodyByTopLevelArray) {
return entityDescriptorOrValue.some((entityDescriptorOrValueElement)=>// ✅ important:
// bodyParser sets body to empty object if body not sent or invalid, so assume {} as undefined
(0, _helpers.resolveEntityValues)(checkMode, Object.keys(request.body).length ? request.body : undefined, entityDescriptorOrValueElement));
if (!Array.isArray(request.body)) return false;
return (0, _helpers.resolveEntityValues)({
actualValue: request.body,
descriptorValue: entityDescriptorOrValue,
checkMode: 'equals'
});
}
const recordOrArrayEntries = Object.entries(entityDescriptorOrValue);
return recordOrArrayEntries.every(([entityKey, mappedEntityDescriptor])=>{
const { checkMode, value: descriptorValue } = (0, _helpers.convertToEntityDescriptor)(mappedEntityDescriptor);
const flattenEntity = (0, _flat.flatten)(request[entityName]);
const actualEntity = (0, _flat.flatten)(request[entityName]);
const entityValueEntries = Object.entries(entityDescriptorOrValue);
return entityValueEntries.every(([entityPropertyKey, entityPropertyDescriptorOrValue])=>{
const entityPropertyDescriptor = (0, _helpers.convertToEntityDescriptor)(entityPropertyDescriptorOrValue);
// ✅ important: transform header keys to lower case because browsers send headers in lowercase
return (0, _helpers.resolveEntityValues)(checkMode, flattenEntity[entityName === 'headers' ? entityKey.toLowerCase() : entityKey], descriptorValue);
const actualPropertyKey = entityName === 'headers' ? entityPropertyKey.toLowerCase() : entityPropertyKey;
const actualPropertyValue = actualEntity[actualPropertyKey];
if (entityPropertyDescriptor.checkMode === 'exists' || entityPropertyDescriptor.checkMode === 'notExists') {
return (0, _helpers.resolveEntityValues)({
actualValue: actualPropertyValue,
checkMode: entityPropertyDescriptor.checkMode
});
}
var _entityPropertyDescriptor_oneOf;
return (0, _helpers.resolveEntityValues)({
actualValue: actualPropertyValue,
descriptorValue: entityPropertyDescriptor.value,
checkMode: entityPropertyDescriptor.checkMode,
oneOf: (_entityPropertyDescriptor_oneOf = entityPropertyDescriptor.oneOf) !== null && _entityPropertyDescriptor_oneOf !== void 0 ? _entityPropertyDescriptor_oneOf : false
});
});

@@ -68,3 +96,3 @@ });

}
let matchedRouteConfigData = null;
const matchedRouteConfigDataDescriptor = {};
if (((_matchedRouteConfig_settings = matchedRouteConfig.settings) === null || _matchedRouteConfig_settings === void 0 ? void 0 : _matchedRouteConfig_settings.polling) && 'queue' in matchedRouteConfig) {

@@ -75,3 +103,3 @@ if (!matchedRouteConfig.queue.length) return next();

let index = (_shallowMatchedRouteConfig___pollingIndex = shallowMatchedRouteConfig.__pollingIndex) !== null && _shallowMatchedRouteConfig___pollingIndex !== void 0 ? _shallowMatchedRouteConfig___pollingIndex : 0;
const { time, data } = matchedRouteConfig.queue[index];
const { time } = matchedRouteConfig.queue[index];
const updateIndex = ()=>{

@@ -85,2 +113,3 @@ if (matchedRouteConfig.queue.length - 1 === index) {

};
const queueItem = matchedRouteConfig.queue[index];
if (time && !shallowMatchedRouteConfig.__timeoutInProgress) {

@@ -96,12 +125,17 @@ shallowMatchedRouteConfig.__timeoutInProgress = true;

}
matchedRouteConfigData = data;
if ('data' in queueItem) {
matchedRouteConfigDataDescriptor.data = queueItem.data;
}
if ('file' in queueItem) {
if (!(0, _helpers.isFilePathValid)(queueItem.file)) return next();
matchedRouteConfigDataDescriptor.file = queueItem.file;
}
}
if ('data' in matchedRouteConfig) {
matchedRouteConfigData = matchedRouteConfig.data;
matchedRouteConfigDataDescriptor.data = matchedRouteConfig.data;
}
if ('file' in matchedRouteConfig) {
if (!(0, _helpers.isFilePathValid)(matchedRouteConfig.file)) return next();
matchedRouteConfigDataDescriptor.file = matchedRouteConfig.file;
}
var _matchedRouteConfig_entities;
const resolvedData = typeof matchedRouteConfigData === 'function' ? await matchedRouteConfigData(request, (_matchedRouteConfig_entities = matchedRouteConfig.entities) !== null && _matchedRouteConfig_entities !== void 0 ? _matchedRouteConfig_entities : {}) : matchedRouteConfigData;
if ((_matchedRouteConfig_settings1 = matchedRouteConfig.settings) === null || _matchedRouteConfig_settings1 === void 0 ? void 0 : _matchedRouteConfig_settings1.status) {

@@ -114,2 +148,14 @@ response.statusCode = matchedRouteConfig.settings.status;

if (request.method === 'GET') response.set('Cache-control', 'no-cache');
let resolvedData = null;
if (matchedRouteConfigDataDescriptor.data) {
var _matchedRouteConfig_entities;
resolvedData = typeof matchedRouteConfigDataDescriptor.data === 'function' ? await matchedRouteConfigDataDescriptor.data(request, (_matchedRouteConfig_entities = matchedRouteConfig.entities) !== null && _matchedRouteConfig_entities !== void 0 ? _matchedRouteConfig_entities : {}) : matchedRouteConfigDataDescriptor.data;
}
if (matchedRouteConfigDataDescriptor.file) {
const buffer = _nodefs.default.readFileSync(_nodepath.default.resolve(matchedRouteConfigDataDescriptor.file));
resolvedData = {
path: matchedRouteConfigDataDescriptor.file,
file: buffer
};
}
const data = await (0, _helpers.callResponseInterceptors)({

@@ -129,6 +175,16 @@ data: resolvedData,

}
if ('file' in matchedRouteConfig) {
return response.sendFile(_path.default.resolve(matchedRouteConfig.file));
if ((0, _helpers.isFileDescriptor)(data)) {
const isFilePathChanged = matchedRouteConfigDataDescriptor.file !== data.path;
if (isFilePathChanged) {
if (!(0, _helpers.isFilePathValid)(data.path)) return next();
data.file = _nodefs.default.readFileSync(_nodepath.default.resolve(data.path));
}
// ✅ important: replace backslashes because windows can use them in file path
const fileName = data.path.replaceAll('\\', '/').split('/').at(-1);
const fileExtension = fileName.split('.').at(-1);
response.type(fileExtension);
response.set('Content-Disposition', `filename=${fileName}`);
return response.send(data.file);
}
return response.json(data);
response.json(data);
}));

@@ -135,0 +191,0 @@ });

import type { Express } from 'express';
import type { DatabaseMockServerConfig } from '../../utils/types';
export declare const createDatabaseMockServer: (databaseMockServerConfig: Omit<DatabaseMockServerConfig, 'port'>, server?: Express) => Express;
export declare const createDatabaseMockServer: (databaseMockServerConfig: Omit<DatabaseMockServerConfig, "port">, server?: Express) => Express;

@@ -15,3 +15,2 @@ "use strict";

const _middlewares = require("../../core/middlewares");
const _helpers = require("../../utils/helpers");
function _interop_require_default(obj) {

@@ -25,5 +24,2 @@ return obj && obj.__esModule ? obj : {

const { cors, staticPath, data, routes } = databaseMockServerConfig;
server.set('view engine', 'ejs');
server.set('views', (0, _helpers.urlJoin)(__dirname, '../../static/views'));
server.use(_express.default.static((0, _helpers.urlJoin)(__dirname, '../../static/views')));
server.use(_bodyparser.default.urlencoded({

@@ -37,3 +33,8 @@ extended: false

server.use(_bodyparser.default.text());
(0, _middlewares.contextMiddleware)(server);
(0, _middlewares.contextMiddleware)(server, {
database: {
data,
routes
}
});
(0, _middlewares.cookieParseMiddleware)(server);

@@ -62,5 +63,4 @@ const serverRequestInterceptor = (_databaseMockServerConfig_interceptors = databaseMockServerConfig.interceptors) === null || _databaseMockServerConfig_interceptors === void 0 ? void 0 : _databaseMockServerConfig_interceptors.request;

server.use(baseUrl, routerWithDatabaseRoutes);
(0, _middlewares.notFoundMiddleware)(server, databaseMockServerConfig);
(0, _middlewares.errorMiddleware)(server);
return server;
};
import type { Express } from 'express';
import type { GraphQLMockServerConfig } from '../../utils/types';
export declare const createGraphQLMockServer: (graphqlMockServerConfig: Omit<GraphQLMockServerConfig, 'port'>, server?: Express) => Express;
export declare const createGraphQLMockServer: (graphqlMockServerConfig: Omit<GraphQLMockServerConfig, "port">, server?: Express) => Express;

@@ -16,3 +16,3 @@ "use strict";

const _middlewares = require("../../core/middlewares");
const _helpers = require("../../utils/helpers");
const _validate = require("../../utils/validate");
function _interop_require_default(obj) {

@@ -25,6 +25,4 @@ return obj && obj.__esModule ? obj : {

var _graphqlMockServerConfig_interceptors;
(0, _validate.validateApiMockServerConfig)(graphqlMockServerConfig, 'graphql');
const { cors, staticPath, configs, database, interceptors } = graphqlMockServerConfig;
server.set('view engine', 'ejs');
server.set('views', (0, _helpers.urlJoin)(__dirname, '../../static/views'));
server.use(_express.default.static((0, _helpers.urlJoin)(__dirname, '../../static/views')));
server.use(_bodyparser.default.urlencoded({

@@ -38,3 +36,3 @@ extended: false

server.use(_bodyparser.default.text());
(0, _middlewares.contextMiddleware)(server);
(0, _middlewares.contextMiddleware)(server, graphqlMockServerConfig);
(0, _middlewares.cookieParseMiddleware)(server);

@@ -70,5 +68,4 @@ const serverRequestInterceptor = (_graphqlMockServerConfig_interceptors = graphqlMockServerConfig.interceptors) === null || _graphqlMockServerConfig_interceptors === void 0 ? void 0 : _graphqlMockServerConfig_interceptors.request;

}
(0, _middlewares.notFoundMiddleware)(server, graphqlMockServerConfig);
(0, _middlewares.errorMiddleware)(server);
return server;
};
import type { Express } from 'express';
import type { MockServerConfig } from '../../utils/types';
export declare const createMockServer: (mockServerConfig: Omit<MockServerConfig, 'port'>, server?: Express) => Express;
export declare const createMockServer: (mockServerConfig: Omit<MockServerConfig, "port">, server?: Express) => Express;

@@ -18,2 +18,3 @@ "use strict";

const _helpers = require("../../utils/helpers");
const _validate = require("../../utils/validate");
function _interop_require_default(obj) {

@@ -26,6 +27,4 @@ return obj && obj.__esModule ? obj : {

var _mockServerConfig_interceptors;
(0, _validate.validateMockServerConfig)(mockServerConfig);
const { cors, staticPath, rest, graphql, database, interceptors } = mockServerConfig;
server.set('view engine', 'ejs');
server.set('views', (0, _helpers.urlJoin)(__dirname, '../../static/views'));
server.use(_express.default.static((0, _helpers.urlJoin)(__dirname, '../../static/views')));
server.use(_bodyparser.default.urlencoded({

@@ -39,3 +38,3 @@ extended: false

server.use(_bodyparser.default.text());
(0, _middlewares.contextMiddleware)(server);
(0, _middlewares.contextMiddleware)(server, mockServerConfig);
(0, _middlewares.cookieParseMiddleware)(server);

@@ -101,5 +100,4 @@ const serverRequestInterceptor = (_mockServerConfig_interceptors = mockServerConfig.interceptors) === null || _mockServerConfig_interceptors === void 0 ? void 0 : _mockServerConfig_interceptors.request;

}
(0, _middlewares.notFoundMiddleware)(server, mockServerConfig);
(0, _middlewares.errorMiddleware)(server);
return server;
};
import type { Express } from 'express';
import type { RestMockServerConfig } from '../../utils/types';
export declare const createRestMockServer: (restMockServerConfig: Omit<RestMockServerConfig, 'port'>, server?: Express) => Express;
export declare const createRestMockServer: (restMockServerConfig: Omit<RestMockServerConfig, "port">, server?: Express) => Express;

@@ -16,3 +16,3 @@ "use strict";

const _rest = require("../../core/rest");
const _helpers = require("../../utils/helpers");
const _validate = require("../../utils/validate");
function _interop_require_default(obj) {

@@ -25,6 +25,4 @@ return obj && obj.__esModule ? obj : {

var _restMockServerConfig_interceptors;
(0, _validate.validateApiMockServerConfig)(restMockServerConfig, 'rest');
const { cors, staticPath, configs, database, interceptors } = restMockServerConfig;
server.set('view engine', 'ejs');
server.set('views', (0, _helpers.urlJoin)(__dirname, '../../static/views'));
server.use(_express.default.static((0, _helpers.urlJoin)(__dirname, '../../static/views')));
server.use(_bodyparser.default.urlencoded({

@@ -38,3 +36,3 @@ extended: false

server.use(_bodyparser.default.text());
(0, _middlewares.contextMiddleware)(server);
(0, _middlewares.contextMiddleware)(server, restMockServerConfig);
(0, _middlewares.cookieParseMiddleware)(server);

@@ -70,5 +68,4 @@ const serverRequestInterceptor = (_restMockServerConfig_interceptors = restMockServerConfig.interceptors) === null || _restMockServerConfig_interceptors === void 0 ? void 0 : _restMockServerConfig_interceptors.request;

}
(0, _middlewares.notFoundMiddleware)(server, restMockServerConfig);
(0, _middlewares.errorMiddleware)(server);
return server;
};
export * from './createDatabaseMockServer/createDatabaseMockServer';
export * from './createFlatMockServer/createFlatMockServer';
export * from './createGraphQLMockServer/createGraphQLMockServer';

@@ -6,4 +7,5 @@ export * from './createMockServer/createMockServer';

export * from './startDatabaseMockServer/startDatabaseMockServer';
export * from './startFlatMockServer/startFlatMockServer';
export * from './startGraphQLMockServer/startGraphQLMockServer';
export * from './startMockServer/startMockServer';
export * from './startRestMockServer/startRestMockServer';

@@ -6,2 +6,3 @@ "use strict";

_export_star(require("./createDatabaseMockServer/createDatabaseMockServer"), exports);
_export_star(require("./createFlatMockServer/createFlatMockServer"), exports);
_export_star(require("./createGraphQLMockServer/createGraphQLMockServer"), exports);

@@ -11,2 +12,3 @@ _export_star(require("./createMockServer/createMockServer"), exports);

_export_star(require("./startDatabaseMockServer/startDatabaseMockServer"), exports);
_export_star(require("./startFlatMockServer/startFlatMockServer"), exports);
_export_star(require("./startGraphQLMockServer/startGraphQLMockServer"), exports);

@@ -13,0 +15,0 @@ _export_star(require("./startMockServer/startMockServer"), exports);

@@ -1,5 +0,4 @@

/// <reference types="node" />
import type { DatabaseMockServerConfig } from '../../utils/types';
export declare const startDatabaseMockServer: (databaseMockServerConfig: DatabaseMockServerConfig) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> & {
destroy: (callback?: ((err?: Error | undefined) => void) | undefined) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
destroy: import("http").Server["close"];
};

@@ -1,5 +0,4 @@

/// <reference types="node" />
import type { GraphQLMockServerConfig } from '../../utils/types';
export declare const startGraphQLMockServer: (graphQLMockServerConfig: GraphQLMockServerConfig) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> & {
destroy: (callback?: ((err?: Error | undefined) => void) | undefined) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
destroy: import("http").Server["close"];
};

@@ -1,5 +0,4 @@

/// <reference types="node" />
import type { MockServerConfig } from '../../utils/types';
export declare const startMockServer: (mockServerConfig: MockServerConfig) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> & {
destroy: (callback?: ((err?: Error | undefined) => void) | undefined) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
destroy: import("http").Server["close"];
};

@@ -1,5 +0,4 @@

/// <reference types="node" />
import type { RestMockServerConfig } from '../../utils/types';
export declare const startRestMockServer: (restMockServerConfig: RestMockServerConfig) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> & {
destroy: (callback?: ((err?: Error | undefined) => void) | undefined) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
destroy: import("http").Server["close"];
};

@@ -6,4 +6,2 @@ export declare const CHECK_ACTUAL_VALUE_CHECK_MODES: readonly ["exists", "notExists"];

export declare const CALCULATE_BY_DESCRIPTOR_VALUE_CHECK_MODES: readonly ["regExp", "function"];
export declare const CHECK_MODES: readonly ["exists", "notExists", "equals", "notEquals", "includes", "notIncludes", "startsWith", "notStartsWith", "endsWith", "notEndsWith", "regExp", "function"];
export declare const PLAIN_ENTITY_CHECK_MODES: readonly ["exists", "notExists", "equals", "notEquals", "function"];
export declare const NEGATION_CHECK_MODES: readonly ["notExists", "notEquals", "notIncludes", "notStartsWith", "notEndsWith"];
export declare const NEGATIVE_CHECK_MODES: readonly ["notExists", "notEquals", "notIncludes", "notStartsWith", "notEndsWith"];

@@ -18,5 +18,2 @@ "use strict";

},
CHECK_MODES: function() {
return CHECK_MODES;
},
COMPARE_WITH_DESCRIPTOR_ANY_VALUE_CHECK_MODES: function() {

@@ -31,7 +28,4 @@ return COMPARE_WITH_DESCRIPTOR_ANY_VALUE_CHECK_MODES;

},
NEGATION_CHECK_MODES: function() {
return NEGATION_CHECK_MODES;
},
PLAIN_ENTITY_CHECK_MODES: function() {
return PLAIN_ENTITY_CHECK_MODES;
NEGATIVE_CHECK_MODES: function() {
return NEGATIVE_CHECK_MODES;
}

@@ -63,13 +57,3 @@ });

];
const CHECK_MODES = [
...CHECK_ACTUAL_VALUE_CHECK_MODES,
...COMPARE_WITH_DESCRIPTOR_VALUE_CHECK_MODES,
...CALCULATE_BY_DESCRIPTOR_VALUE_CHECK_MODES
];
const PLAIN_ENTITY_CHECK_MODES = [
...CHECK_ACTUAL_VALUE_CHECK_MODES,
...COMPARE_WITH_DESCRIPTOR_ANY_VALUE_CHECK_MODES,
'function'
];
const NEGATION_CHECK_MODES = [
const NEGATIVE_CHECK_MODES = [
'notExists',

@@ -76,0 +60,0 @@ 'notEquals',

@@ -1,2 +0,20 @@

import type { CheckMode } from '../../../types';
export declare const resolveEntityValues: (checkMode: CheckMode, actualValue: any, descriptorValue?: any) => any;
import type { CheckActualValueCheckMode, CheckMode } from '../../../types';
interface ResolveEntityValuesParamsWithCheckActualValueCheckMode {
actualValue: unknown;
checkMode: CheckActualValueCheckMode;
}
interface ResolveEntityValuesParamsWithEnabledOneOf {
actualValue: unknown;
checkMode: Exclude<CheckMode, CheckActualValueCheckMode>;
descriptorValue: unknown[];
oneOf: true;
}
interface ResolveEntityValuesParamsWithDisabledOneOf {
actualValue: unknown;
checkMode: Exclude<CheckMode, CheckActualValueCheckMode>;
descriptorValue: unknown;
oneOf?: false;
}
type ResolveEntityValuesParams = ResolveEntityValuesParamsWithCheckActualValueCheckMode | ResolveEntityValuesParamsWithDisabledOneOf | ResolveEntityValuesParamsWithEnabledOneOf;
export declare const resolveEntityValues: (params: ResolveEntityValuesParams) => boolean;
export {};

@@ -15,10 +15,13 @@ "use strict";

const _isPrimitive = require("../../isPrimitive/isPrimitive");
const _isRegExp = require("../../isRegExp/isRegExp");
const checkFunction = (checkMode, actualValue, descriptorValue)=>{
if (checkMode === 'function' && typeof descriptorValue === 'function') return descriptorValue(actualValue, checkFunction);
const actualValueString = String(actualValue);
if (checkMode === 'regExp' && (0, _isRegExp.isRegExp)(descriptorValue)) return descriptorValue.test(actualValueString);
const isActualValueUndefined = typeof actualValue === 'undefined';
if (checkMode === 'exists') return !isActualValueUndefined;
if (checkMode === 'notExists') return isActualValueUndefined;
if (checkMode === 'function') {
return !!descriptorValue(actualValue, checkFunction);
}
const actualValueString = String(actualValue);
if (checkMode === 'regExp' && descriptorValue instanceof RegExp) {
return new RegExp(descriptorValue).test(actualValueString);
}
// ✅ important:

@@ -35,79 +38,42 @@ // cast values to string for ignore types of values

if (checkMode === 'notEndsWith') return !actualValueString.endsWith(descriptorValueString);
throw new Error('Wrong checkMode');
throw new Error(`Wrong checkMode ${checkMode}`);
};
const resolveEntityValues = (checkMode, actualValue, descriptorValue)=>{
if (checkMode === 'function') return descriptorValue(actualValue, checkFunction);
if (checkMode === 'exists' || checkMode === 'notExists') return checkFunction(checkMode, actualValue, descriptorValue);
// ✅ actual: primitive, descriptor: primitive
const isActualValuePrimitive = (0, _isPrimitive.isPrimitive)(actualValue);
const isDescriptorValuePrimitive = (0, _isPrimitive.isPrimitive)(descriptorValue);
if (isActualValuePrimitive && isDescriptorValuePrimitive) return checkFunction(checkMode, actualValue, descriptorValue);
// ✅ actual: primitive, descriptor: array
const isDescriptorValueArray = Array.isArray(descriptorValue);
const isNegativeCheckMode = _constants.NEGATION_CHECK_MODES.includes(checkMode);
if (isActualValuePrimitive && isDescriptorValueArray) {
if (isNegativeCheckMode) {
return descriptorValue.every((descriptorValueElement)=>checkFunction(checkMode, actualValue, descriptorValueElement));
}
return descriptorValue.some((descriptorValueElement)=>checkFunction(checkMode, actualValue, descriptorValueElement));
const compareEntityValues = (checkMode, actualValue, descriptorValue)=>{
if (checkMode === 'exists' || checkMode === 'notExists') {
return checkFunction(checkMode, actualValue);
}
// ✅ actual: primitive, descriptor: object => skip
const isDescriptorValueObject = (0, _isPlainObject.isPlainObject)(descriptorValue) || (0, _isRegExp.isRegExp)(descriptorValue);
if (isActualValuePrimitive && isDescriptorValueObject) {
if (checkMode === 'regExp') return checkFunction(checkMode, actualValue, descriptorValue);
// ✅ important: resolving primitive with object make no sense
return isNegativeCheckMode;
if (checkMode === 'function') {
return !!descriptorValue(actualValue, checkFunction);
}
// ✅ actual: array, descriptor: primitive => skip
const isActualValueArray = Array.isArray(actualValue);
// ✅ important: resolving array with primitive make no sense
if (isActualValueArray && isDescriptorValuePrimitive) return isNegativeCheckMode;
// ✅ actual: array, descriptor: array
if (isActualValueArray && isDescriptorValueArray) {
if (actualValue.length !== descriptorValue.length) return isNegativeCheckMode;
const flattenActualValue = (0, _flat.flatten)(actualValue);
const flattenDescriptorValue = (0, _flat.flatten)(descriptorValue);
if (Object.keys(flattenActualValue).length === Object.keys(flattenDescriptorValue).length) return Object.keys(flattenDescriptorValue).every((flattenDescriptorValueKey)=>checkFunction(checkMode, flattenActualValue[flattenDescriptorValueKey], flattenDescriptorValue[flattenDescriptorValueKey]));
return isNegativeCheckMode;
if (checkMode === 'regExp') {
return checkFunction(checkMode, actualValue, descriptorValue);
}
// ✅ actual: array, descriptor: object => skip
if (isActualValueArray && isDescriptorValueObject) {
if (checkMode === 'regExp') return actualValue.some((actualValueElement)=>checkFunction(checkMode, actualValueElement, descriptorValue));
// ✅ important: resolving array with object make no sense
return isNegativeCheckMode;
const isActualValuePrimitive = (0, _isPrimitive.isPrimitive)(actualValue);
const isDescriptorValuePrimitive = (0, _isPrimitive.isPrimitive)(descriptorValue);
if (isActualValuePrimitive && isDescriptorValuePrimitive) {
return checkFunction(checkMode, actualValue, descriptorValue);
}
// ✅ actual: object, descriptor: primitive => skip
const isActualValueObject = (0, _isPlainObject.isPlainObject)(actualValue);
// ✅ important: resolving object with primitive make no sense
if (isActualValueObject && isDescriptorValuePrimitive) return isNegativeCheckMode;
// ✅ actual: object, descriptor: array
if (isActualValueObject && isDescriptorValueArray) {
// ✅ important: any object can not pass RegExp check
if (checkMode === 'regExp') return false;
const flattenActualValue = (0, _flat.flatten)(actualValue);
if (isNegativeCheckMode) {
return descriptorValue.every((descriptorValueElement)=>{
const flattenDescriptorValue = (0, _flat.flatten)(descriptorValueElement);
if (Object.keys(flattenActualValue).length !== Object.keys(flattenDescriptorValue).length) return isNegativeCheckMode;
return Object.keys(flattenActualValue).every((flattenActualValueKey)=>checkFunction(checkMode, flattenActualValue[flattenActualValueKey], flattenDescriptorValue[flattenActualValueKey]));
});
}
return descriptorValue.some((descriptorValueElement)=>{
const flattenDescriptorValue = (0, _flat.flatten)(descriptorValueElement);
if (Object.keys(flattenActualValue).length !== Object.keys(flattenDescriptorValue).length) return isNegativeCheckMode;
return Object.keys(flattenActualValue).every((flattenActualValueKey)=>checkFunction(checkMode, flattenActualValue[flattenActualValueKey], flattenDescriptorValue[flattenActualValueKey]));
});
}
// ✅ actual: object, descriptor: object
const isActualValueObject = (0, _isPlainObject.isPlainObject)(actualValue) || Array.isArray(actualValue);
const isDescriptorValueObject = (0, _isPlainObject.isPlainObject)(descriptorValue) || Array.isArray(descriptorValue);
const isNegativeCheckMode = _constants.NEGATIVE_CHECK_MODES.includes(checkMode);
if (isActualValueObject && isDescriptorValueObject) {
// ✅ important: any object can not pass RegExp check
if (checkMode === 'regExp') return false;
const flattenActualValue = (0, _flat.flatten)(actualValue);
const flattenDescriptorValue = (0, _flat.flatten)(descriptorValue);
if (Object.keys(flattenActualValue).length !== Object.keys(flattenDescriptorValue).length) return isNegativeCheckMode;
if (isNegativeCheckMode) {
return Object.keys(flattenDescriptorValue).some((flattenDescriptorValueKey)=>checkFunction(checkMode, flattenActualValue[flattenDescriptorValueKey], flattenDescriptorValue[flattenDescriptorValueKey]));
if (Object.keys(flattenActualValue).length !== Object.keys(flattenDescriptorValue).length) {
return isNegativeCheckMode;
}
return Object.keys(flattenDescriptorValue).every((flattenDescriptorValueKey)=>checkFunction(checkMode, flattenActualValue[flattenDescriptorValueKey], flattenDescriptorValue[flattenDescriptorValueKey]));
return Object.keys(flattenDescriptorValue)[isNegativeCheckMode ? 'some' : 'every']((flattenDescriptorValueKey)=>checkFunction(checkMode, flattenActualValue[flattenDescriptorValueKey], flattenDescriptorValue[flattenDescriptorValueKey]));
}
return isNegativeCheckMode;
};
const resolveEntityValues = (params)=>{
const { checkMode, actualValue } = params;
if (checkMode === 'exists' || checkMode === 'notExists') {
return compareEntityValues(checkMode, actualValue);
}
const { oneOf, descriptorValue } = params;
if (!oneOf) {
return compareEntityValues(checkMode, actualValue, descriptorValue);
}
return descriptorValue.some((descriptorValueElement)=>compareEntityValues(checkMode, actualValue, descriptorValueElement));
};

@@ -0,1 +1,2 @@

export * from './isFileDescriptor/isFileDescriptor';
export * from './isFilePathValid/isFilePathValid';

@@ -5,2 +5,3 @@ "use strict";

});
_export_star(require("./isFileDescriptor/isFileDescriptor"), exports);
_export_star(require("./isFilePathValid/isFilePathValid"), exports);

@@ -7,0 +8,0 @@ function _export_star(from, to) {

@@ -11,3 +11,3 @@ "use strict";

});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
function _interop_require_default(obj) {

@@ -20,4 +20,4 @@ return obj && obj.__esModule ? obj : {

try {
if (!_fs.default.existsSync(path)) return false;
if (!_fs.default.statSync(path).isFile()) return false;
if (!_nodefs.default.existsSync(path)) return false;
if (!_nodefs.default.statSync(path).isFile()) return false;
return true;

@@ -24,0 +24,0 @@ } catch (error) {

import type { OperationTypeNode } from 'graphql';
interface ParseDocumentNodeResult {
operationName: string | undefined;
operationType: OperationTypeNode;
operationName: string | undefined;
}
export declare const parseQuery: (query: string) => ParseDocumentNodeResult | null;
export {};

@@ -10,5 +10,4 @@ export * from './asyncHandler';

export * from './isPrimitive/isPrimitive';
export * from './isRegExp/isRegExp';
export * from './logger';
export * from './sleep';
export * from './url';

@@ -14,3 +14,2 @@ "use strict";

_export_star(require("./isPrimitive/isPrimitive"), exports);
_export_star(require("./isRegExp/isRegExp"), exports);
_export_star(require("./logger"), exports);

@@ -17,0 +16,0 @@ _export_star(require("./sleep"), exports);

import type { Request } from 'express';
import type { RequestInterceptor } from '../../../types';
interface CallRequestInterceptorParams {
interceptor: RequestInterceptor;
request: Request;
interceptor: RequestInterceptor;
}
export declare const callRequestInterceptor: (params: CallRequestInterceptorParams) => Promise<void>;
export {};

@@ -28,5 +28,6 @@ "use strict";

getCookie,
log
log,
orm: request.context.orm
};
await interceptor(requestInterceptorParams);
};

@@ -15,4 +15,6 @@ "use strict";

const { data, request, response, interceptors } = params;
const getHeader = (field)=>response.getHeader(field);
const getHeaders = ()=>response.getHeaders();
const getRequestHeader = (field)=>request.headers[field];
const getRequestHeaders = ()=>request.headers;
const getResponseHeader = (field)=>response.getHeader(field);
const getResponseHeaders = ()=>response.getHeaders();
const setHeader = (field, value)=>{

@@ -54,4 +56,6 @@ response.set(field, value);

appendHeader,
getHeader,
getHeaders,
getRequestHeader,
getRequestHeaders,
getResponseHeader,
getResponseHeaders,
setCookie,

@@ -61,3 +65,4 @@ getCookie,

attachment,
log
log,
orm: request.context.orm
};

@@ -64,0 +69,0 @@ let updatedData = data;

import type { Request, Response } from 'express';
import type { Data, Logger } from '../../../types';
interface CallResponseLoggerParams {
data: Data;
logger?: Logger<'response'>;
data: Data;
request: Request;

@@ -7,0 +7,0 @@ response: Response;

@@ -11,5 +11,5 @@ "use strict";

});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _os = /*#__PURE__*/ _interop_require_default(require("os"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
const _nodeos = /*#__PURE__*/ _interop_require_default(require("node:os"));
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
function _interop_require_default(obj) {

@@ -20,2 +20,2 @@ return obj && obj.__esModule ? obj : {

}
const createTmpDir = ()=>_fs.default.mkdtempSync(`${_os.default.tmpdir()}${_path.default.sep}`);
const createTmpDir = ()=>_nodefs.default.mkdtempSync(`${_nodeos.default.tmpdir()}${_nodepath.default.sep}`);

@@ -11,2 +11,2 @@ "use strict";

});
const convertWin32PathToUnix = (win32Path)=>win32Path.replace(/^\\\\\?\\/, '').replace(/\\/g, '/').replace(/\/\/+/g, '/');
const convertWin32PathToUnix = (win32Path)=>win32Path.replace(/^\\\\\?\\/, '').replace(/\\/g, '/').replace(/\/{2,}/g, '/');

@@ -11,4 +11,4 @@ "use strict";

});
const _os = /*#__PURE__*/ _interop_require_default(require("os"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _nodeos = /*#__PURE__*/ _interop_require_default(require("node:os"));
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
const _convertWin32PathToUnix = require("../convertWin32PathToUnix/convertWin32PathToUnix");

@@ -21,4 +21,4 @@ function _interop_require_default(obj) {

const urlJoin = (...paths)=>{
const pathsToJoin = _os.default.platform() === 'win32' ? paths.map((path)=>(0, _convertWin32PathToUnix.convertWin32PathToUnix)(path)) : paths;
return _path.default.posix.join(...pathsToJoin);
const pathsToJoin = _nodeos.default.platform() === 'win32' ? paths.map((path)=>(0, _convertWin32PathToUnix.convertWin32PathToUnix)(path)) : paths;
return _nodepath.default.posix.join(...pathsToJoin);
};
export type CheckActualValueCheckMode = 'exists' | 'notExists';
export type CompareWithDescriptorAnyValueCheckMode = 'equals' | 'notEquals';
export type CompareWithDescriptorStringValueCheckMode = 'includes' | 'notIncludes' | 'startsWith' | 'notStartsWith' | 'endsWith' | 'notEndsWith';
export type CompareWithDescriptorStringValueCheckMode = 'endsWith' | 'includes' | 'notEndsWith' | 'notIncludes' | 'notStartsWith' | 'startsWith';
export type CompareWithDescriptorValueCheckMode = CompareWithDescriptorAnyValueCheckMode | CompareWithDescriptorStringValueCheckMode;
export type CalculateByDescriptorValueCheckMode = 'regExp' | 'function';
export type CheckMode = CheckActualValueCheckMode | CompareWithDescriptorValueCheckMode | CalculateByDescriptorValueCheckMode;
export interface EntityDescriptor {
checkMode: CheckMode;
value?: any;
}
export type CalculateByDescriptorValueCheckMode = 'function' | 'regExp';
export type CheckMode = CalculateByDescriptorValueCheckMode | CheckActualValueCheckMode | CompareWithDescriptorValueCheckMode;
export type EntityDescriptor<Check extends CheckMode = CheckMode, Value = any> = Check extends CheckActualValueCheckMode ? {
checkMode: Check;
} : {
checkMode: Check;
value: Value;
oneOf?: false;
} | {
checkMode: Check;
value: Value[];
oneOf: true;
};
export type CheckFunction = <ActualValue = any, DescriptorValue = any>(checkMode: CheckMode, actualValue: ActualValue, descriptorValue?: DescriptorValue) => boolean;

@@ -0,1 +1,3 @@

export interface Database extends Record<string, unknown> {
}
export type ShallowDatabase = Record<string, unknown>;

@@ -7,1 +9,29 @@ export type NestedDatabaseId = number | string;

}[]>;
export type StorageIndex = number | string;
export interface Storage {
delete: (key: StorageIndex | StorageIndex[]) => void;
read: (key?: StorageIndex | StorageIndex[]) => any;
write: (key: StorageIndex | StorageIndex[], value: unknown) => void;
}
export interface ShallowOrm<Item = unknown> {
get: () => Item;
update: (data: Item) => void;
}
export interface NestedOrm<Item = Record<string, unknown>> {
count: () => number;
create: (item: Omit<Item, 'id'>) => Item;
createMany: (items: Omit<Item, 'id'>[]) => void;
delete: (id: StorageIndex) => void;
deleteMany: (ids: StorageIndex[]) => void;
exists: (filters: Partial<Item>) => boolean;
findById: (id: StorageIndex) => Item | undefined;
findFirst: (filters?: Partial<Item>) => Item | undefined;
findMany: (filters?: Partial<Item>) => Item[];
update: (id: StorageIndex, item: Partial<Omit<Item, 'id'>>) => void;
updateMany: (ids: StorageIndex[], item: Partial<Omit<Item, 'id'>>) => number;
}
export type Orm<Database extends Record<string, unknown>> = {
[Key in keyof Database]: Database[Key] extends Array<infer Item> ? Item extends {
id: StorageIndex;
} ? NestedOrm<Item> : ShallowOrm<Database[Key]> : ShallowOrm<Database[Key]>;
};

@@ -1,48 +0,18 @@

import type { CheckActualValueCheckMode, CheckFunction, CheckMode, CompareWithDescriptorAnyValueCheckMode, CompareWithDescriptorStringValueCheckMode, CompareWithDescriptorValueCheckMode } from './checkModes';
import type { CheckActualValueCheckMode, CheckFunction, CheckMode, CompareWithDescriptorAnyValueCheckMode, CompareWithDescriptorStringValueCheckMode, CompareWithDescriptorValueCheckMode, EntityDescriptor } from './checkModes';
import type { NestedObjectOrArray } from './utils';
type PlainEntityValue = string | number | boolean | null;
export type TopLevelPlainEntityDescriptor<Check extends CheckMode = CheckMode> = Check extends 'function' ? {
checkMode: Check;
value: (actualValue: NestedObjectOrArray<PlainEntityValue>, checkFunction: CheckFunction) => boolean;
} : Check extends CompareWithDescriptorAnyValueCheckMode ? {
checkMode: Check;
value: NestedObjectOrArray<PlainEntityValue>;
} : Check extends CheckActualValueCheckMode ? {
checkMode: Check;
} : never;
type PropertyLevelPlainEntityDescriptor<Check extends CheckMode = CheckMode> = Check extends 'function' ? {
checkMode: Check;
value: (actualValue: PlainEntityValue | NestedObjectOrArray<PlainEntityValue>, checkFunction: CheckFunction) => boolean;
} : Check extends CompareWithDescriptorAnyValueCheckMode ? {
checkMode: Check;
value: PlainEntityValue | NestedObjectOrArray<PlainEntityValue>;
} : Check extends 'regExp' ? {
checkMode: Check;
value: RegExp | RegExp[];
} : Check extends CompareWithDescriptorStringValueCheckMode ? {
checkMode: Check;
value: PlainEntityValue | PlainEntityValue[];
} : Check extends CheckActualValueCheckMode ? {
checkMode: Check;
} : never;
type PlainEntityPrimitiveValue = boolean | number | string | null;
type PlainEntityObjectiveValue = NestedObjectOrArray<PlainEntityPrimitiveValue>;
export type EntityFunctionDescriptorValue<ActualValue> = (actualValue: ActualValue, checkFunction: CheckFunction) => boolean;
export type TopLevelPlainEntityDescriptor<Check extends CheckMode = CheckMode> = Check extends 'function' ? EntityDescriptor<Check, EntityFunctionDescriptorValue<PlainEntityObjectiveValue>> : Check extends CompareWithDescriptorAnyValueCheckMode ? EntityDescriptor<Check, PlainEntityObjectiveValue> : Check extends CheckActualValueCheckMode ? EntityDescriptor<Check> : never;
type PropertyLevelPlainEntityDescriptor<Check extends CheckMode = CheckMode> = Check extends 'function' ? EntityDescriptor<Check, EntityFunctionDescriptorValue<PlainEntityObjectiveValue | PlainEntityPrimitiveValue>> : Check extends 'regExp' ? EntityDescriptor<Check, RegExp> : Check extends CompareWithDescriptorAnyValueCheckMode ? EntityDescriptor<Check, PlainEntityObjectiveValue | PlainEntityPrimitiveValue> : Check extends CompareWithDescriptorStringValueCheckMode ? EntityDescriptor<Check, PlainEntityPrimitiveValue> : Check extends CheckActualValueCheckMode ? EntityDescriptor<Check> : never;
type NonCheckMode<T extends object> = T & {
checkMode?: never;
};
type TopLevelPlainEntityRecord = NonCheckMode<Record<string, PropertyLevelPlainEntityDescriptor | NonCheckMode<NestedObjectOrArray<PlainEntityValue>> | PlainEntityValue>>;
export type TopLevelPlainEntityArray = Array<NestedObjectOrArray<PlainEntityValue>>;
export type PlainEntity = TopLevelPlainEntityDescriptor | TopLevelPlainEntityRecord | TopLevelPlainEntityArray;
type MappedEntityValue = string | number | boolean;
type MappedEntityDescriptor<Check extends CheckMode = CheckMode> = Check extends 'function' ? {
checkMode: Check;
value: (actualValue: MappedEntityValue, checkFunction: CheckFunction) => boolean;
} : Check extends 'regExp' ? {
checkMode: Check;
value: RegExp | RegExp[];
} : Check extends CompareWithDescriptorValueCheckMode ? {
checkMode: Check;
value: MappedEntityValue | MappedEntityValue[];
} : Check extends CheckActualValueCheckMode ? {
checkMode: Check;
} : never;
export type MappedEntity = Record<string, MappedEntityDescriptor | MappedEntityValue | MappedEntityValue[]>;
type TopLevelPlainEntityRecord = NonCheckMode<Record<string, NonCheckMode<PlainEntityObjectiveValue> | PlainEntityPrimitiveValue | PropertyLevelPlainEntityDescriptor>>;
export type TopLevelPlainEntityArray = Array<PlainEntityObjectiveValue | PlainEntityPrimitiveValue>;
export type BodyPlainEntity = TopLevelPlainEntityArray | TopLevelPlainEntityDescriptor | TopLevelPlainEntityRecord;
export type VariablesPlainEntity = TopLevelPlainEntityDescriptor | TopLevelPlainEntityRecord;
type MappedEntityValue = boolean | number | string;
type MappedEntityDescriptor<Check extends CheckMode = CheckMode> = Check extends 'function' ? EntityDescriptor<Check, EntityFunctionDescriptorValue<MappedEntityValue>> : Check extends 'regExp' ? EntityDescriptor<Check, RegExp> : Check extends CompareWithDescriptorValueCheckMode ? EntityDescriptor<Check, MappedEntityValue> : Check extends CheckActualValueCheckMode ? EntityDescriptor<Check> : never;
export type MappedEntity = Record<string, MappedEntityDescriptor | MappedEntityValue>;
export {};
import type { Request } from 'express';
import type { MappedEntity, PlainEntity } from './entities';
import type { MappedEntity, VariablesPlainEntity } from './entities';
import type { Interceptors } from './interceptors';
import type { Data } from './values';
export type GraphQLEntityName = 'headers' | 'cookies' | 'query' | 'variables';
export type GraphQLEntity<EntityName extends GraphQLEntityName = GraphQLEntityName> = EntityName extends 'variables' ? PlainEntity : MappedEntity;
export type GraphQLOperationType = 'query' | 'mutation';
export type GraphQLEntityName = 'cookies' | 'headers' | 'query' | 'variables';
export type GraphQLEntity<EntityName extends GraphQLEntityName = GraphQLEntityName> = EntityName extends 'variables' ? VariablesPlainEntity : MappedEntity;
export type GraphQLOperationType = 'mutation' | 'query';
export type GraphQLOperationName = string | RegExp;

@@ -13,6 +13,7 @@ export type GraphQLEntitiesByEntityName = {

interface GraphQLSettings {
readonly delay?: number;
readonly polling?: boolean;
readonly status?: number;
readonly delay?: number;
}
export type GraphqlDataResponse = ((request: Request, entities: GraphQLEntitiesByEntityName) => Data | Promise<Data>) | Data;
export type GraphQLRouteConfig = ({

@@ -24,3 +25,3 @@ settings: GraphQLSettings & {

time?: number;
data: ((request: Request, entities: GraphQLEntitiesByEntityName) => Data | Promise<Data>) | Data;
data: GraphqlDataResponse;
}>;

@@ -31,3 +32,3 @@ } | {

};
data: ((request: Request, entities: GraphQLEntitiesByEntityName) => Data | Promise<Data>) | Data;
data: GraphqlDataResponse;
}) & {

@@ -38,5 +39,5 @@ entities?: GraphQLEntitiesByEntityName;

interface BaseGraphQLRequestConfig {
interceptors?: Interceptors<'graphql'>;
operationType: GraphQLOperationType;
routes: GraphQLRouteConfig[];
interceptors?: Interceptors<'graphql'>;
}

@@ -43,0 +44,0 @@ export interface OperationNameGraphQLRequestConfig extends BaseGraphQLRequestConfig {

export * from './checkModes';
export * from './database';
export * from './entities';
export * from './files';
export * from './graphql';

@@ -5,0 +6,0 @@ export * from './interceptors';

@@ -8,2 +8,3 @@ "use strict";

_export_star(require("./entities"), exports);
_export_star(require("./files"), exports);
_export_star(require("./graphql"), exports);

@@ -10,0 +11,0 @@ _export_star(require("./interceptors"), exports);

import type { CookieOptions, Request, Response } from 'express';
import type { Database, Orm } from './database';
import type { Logger, LoggerTokens } from './logger';
import type { ApiType } from './shared';
type RequestInterceptorCookieValue = string | undefined;
type RequestInterceptorHeaderValue = string | number | string[] | undefined;
type InterceptorCookieValue = string | undefined;
type InterceptorHeaderValue = number | string | string[] | undefined;
export interface RequestInterceptorParams<Api extends ApiType = ApiType> {
orm: Orm<Database>;
request: Request;
getCookie: (name: string) => InterceptorCookieValue;
getHeader: (field: string) => InterceptorHeaderValue;
getHeaders: () => Record<string, InterceptorHeaderValue>;
log: (logger?: Logger<'request', Api>) => Partial<LoggerTokens>;
setDelay: (delay: number) => Promise<void>;
getCookie: (name: string) => RequestInterceptorCookieValue;
getHeader: (field: string) => RequestInterceptorHeaderValue;
getHeaders: () => Record<string, RequestInterceptorHeaderValue>;
log: (logger?: Logger<'request', Api>) => Partial<LoggerTokens>;
}
export type RequestInterceptor<Api extends ApiType = ApiType> = (params: RequestInterceptorParams<Api>) => void | Promise<void>;
export type RequestInterceptor<Api extends ApiType = ApiType> = (params: RequestInterceptorParams<Api>) => Promise<void> | void;
export interface ResponseInterceptorParams<Api extends ApiType = ApiType> {
orm: Orm<Database>;
request: Request;
response: Response;
appendHeader: (field: string, value?: string | string[]) => void;
attachment: (filename: string) => void;
clearCookie: (name: string, options?: CookieOptions) => void;
getCookie: (name: string) => InterceptorCookieValue;
getRequestHeader: (field: string) => InterceptorHeaderValue;
getRequestHeaders: () => Record<string, InterceptorHeaderValue>;
getResponseHeader: (field: string) => InterceptorHeaderValue;
getResponseHeaders: () => Record<string, InterceptorHeaderValue>;
log: (logger?: Logger<'response', Api>) => Partial<LoggerTokens>;
setCookie: (name: string, value: string, options?: CookieOptions) => void;
setDelay: (delay: number) => Promise<void>;
setHeader: (field: string, value?: string | string[]) => void;
setStatusCode: (statusCode: number) => void;
setHeader: (field: string, value?: string | string[]) => void;
appendHeader: (field: string, value?: string[] | string) => void;
getHeader: (field: string) => RequestInterceptorHeaderValue;
getHeaders: () => Record<string, RequestInterceptorHeaderValue>;
setCookie: (name: string, value: string, options?: CookieOptions) => void;
getCookie: (name: string) => RequestInterceptorCookieValue;
clearCookie: (name: string, options?: CookieOptions) => void;
attachment: (filename: string) => void;
log: (logger?: Logger<'response', Api>) => Partial<LoggerTokens>;
}

@@ -30,0 +35,0 @@ export type ResponseInterceptor<Data = any, Api extends ApiType = ApiType> = (data: Data, params: ResponseInterceptorParams<Api>) => any;

@@ -6,12 +6,12 @@ import type { GraphQLOperationName, GraphQLOperationType } from './graphql';

export interface LoggerBaseTokens {
type: string;
body: any;
cookies: Cookies;
headers: Headers;
id: number;
method: RestMethod;
params: Params;
query: Query;
timestamp: number;
method: RestMethod;
type: string;
url: string;
headers: Headers;
cookies: Cookies;
query: Query;
params: Params;
body: any;
}

@@ -21,8 +21,8 @@ interface LoggerRestRequestTokens extends LoggerBaseTokens {

interface LoggerRestResponseTokens extends LoggerRestRequestTokens {
data: any;
statusCode: number;
data: any;
}
interface LoggerGraphQLRequestTokens extends LoggerBaseTokens {
graphQLOperationName: GraphQLOperationName | null;
graphQLOperationType: GraphQLOperationType | null;
graphQLOperationName: GraphQLOperationName | null;
graphQLQuery: string | null;

@@ -32,4 +32,4 @@ variables: PlainObject | null;

interface LoggerGraphQLResponseTokens extends LoggerGraphQLRequestTokens {
data: any;
statusCode: number;
data: any;
}

@@ -39,3 +39,3 @@ export type LoggerType = 'request' | 'response';

type LoggerTokensToLoggerOptions<Type> = {
[Key in keyof Type]?: Type[Key] extends PlainObject ? Record<string, boolean> | boolean : boolean;
[Key in keyof Type]?: Type[Key] extends PlainObject ? boolean | Record<string, boolean> : boolean;
};

@@ -42,0 +42,0 @@ export type LoggerOptions<Type extends LoggerType = LoggerType, Api extends ApiType = ApiType> = LoggerTokensToLoggerOptions<LoggerTokens<Type, Api>>;

import type { Request } from 'express';
import type { MappedEntity, PlainEntity } from './entities';
import type { BodyPlainEntity, MappedEntity } from './entities';
import type { Interceptors } from './interceptors';
import type { Data } from './values';
export type RestMethod = 'get' | 'post' | 'delete' | 'put' | 'patch' | 'options';
export type RestEntityName = 'headers' | 'cookies' | 'query' | 'params' | 'body';
export type RestEntity<EntityName extends RestEntityName = RestEntityName> = EntityName extends 'body' ? PlainEntity : MappedEntity;
export type RestMethod = 'delete' | 'get' | 'options' | 'patch' | 'post' | 'put';
export type RestEntityName = 'body' | 'cookies' | 'headers' | 'params' | 'query';
export type RestEntity<EntityName extends RestEntityName = RestEntityName> = EntityName extends 'body' ? BodyPlainEntity : MappedEntity;
export type RestEntityNamesByMethod = {
[key in RestMethod]: key extends 'get' | 'delete' | 'options' ? Exclude<RestEntityName, 'body'> : RestEntityName;
[key in RestMethod]: key extends 'delete' | 'get' | 'options' ? Exclude<RestEntityName, 'body'> : RestEntityName;
};

@@ -15,6 +15,8 @@ export type RestEntitiesByEntityName<Method extends RestMethod = RestMethod> = {

interface RestSettings {
readonly delay?: number;
readonly polling?: boolean;
readonly status?: number;
readonly delay?: number;
}
export type RestDataResponse<Method extends RestMethod = RestMethod> = ((request: Request, entities: RestEntitiesByEntityName<Method>) => Data | Promise<Data>) | Data;
export type RestFileResponse = string;
export type RestRouteConfig<Method extends RestMethod> = ({

@@ -26,3 +28,6 @@ settings: RestSettings & {

time?: number;
data: ((request: Request, entities: RestEntitiesByEntityName<Method>) => Data | Promise<Data>) | Data;
data: RestDataResponse<Method>;
} | {
time?: number;
file: RestFileResponse;
}>;

@@ -33,3 +38,3 @@ } | {

};
data: ((request: Request, entities: RestEntitiesByEntityName<Method>) => Data | Promise<Data>) | Data;
data: RestDataResponse<Method>;
} | {

@@ -39,3 +44,3 @@ settings?: RestSettings & {

};
file: string;
file: RestFileResponse;
}) & {

@@ -47,6 +52,6 @@ entities?: RestEntitiesByEntityName<Method>;

interface BaseRestRequestConfig<Method extends RestMethod> {
path: RestPathString | RegExp;
interceptors?: Interceptors<'rest'>;
method: Method;
path: RegExp | RestPathString;
routes: RestRouteConfig<Method>[];
interceptors?: Interceptors<'rest'>;
}

@@ -59,3 +64,3 @@ type RestGetRequestConfig = BaseRestRequestConfig<'get'>;

type RestOptionsRequestConfig = BaseRestRequestConfig<'options'>;
export type RestRequestConfig = RestGetRequestConfig | RestPostRequestConfig | RestPutRequestConfig | RestDeleteRequestConfig | RestPatchRequestConfig | RestOptionsRequestConfig;
export type RestRequestConfig = RestDeleteRequestConfig | RestGetRequestConfig | RestOptionsRequestConfig | RestPatchRequestConfig | RestPostRequestConfig | RestPutRequestConfig;
export {};
import type { Request } from 'express';
import type { Arguments } from 'yargs';
import type { Database, Orm } from './database';
import type { GraphQLRequestConfig } from './graphql';
import type { Interceptors } from './interceptors';
import type { RestMethod, RestRequestConfig } from './rest';
type StaticPathObject = {
interface StaticPathObject {
path: `/${string}`;
prefix: `/${string}`;
path: `/${string}`;
};
export type StaticPath = `/${string}` | StaticPathObject | (StaticPathObject | `/${string}`)[];
}
export type StaticPath = `/${string}` | (`/${string}` | StaticPathObject)[] | StaticPathObject;
type CorsHeader = string;
export type CorsOrigin = string | RegExp | (RegExp | string)[];
export type Cors = {
origin: CorsOrigin | ((request: Request) => Promise<CorsOrigin> | CorsOrigin);
methods?: Uppercase<RestMethod>[];
export type CorsOrigin = string | (string | RegExp)[] | RegExp;
export interface Cors {
allowedHeaders?: CorsHeader[];
credentials?: boolean;
exposedHeaders?: CorsHeader[];
credentials?: boolean;
maxAge?: number;
};
methods?: Uppercase<RestMethod>[];
origin: ((request: Request) => CorsOrigin | Promise<CorsOrigin>) | CorsOrigin;
}
type Port = number;

@@ -33,17 +34,17 @@ export type BaseUrl = `/${string}`;

}
export type DatabaseConfig = {
data: Record<string, unknown> | `${string}.json`;
routes?: Record<`/${string}`, `/${string}`> | `${string}.json`;
};
export interface DatabaseConfig {
data: `${string}.json` | Record<string, unknown>;
routes?: `${string}.json` | Record<`/${string}`, `/${string}`>;
}
export interface BaseMockServerConfig {
baseUrl?: BaseUrl;
cors?: Cors;
interceptors?: Interceptors;
port?: Port;
staticPath?: StaticPath;
interceptors?: Interceptors;
cors?: Cors;
}
export interface MockServerConfig extends BaseMockServerConfig {
database?: DatabaseConfig;
graphql?: GraphqlConfig;
rest?: RestConfig;
graphql?: GraphqlConfig;
database?: DatabaseConfig;
}

@@ -59,4 +60,4 @@ export interface RestMockServerConfig extends BaseMockServerConfig {

export interface DatabaseMockServerConfig extends BaseMockServerConfig {
data: Record<string, unknown> | `${string}.json`;
routes?: Record<`/${string}`, `/${string}`> | `${string}.json`;
data: `${string}.json` | Record<string, unknown>;
routes?: `${string}.json` | Record<`/${string}`, `/${string}`>;
}

@@ -70,2 +71,29 @@ export type MockServerConfigArgv = Arguments<{

}>;
declare global {
namespace Express {
interface Request {
context: {
orm: Orm<Database>;
};
}
}
}
export interface FlatMockServerComponent {
baseUrl?: BaseUrl;
configs: Array<GraphQLRequestConfig | RestRequestConfig>;
interceptors?: Interceptors;
name?: string;
}
export interface FlatMockServerSettings {
baseUrl?: BaseUrl;
cors?: Cors;
database?: DatabaseConfig;
interceptors?: Interceptors;
port?: Port;
staticPath?: StaticPath;
}
export type FlatMockServerConfig = [
option: FlatMockServerComponent | FlatMockServerSettings,
...flatMockServerComponents: FlatMockServerComponent[]
];
export {};

@@ -1,1 +0,1 @@

export type ApiType = 'rest' | 'graphql';
export type ApiType = 'graphql' | 'rest';
import type { PlainObject } from './values';
export type ValueOf<T extends PlainObject | Array<any>> = T extends Array<any> ? T[number] : T[keyof T];
export type Entries<T extends PlainObject | Array<any>> = ValueOf<{
export type ValueOf<T extends Array<any> | PlainObject> = T extends Array<any> ? T[number] : T[keyof T];
export type Entries<T extends Array<any> | PlainObject> = ValueOf<{
[K in keyof T]-?: [K, T[K]];
}>[];
export type NestedObjectOrArray<T> = {
export type NestedObjectOrArray<T> = Array<NestedObjectOrArray<T> | T> | {
[key: string]: NestedObjectOrArray<T> | T;
} | Array<NestedObjectOrArray<T> | T>;
};

@@ -1,6 +0,5 @@

/// <reference types="node" />
import type { ParamsDictionary, Query as ExpressQuery } from 'express-serve-static-core';
import type { IncomingHttpHeaders } from 'http';
import type { Query as ExpressQuery, ParamsDictionary } from 'express-serve-static-core';
import type { IncomingHttpHeaders } from 'node:http';
export type PlainObject = Record<string, any>;
export type Primitive = boolean | number | bigint | string | null | undefined | symbol;
export type Primitive = bigint | boolean | number | string | symbol | null | undefined;
export type Headers = IncomingHttpHeaders;

@@ -7,0 +6,0 @@ export type Query = ExpressQuery;

{
"name": "mock-config-server",
"version": "3.7.1",
"version": "4.0.0",
"description": "Tool that easily and quickly imitates server operation, create full fake api in few steps",

@@ -32,2 +32,19 @@ "author": {

"license": "MIT",
"homepage": "https://github.com/siberiacancode/mock-config-server",
"repository": {
"type": "git",
"url": "https://github.com/siberiacancode/mock-config-server.git"
},
"keywords": [
"server",
"fake",
"REST",
"rest",
"API",
"api",
"mock",
"mocking",
"config",
"data"
],
"main": "dist/index.js",

@@ -43,7 +60,7 @@ "types": "./dist/index.d.ts",

"engines": {
"node": ">=12"
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
},
"scripts": {
"prepublishOnly": "git diff --exit-code",
"prepare": "husky install && yarn build",
"prepare": "husky && yarn build",
"build:types": "tsc -p tsconfig.production.json && tsc-alias -p tsconfig.production.json",

@@ -54,5 +71,7 @@ "build:swc": "swc bin src index.ts -d dist --extensions .ts --copy-files --ignore **/*.test.ts --ignore bin/templates",

"start": "yarn build && node ./dist/bin/bin.js",
"dev": "nodemon --watch src --watch bin --watch mock-server.config.* -e js,ts,ejs --exec \"yarn start\"",
"dev": "nodemon --watch src --watch bin --watch mock-server.config.* -e js,ts --exec \"yarn start\"",
"type": "tsc --noEmit",
"unit-test": "vitest",
"lint": "eslint . --ext .ts --no-error-on-unmatched-pattern --fix",
"lint": "eslint . --fix",
"lint-inspector": "npx @eslint/config-inspector",
"stylelint": "stylelint \"src/static/**/*.css\" --fix",

@@ -62,14 +81,2 @@ "format": "prettier --write \"**/*.(ts|js)\"",

},
"lint-staged": {
"*.css": [
"stylelint --fix"
],
"*.js": [
"prettier --write"
],
"*.ts": [
"prettier --write",
"eslint --no-error-on-unmatched-pattern --fix"
]
},
"dependencies": {

@@ -80,50 +87,42 @@ "@types/body-parser": "^1.19.5",

"@types/prompts": "^2.4.9",
"@types/yargs": "^17.0.32",
"@types/yargs": "^17.0.33",
"ansi-colors": "^4.1.3",
"body-parser": "^1.20.2",
"ejs": "^3.1.10",
"esbuild": "^0.21.4",
"express": "^4.19.2",
"express-urlrewrite": "^2.0.2",
"body-parser": "^2.0.2",
"esbuild": "^0.24.2",
"express": "^4.21.2",
"express-urlrewrite": "^2.0.3",
"flat": "^5.0.2",
"graphql": "^16.8.1",
"graphql": "^16.10.0",
"please-upgrade-node": "^3.2.0",
"prompts": "^2.4.2",
"yargs": "^17.7.2",
"zod": "^3.23.8"
"zod": "^3.24.1"
},
"devDependencies": {
"@siberiacancode/eslint": "^1.1.1",
"@siberiacancode/eslint": "^2.6.0",
"@siberiacancode/prettier": "^1.1.1",
"@siberiacancode/stylelint": "^1.1.1",
"@siberiacancode/vitest": "^1.2.3",
"@swc/cli": "^0.3.12",
"@swc/core": "^1.5.24",
"@siberiacancode/vitest": "^1.2.4",
"@swc/cli": "^0.6.0",
"@swc/core": "^1.10.7",
"@types/supertest": "^6.0.2",
"husky": "^9.0.11",
"lint-staged": "^15.2.5",
"nodemon": "^3.1.2",
"husky": "^9.1.7",
"lint-staged": "^15.3.0",
"nodemon": "^3.1.9",
"shx": "^0.3.4",
"style-loader": "^4.0.0",
"supertest": "^7.0.0",
"tsc-alias": "^1.8.10",
"typescript": "^5.4.5"
"typescript": "^5.7.3"
},
"homepage": "https://github.com/siberiacancode/mock-config-server",
"repository": {
"type": "git",
"url": "https://github.com/siberiacancode/mock-config-server.git"
},
"keywords": [
"server",
"fake",
"REST",
"rest",
"API",
"api",
"mock",
"mocking",
"config",
"data"
]
"lint-staged": {
"*.css": [
"stylelint --fix"
],
"*.js": [
"prettier --write"
],
"*.ts": [
"prettier --write",
"eslint --no-error-on-unmatched-pattern --fix"
]
}
}

@@ -41,6 +41,8 @@ # 🎉 Mock Config Server

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -54,5 +56,5 @@ {

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```

@@ -70,19 +72,20 @@

- `rest?` Rest configs for mock requests
- `baseUrl?` `string` part of the url that will be substituted at the beginning of rest request url (default: `'/'`)
- `configs` `Array<RestRequestConfig>` configs for mock requests, [read](#configs)
- `interceptors?` `Interceptors` functions to change request or response parameters, [read](#interceptors)
- `graphql?` GraphQL configs for mock requests
- `baseUrl?` `string` part of the url that will be substituted at the beginning of graphql request url (default: `'/'`)
- `configs` `Array<GraphQLRequestConfig>` configs for mock requests, [read](#configs)
- `interceptors?` `Interceptors` functions to change request or response parameters, [read](#interceptors)
### Settings
- `staticPath?` {StaticPath} entity for working with static files, [read](#static-path)
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
- `cors?` {Cors} CORS settings object (default: `CORS is turn off`), [read](#cors)
- `port?` {number} server port (default: `31299`)
- `baseUrl?` {string} part of the url that will be substituted at the beginning of the request url (default: `'/'`)
- `database?` Database config for mock requests [read](#database)
- `data` `Object | string` initial data for database
- `routes?` `Object | string` map of custom routes for database
- `staticPath?` `StaticPath` entity for working with static files, [read](#static-path)
- `interceptors?` `Interceptors` functions to change request or response parameters, [read](#interceptors)
- `cors?` `Cors` CORS settings object (default: `CORS is turn off`), [read](#cors)
- `port?` `number` server port (default: `31299`)
- `baseUrl?` `string` part of the url that will be substituted at the beginning of the request url (default: `'/'`)
- `data` {Object | string} initial data for database
- `routes?` {Object | string} map of custom routes for database
### Components
- `name` {string} name of component
- `baseUrl?` {string} part of the url that will be substituted at the beginning of rest request url (default: `'/'`)
- `configs` {Array<RestRequestConfig | GraphQLRequestConfig>} configs for mock requests, [read](#configs)
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
### Configs

@@ -110,6 +113,8 @@

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -136,5 +141,5 @@ {

}
};
];
module.exports = mockServerConfig;
export default flatMockServerConfig;
```

@@ -175,6 +180,8 @@

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
graphql: {
baseUrl: '/graphql',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/graphql'
},
{
configs: [

@@ -201,5 +208,5 @@ {

}
};
];
module.exports = mockServerConfig;
export default flatMockServerConfig;
```

@@ -246,9 +253,9 @@

Value for `checkMode` except `function` | `exists` | `notExists` can be array, so you can write even more complex logic. For example "does not contain these values" or "must be match to one of these regExp".
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -262,8 +269,9 @@ {

headers: {
// 'name-header' is 'Dmitriy' or 'Nursultan'
// 'name-header' is 'Dmitriy'
'name-header': {
checkMode: 'equals',
value: ['Dmitriy', 'Nursultan']
value: 'Dmitriy'
},
// check for 'equals' if descriptor not provided
// i.e. it is the same as `role: { checkMode: 'equals', value: 'developer' }`
role: 'developer'

@@ -276,10 +284,10 @@ },

},
// 'someSecretToken' cookie can be '123-abc' or 'abc-999' for example
// 'someSecretToken' cookie can be '123-abc' or '456-abc' for example
someSecretToken: {
checkMode: 'regExp',
value: [/^\d\d\d-abc$/, /^abc-\d\d\d$/]
value: /^\d\d\d-abc$/
}
}
},
data: 'Some user data for Dmitriy and Nursultan'
data: 'Some user data for Dmitriy'
}

@@ -290,15 +298,20 @@ ]

}
};
];
module.exports = mockServerConfig;
export default flatMockServerConfig;
```
Also you can use array as value for REST body and GraphQL variables entities: in this case mock-config-server will iterate
over array until `checkMode=equals` finds a match or return 404
#### Descriptor _oneOf_ property
For `checkMode` with the `value` property (all `checkMode` options except `exists` and `notExists`) you can use an array as value.
Mock server will find matches by iterating through the array until **some** match is found.
To be able to use this functionality you need to explicitly set `oneOf: true` property in descriptor object.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -311,6 +324,21 @@ {

entities: {
// if body equals to { key1: 'value1' } or ['value1'] then mock-config-server return data
body: [{ key1: 'value1' }, ['value1']]
// if body equals to { key1: 'value1' } OR { key2: 'value2' } then mock-config-server return 'Some user data 1'
body: {
checkMode: 'equals',
value: [{ key1: 'value1' }, { key2: 'value2' }],
oneOf: true
}
},
data: 'Some user data'
data: 'Some user data 1'
},
{
entities: {
// if body equals to [{ key1: 'value1' }, { key2: 'value2' }] then mock-config-server return 'Some user data 2'
// NO `oneOf` => array processed entirely
body: {
checkMode: 'equals',
value: [{ key1: 'value1' }, { key2: 'value2' }]
}
},
data: 'Some user data 2'
}

@@ -321,7 +349,9 @@ ]

}
};
];
module.exports = mockServerConfig;
export default flatMockServerConfig;
```
#### Function check mode
`function checkMode` is the most powerful way to describe your `entities` logic, but in most cases you will be fine using other `checkModes`.

@@ -336,6 +366,8 @@

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -357,3 +389,3 @@ {

checkMode: 'function',
value: (actualValue, checkFunction) =>
value: (actualValue, checkFunction) =>
checkFunction('equals', actualValue, 123) ||

@@ -370,5 +402,5 @@ checkFunction('startsWith', actualValue, 2)

}
};
];
module.exports = mockServerConfig;
module.exports = flatMockServerConfig;
```

@@ -378,10 +410,11 @@

If you want to check a certain field of your body or variables, you can use descriptors in flatten object style. In this case server will check every field in entity with corresponding actual field.
You can use descriptors for array body elements as well.
If you want to check a deep nested property of your body or variables via descriptor you can use flatten object style. In this case server will check every field in entity with corresponding actual field. I.e. you can use descriptors only for properties of entity object (not for properties of nested objects).
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -395,3 +428,7 @@ {

body: {
'user.name': 'Sergey'
// if body has properties like { user: { name: 'Sergey' } } OR { 'user.name': 'Sergey' } then mock-config-server return data
'user.name': {
checkMode: 'equals',
value: 'Sergey'
}
}

@@ -402,52 +439,21 @@ },

]
},
{
path: '/posts',
method: 'post',
routes: [
{
entities: {
body: {
title: {
checkMode: 'startsWith',
value: 'A'
}
}
},
data: 'title in body starts with "A"'
}
]
},
{
path: '/posts',
method: 'post',
routes: [
{
entities: {
body: [
{
checkMode: 'startsWith',
value: 1
},
2
]
},
data: 'array[0] starts with "1" and array[1] equals "2"'
}
]
}
]
}
};
];
module.exports = mockServerConfig;
export default flatMockServerConfig;
```
> To enable whole body/variables checking as plain object you should use descriptor for entire body/variables.
You can also use descriptor for whole body or variables entity.
> When you use 'equals'/'notEquals' check mode for whole body or variables mock-config-server is strictly compare entity and actual value. It means that you must specify **ALL** properties from actual body or variables.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -461,2 +467,3 @@ {

body: {
// if actual body contains some extra property(-ies) then this entity won't match
checkMode: 'equals',

@@ -478,29 +485,25 @@ value: {

}
};
];
module.exports = mockServerConfig;
export default flatMockServerConfig;
```
#### Polling
#### File responses
Routes support polling for data. To add polling for data, you must specify the `polling setting` and change `data` property to `queue`.
Rest routes support paths to files. If a route is matched, the server will send data from the file. If the file is not found, the server will return 404.
> After receiving the last value from polling, the queue is reset and the next request will return the first value from the queue.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [
{
path: '/user',
path: '/files/settings',
method: 'get',
routes: [
{
settings: { polling: true },
queue: [
{ data: { emoji: '🦁', name: 'Nursultan' } },
{ data: { emoji: '☄', name: 'Dmitriy' } }
]
file: './settings.json'
}

@@ -511,25 +514,41 @@ ]

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```
Using the additional `time` properties in milliseconds, you can specify how much time certain data should be returned
> If the file path is absolute, then this path will be used as is. If the file path is relative, it will be appended to the current working directory.
If the file exists, response interceptors will receive `file descriptor` as the `data` argument:
`File descriptor` is an object with `path` and `file` fields that describe file location and file content.
- `path` `string` path to the file. Same as `file` passed in route
- `file` `Buffer` file content as binary buffer
> Note to return file descriptor from interceptor. Server will send a buffer from `data.file` with corresponding `Content-Type` and `Content-Disposition` headers.
> If you return invalid file descriptor, server will send it as json data.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [
{
path: '/user',
path: '/files/settings',
method: 'get',
routes: [
{
settings: { polling: true },
queue: [
{ time: 5000, data: { emoji: '🦁', name: 'Nursultan' } },
{ data: { emoji: '☄', name: 'Dmitriy' } }
]
file: './settings.json',
interceptors: {
response: (data) => {
const { file, path } = data;
const buffer = file; // some logic with buffer
fs.writeFileSync(path, buffer); // rewrite ./settings.json file on disk with new content
return { path, file: buffer };
}
}
}

@@ -540,23 +559,38 @@ ]

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```
#### File responses
> Any changes to the data will not affect the file on disk unless you manually rewrite it.
Rest routes support paths to files. If a route is matched, the server will send data from the file. If the file is not found, the server will return 404.
> If you return a new `path` from interceptor, server will send file corresponding to this path or 404 error otherwise.
#### Polling
Routes support polling for data. To add polling for data, you must specify the `polling setting` and use `queue` property instead of `data` or `file`.
`queue` is an array containing `data` or `file` that should be returned in order.
> After receiving the last value from polling, the queue is reset and the next request will return the first value from the queue.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [
{
path: '/files/settings',
path: '/user',
method: 'get',
routes: [
{
file: './settings.json'
settings: { polling: true },
queue: [
{ data: { emoji: '🦁', name: 'Nursultan' } },
{ data: { emoji: '☄', name: 'Dmitriy' } },
{ file: './users/Sergey.json' }
]
}

@@ -567,29 +601,27 @@ ]

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```
> If the file path is absolute, then this path will be used as is. If the file path is relative, it will be appended to the current working directory.
Using the additional `time` properties in milliseconds, you can specify how much time certain data should be returned
If the file exists, response interceptors will receive null as the data argument.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [
{
path: '/files/settings',
path: '/user',
method: 'get',
routes: [
{
file: './settings.json',
interceptors: {
response: (data) => {
console.log(data); // null
return data;
}
}
settings: { polling: true },
queue: [
{ time: 5000, data: { emoji: '🦁', name: 'Nursultan' } },
{ data: { emoji: '☄', name: 'Dmitriy' } }
]
}

@@ -600,9 +632,7 @@ ]

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```
> Any changes to the data will not affect the file (and the response, respectively).
#### Static Path

@@ -713,6 +743,8 @@

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -726,15 +758,19 @@ {

request: ({ log }) => {
log({ // logs following object in terminal
options: { // {
id: true, // id: 1,
type: true, // type: 'request',
timestamp: true, // timestamp: '31.12.2024, 23:59:59,999',
method: true, // method: 'GET',
url: true // url: 'http://localhost:31299/api/rest/posts/1'
} // }
log({
// logs following object in terminal
options: {
// {
id: true, // id: 1,
type: true, // type: 'request',
timestamp: true, // timestamp: '31.12.2024, 23:59:59,999',
method: true, // method: 'GET',
url: true // url: 'http://localhost:31299/api/rest/posts/1'
} // }
});
},
response: (data, { log }) => {
log({ // logs following string in terminal
options: { // response get: http://localhost:31299/api/rest/posts/1 => 200
log({
// logs following string in terminal
options: {
// response get: http://localhost:31299/api/rest/posts/1 => 200
type: true,

@@ -757,5 +793,5 @@ statusCode: true,

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```

@@ -766,3 +802,3 @@

> Method transforms from lower case to upper case.
> If `rewrite` function is used, those tokens will remain unformatted. You can format them as you need.
> If `rewrite` function is used, those tokens will remain unformatted. You can format them as you need.

@@ -787,2 +823,3 @@ ##### Logger tokens

Response logger has additional tokens
- `statusCode?` `number` response status code

@@ -794,4 +831,4 @@ - `data?` `any` data returned to client

- if some token is `true`, entity will be filtered by `whitelist` logic. *Only* enabled ones will be logged.
- if all tokens is `false`, entity will be filtered by `blacklist` logic. All entities will be logged *except* disabled ones.
- if some token is `true`, entity will be filtered by `whitelist` logic. _Only_ enabled ones will be logged.
- if all tokens is `false`, entity will be filtered by `blacklist` logic. All entities will be logged _except_ disabled ones.

@@ -801,6 +838,8 @@ > Whitelist logic have priority over blacklist if you pass `true` and `false` in same entity.

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
/** @type {import('mock-config-server').FlatMockServerConfig} */
const flatMockServerConfig = [
{
baseUrl: '/api'
},
{
configs: [

@@ -814,3 +853,4 @@ {

request: ({ log }) => {
log({ // whitelist. only query1 and query2 will be logged
log({
// whitelist. only query1 and query2 will be logged
options: {

@@ -823,3 +863,4 @@ query: {

});
log({ // whitelist. only cookie1 and cookie2 will be logged
log({
// whitelist. only cookie1 and cookie2 will be logged
options: {

@@ -833,3 +874,4 @@ cookies: {

});
log({ // blacklist. all headers will be logged except header1
log({
// blacklist. all headers will be logged except header1
options: {

@@ -849,5 +891,5 @@ headers: {

}
};
];
export default mockServerConfig;
export default flatMockServerConfig;
```

@@ -865,12 +907,14 @@

```javascript
const mockServerConfig = {
database: {
data: {
users: [{ id: 1, name: 'John' }],
settings: {
blocked: false
const flatMockServerConfig = [
{
database: {
data: {
users: [{ id: 1, name: 'John' }],
settings: {
blocked: false
}
}
}
}
};
];
```

@@ -912,16 +956,18 @@

```javascript
const mockServerConfig = {
database: {
data: {
users: [{ id: 1, name: 'John' }],
settings: {
blocked: false
const flatMockServerConfig = [
{
database: {
data: {
users: [{ id: 1, name: 'John' }],
settings: {
blocked: false
}
},
routes: {
'/api/users/:id': '/users/:id',
'/*/my-settings': '/settings'
}
},
routes: {
'/api/users/:id': '/users/:id',
'/*/my-settings': '/settings'
}
}
};
];
```

@@ -1027,8 +1073,10 @@

```javascript
const mockServerConfig = {
database: {
data: './data.json',
routes: './routes.json'
const flatMockServerConfig = [
{
database: {
data: './data.json',
routes: './routes.json'
}
}
};
];
```

@@ -1035,0 +1083,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc