ReplAPI.it-NodeJS icon indicating copy to clipboard operation
ReplAPI.it-NodeJS copied to clipboard

Restructure Package Meta

Open rayhanadev opened this issue 4 years ago • 4 comments

This issue correlates with the similar project. Tasks include:

  • [x] Redesign the Custom Class to match up with the current design of API Classes
  • [x] Implement lightfetch for HTTPS fetching (#67)
  • [x] Add helper functions to parse custom Objects to GraphQL querystrings
  • [ ] Rewrite all API Classes to dogfood the new Custom Class

This will be released as 2.4.x, a minor version and beta releases will be made under 2.4.0-beta.x. As always, help is appreciated!

Edit: I thought a table documenting the current progress might be useful (~~to me~~).

Key:

  • ✔️: Completed
  • ❌: Not Started
  • ✍️: In Progress
Class Name Status
Board ✔️
Comment ✍️
Explore ✔️
Leaderboard
Post
Repl
User

* Note: This chart discludes non-GraphQL related classes that won't be getting structural changes. The Login class has been (yet again) revamped in addition to usage of logged-in queries.

rayhanadev avatar Jun 17 '21 15:06 rayhanadev

Code to Parse Objects to GraphQL Querystrings and Fetch!:

function whatis(value) {
	return Object.prototype.toString
		.call(value)
		.replace(/^\[object\s+([a-z]+)\]$/i, '$1')
		.toLowerCase();
}

function variablesString(queryVariables) {
	let queryString = '';
	for (const [key, value] of Object.entries(queryVariables)) {
		queryString += `$${key}: ${value},`;
	}
	return queryString.slice(0, -1);
}

function itemsString(queryItems, tabLength = 1) {
	let queryString = '';
	let tabPadding = '';
	for (let i = tabLength; i > 0; i -= 1) {
		tabPadding += '\t';
	}

	for (const [key, value] of Object.entries(queryItems)) {
		switch (whatis(value)) {
			case 'string': {
				queryString += `${tabPadding}${key}\n`;
				break;
			}
			case 'array': {
				const propOptions = Object.entries(value[0])
					.join('* ')
					.replace(/,/g, ': $')
					.replace(/\*/g, ',');
				const propAlias = value[1];
				queryString += `${tabPadding}${
					propAlias ? `${propAlias}: ` : ''
				}${key}${propOptions ? `(${propOptions})` : ''}\n`;
				break;
			}
			case 'object': {
				const propOptions = Object.entries(value.args[0] || {})
					.join('* ')
					.replace(/,/g, ': $')
					.replace(/\*/g, ',');
				const propAlias = value.args[1];
				// prettier-ignore
				queryString += 
`${tabPadding}${propAlias ? `${propAlias}: ` : ''}${key}${value.args[0] ? `(${propOptions})` : ''} {
${itemsString(value.items, tabLength + 1)}
${tabPadding}}\n`;
				break;
			}
			default: {
				throw new Error('Unknown type when generating property string.');
			}
		}
	}

	return queryString.slice(0, -1);
}

function createQueryWrapper(name, variables, items) {
	const queryTemplate =
		'query __QUERY_NAME__(__QUERY_VARIABLES__) {\n__QUERY_PROPERTIES__\n}';
	const queryVariablesString = variablesString(variables);
	const queryItemsString = itemsString(items);

	return queryTemplate
		.replace(/__QUERY_NAME__/, name)
		.replace(/__QUERY_VARIABLES__/, queryVariablesString)
		.replace(/__QUERY_PROPERTIES__/, queryItemsString);
}

async function runGraphQL(name, variables, items) {
	const wrapperVariables = Object.fromEntries(Object.entries(variables).map(([key, value]) => {
		return [key, value[0]];
	}));
	const queryVariables = Object.fromEntries(Object.entries(variables).map(([key, value]) => {
		return [key, value[1]];
	}));

	const query = createQueryWrapper(name, wrapperVariables, items);

	const info = await lightfetch('https://replit.com/graphql', {
		headers,
		method: 'POST',
		body: {
			query,
			variables: JSON.stringify(queryVariables),
		},
	});
	return info.toJSON();
}

rayhanadev avatar Jun 18 '21 03:06 rayhanadev

Turned that hunk of code into a neat package: https://github.com/RayhanADev/gql-query-creator

rayhanadev avatar Jun 18 '21 21:06 rayhanadev

Rewrote the Board class with the new structure and it works beautifully!!!

rayhanadev avatar Jun 19 '21 17:06 rayhanadev

Publicly released [email protected] which should give some idea of what it feels out of source. I posted the package size here and there is a huge decrease in size (good!). Several classes work with the new structure.

rayhanadev avatar Jun 23 '21 00:06 rayhanadev