@newmo/graphql-fake-server
Version:
GraphQL fake server for testing
190 lines • 7.44 kB
JavaScript
import path from "node:path";
import { pathToFileURL } from "node:url";
/**
* Default values for server configuration.
* @internal
*/
const ServerDefaults = {
ports: {
fakeServer: 4000,
apolloServer: 4002,
},
maxRegisteredSequences: 1000,
maxQueryDepth: 10,
allowedCORSOrigins: [],
allowedHosts: "auto",
};
/**
* Default log level.
* @internal
*/
const LogLevelDefault = "info";
/**
* Default values for mock generation options.
* @see RawMockConfig
* @internal
*/
const MockDefaultValues = {
maxDepth: 9,
maxTypeRecursion: 2,
listLength: 3,
};
/**
* Default values for GraphQL scalar types.
* @internal
*/
const ScalarDefaults = {
String: "string",
Int: 12,
Float: 12.3,
Boolean: true,
ID: "xxxx-xxxx-xxxx-xxxx",
};
export const normalizeFakeServerConfig = (config) => {
return {
schemaFilePath: config.schemaFilePath,
logLevel: config.logLevel ?? LogLevelDefault,
server: {
ports: {
fakeServer: config.server?.ports?.fakeServer ?? ServerDefaults.ports.fakeServer,
apolloServer: config.server?.ports?.apolloServer ?? ServerDefaults.ports.apolloServer,
},
maxRegisteredSequences: config.server?.maxRegisteredSequences ?? ServerDefaults.maxRegisteredSequences,
maxQueryDepth: config.server?.maxQueryDepth ?? ServerDefaults.maxQueryDepth,
allowedCORSOrigins: config.server?.allowedCORSOrigins ?? ServerDefaults.allowedCORSOrigins,
allowedHosts: config.server?.allowedHosts ?? ServerDefaults.allowedHosts,
},
mock: {
maxDepth: config.mock?.maxDepth ?? MockDefaultValues.maxDepth,
maxTypeRecursion: config.mock?.maxTypeRecursion ?? MockDefaultValues.maxTypeRecursion,
listLength: config.mock?.listLength ?? MockDefaultValues.listLength,
defaultValues: {
String: config.mock?.defaultValues?.String ?? ScalarDefaults.String,
Int: config.mock?.defaultValues?.Int ?? ScalarDefaults.Int,
Float: config.mock?.defaultValues?.Float ?? ScalarDefaults.Float,
Boolean: config.mock?.defaultValues?.Boolean ?? ScalarDefaults.Boolean,
ID: config.mock?.defaultValues?.ID ?? ScalarDefaults.ID,
CustomScalar: config.mock?.defaultValues?.CustomScalar ?? {},
},
},
};
};
export const validateFakeServerConfig = (config) => {
if (!config.schemaFilePath) {
throw new Error("The schemaFilePath is required.");
}
if (typeof config.schemaFilePath !== "string") {
throw new Error("The schemaPath must be a string.");
}
// logLevel validation
if (config.logLevel && !["debug", "info", "warn", "error"].includes(config.logLevel)) {
throw new Error("The logLevel must be one of 'debug', 'info', 'warn', 'error'.");
}
// Server validation
if (config.server) {
if (typeof config.server !== "object") {
throw new Error("The server must be an object.");
}
if (config.server.ports) {
if (typeof config.server.ports !== "object") {
throw new Error("The server.ports must be an object.");
}
if (config.server.ports.fakeServer &&
typeof config.server.ports.fakeServer !== "number") {
throw new Error("The server.ports.fakeServer must be a number.");
}
if (config.server.ports.apolloServer &&
typeof config.server.ports.apolloServer !== "number") {
throw new Error("The server.ports.apolloServer must be a number.");
}
}
if (config.server.maxRegisteredSequences &&
typeof config.server.maxRegisteredSequences !== "number") {
throw new Error("The server.maxRegisteredSequences must be a number.");
}
if (config.server.maxQueryDepth && typeof config.server.maxQueryDepth !== "number") {
throw new Error("The server.maxQueryDepth must be a number.");
}
if (config.server.allowedCORSOrigins) {
if (!Array.isArray(config.server.allowedCORSOrigins)) {
throw new Error("The server.allowedCORSOrigins must be an array.");
}
for (const origin of config.server.allowedCORSOrigins) {
if (typeof origin !== "string") {
throw new Error("Each server.allowedCORSOrigin must be a string.");
}
}
}
if (config.server.allowedHosts) {
if (config.server.allowedHosts !== "auto" &&
!Array.isArray(config.server.allowedHosts)) {
throw new Error("The server.allowedHosts must be 'auto' or an array of strings.");
}
if (Array.isArray(config.server.allowedHosts)) {
for (const host of config.server.allowedHosts) {
if (typeof host !== "string") {
throw new Error("Each server.allowedHost must be a string.");
}
}
}
}
}
// Mock validation
if (config.mock) {
if (typeof config.mock !== "object") {
throw new Error("The mock must be an object.");
}
if (config.mock.maxDepth !== undefined) {
if (typeof config.mock.maxDepth !== "number") {
throw new Error("The mock.maxDepth must be a number.");
}
if (config.mock.maxDepth < 1) {
throw new Error("The mock.maxDepth must be at least 1.");
}
}
if (config.mock.maxTypeRecursion !== undefined) {
if (typeof config.mock.maxTypeRecursion !== "number") {
throw new Error("The mock.maxTypeRecursion must be a number.");
}
if (config.mock.maxTypeRecursion < 1) {
throw new Error("The mock.maxTypeRecursion must be at least 1.");
}
}
if (config.mock.listLength !== undefined && typeof config.mock.listLength !== "number") {
throw new Error("The mock.listLength must be a number.");
}
if (config.mock.defaultValues) {
if (typeof config.mock.defaultValues !== "object") {
throw new Error("The mock.defaultValues must be an object.");
}
}
}
return config;
};
/**
* Load the fake server configuration from the file.
* @param configPath
*/
export const loadConfig = async (cwd, configPath) => {
const fileUrl = pathToFileURL(path.resolve(cwd, configPath)).href;
const { default: config } = await import(fileUrl);
const normalizedConfig = normalizeFakeServerConfig(config);
validateFakeServerConfig(normalizedConfig);
return normalizedConfig;
};
/**
* Load the fake server configuration from the CLI flags.
* @param cliFlag
*/
export const loadFakeServerConfigFromCLI = ({ schemaFilePath, logLevel, }) => {
if (!schemaFilePath) {
throw new Error("The --schema is required. or pass --config ./fake-server.config.js to load the config file.");
}
const normalizedConfig = normalizeFakeServerConfig({
schemaFilePath,
logLevel,
});
validateFakeServerConfig(normalizedConfig);
return normalizedConfig;
};
//# sourceMappingURL=config.js.map