@graphql-codegen/cli
Version:
<p align="center"> <img src="https://github.com/dotansimha/graphql-code-generator/blob/master/logo.png?raw=true" /> </p>
141 lines (140 loc) • 6.1 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWatcher = void 0;
const tslib_1 = require("tslib");
const codegen_js_1 = require("../codegen.js");
const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
const is_glob_1 = tslib_1.__importDefault(require("is-glob"));
const debounce_1 = tslib_1.__importDefault(require("debounce"));
const log_symbols_1 = tslib_1.__importDefault(require("log-symbols"));
const debugging_js_1 = require("./debugging.js");
const logger_js_1 = require("./logger.js");
const path_1 = require("path");
const hooks_js_1 = require("../hooks.js");
const config_js_1 = require("../config.js");
const utils_1 = require("@graphql-tools/utils");
function log(msg) {
// double spaces to inline the message with Listr
(0, logger_js_1.getLogger)().info(` ${msg}`);
}
function emitWatching() {
log(`${log_symbols_1.default.info} Watching for changes...`);
}
const createWatcher = (initalContext, onNext) => {
(0, debugging_js_1.debugLog)(`[Watcher] Starting watcher...`);
let config = initalContext.getConfig();
const files = [initalContext.filepath].filter(a => a);
const documents = (0, plugin_helpers_1.normalizeInstanceOrArray)(config.documents);
const schemas = (0, plugin_helpers_1.normalizeInstanceOrArray)(config.schema);
// Add schemas and documents from "generates"
Object.keys(config.generates)
.map(filename => (0, plugin_helpers_1.normalizeOutputParam)(config.generates[filename]))
.forEach(conf => {
schemas.push(...(0, plugin_helpers_1.normalizeInstanceOrArray)(conf.schema));
documents.push(...(0, plugin_helpers_1.normalizeInstanceOrArray)(conf.documents));
});
if (documents) {
documents.forEach(doc => {
if (typeof doc === 'string') {
files.push(doc);
}
else {
files.push(...Object.keys(doc));
}
});
}
schemas.forEach((schema) => {
if ((0, is_glob_1.default)(schema) || (0, utils_1.isValidPath)(schema)) {
files.push(schema);
}
});
if (typeof config.watch !== 'boolean') {
files.push(...(0, plugin_helpers_1.normalizeInstanceOrArray)(config.watch));
}
let watcher;
const runWatcher = async () => {
var _a, _b;
const chokidar = await Promise.resolve().then(() => tslib_1.__importStar(require('chokidar')));
let isShutdown = false;
const debouncedExec = (0, debounce_1.default)(() => {
if (!isShutdown) {
(0, codegen_js_1.executeCodegen)(initalContext)
.then(onNext, () => Promise.resolve())
.then(() => emitWatching());
}
}, 100);
emitWatching();
const ignored = [];
Object.keys(config.generates)
.map(filename => ({ filename, config: (0, plugin_helpers_1.normalizeOutputParam)(config.generates[filename]) }))
.forEach(entry => {
if (entry.config.preset) {
const extension = entry.config.presetConfig && entry.config.presetConfig.extension;
if (extension) {
ignored.push((0, path_1.join)(entry.filename, '**', '*' + extension));
}
}
else {
ignored.push(entry.filename);
}
});
watcher = chokidar.watch(files, {
persistent: true,
ignoreInitial: true,
followSymlinks: true,
cwd: process.cwd(),
disableGlobbing: false,
usePolling: (_a = config.watchConfig) === null || _a === void 0 ? void 0 : _a.usePolling,
interval: (_b = config.watchConfig) === null || _b === void 0 ? void 0 : _b.interval,
depth: 99,
awaitWriteFinish: true,
ignorePermissionErrors: false,
atomic: true,
ignored,
});
(0, debugging_js_1.debugLog)(`[Watcher] Started`);
const shutdown = () => {
isShutdown = true;
(0, debugging_js_1.debugLog)(`[Watcher] Shutting down`);
log(`Shutting down watch...`);
watcher.close();
(0, hooks_js_1.lifecycleHooks)(config.hooks).beforeDone();
};
// it doesn't matter what has changed, need to run whole process anyway
watcher.on('all', async (eventName, path) => {
(0, hooks_js_1.lifecycleHooks)(config.hooks).onWatchTriggered(eventName, path);
(0, debugging_js_1.debugLog)(`[Watcher] triggered due to a file ${eventName} event: ${path}`);
const fullPath = (0, path_1.join)(process.cwd(), path);
// In ESM require is not defined
try {
delete require.cache[fullPath];
}
catch (err) { }
if (eventName === 'change' && config.configFilePath && fullPath === config.configFilePath) {
log(`${log_symbols_1.default.info} Config file has changed, reloading...`);
const context = await (0, config_js_1.loadContext)(config.configFilePath);
const newParsedConfig = context.getConfig();
newParsedConfig.watch = config.watch;
newParsedConfig.silent = config.silent;
newParsedConfig.overwrite = config.overwrite;
newParsedConfig.configFilePath = config.configFilePath;
config = newParsedConfig;
initalContext.updateConfig(config);
}
debouncedExec();
});
process.once('SIGINT', shutdown);
process.once('SIGTERM', shutdown);
};
// the promise never resolves to keep process running
return new Promise((resolve, reject) => {
(0, codegen_js_1.executeCodegen)(initalContext)
.then(onNext, () => Promise.resolve())
.then(runWatcher)
.catch(err => {
watcher.close();
reject(err);
});
});
};
exports.createWatcher = createWatcher;
;