blessing-skin-server/tools/generateUrls.ts
Zephyr Lykos 9524a234cf
cleanup: wip 3.1
mostly misc cleanups
2024-02-24 23:01:32 +08:00

144 lines
3.5 KiB
TypeScript

import {spawnSync} from 'node:child_process';
import fs from 'node:fs';
import ts from 'typescript';
type Route = {uri: string; name: string | undefined};
const supportedPrefixes = ['auth.', 'user.', 'skinlib.', 'texture.', 'admin.'];
type TreeObject = Record<string, Tree>;
type Tree = TreeObject | string;
const tree: TreeObject = {};
function parseURI(uri: string): ts.ArrowFunction {
const matches = /{([a-z]+)}/.exec(uri);
if (matches?.[0] && matches?.[1]) {
const parameter = matches[1];
const type = parameter.endsWith('id')
|| parameter === 'texture'
|| parameter === 'user'
|| parameter === 'player'
|| parameter === 'report'
? ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
return ts.factory.createArrowFunction(
undefined,
undefined,
[
ts.factory.createParameterDeclaration(
undefined,
undefined,
ts.factory.createIdentifier(parameter),
undefined,
type,
),
],
undefined,
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
ts.factory.createTemplateExpression(
ts.factory.createTemplateHead(
'/' + uri.slice(0, matches.index),
'/' + uri.slice(0, matches.index),
),
[
ts.factory.createTemplateSpan(
ts.factory.createIdentifier(parameter),
ts.factory.createTemplateTail(
uri.slice(matches.index + matches[0].length),
uri.slice(matches.index + matches[0].length),
),
),
],
),
);
}
return ts.factory.createArrowFunction(
undefined,
undefined,
[],
undefined,
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
ts.factory.createAsExpression(
ts.factory.createStringLiteral(`/${uri}`),
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('const'), undefined),
),
);
}
function parseTree(tree: Tree): ts.ObjectLiteralExpression {
const properties = Object.entries(tree)
.sort(([a], [b]) => (a > b ? 1 : -1))
.map(([key, value]) => {
if (typeof value === 'string') {
return ts.factory.createPropertyAssignment(
ts.factory.createIdentifier(key),
parseURI(value),
);
}
return ts.factory.createPropertyAssignment(
ts.factory.createIdentifier(key),
parseTree(value),
);
});
return ts.factory.createObjectLiteralExpression(properties);
}
const {stdout} = spawnSync(
'php',
['artisan', 'route:list', '--json', '--columns=uri,name'],
{encoding: 'utf8'},
);
let routes: Route[] = [];
try {
routes = JSON.parse(stdout) as Route[];
} catch (error) {
console.error(stdout);
throw error;
}
for (const route of routes
.filter(
route =>
route.name
&& supportedPrefixes.some(prefix => route.name!.startsWith(prefix))
&& !route.name.endsWith('.'),
)) {
const path = route.name!.split('.');
const {length} = path;
// eslint-disable-next-line unicorn/no-array-reduce
path.reduce((object: TreeObject, p, index) => {
if (index === length - 1) {
object[p] = route.uri;
return tree;
}
object[p] ||= {};
return object[p];
}, tree);
}
const ast = ts.factory.createExportAssignment(
undefined,
undefined,
parseTree(tree),
);
const sourceFile = ts.createSourceFile(
'urls.ts',
'',
ts.ScriptTarget.ES2020,
false,
ts.ScriptKind.TS,
);
const printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed,
});
const code = printer.printNode(ts.EmitHint.Unspecified, ast, sourceFile);
fs.writeFileSync('./resources/assets/src/scripts/urls.ts', code, {
encoding: 'utf8',
});