@graphql-mesh/migrate-config-cli
Version:
131 lines (130 loc) • 4.91 kB
JavaScript
// eslint-disable-next-line import/no-nodejs-modules
import { existsSync, writeFileSync } from 'node:fs';
// eslint-disable-next-line import/no-nodejs-modules
import { join } from 'node:path';
import { format } from 'prettier';
import { findConfig } from '@graphql-mesh/cli';
import { getPackage } from '@graphql-mesh/config';
import { defaultImportFn } from '@graphql-mesh/utils';
import { migrateLegacyConfig, } from './migrate.js';
export { migrateLegacyConfig } from './migrate.js';
function pluginFactoryName(pluginName) {
const cleaned = pluginName.replace(/^@/, '').replace(/[^a-zA-Z0-9]+/g, '_');
return camelCase(`use_${cleaned}`);
}
function camelCase(value) {
return value.replace(/[-_]+(\w)/g, (_, char) => char.toUpperCase());
}
export const createDefaultPluginResolver = (cwd) => async ({ name }) => {
try {
const { resolved: possiblePluginFactory, moduleName } = await getPackage({
name,
type: 'plugin',
importFn: defaultImportFn,
cwd,
additionalPrefixes: ['@envelop/', '@graphql-yoga/plugin-', '@escape.tech/graphql-armor-'],
});
if (typeof possiblePluginFactory === 'function') {
const fnName = pluginFactoryName(name);
return {
moduleName,
importName: `default as ${fnName}`,
factoryName: fnName,
};
}
const importName = Object.keys(possiblePluginFactory || {}).find(iName => (iName.toString().startsWith('use') || iName.toString().endsWith('Plugin')) &&
typeof possiblePluginFactory[iName] === 'function');
if (!importName) {
return undefined;
}
return {
moduleName,
importName: importName.toString(),
factoryName: importName.toString(),
};
}
catch (error) {
console.warn(`Plugin "${name}" could not be loaded: ${error instanceof Error ? error.message : String(error)}`);
return undefined;
}
};
export async function run(argv = process.argv) {
const args = argv.slice(2).filter(arg => arg !== '--');
const dryRun = args.includes('--dry-run');
const force = args.includes('--force');
const positional = args.filter(arg => !arg.startsWith('--'));
const cwd = positional[0] || process.cwd();
const { config: legacyConfig, filepath, isEmpty, } = await findConfig({
initialLoggerPrefix: 'Mesh Config Migrate',
dir: cwd,
});
const log = (...parts) => {
(dryRun ? console.error : console.log)(...parts);
};
if (isEmpty || !legacyConfig) {
console.error('No config file found');
process.exitCode = 1;
return {
code: '',
addedPackages: [],
removedPackages: [],
messages: [{ level: 'error', message: 'No config file found' }],
fatal: true,
};
}
log(`Found config at ${filepath}`);
const result = await migrateLegacyConfig(legacyConfig, {
cwd,
resolvePlugin: createDefaultPluginResolver(cwd),
});
try {
result.code = await format(result.code, { parser: 'typescript' });
}
catch (error) {
console.warn(`Could not format the generated config: ${error instanceof Error ? error.message : String(error)}`);
}
for (const message of result.messages) {
if (message.level === 'error') {
console.error(message.message);
}
else {
console.warn(message.message);
}
}
if (result.fatal) {
console.error('Migration did not write mesh.config.ts because of the errors above.');
process.exitCode = 1;
return result;
}
const newConfigPath = join(cwd, 'mesh.config.ts');
if (!dryRun) {
if (existsSync(newConfigPath) && !force) {
console.error(`${newConfigPath} already exists. Pass --force to overwrite, or --dry-run to print the result.`);
process.exitCode = 1;
return result;
}
writeFileSync(newConfigPath, result.code);
}
else {
process.stdout.write(result.code);
}
log('Migration successful!');
log(' ');
if (!dryRun) {
log(`New config file created at ${newConfigPath}`);
log(' ');
}
log('Please make sure to install the following packages in package.json:');
for (const packageName of result.addedPackages) {
log(`- ${packageName}`);
}
log(' ');
log('Please make sure to remove the following packages in package.json:');
for (const packageName of result.removedPackages) {
log(`- ${packageName}`);
}
log(' ');
log(`Then run "npx mesh-compose -o supergraph.graphql" to generate the supergraph schema!`);
log(`Finally, run "npx hive-gateway supergraph" to start the gateway server!`);
return result;
}