From 83aa5a195ab589206d77c6c44c864d8fa4fdf401 Mon Sep 17 00:00:00 2001 From: Jacob Thomason Date: Thu, 12 Oct 2023 23:06:10 -0400 Subject: [PATCH] Use proper directories for action files, use javascript formatted objects instead of JSON and use dynamic dates in sample data --- lib/index.js | 91 ++++++++++++++++++++++++++++++++++---------------- package.json | 1 + pnpm-lock.yaml | 3 ++ 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/lib/index.js b/lib/index.js index 5e31268..54eeca6 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,6 +4,7 @@ require('dotenv').config(); const fs = require('fs'); const path = require('path'); +const JSON5 = require('json5'); const inflection = require('inflection'); const { Agent } = require('undici'); @@ -32,6 +33,50 @@ let config; let cachedSchema; +/** + * A hacked JSON.stringify that will preserve functions and regexes, etc. + * This isn't perfect for sure and could use improvment, but is sufficient for single layer sample + * data at the moment. It's really nasty, I'm aware. + * + * @param {Object|Array} input + * + * @returns {String} + */ +const stringifyObject = (input, indentation = 0) => { + if (Array.isArray(input)) { + return `[ +${' '.repeat(indentation > 2 ? (indentation - 2) : indentation)}${input.map((v) => stringifyObject(v, indentation)).join(`,\n${' '.repeat(indentation > 2 ? (indentation - 2) : indentation)}`)} +${' '.repeat(indentation > 2 ? (indentation - 2) : indentation)}]`; + } + + if (typeof input === 'object') { + return `{ +${' '.repeat(indentation)}${Object.entries(input).map(([k, v]) => `${k}: ${stringifyObject(v, indentation)}`).join(`,\n${' '.repeat(indentation)}`)} +${' '.repeat(indentation > 2 ? (indentation - 2) : indentation)}}`; + } + + if (input === 'CURRENT_TIMESTAMP') { + return `new Date().toISOString()`; + } + + if (typeof input === 'string') { + return `${JSON.stringify(input)}`; + } + + return `${input}`; +}; + + +/** + * Helper function to indent in every line of a multi-line string. + * + * @param {String} string + */ +const indentString = (string, spaces = 0) => { + return string.replaceAll('\n', `\n${' '.repeat(spaces)}`); +} + + /** * Gets the GraphQL request configuration and performs necessary validation. * @@ -68,16 +113,6 @@ const setConfig = (newConfig) => { } -/** - * Helper function to indent in every line of a multi-line string. - * - * @param {String} string - */ -const indentString = (string, spaces = 0) => { - return string.replaceAll('\n', `\n${' '.repeat(spaces)}`); -} - - /** * Makes a GraphQL request to the API server. * @@ -688,7 +723,7 @@ const createSamples = (fields) => { case 'boolean': return true; case 'datetime': - return new Date().toISOString(); + return 'CURRENT_TIMESTAMP'; default: throw new Error(`Unable to create sample data for "${field.key}" field`); }; @@ -783,11 +818,11 @@ module.exports = { operation: { perform, - inputFields: ${indentString(JSON.stringify(inputFields, null, 2), 4)}, + inputFields: ${indentString(JSON5.stringify(inputFields, null, 2), 4)}, - sample: ${indentString(JSON.stringify(samples, null, 2), 4)}, + sample: ${stringifyObject(samples, 6)}, - outputFields: ${indentString(JSON.stringify(outputFields, null, 2), 4)}, + outputFields: ${indentString(JSON5.stringify(outputFields, null, 2), 4)}, } }; `; @@ -869,11 +904,11 @@ module.exports = { operation: { perform, - inputFields: ${indentString(JSON.stringify(inputFields, null, 2), 4)}, + inputFields: ${indentString(JSON5.stringify(inputFields, null, 2), 4)}, - sample: ${indentString(JSON.stringify(samples, null, 2), 4)}, + sample: ${stringifyObject(samples, 6)}, - outputFields: ${indentString(JSON.stringify(outputFields, null, 2), 4)}, + outputFields: ${indentString(JSON5.stringify(outputFields, null, 2), 4)}, } }; `; @@ -905,10 +940,10 @@ const createActionFile = async (action, operation) => { const filename = inflection.dasherize(inflection.underscore(definition.name)) + '.js'; - console.log(`Creating ${operation} action file: ${action}s/${filename}`); + console.log(`Creating ${operation} action file: ${inflection.pluralize(action)}/${filename}`); - fs.mkdirSync(`${process.cwd()}/${action}s/`, { recursive: true }); - const file = `${process.cwd()}/${action}s/${filename}`; + fs.mkdirSync(`${process.cwd()}/${inflection.pluralize(action)}/`, { recursive: true }); + const file = `${process.cwd()}/${inflection.pluralize(action)}/${filename}`; fs.writeFileSync(file, contents); return { file, contents }; @@ -938,7 +973,7 @@ const createTestFile = async (action, operation) => { const filename = inflection.dasherize(inflection.underscore(definition.name)) + '.test.js'; - console.log(`Creating ${queryOrMutation} test file: test/${action}s/${filename}`); + console.log(`Creating ${queryOrMutation} test file: test/${inflection.pluralize(action)}/${filename}`); const inputFields = getInputFieldsFlattened(definition.args); const samples = createSamples(inputFields); @@ -993,19 +1028,19 @@ describe('${definition.name} ${queryOrMutation}', () => { } } - let results = await appTester(App.${action}s.${operation}.operation.perform, bundle); + let results = await appTester(App.${inflection.pluralize(action)}.${operation}.operation.perform, bundle); results = results instanceof Array ? results : [results]; const firstResult = results[0]; - const outputFields = App.${action}s.${operation}.operation.outputFields + const outputFields = App.${inflection.pluralize(action)}.${operation}.operation.outputFields expect(Object.keys(firstResult).length).toBe(outputFields.length); assertTypes(outputFields, firstResult); }); }); `; - fs.mkdirSync(`${process.cwd()}/test/${action}s/`, { recursive: true }); - const file = `${process.cwd()}/test/${action}s/${filename}`; + fs.mkdirSync(`${process.cwd()}/test/${inflection.pluralize(action)}/`, { recursive: true }); + const file = `${process.cwd()}/test/${inflection.pluralize(action)}/${filename}`; fs.writeFileSync(file, contents); return { file, contents }; @@ -1071,7 +1106,7 @@ const addTriggerQuery = async (query) => { console.log(`Adding triggers "${query}" query to index.js`); await updateEntryFile( `./index.js`, - `${query}Query`, + `${query}Trigger`, `${path.parse(file).dir}/${path.parse(file).name}`, 'trigger', query, @@ -1104,7 +1139,7 @@ const addSearchQuery = async (query) => { console.log(`Adding searches "${query}" query to index.js`); await updateEntryFile( `./index.js`, - `${query}Query`, + `${query}Search`, `${path.parse(file).dir}/${path.parse(file).name}`, 'search', query, @@ -1132,7 +1167,7 @@ const addCreateMutation = async (mutation) => { console.log(`Adding create "${mutation}" mutation to index.js`); await updateEntryFile( `./index.js`, - `${mutation}Mutation`, + `${mutation}Create`, `${path.parse(file).dir}/${path.parse(file).name}`, 'create', mutation, diff --git a/package.json b/package.json index 88e35e1..e0f4e0b 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "graphql": "^16.8.1", "inflection": "^3.0.0", "inquirer": "^8.2.6", + "json5": "^2.2.3", "undici": "5.14.0", "uuid": "^9.0.1", "zapier-platform-cli": "15.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30a91c2..14eb19d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: inquirer: specifier: ^8.2.6 version: 8.2.6 + json5: + specifier: ^2.2.3 + version: 2.2.3 undici: specifier: 5.14.0 version: 5.14.0