Files

180 lines
6.7 KiB
JavaScript

/**
* Script to generate declaration statements for all creatable Roblox instances
* This will produce declarations in the format:
* declare const INSTANCENAME: CreatableInstancesWithConstructors["INSTANCENAME"]
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
/**
* Get all creatable instance class names by examining the @rbxts/types package
*/
function getCreatableInstanceNames() {
try {
// Find the location of @rbxts/types in node_modules
let typesPath;
try {
// Try to find the path to @rbxts/types
typesPath = path.dirname(require.resolve('@rbxts/types/package.json'));
} catch (e) {
console.error('Could not find @rbxts/types. Make sure it is installed.');
process.exit(1);
}
// Read the CreatableInstances interface definition file
// This could be in a few different locations depending on the package structure
let instancesFile;
const possiblePaths = [
path.join(typesPath, 'include', 'generated', 'None.d.ts'),
path.join(typesPath, 'types', 'generated', 'None.d.ts'),
path.join(typesPath, 'generated', 'None.d.ts')
];
for (const filePath of possiblePaths) {
if (fs.existsSync(filePath)) {
instancesFile = filePath;
break;
}
}
if (!instancesFile) {
throw new Error('Could not find None.d.ts file in @rbxts/types');
}
// Read the file content
const content = fs.readFileSync(instancesFile, 'utf-8');
// Extract interface names that appear in CreatableInstances
// This regex might need adjustment depending on the exact format
const creatableInstancesRegex = /interface CreatableInstances \{([\s\S]*?)\}/;
const creatablesMatch = content.match(creatableInstancesRegex);
if (!creatablesMatch || !creatablesMatch[1]) {
throw new Error('Could not find CreatableInstances interface in the types file');
}
// Extract class names by looking for patterns like "ClassName: ClassName;"
const classNameRegex = /([A-Za-z0-9_]+)\s*:\s*([A-Za-z0-9_]+);/g;
const classNames = [];
let match;
while ((match = classNameRegex.exec(creatablesMatch[1])) !== null) {
classNames.push(match[1]);
}
return classNames.sort();
} catch (error) {
console.error('Error extracting instance names:', error);
// Fallback to a predefined list of common instances
console.log('Falling back to predefined list of common instances...');
return [
"Accessory", "Accoutrement", "Animation", "Attachment", "BillboardGui",
"BindableEvent", "BindableFunction", "BlockMesh", "BodyAngularVelocity",
"BodyForce", "BodyGyro", "BodyPosition", "BodyThrust", "BodyVelocity",
"BoolValue", "BrickColorValue", "Camera", "CFrameValue", "ClickDetector",
"Clothing", "Color3Value", "ColorCorrectionEffect", "Configuration",
"CornerWedgePart", "Decal", "Dialog", "DialogChoice", "DoubleConstrainedValue",
"Explosion", "Folder", "ForceField", "Frame", "GuiButton", "GuiObject",
"Highlight", "Humanoid", "HumanoidDescription", "ImageButton", "ImageLabel",
"IntConstrainedValue", "IntValue", "LocalScript", "MeshPart", "Model",
"ModuleScript", "Motor", "Motor6D", "NumberValue", "ObjectValue", "Part",
"ParticleEmitter", "ProximityPrompt", "RayValue", "RemoteEvent", "RemoteFunction",
"ScreenGui", "Script", "ScrollingFrame", "Seat", "Sky", "Sound", "SpecialMesh",
"SpotLight", "StringValue", "SurfaceGui", "TextBox", "TextButton",
"TextLabel", "Texture", "Tool", "TouchTransmitter", "Trail", "TrussPart",
"UIAspectRatioConstraint", "UICorner", "UIGradient", "UIGridLayout",
"UIListLayout", "UIPadding", "UIPageLayout", "UIScale", "UIStroke",
"UITableLayout", "UITextSizeConstraint", "UnionOperation", "Vector3Value",
"VectorForce", "VideoFrame", "WedgePart", "Weld"
].sort();
}
}
/**
* Generate the declarations file content
* @param {string[]} classNames List of creatable instance class names
* @returns {string} The content for the declarations file
*/
function generateDeclarations(classNames) {
// Header part
let content = `/// <reference no-default-lib="true"/>
/// <reference types="@rbxts/types" />
/**
* Add constructors to all Roblox CreatableInstances
* This adds \`new ClassName()\` constructors for all Roblox instance types
* that can be created with Instance.new()
*
* The transformer will convert these to \`new Instance("ClassName")\`
*/
type CreatableInstancesWithConstructors = {
[K in keyof CreatableInstances]: {
new (parent?: Instance): CreatableInstances[K];
new (...args: any[]): CreatableInstances[K];
}
}
declare const CreatableInstancesWithConstructors: CreatableInstancesWithConstructors;
`;
// Add declarations for each class
for (const className of classNames) {
content += `declare const ${className}: CreatableInstancesWithConstructors["${className}"];\n`;
}
return content;
}
/**
* Generate the instance-classes.ts file content
* @param {string[]} classNames List of creatable instance class names
* @returns {string} The content for the instance-classes.ts file
*/
function generateInstanceClassesFile(classNames) {
return `/**
* This file is auto-generated by the generate-instance-classes script.
* Do not modify manually.
*/
/**
* Array of all creatable Roblox instance class names
* Used by the transformer to identify constructor calls
*/
export const CREATABLE_INSTANCES = [
${classNames.map(name => `"${name}"`).join(",\n ")}
];`;
}
/**
* Main function
*/
function main() {
const classNames = getCreatableInstanceNames();
console.log(`Found ${classNames.length} creatable instance types`);
// Generate and write declarations file
const declarationsContent = generateDeclarations(classNames);
const declarationsPath = path.join(__dirname, '..', 'index.d.ts');
fs.writeFileSync(declarationsPath, declarationsContent, 'utf-8');
console.log(`Successfully generated declarations in ${declarationsPath}`);
// Generate and write instance-classes.ts
const instanceClassesContent = generateInstanceClassesFile(classNames);
const instanceClassesPath = path.join(__dirname, '..', 'src', 'instance-classes.ts');
fs.writeFileSync(instanceClassesPath, instanceClassesContent, 'utf-8');
console.log(`Successfully generated instance classes in ${instanceClassesPath}`);
console.log('Example declarations:');
const examples = classNames.slice(0, 5);
for (const className of examples) {
console.log(`declare const ${className}: CreatableInstancesWithConstructors["${className}"];`);
}
console.log(`...and ${classNames.length - 5} more`);
}
// Run the script
main();