blob: 2095c6c258a16e294d9677a094db7901825b3480 [file] [log] [blame]
const { readFileSync, writeFileSync } = require("fs");
const { resolve } = require("path");
const Handlebars = require("handlebars");
const set = require("lodash.set");
const pascalCase = require("pascal-case");
const prettier = require("prettier");
const { stringToJsdocComment } = require("string-to-jsdoc-comment");
const sortKeys = require("sort-keys");
const ENDPOINTS = require("./generated/Endpoints.json");
const ENDPOINTS_PATH = resolve(
process.cwd(),
"src",
"generated",
"Endpoints.ts"
);
const ENDPOINTS_TEMPLATE_PATH = resolve(
process.cwd(),
"scripts",
"update-endpoints",
"templates",
"endpoints.ts.template"
);
Handlebars.registerHelper("union", function(endpoints, key) {
return endpoints.map(endpoint => endpoint[key]).join(" | ");
});
Handlebars.registerHelper("name", function(parameter) {
let name = parameter.key;
if (/[.\[]/.test(name)) {
name = `"${name}"`;
}
if (parameter.required) {
return name;
}
return `${name}?`;
});
Handlebars.registerHelper("type", function(parameter) {
const type = typeMap[parameter.type] || parameter.type;
if (parameter.allowNull) {
return `${type} | null`;
}
return type;
});
const template = Handlebars.compile(
readFileSync(ENDPOINTS_TEMPLATE_PATH, "utf8")
);
const endpointsByRoute = {};
const typeMap = {
integer: "number",
"integer[]": "number[]"
};
for (const endpoint of ENDPOINTS) {
const route = `${endpoint.method} ${endpoint.url.replace(
/\{([^}]+)}/g,
":$1"
)}`;
if (!endpointsByRoute[route]) {
endpointsByRoute[route] = [];
}
endpointsByRoute[route].push({
optionsTypeName:
pascalCase(`${endpoint.scope} ${endpoint.id}`) + "Endpoint",
requestOptionsTypeName:
pascalCase(`${endpoint.scope} ${endpoint.id}`) + "RequestOptions"
});
}
const options = [];
const childParams = {};
for (const endpoint of ENDPOINTS) {
const { method, parameters } = endpoint;
const optionsTypeName =
pascalCase(`${endpoint.scope} ${endpoint.id}`) + "Endpoint";
const requestOptionsTypeName =
pascalCase(`${endpoint.scope} ${endpoint.id}`) + "RequestOptions";
options.push({
in: {
name: optionsTypeName,
parameters: parameters
.map(parameterize)
// handle "object" & "object[]" types
.map(parameter => {
if (parameter.deprecated) {
return;
}
const namespacedParamsName = pascalCase(
`${endpoint.scope}.${endpoint.id}.Params`
);
if (parameter.type === "object" || parameter.type === "object[]") {
const childParamsName = pascalCase(
`${namespacedParamsName}.${parameter.key}`
);
parameter.type = parameter.type.replace("object", childParamsName);
if (!childParams[childParamsName]) {
childParams[childParamsName] = {};
}
}
if (!/\./.test(parameter.key)) {
return parameter;
}
const childKey = parameter.key.split(".").pop();
const parentKey = parameter.key.replace(/\.[^.]+$/, "");
parameter.key = childKey;
const childParamsName = pascalCase(
`${namespacedParamsName}.${parentKey}`
);
set(childParams, `${childParamsName}.${childKey}`, parameter);
})
.filter(Boolean)
},
out: {
name: requestOptionsTypeName,
method
}
});
}
const result = template({
endpointsByRoute: sortKeys(endpointsByRoute, { deep: true }),
options,
childParams: Object.keys(childParams).map(key => {
if (key === "GistsCreateParamsFiles") {
debugger;
}
return {
paramTypeName: key,
params: Object.values(childParams[key])
};
})
});
writeFileSync(
ENDPOINTS_PATH,
prettier.format(result, { parser: "typescript" })
);
console.log(`${ENDPOINTS_PATH} updated.`);
function parameterize(parameter) {
const key = parameter.name;
const type = typeMap[parameter.type] || parameter.type;
const enums = parameter.enum
? parameter.enum.map(JSON.stringify).join("|")
: null;
return {
name: pascalCase(key),
key: key,
required: parameter.required,
type: enums || type,
alias: parameter.alias,
deprecated: parameter.deprecated,
allowNull: parameter.allowNull,
jsdoc: stringToJsdocComment(parameter.description)
};
}