UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

293 lines (292 loc) 12.3 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const BehaviorManifestDefinition_1 = __importDefault(require("../minecraft/BehaviorManifestDefinition")); const Database_1 = __importDefault(require("../minecraft/Database")); const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities")); const esbuild = __importStar(require("esbuild-wasm")); const Status_1 = require("./Status"); const IProjectItemData_1 = require("./IProjectItemData"); const IFile_1 = require("../storage/IFile"); class ProjectBuild { project; mainScriptsFolder = undefined; libs = null; distScriptsFolder = undefined; entry = undefined; static isInitialized = false; constructor(projectIn) { this.project = projectIn; this.loadFile = this.loadFile.bind(this); } isInErrorState; errorMessages; resolveFile(resolve) { if (Database_1.default.minecraftModuleNames.includes(resolve.path)) { return { external: true, namespace: "ct", }; } return { path: resolve.path, namespace: "ct", }; } _pushError(message) { this.isInErrorState = true; if (!this.errorMessages) { this.errorMessages = []; } this.errorMessages.push({ message: message }); } _getErrorResponse(id, message) { this._pushError("Project Build:" + message); return { errors: [ { id: id, text: message, }, ], }; } getTypeDefContentFor(name, isTs) { if (!this.libs) { return this._getErrorResponse("esb-typenotfound", "Could not find typedef '" + name + "'"); } for (const typeDef of this.libs.typeDefs) { if (typeDef.name === name) { return { contents: typeDef.content.join("\n"), loader: isTs ? "ts" : "js", }; } } return this._getErrorResponse("esb-typenotfound", "Could not find typedef '" + name + "'"); } get isBuildable() { return this.project && this.project.projectFolder !== undefined; } getHasBuildableElements() { for (const projectItem of this.project.items) { if (projectItem.itemType === IProjectItemData_1.ProjectItemType.ts) { return true; } } return false; } async loadFile(build) { if (!this.project || !this.project.projectFolder || !this.mainScriptsFolder || !this.distScriptsFolder || !this.libs) { return this._getErrorResponse("esb-uninit", "Project does not have buildable elements."); } if (build.path === "@minecraft/vanilla-data") { return this.getTypeDefContentFor("@minecraft/vanilla-data", true); } else if (build.path === "@minecraft/math") { return this.getTypeDefContentFor("@minecraft/math", false); } let path = build.path; if (path.startsWith("./")) { path = path.substring(1); } const ext = StorageUtilities_1.default.getTypeFromName(path); if (ext === "js") { path = path.substring(0, path.length - 3) + ".ts"; } else if (ext === "") { path = path + ".ts"; } if (!path.startsWith("/")) { return this._getErrorResponse("esb-importnotfound", "Could not find import '" + path + "'"); } let file = await this.mainScriptsFolder.ensureFileFromRelativePath(path); // Use existing in-memory content if already loaded (it may have been modified by the editor) // Only load from storage if not yet loaded if (!file.isContentLoaded) { await file.loadContent(true); } let content = file.content; if (!content || typeof content !== "string") { if (StorageUtilities_1.default.getTypeFromName(path) === "ts") { path = path.substring(0, path.length - 3) + ".js"; file = await this.mainScriptsFolder.ensureFileFromRelativePath(path); // Use existing in-memory content if available if (!file.isContentLoaded) { await file.loadContent(true); } content = file.content; if (!content || typeof content !== "string") { content = ""; } } else { return this._getErrorResponse("esb-filenotfound", "Could not find file '" + build.path + "'"); } } return { contents: content, loader: "ts", resolveDir: StorageUtilities_1.default.getFolderPath(build.path), }; } async build() { if (!this.isBuildable) { return; } if (!this.getHasBuildableElements()) { return; } const operId = await this.project.creatorTools.notifyOperationStarted("Script building '" + this.project.name + "'"); const defaultBehaviorPack = await this.project.getDefaultBehaviorPack(); if (defaultBehaviorPack === undefined) { return; } const behaviorPackDefinition = await defaultBehaviorPack.ensureManifest(); if (!behaviorPackDefinition || !(behaviorPackDefinition instanceof BehaviorManifestDefinition_1.default)) { return; } const scriptModule = behaviorPackDefinition.getScriptModule(); const libScriptsFolder = this.project.getLibScriptsFolder(); this.mainScriptsFolder = await this.project.getMainScriptsFolder(); if (scriptModule && scriptModule.entry && libScriptsFolder) { this.libs = await Database_1.default.getLibs(); this.distScriptsFolder = await this.project.ensureDistBuildScriptsFolder(); if (this.libs) { this.entry = scriptModule.entry; if (this.entry.toLowerCase().startsWith("scripts/")) { this.entry = this.entry.substring(7); } if (!ProjectBuild.isInitialized) { try { // In Node.js, esbuild-wasm auto-locates its .wasm file from the // package directory — no wasmURL needed. In browsers, wasmURL must // point to the .wasm file served by the web server. const isNodeJs = typeof process !== "undefined" && process.versions?.node; if (isNodeJs) { await esbuild.initialize({}); } else { await esbuild.initialize({ wasmURL: "./dist/esbuild-wasm/esbuild.wasm", }); } } catch (e) { this._pushError("Failed to initialize build system: " + e.toString()); await this.project.creatorTools?.notifyOperationEnded(operId, "Unable to continue script building '" + this.project.name + "'", Status_1.StatusTopic.scriptBuild, this.isInErrorState); return; } ProjectBuild.isInitialized = true; } const me = this; try { const result = await esbuild.build({ bundle: true, entryPoints: [this.entry], format: "esm", external: Database_1.default.minecraftModuleNames, plugins: [ { name: "ct", setup(build) { build.onResolve({ filter: /.*/ }, me.resolveFile); build.onLoad({ filter: /.*/, namespace: "ct" }, me.loadFile); }, }, ], }); if (result && result.outputFiles && result.outputFiles.length > 0) { const mainJsFile = await this.distScriptsFolder.ensureFileFromRelativePath(this.entry); mainJsFile.setContent(result.outputFiles[0].text, IFile_1.FileUpdateType.regularEdit); await mainJsFile.saveContent(); } } catch (e) { if (!this.isInErrorState && e) { this._pushError(e.toString()); } } await me.project.creatorTools?.notifyOperationEnded(operId, "Completed script building '" + this.project.name + "'", Status_1.StatusTopic.scriptBuild, this.isInErrorState); } } } async aggregateScripts(scriptFolder) { if (!scriptFolder.isLoaded) { await scriptFolder.load(); } let script = ""; for (const fileName in scriptFolder.files) { const ext = StorageUtilities_1.default.getTypeFromName(fileName); if (ext === "js") { const scriptFile = scriptFolder.files[fileName]; if (scriptFile) { if (!scriptFile.isContentLoaded) { await scriptFile.loadContent(); } if (scriptFile.content && typeof scriptFile.content === "string") { script += "// " + fileName + "\n" + scriptFile.content + "\n"; } } } } for (const folderName in scriptFolder.folders) { const childFolder = scriptFolder.folders[folderName]; if (childFolder) { const fileScript = await this.aggregateScripts(childFolder); script += fileScript; } } return script; } async syncToBehaviorPack(bpTargetFolder) { if (!this.getHasBuildableElements()) { return; } const distScriptsFolder = await this.project.ensureDistBuildScriptsFolder(); const scriptsFolder = bpTargetFolder.ensureFolder("scripts"); await StorageUtilities_1.default.syncFolderTo(distScriptsFolder, scriptsFolder, true, true, false, []); } } exports.default = ProjectBuild;