/** * 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 = `/// /// /** * 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 (...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; } /** * Main function */ function main() { const classNames = getCreatableInstanceNames(); console.log(`Found ${classNames.length} creatable instance types`); const declarationsContent = generateDeclarations(classNames); const outputPath = path.join(__dirname, '..', 'index.d.ts'); // Write to file fs.writeFileSync(outputPath, declarationsContent, 'utf-8'); console.log(`Successfully generated declarations in ${outputPath}`); 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();