Skip to content

Commit

Permalink
Go
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Aug 10, 2022
1 parent 683b736 commit cef78e1
Show file tree
Hide file tree
Showing 23 changed files with 493 additions and 1,978 deletions.
2 changes: 1 addition & 1 deletion examples/hello-world-esm/.meshrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sources:
method: GET
path: /
responseSample: greeting.json
transforms:
plugins:
- mock:
mocks:
- apply: Query.greeting
Expand Down
2 changes: 1 addition & 1 deletion examples/hello-world-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@graphql-mesh/cli": "0.75.7",
"@graphql-mesh/json-schema": "0.31.0",
"@graphql-mesh/transform-mock": "0.15.6",
"@graphql-mesh/plugin-mock": "0.0.0",
"graphql": "16.5.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/hello-world/.meshrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sources:
method: GET
path: /
responseSample: greeting.json
transforms:
plugins:
- mock:
mocks:
- apply: Query.greeting
Expand Down
2 changes: 1 addition & 1 deletion examples/hello-world/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"dependencies": {
"@graphql-mesh/cli": "0.75.7",
"@graphql-mesh/json-schema": "0.31.0",
"@graphql-mesh/transform-mock": "0.15.6",
"@graphql-mesh/plugin-mock": "0.0.0",
"graphql": "16.5.0"
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions examples/json-schema-example/.meshrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ transforms:
- namingConvention:
typeNames: pascalCase
fieldNames: camelCase

plugins:
- mock:
mocks:
- apply: User.firstName
Expand Down
2 changes: 1 addition & 1 deletion examples/json-schema-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@graphql-mesh/cli": "0.75.7",
"@graphql-mesh/json-schema": "0.31.0",
"@graphql-mesh/transform-mock": "0.15.6",
"@graphql-mesh/plugin-mock": "0.0.0",
"graphql": "16.5.0"
},
"devDependencies": {
Expand Down
6 changes: 5 additions & 1 deletion packages/config/src/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ export async function processConfig(
Promise.all(
config.plugins?.map(async (p, pluginIndex) => {
const pluginName = Object.keys(p)[0].toString();
const pluginConfig = p[pluginName];
const pluginConfig: any = p[pluginName];
if (ENVELOP_CORE_PLUGINS_MAP[pluginName] != null) {
const { importName, moduleName, pluginFactory } = ENVELOP_CORE_PLUGINS_MAP[pluginName];
if (options.generateCode) {
Expand Down Expand Up @@ -340,6 +340,8 @@ export async function processConfig(
logger: logger.child(${JSON.stringify(pluginName)}),
cache,
pubsub,
baseDir,
importFn,
})`);
}
} else {
Expand All @@ -360,6 +362,8 @@ export async function processConfig(
logger: logger.child(pluginName),
cache,
pubsub,
baseDir: dir,
importFn,
});
}) || []
),
Expand Down
2 changes: 1 addition & 1 deletion packages/container/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@graphql-mesh/odata": "0.18.9",
"@graphql-mesh/soap": "0.12.7",
"@graphql-mesh/postgraphile": "0.20.39",
"@graphql-mesh/transform-mock": "0.15.6",
"@graphql-mesh/plugin-mock": "0.0.0",
"@graphql-mesh/transform-prefix": "0.11.62",
"@graphql-mesh/transform-encapsulate": "0.3.74",
"@graphql-mesh/transform-cache": "0.12.28",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@graphql-mesh/transform-mock",
"version": "0.15.6",
"name": "@graphql-mesh/plugin-mock",
"version": "0.0.0",
"sideEffects": false,
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand All @@ -22,14 +22,11 @@
"repository": {
"type": "git",
"url": "Urigo/graphql-mesh",
"directory": "packages/transforms/mock"
"directory": "packages/plugins/mock"
},
"peerDependencies": {
"graphql": "*"
},
"devDependencies": {
"@types/faker": "5.5.9"
},
"dependencies": {
"@graphql-mesh/cross-helpers": "0.2.0",
"@graphql-mesh/types": "0.78.6",
Expand All @@ -40,8 +37,14 @@
"@graphql-tools/schema": "9.0.0",
"faker": "5.5.3",
"graphql-scalars": "1.17.0",
"@envelop/core": "^2.3.2",
"tslib": "^2.4.0"
},
"devDependencies": {
"@types/faker": "5.5.9",
"@envelop/core": "2.4.2",
"@graphql-mesh/cache-localforage": "0.6.23"
},
"publishConfig": {
"access": "public",
"directory": "dist"
Expand Down
146 changes: 146 additions & 0 deletions packages/plugins/mock/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { MeshPluginOptions, YamlConfig } from '@graphql-mesh/types';
import { Plugin } from '@envelop/core';
import faker from 'faker';
import { mocks as graphqlScalarsMocks } from 'graphql-scalars';
import { addMocksToSchema, createMockStore, IMocks } from '@graphql-tools/mock';
import { loadFromModuleExportExpression } from '@graphql-mesh/utils';
import { getInterpolatedStringFactory } from '@graphql-mesh/string-interpolation';
import { GraphQLResolveInfo, GraphQLFieldResolver, GraphQLSchema, execute } from 'graphql';

const mockedSchemas = new WeakSet<GraphQLSchema>();

// eslint-disable-next-line @typescript-eslint/ban-types
export default function useMock(config: MeshPluginOptions<YamlConfig.MockingConfig>): Plugin<{}> {
const configIf = config != null && 'if' in config ? config.if : true;

if (configIf) {
return {
onSchemaChange({ schema, replaceSchema }) {
if (mockedSchemas.has(schema)) {
return;
}
const mocks: IMocks = {
...graphqlScalarsMocks,
};
const resolvers: any = {};
const typeMap = schema.getTypeMap();
for (const typeName in typeMap) {
const type = typeMap[typeName];
const examples = type.extensions.examples as any[];
if (examples?.length) {
mocks[typeName] = () => examples[Math.floor(Math.random() * examples.length)];
}
}
if (config?.mocks?.length) {
for (const fieldConfig of config.mocks) {
const fieldConfigIf = 'if' in fieldConfig ? fieldConfig.if : true;
if (fieldConfigIf) {
const [typeName, fieldName] = fieldConfig.apply.split('.');
if (fieldName) {
if (fieldConfig.faker) {
let fakerFn: Function; // eslint-disable-line
const [service, method] = fieldConfig.faker.split('.');
if (service in faker) {
fakerFn = () => (faker as any)[service][method]();
} else {
fakerFn = () => faker.fake(fieldConfig.faker || '');
}
resolvers[typeName] = resolvers[typeName] || {};
resolvers[typeName][fieldName] = fakerFn;
} else if (fieldConfig.custom) {
const exportedVal$ = loadFromModuleExportExpression<any>(fieldConfig.custom, {
cwd: config.baseDir,
defaultExportName: 'default',
importFn: config.importFn,
});
resolvers[typeName] = resolvers[typeName] || {};
resolvers[typeName][fieldName] = (root: any, args: any, context: any, info: GraphQLResolveInfo) => {
context = context || {};
context.mockStore = store;
return exportedVal$.then(exportedVal =>
typeof exportedVal === 'function' ? exportedVal(root, args, context, info) : exportedVal
);
};
} else if ('length' in fieldConfig) {
resolvers[typeName] = resolvers[typeName] || {};
resolvers[typeName][fieldName] = () => new Array(fieldConfig.length).fill({});
} else if ('updateStore' in fieldConfig) {
const getFromStoreKeyFactory = getInterpolatedStringFactory(fieldConfig.store.key);
const updateStoreFactories = fieldConfig.updateStore.map(updateStoreConfig => ({
updateStoreConfig,
keyFactory: getInterpolatedStringFactory(updateStoreConfig.key),
valueFactory: getInterpolatedStringFactory(updateStoreConfig.value),
}));
resolvers[typeName] = resolvers[typeName] || {};
resolvers[typeName][fieldName] = (root: any, args: any, context: any, info: GraphQLResolveInfo) => {
const resolverData = { root, args, context, info, random: Date.now().toString(), env: process.env };
updateStoreFactories.forEach(({ updateStoreConfig, keyFactory, valueFactory }) => {
const key = keyFactory(resolverData);
const value = valueFactory(resolverData);
store.set(updateStoreConfig.type, key, updateStoreConfig.fieldName, value);
});
const key = getFromStoreKeyFactory(resolverData);
return store.get(fieldConfig.store.type, key, fieldConfig.store.fieldName);
};
} else if ('store' in fieldConfig) {
const keyFactory = getInterpolatedStringFactory(fieldConfig.store.key);
resolvers[typeName] = resolvers[typeName] || {};
resolvers[typeName][fieldName] = (root: any, args: any, context: any, info: GraphQLResolveInfo) => {
const key = keyFactory({ root, args, context, info, env: process.env });
return store.get(fieldConfig.store.type, key, fieldConfig.store.fieldName);
};
}
} else {
if (fieldConfig.faker) {
let fakerFn: GraphQLFieldResolver<any, any, { [argName: string]: any }>;
const [service, method] = fieldConfig.faker.split('.');
if (service in faker) {
fakerFn = () => (faker as any)[service][method]();
} else {
fakerFn = () => faker.fake(fieldConfig.faker || '');
}
mocks[typeName] = fakerFn;
} else if (fieldConfig.custom) {
const exportedVal$ = loadFromModuleExportExpression<any>(fieldConfig.custom, {
cwd: config.baseDir,
defaultExportName: 'default',
importFn: config.importFn,
});
mocks[typeName] = () => {
return exportedVal$.then(exportedVal =>
typeof exportedVal === 'function' ? exportedVal(store) : exportedVal
);
};
}
}
}
}
}
const store = createMockStore({ schema, mocks });
if (config?.initializeStore) {
const initializeStoreFn$ = loadFromModuleExportExpression(config.initializeStore, {
cwd: config.baseDir,
defaultExportName: 'default',
importFn: config.importFn,
});
// eslint-disable-next-line no-void
void initializeStoreFn$.then(fn => fn(store));
}
const mockedSchema = addMocksToSchema({
schema,
store,
mocks,
resolvers,
preserveResolvers: config?.preserveResolvers,
});
mockedSchemas.add(mockedSchema);
replaceSchema(mockedSchema);
},
onExecute({ setExecuteFn }) {
setExecuteFn(execute);
},
};
}

return {};
}
Loading

0 comments on commit cef78e1

Please sign in to comment.