ReplAPI.it-NodeJS
ReplAPI.it-NodeJS copied to clipboard
Restructure Package Meta
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.
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();
}
Turned that hunk of code into a neat package: https://github.com/RayhanADev/gql-query-creator
Rewrote the Board class with the new structure and it works beautifully!!!
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.