UNPKG

@fragment-dev/cli

Version:
337 lines (334 loc) 8.73 kB
import { standardQueries } from "./chunk-6DAZJ3YI.js"; import { InvalidGraphQlError } from "./chunk-73ZTML2E.js"; import { getSchemaObjectParameters, getStructuralSubpaths } from "./chunk-JQCVGUVA.js"; import { require_parser, require_printer } from "./chunk-7K4RMTU4.js"; import { require_source } from "./chunk-M5OAS5QZ.js"; import { __toESM, init_cjs_shims } from "./chunk-7GH3YGSC.js"; // src/graphql.ts init_cjs_shims(); var import_chalk = __toESM(require_source(), 1); var import_parser = __toESM(require_parser(), 1); var import_printer = __toESM(require_printer(), 1); import { statSync, existsSync } from "node:fs"; var schemaToEntryDefinitions = ({ schema }) => { return schema.ledgerEntries.types.flatMap((ledgerEntry) => { const entryParameters = getSchemaObjectParameters(ledgerEntry); const lineAccountParameters = (ledgerEntry.lines ?? []).flatMap( (line) => { const subpaths = getStructuralSubpaths(line.account.path); return subpaths.flatMap( (subp) => getSchemaObjectParameters( schema.chartOfAccounts.accountPathToAccount.get(subp) ) ); } ); const conditionAccountParameters = (ledgerEntry.conditions ?? []).flatMap( (condition) => { const subpaths = getStructuralSubpaths( condition.account.path ); return subpaths.flatMap( (subp) => getSchemaObjectParameters( schema.chartOfAccounts.accountPathToAccount.get(subp) ) ); } ); const parameters = Array.from( /* @__PURE__ */ new Set([ ...conditionAccountParameters, ...lineAccountParameters, ...entryParameters ]) ); const isReconciliationEntry = (ledgerEntry.lines ?? []).some( (line) => !!line.tx ); const isRuntimeEntry = (ledgerEntry.lines ?? []).length === 0; const codegenInput = { entryType: ledgerEntry.type, typeVersion: ledgerEntry.typeVersion, runtimeEntry: isRuntimeEntry, parameters }; if (isRuntimeEntry) { return [ { ...codegenInput, method: "reconcileTx" }, { ...codegenInput, method: "addLedgerEntry" } ]; } return [ { ...codegenInput, method: isReconciliationEntry ? "reconcileTx" : "addLedgerEntry" } ]; }); }; var camelCase = (value, delimiter) => { return value.split(delimiter).filter((x) => !!x).map((word, index) => { if (index === 0) { return word; } return word[0].toUpperCase() + word.slice(1); }).join(""); }; var OnErrorFragment = ` ... on BadRequestError { code message retryable } ... on InternalError { code message retryable } `; var LedgerEntryFragment = ` ik id created type posted description ledger { ik } tags { key value } groups { key value } `; var LedgerLineFragment = ` account { path } amount currency { code customCurrencyId } key `; var AddLedgerEntryFragment = ` __typename ... on AddLedgerEntryResult { entry { ${LedgerEntryFragment} } lines { ${LedgerLineFragment} } isIkReplay } ${OnErrorFragment} `; var ReconcileTxFragment = ` __typename ... on ReconcileTxResult { entry { ${LedgerEntryFragment} } lines { ${LedgerLineFragment} tx { externalId externalAccount { externalId } } } isIkReplay } ${OnErrorFragment} `; var isValidGraphQlName = (name) => { return /^[a-zA-Z_]+[a-zA-Z0-9_]*$/.exec(name) !== null; }; var generateGraphQlEntryType = (entryType, typeVersion) => { const readableEntryType = camelCase(camelCase(entryType, "_"), "-").split("").map((ch, idx) => { if (idx === 0) { return ch.toUpperCase(); } return ch; }).join("").replace(/\s+/g, "_").replace(/\./g, "_").replace(/[^a-zA-Z0-9_]/g, "").replace(/^(\d)/, "_$1").concat(typeVersion && typeVersion > 1 ? `_v${typeVersion}` : ""); if (!isValidGraphQlName(readableEntryType)) { throw new InvalidGraphQlError( `Operation name ${readableEntryType} (for entry: ${import_chalk.default.yellow( entryType )}) is not a valid GraphQL name` ); } return readableEntryType; }; var getPredefinedParameters = (definition) => { const params = {}; if (definition.method === "addLedgerEntry") { params["ik"] = "SafeString!"; params["posted"] = "DateTime"; } if (definition.runtimeEntry) { params["lines"] = "[LedgerLineInput!]!"; params["tags"] = "[LedgerEntryTagInput!]"; params["groups"] = "[LedgerEntryGroupInput!]"; } params["ledgerIk"] = "SafeString!"; return params; }; var entryDefinitionToMutation = (definition) => { const { typeVersion } = definition; const predefinedParameters = getPredefinedParameters(definition); const filteredParameters = definition.parameters.filter( (p) => !Object.prototype.hasOwnProperty.call(predefinedParameters, p) ); filteredParameters.forEach((param) => { if (!isValidGraphQlName(param)) { throw new InvalidGraphQlError( `Parameter name ${param} is not a valid GraphQL name` ); } }); const readableEntryType = generateGraphQlEntryType(definition.entryType, typeVersion); const mutationArgs = filteredParameters.map((p) => `$${p}: String!`).join("\n"); const graphQlFragment = definition.method === "addLedgerEntry" ? AddLedgerEntryFragment : ReconcileTxFragment; const operationPrefix = definition.method === "addLedgerEntry" ? "Post" : "Reconcile"; const isIkRequired = Object.prototype.hasOwnProperty.call( predefinedParameters, "ik" ); const isPostedAllowed = Object.prototype.hasOwnProperty.call( predefinedParameters, "posted" ); const operationName = `${operationPrefix}${readableEntryType}`; const predefinedArgs = Object.entries(predefinedParameters).map(([name, type]) => `$${name}: ${type}`).join(",\n"); const command = [ // Named mutation with input parameters block `mutation ${operationName} (`, `${predefinedArgs},`, `${mutationArgs}) {`, // The actual mutation method `${definition.method}(`, // The input object `${isIkRequired ? "ik: $ik," : ""}`, `entry: {`, `ledger: { ik: $ledgerIk },`, `type: "${definition.entryType}",` ]; if (typeVersion !== void 0) { command.push(`typeVersion: ${typeVersion},`); } if (isPostedAllowed) { command.push(`posted: $posted,`); } if (definition.runtimeEntry) { command.push(`lines: $lines, tags: $tags, groups: $groups,`); } if (Object.keys(definition.parameters).length > 0) { command.push(`parameters: {`); command.push(definition.parameters.map((p) => `${p}: $${p}`).join("\n")); command.push(`}`); } command.push(`}) { ${graphQlFragment} } }`); return { mutation: (0, import_printer.print)((0, import_parser.parse)(command.join(""))), operationName }; }; var generateQueriesFileContent = ({ definitions, includeStandardQueries }) => { const generatedCode = definitions.map( (def) => entryDefinitionToMutation(def).mutation ); if (includeStandardQueries) { generatedCode.push(standardQueries); } return `${generatedCode.join("\n")} `; }; var generateQueryFiles = ({ definitions, includeStandardQueries }) => { const generatedCode = definitions.map((def) => { const { operationName, mutation } = entryDefinitionToMutation(def); return { content: `${mutation} `, fileName: `${operationName}.graphql` }; }); if (includeStandardQueries) { const parsedStdQueries = (0, import_parser.parse)(standardQueries); parsedStdQueries.definitions.forEach((def) => { if (def.kind !== "OperationDefinition") { return; } generatedCode.push({ content: `${(0, import_printer.print)(def)} `, fileName: `${def.name.value}.standard-query.graphql` }); }); } return generatedCode; }; var validateOutputName = ({ output, outputFilePerQuery }) => { if (outputFilePerQuery) { if (!existsSync(output)) { throw new Error("Output path must exist"); } if (!statSync(output).isDirectory()) { throw new Error("Output path must be a directory"); } } else { if (/.+\.(graphql|gql)/.exec(output) === null) { throw new Error("Output name must end with .graphql or .gql"); } } }; export { schemaToEntryDefinitions, camelCase, isValidGraphQlName, generateGraphQlEntryType, getPredefinedParameters, entryDefinitionToMutation, generateQueriesFileContent, generateQueryFiles, validateOutputName };