@graphql-hive/cli
Version:
A CLI util to manage and control your GraphQL Hive
121 lines • 4.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadAppOperations = loadAppOperations;
const node_crypto_1 = require("node:crypto");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const graphql_1 = require("graphql");
const zod_1 = require("zod");
const graphql_file_loader_1 = require("@graphql-tools/graphql-file-loader");
const load_1 = require("@graphql-tools/load");
const core_1 = require("@oclif/core");
const errors_1 = require("./errors");
const ManifestModel = zod_1.z.record(zod_1.z.string());
const ApolloManifestModel = zod_1.z.object({
format: zod_1.z.literal('apollo-persisted-query-manifest'),
version: zod_1.z.literal(1),
operations: zod_1.z.array(zod_1.z.object({
id: zod_1.z.string(),
body: zod_1.z.string(),
})),
});
async function loadAppOperations(file) {
var _a;
const isFile = (() => {
try {
return (0, node_fs_1.statSync)(file).isFile();
}
catch (_a) {
return false;
}
})();
if (isFile) {
const input = JSON.parse(await node_fs_1.promises.readFile(file, 'utf8'));
const manifestValidationResult = ManifestModel.safeParse(input);
let entries;
if (manifestValidationResult.success) {
entries = Object.entries(manifestValidationResult.data);
}
else {
const apolloValidationResult = ApolloManifestModel.safeParse(input);
if (!apolloValidationResult.success) {
throw new errors_1.PersistedOperationsMalformedError(file);
}
entries = apolloValidationResult.data.operations.map(operation => [
operation.id,
operation.body,
]);
}
const location = (0, node_path_1.relative)(process.cwd(), file);
return {
manifest: Object.fromEntries(entries),
operations: entries.map(([operationHash, content]) => ({
operationHash,
content,
location,
})),
warnings: [],
};
}
const globPattern = (() => {
try {
if ((0, node_fs_1.statSync)(file).isDirectory()) {
return `${(0, node_path_1.resolve)(file)}/**/*.graphql`;
}
}
catch (_a) {
// Not a directory, treat it as a glob pattern.
}
return file;
})();
let sources;
try {
sources = await (0, load_1.loadDocuments)(globPattern, {
loaders: [new graphql_file_loader_1.GraphQLFileLoader()],
});
}
catch (error) {
throw new core_1.Errors.CLIError(`Failed to load GraphQL files from "${(0, node_path_1.relative)(process.cwd(), file)}": ${String(error)}`);
}
if (sources.length === 0) {
throw new core_1.Errors.CLIError(`No .graphql files found in "${(0, node_path_1.relative)(process.cwd(), file)}".`);
}
sources.sort((a, b) => { var _a, _b; return ((_a = a.location) !== null && _a !== void 0 ? _a : '').localeCompare((_b = b.location) !== null && _b !== void 0 ? _b : ''); });
const manifest = {};
const locations = new Map();
const warnings = [];
for (const source of sources) {
const sourceFile = (_a = source.location) !== null && _a !== void 0 ? _a : '<unknown>';
const location = (0, node_path_1.relative)(process.cwd(), sourceFile);
if (!source.document) {
warnings.push(`Skipping empty operation in file "${location}".`);
continue;
}
const operation = (0, graphql_1.print)(source.document).replace('\n', ' ').replace(/\s+/g, ' ').trim();
if (!operation) {
warnings.push(`Skipping empty operation in file "${location}".`);
continue;
}
const hash = (0, node_crypto_1.createHash)('sha256').update(operation).digest('hex');
if (hash in manifest) {
warnings.push(`Hash collision detected for file "${location}". The operation is identical to another operation already in the manifest. Skipping.`);
continue;
}
manifest[hash] = operation;
locations.set(hash, location);
}
if (Object.keys(manifest).length === 0) {
throw new core_1.Errors.CLIError(`No valid GraphQL operations found in "${(0, node_path_1.relative)(process.cwd(), file)}".`);
}
return {
manifest,
operations: Object.entries(manifest).map(([operationHash, content]) => ({
operationHash,
content,
location: locations.get(operationHash),
})),
generatedFrom: globPattern,
warnings,
};
}
//# sourceMappingURL=app-operations.js.map