UNPKG

@graphql-hive/cli

Version:

A CLI util to manage and control your GraphQL Hive

121 lines 4.78 kB
"use strict"; 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