From c1fb5000f9b01b0a625ff06b48e78672bdfc2aaa Mon Sep 17 00:00:00 2001 From: Francisco Alejandro Garcia Cebada <93944312+frgarc@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:02:01 -0800 Subject: [PATCH] Adding starter build tasks (#10) * - Adding starter build tasks --- ...-66af045e-4835-4f95-aca5-5a36cd486f4d.json | 7 + ...-440fe7aa-75d8-40f3-8e8e-e331ccdf0b56.json | 7 + ...-1c88b9c3-5a98-45af-a994-35aed44d739f.json | 7 + libraries/math/src/general/clamp.ts | 3 +- libraries/math/src/general/index.ts | 3 +- libraries/math/src/index.test.ts | 3 +- libraries/math/src/index.ts | 3 +- .../math/src/vector3/coreHelpers.test.ts | 3 +- libraries/math/src/vector3/coreHelpers.ts | 3 +- libraries/math/src/vector3/index.ts | 3 +- .../math/src/vector3/vectorWrapper.test.ts | 3 +- libraries/math/src/vector3/vectorWrapper.ts | 3 +- package-lock.json | 464 +++++++++++++++++- tools/core-build-tasks/package.json | 8 +- tools/core-build-tasks/src/index.test.ts | 3 + tools/core-build-tasks/src/index.ts | 5 + .../src/platforms/MinecraftProduct.ts | 11 + tools/core-build-tasks/src/platforms/index.ts | 4 + .../core-build-tasks/src/setupEnvironment.ts | 12 + .../src/tasks/api-extractor.ts | 3 + tools/core-build-tasks/src/tasks/bundle.ts | 36 ++ tools/core-build-tasks/src/tasks/clean.ts | 3 + .../src/tasks/cleanCollateral.ts | 68 +++ tools/core-build-tasks/src/tasks/copy.ts | 55 +++ tools/core-build-tasks/src/tasks/coreLint.ts | 5 +- .../src/tasks/helpers/copyFiles.ts | 25 + .../helpers/getGameDeploymentRootPaths.ts | 43 ++ .../tasks/helpers/getOrThrowFromProcess.ts | 19 + .../src/tasks/helpers/index.ts | 6 + tools/core-build-tasks/src/tasks/index.ts | 10 + .../core-build-tasks/src/tasks/updateWorld.ts | 37 ++ tools/core-build-tasks/src/tasks/vitest.ts | 3 + tools/core-build-tasks/src/tasks/watch.ts | 67 +++ tools/core-build-tasks/src/tasks/zip.ts | 108 ++++ .../index.js | 2 +- .../package.json | 2 +- .../package.json | 3 +- .../src/Rules/AvoidUnnecessaryCommand.test.ts | 3 +- .../src/Rules/AvoidUnnecessaryCommand.ts | 3 +- .../src/Rules/TestProject/estree.ts | 3 +- .../src/index.ts | 3 +- 41 files changed, 1042 insertions(+), 20 deletions(-) create mode 100644 change/@minecraft-core-build-tasks-66af045e-4835-4f95-aca5-5a36cd486f4d.json create mode 100644 change/@minecraft-math-440fe7aa-75d8-40f3-8e8e-e331ccdf0b56.json create mode 100644 change/eslint-plugin-minecraft-linting-1c88b9c3-5a98-45af-a994-35aed44d739f.json create mode 100644 tools/core-build-tasks/src/platforms/MinecraftProduct.ts create mode 100644 tools/core-build-tasks/src/platforms/index.ts create mode 100644 tools/core-build-tasks/src/setupEnvironment.ts create mode 100644 tools/core-build-tasks/src/tasks/bundle.ts create mode 100644 tools/core-build-tasks/src/tasks/cleanCollateral.ts create mode 100644 tools/core-build-tasks/src/tasks/copy.ts create mode 100644 tools/core-build-tasks/src/tasks/helpers/copyFiles.ts create mode 100644 tools/core-build-tasks/src/tasks/helpers/getGameDeploymentRootPaths.ts create mode 100644 tools/core-build-tasks/src/tasks/helpers/getOrThrowFromProcess.ts create mode 100644 tools/core-build-tasks/src/tasks/helpers/index.ts create mode 100644 tools/core-build-tasks/src/tasks/updateWorld.ts create mode 100644 tools/core-build-tasks/src/tasks/watch.ts create mode 100644 tools/core-build-tasks/src/tasks/zip.ts diff --git a/change/@minecraft-core-build-tasks-66af045e-4835-4f95-aca5-5a36cd486f4d.json b/change/@minecraft-core-build-tasks-66af045e-4835-4f95-aca5-5a36cd486f4d.json new file mode 100644 index 0000000..ad8c6a6 --- /dev/null +++ b/change/@minecraft-core-build-tasks-66af045e-4835-4f95-aca5-5a36cd486f4d.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Adding new tasks: bundle, cleanCollateral, copy, updateWorld, mcaddon, watch", + "packageName": "@minecraft/core-build-tasks", + "email": "frgarc@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@minecraft-math-440fe7aa-75d8-40f3-8e8e-e331ccdf0b56.json b/change/@minecraft-math-440fe7aa-75d8-40f3-8e8e-e331ccdf0b56.json new file mode 100644 index 0000000..ebc9eb9 --- /dev/null +++ b/change/@minecraft-math-440fe7aa-75d8-40f3-8e8e-e331ccdf0b56.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "- Updating headers at math library", + "packageName": "@minecraft/math", + "email": "frgarc@microsoft.com", + "dependentChangeType": "none" +} diff --git a/change/eslint-plugin-minecraft-linting-1c88b9c3-5a98-45af-a994-35aed44d739f.json b/change/eslint-plugin-minecraft-linting-1c88b9c3-5a98-45af-a994-35aed44d739f.json new file mode 100644 index 0000000..4aa43ea --- /dev/null +++ b/change/eslint-plugin-minecraft-linting-1c88b9c3-5a98-45af-a994-35aed44d739f.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Adding header dependency.", + "packageName": "eslint-plugin-minecraft-linting", + "email": "frgarc@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/libraries/math/src/general/clamp.ts b/libraries/math/src/general/clamp.ts index c0c22ec..65036b9 100644 --- a/libraries/math/src/general/clamp.ts +++ b/libraries/math/src/general/clamp.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. /** * Clamps the passed in number to the passed in min and max values. diff --git a/libraries/math/src/general/index.ts b/libraries/math/src/general/index.ts index 8e372c0..3ea05fc 100644 --- a/libraries/math/src/general/index.ts +++ b/libraries/math/src/general/index.ts @@ -1,3 +1,4 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. export * from './clamp'; diff --git a/libraries/math/src/index.test.ts b/libraries/math/src/index.test.ts index 23f2b17..026a67c 100644 --- a/libraries/math/src/index.test.ts +++ b/libraries/math/src/index.test.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { describe, expect, it } from 'vitest'; diff --git a/libraries/math/src/index.ts b/libraries/math/src/index.ts index 6c51f74..48f70c1 100644 --- a/libraries/math/src/index.ts +++ b/libraries/math/src/index.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. export * from './vector3'; export * from './general'; diff --git a/libraries/math/src/vector3/coreHelpers.test.ts b/libraries/math/src/vector3/coreHelpers.test.ts index 7e67ebf..4b002c9 100644 --- a/libraries/math/src/vector3/coreHelpers.test.ts +++ b/libraries/math/src/vector3/coreHelpers.test.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { Vector2, Vector3 } from '@minecraft/server'; import { describe, expect, it } from 'vitest'; diff --git a/libraries/math/src/vector3/coreHelpers.ts b/libraries/math/src/vector3/coreHelpers.ts index b0a33a8..f49abb4 100644 --- a/libraries/math/src/vector3/coreHelpers.ts +++ b/libraries/math/src/vector3/coreHelpers.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import type { Vector2, Vector3 } from '@minecraft/server'; import { clampNumber } from '../general/clamp'; diff --git a/libraries/math/src/vector3/index.ts b/libraries/math/src/vector3/index.ts index de26298..e303b5e 100644 --- a/libraries/math/src/vector3/index.ts +++ b/libraries/math/src/vector3/index.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. export * from './coreHelpers'; export * from './vectorWrapper'; diff --git a/libraries/math/src/vector3/vectorWrapper.test.ts b/libraries/math/src/vector3/vectorWrapper.test.ts index 1b158f9..5ebec30 100644 --- a/libraries/math/src/vector3/vectorWrapper.test.ts +++ b/libraries/math/src/vector3/vectorWrapper.test.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import type { Vector3 } from '@minecraft/server'; import { describe, expect, it } from 'vitest'; diff --git a/libraries/math/src/vector3/vectorWrapper.ts b/libraries/math/src/vector3/vectorWrapper.ts index 995e354..002f1c4 100644 --- a/libraries/math/src/vector3/vectorWrapper.ts +++ b/libraries/math/src/vector3/vectorWrapper.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import type { Vector2, Vector3 } from '@minecraft/server'; import { Vector2Utils, Vector3Utils } from './coreHelpers'; diff --git a/package-lock.json b/package-lock.json index 0f24c25..63a7537 100644 --- a/package-lock.json +++ b/package-lock.json @@ -233,6 +233,21 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", + "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.19.9", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.9.tgz", @@ -2171,6 +2186,14 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2542,6 +2565,17 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", + "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.578", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.578.tgz", @@ -3014,6 +3048,14 @@ "reusify": "^1.0.4" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4348,6 +4390,11 @@ "node": "*" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -5888,6 +5935,23 @@ "node": ">=10" } }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -5927,6 +5991,18 @@ "commander": "^9.4.1" } }, + "node_modules/zip-lib": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/zip-lib/-/zip-lib-0.7.3.tgz", + "integrity": "sha512-hp40KYzTJvoaCRr2t6hztlPnVmHYqDUDiIn0hlfAFwVBs3/jwkLy8aZ7NVGHECeWH2Tv8WPwWyR6QuWYarIjJQ==", + "dependencies": { + "yauzl": "^2.10.0", + "yazl": "^2.5.1" + }, + "engines": { + "node": ">=8" + } + }, "tools/api-extractor-base": { "name": "@minecraft/api-extractor-base", "version": "0.0.1" @@ -5937,9 +6013,13 @@ "dependencies": { "@microsoft/api-extractor": "^7.38.3", "@rushstack/node-core-library": "^3.59.6", + "dotenv": "^16.0.2", + "esbuild": "^0.20.1", + "prettier": "^2.8.2", "rimraf": "^3.0.2", "vitest": "^0.34.6", - "webpack": "^5.86.0" + "webpack": "^5.86.0", + "zip-lib": "^0.7.3" }, "devDependencies": { "@types/node": "^14.0.0 || ^16.0.0 || ^18.0.0", @@ -5950,6 +6030,336 @@ "typescript": "^5.2.2" } }, + "tools/core-build-tasks/node_modules/@esbuild/android-arm": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", + "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/android-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", + "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/android-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", + "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", + "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/darwin-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", + "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", + "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", + "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-arm": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", + "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", + "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-ia32": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", + "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-loong64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", + "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", + "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", + "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", + "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-s390x": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", + "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/linux-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", + "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", + "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", + "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/sunos-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", + "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/win32-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", + "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/win32-ia32": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", + "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "tools/core-build-tasks/node_modules/@esbuild/win32-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", + "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "tools/core-build-tasks/node_modules/@types/node": { "version": "18.18.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", @@ -5959,6 +6369,57 @@ "undici-types": "~5.26.4" } }, + "tools/core-build-tasks/node_modules/esbuild": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", + "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.1", + "@esbuild/android-arm": "0.20.1", + "@esbuild/android-arm64": "0.20.1", + "@esbuild/android-x64": "0.20.1", + "@esbuild/darwin-arm64": "0.20.1", + "@esbuild/darwin-x64": "0.20.1", + "@esbuild/freebsd-arm64": "0.20.1", + "@esbuild/freebsd-x64": "0.20.1", + "@esbuild/linux-arm": "0.20.1", + "@esbuild/linux-arm64": "0.20.1", + "@esbuild/linux-ia32": "0.20.1", + "@esbuild/linux-loong64": "0.20.1", + "@esbuild/linux-mips64el": "0.20.1", + "@esbuild/linux-ppc64": "0.20.1", + "@esbuild/linux-riscv64": "0.20.1", + "@esbuild/linux-s390x": "0.20.1", + "@esbuild/linux-x64": "0.20.1", + "@esbuild/netbsd-x64": "0.20.1", + "@esbuild/openbsd-x64": "0.20.1", + "@esbuild/sunos-x64": "0.20.1", + "@esbuild/win32-arm64": "0.20.1", + "@esbuild/win32-ia32": "0.20.1", + "@esbuild/win32-x64": "0.20.1" + } + }, + "tools/core-build-tasks/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "tools/eslint-config-minecraft-scripting": { "version": "0.0.1", "license": "MIT", @@ -5988,6 +6449,7 @@ "@typescript-eslint/typescript-estree": "^6.10.0", "eslint": "^8.53.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-header": "^3.1.1", "eslint-plugin-unicorn": "^42.0.0", "just-scripts": "^2.1.3", "tsconfig": "*" diff --git a/tools/core-build-tasks/package.json b/tools/core-build-tasks/package.json index 1abb5da..495fd96 100644 --- a/tools/core-build-tasks/package.json +++ b/tools/core-build-tasks/package.json @@ -16,9 +16,13 @@ "dependencies": { "@rushstack/node-core-library": "^3.59.6", "@microsoft/api-extractor": "^7.38.3", + "esbuild": "^0.20.1", + "dotenv": "^16.0.2", + "prettier": "^2.8.2", "rimraf": "^3.0.2", "vitest": "^0.34.6", - "webpack": "^5.86.0" + "webpack": "^5.86.0", + "zip-lib": "^0.7.3" }, "devDependencies": { "@types/node": "^14.0.0 || ^16.0.0 || ^18.0.0", @@ -28,4 +32,4 @@ "tsconfig": "*", "typescript": "^5.2.2" } -} +} \ No newline at end of file diff --git a/tools/core-build-tasks/src/index.test.ts b/tools/core-build-tasks/src/index.test.ts index c43f612..c24c8b6 100644 --- a/tools/core-build-tasks/src/index.test.ts +++ b/tools/core-build-tasks/src/index.test.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + import { describe, expect, it } from 'vitest'; describe('Remove when tests are added', () => { diff --git a/tools/core-build-tasks/src/index.ts b/tools/core-build-tasks/src/index.ts index 954dac4..2478ee3 100644 --- a/tools/core-build-tasks/src/index.ts +++ b/tools/core-build-tasks/src/index.ts @@ -1 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export * from './platforms'; +export * from './setupEnvironment'; export * from './tasks'; diff --git a/tools/core-build-tasks/src/platforms/MinecraftProduct.ts b/tools/core-build-tasks/src/platforms/MinecraftProduct.ts new file mode 100644 index 0000000..54db954 --- /dev/null +++ b/tools/core-build-tasks/src/platforms/MinecraftProduct.ts @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * Non-exhaustive list of product variants used to deploy files to the correct location. + */ +export enum MinecraftProduct { + Bedrock = 'BedrockUWP', + Preview = 'PreviewUWP', + Custom = 'Custom', +} diff --git a/tools/core-build-tasks/src/platforms/index.ts b/tools/core-build-tasks/src/platforms/index.ts new file mode 100644 index 0000000..462c06e --- /dev/null +++ b/tools/core-build-tasks/src/platforms/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export * from './MinecraftProduct'; diff --git a/tools/core-build-tasks/src/setupEnvironment.ts b/tools/core-build-tasks/src/setupEnvironment.ts new file mode 100644 index 0000000..4beb2e5 --- /dev/null +++ b/tools/core-build-tasks/src/setupEnvironment.ts @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import dotenv from 'dotenv'; + +/** + * Loads the environment variables. + * @param envPath - path to the .env file. + */ +export function setupEnvironment(envPath: string) { + dotenv.config({ path: envPath }); +} diff --git a/tools/core-build-tasks/src/tasks/api-extractor.ts b/tools/core-build-tasks/src/tasks/api-extractor.ts index 1bc13c0..ed78f22 100644 --- a/tools/core-build-tasks/src/tasks/api-extractor.ts +++ b/tools/core-build-tasks/src/tasks/api-extractor.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + import { Extractor, ExtractorConfig, ExtractorResult } from '@microsoft/api-extractor'; /** diff --git a/tools/core-build-tasks/src/tasks/bundle.ts b/tools/core-build-tasks/src/tasks/bundle.ts new file mode 100644 index 0000000..7d9c536 --- /dev/null +++ b/tools/core-build-tasks/src/tasks/bundle.ts @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { parallel } from 'just-scripts'; +import esbuild from 'esbuild'; + +export type BundleTaskParameters = { + /** Initial script to be evaluated for the build. Documentation: https://esbuild.github.io/api/#entry-points */ + entryPoint: string; + + /** Packages to be considered as external. Documentation: https://esbuild.github.io/api/#external */ + external?: string[]; + + /** When enabled, the generated code will be minified instead of pretty-printed. Documentation: https://esbuild.github.io/api/#minify */ + minifyWhitespace?: boolean; + + /** The output file for the bundle. Documentation: https://esbuild.github.io/api/#outfile */ + outfile: string; + + /** Flag to specify how to generate source map. Documentation: https://esbuild.github.io/api/#sourcemap */ + sourcemap?: boolean | 'linked' | 'inline' | 'external' | 'both'; +}; + +export function bundleTask(options: BundleTaskParameters): ReturnType { + return async () => { + return esbuild.build({ + entryPoints: [options.entryPoint], + bundle: true, + format: 'esm', + minifyWhitespace: options.minifyWhitespace, + outfile: options.outfile, + sourcemap: options.sourcemap, + external: options.external, + }); + }; +} diff --git a/tools/core-build-tasks/src/tasks/clean.ts b/tools/core-build-tasks/src/tasks/clean.ts index 746231d..2eae288 100644 --- a/tools/core-build-tasks/src/tasks/clean.ts +++ b/tools/core-build-tasks/src/tasks/clean.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + import path from 'path'; import rimraf from 'rimraf'; diff --git a/tools/core-build-tasks/src/tasks/cleanCollateral.ts b/tools/core-build-tasks/src/tasks/cleanCollateral.ts new file mode 100644 index 0000000..215e17c --- /dev/null +++ b/tools/core-build-tasks/src/tasks/cleanCollateral.ts @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as fs from 'fs'; +import * as Path from 'path'; +import rimraf from 'rimraf'; +import { getOrThrowFromProcess } from './helpers/getOrThrowFromProcess'; + +export const STANDARD_CLEAN_PATHS = [ + 'LOCALAPPDATA/Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang/development_behavior_packs/PROJECT_NAME', + 'LOCALAPPDATA/Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang/development_resource_packs/PROJECT_NAME', + 'LOCALAPPDATA/Packages/Microsoft.MinecraftWindowsBeta_8wekyb3d8bbwe/LocalState/games/com.mojang/development_behavior_packs/PROJECT_NAME', + 'LOCALAPPDATA/Packages/Microsoft.MinecraftWindowsBeta_8wekyb3d8bbwe/LocalState/games/com.mojang/development_resource_packs/PROJECT_NAME', +]; + +/** + * Cleans the specified outputs. Outputs could be either folders or files. Has support for the following variable replacements + * + * APPDATA, LOCALAPPDATA, PROJECT_NAME + * + * This constant is replaced at task execution with a value provided by the process environment. + * + */ +export function cleanCollateralTask(pathsToClean: string[]) { + return () => { + const projectName = getOrThrowFromProcess('PROJECT_NAME'); + + // The following variables are not used on all platforms. In those cases, set up an error token so that if the + // config requires these on the platform, we error out immediately. + const errorToken = '$ERROR_TOKEN$'; + let appData = process.env.APPDATA; + if (!appData) { + console.warn('Proceeding without APPDATA on this platform. File copy will fail if APPDATA is required.'); + appData = errorToken; + } + + let localAppData = process.env.LOCALAPPDATA; + if (!localAppData) { + console.warn( + 'Proceeding without LOCALAPPDATA on this platform. File copy will fail if LOCALAPPDATA is required.' + ); + localAppData = errorToken; + } + + // For each output path, replace tokens with env values + for (const cleanPathRaw of pathsToClean) { + const cleanPath = cleanPathRaw + .replace('LOCALAPPDATA', localAppData) + .replace('APPDATA', appData) + .replace('PROJECT_NAME', projectName); + + if (cleanPath.includes(errorToken)) { + console.warn( + `Skipping clean of ${cleanPath} on current platform due to APPDATA or LOCALAPPDATA being missing.` + ); + continue; + } + + try { + const stats = fs.statSync(cleanPath); + console.log(`Cleaning ${stats.isDirectory() ? 'directory' : 'file'} ${Path.resolve(cleanPath)}.`); + rimraf.sync(cleanPath); + } catch (_: unknown) { + // File or directory did not exist, so we no-op + } + } + }; +} diff --git a/tools/core-build-tasks/src/tasks/copy.ts b/tools/core-build-tasks/src/tasks/copy.ts new file mode 100644 index 0000000..df9b767 --- /dev/null +++ b/tools/core-build-tasks/src/tasks/copy.ts @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import path from 'path'; +import { copyFiles } from './helpers/copyFiles'; +import { getOrThrowFromProcess } from './helpers/getOrThrowFromProcess'; +import { getGameDeploymentRootPaths } from './helpers/getGameDeploymentRootPaths'; +import { MinecraftProduct } from '../platforms/MinecraftProduct'; + +const BehaviorPacksPath = 'development_behavior_packs'; +const ResourcePacksPath = 'development_resource_packs'; + +export type CopyTaskParameters = { + /** + * The paths to copy to behavior packs directory in the game. + */ + copyToBehaviorPacks: string[]; + /** + * The paths to copy to the scripts directory in the game. + * This is copied after copyToBehaviorPacks. + */ + copyToScripts: string[]; + /** + * The paths to copy to resource packs directory in the game. + */ + copyToResourcePacks?: string[]; +}; + +/** + * A just task which copies files to a specified output location. + * Where there may be multiple output paths, and for each output path there may be multiple files. + */ +export function copyTask(params: CopyTaskParameters) { + return () => { + const projectName = getOrThrowFromProcess('PROJECT_NAME'); + + let deploymentPath: string | undefined = undefined; + try { + const product = getOrThrowFromProcess('MINECRAFT_PRODUCT'); + deploymentPath = getGameDeploymentRootPaths()[product]; + } catch (_) { + throw new Error('Unable to get deployment path. Make sure to configure package root correctly.'); + } + + if (deploymentPath === undefined) { + throw new Error('Deployment path is undefined. Make sure to configure package root correctly.'); + } + + copyFiles(params.copyToBehaviorPacks, path.join(deploymentPath, BehaviorPacksPath, projectName)); + copyFiles(params.copyToScripts, path.join(deploymentPath, BehaviorPacksPath, projectName, 'scripts')); + if (params.copyToResourcePacks) { + copyFiles(params.copyToResourcePacks, path.join(deploymentPath, ResourcePacksPath, projectName)); + } + }; +} diff --git a/tools/core-build-tasks/src/tasks/coreLint.ts b/tools/core-build-tasks/src/tasks/coreLint.ts index 034ab35..5d50efe 100644 --- a/tools/core-build-tasks/src/tasks/coreLint.ts +++ b/tools/core-build-tasks/src/tasks/coreLint.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + import { existsSync } from 'fs'; import type { TaskFunction } from 'just-scripts'; import { condition, eslintTask, prettierCheckTask, prettierTask, series, task } from 'just-scripts'; @@ -20,6 +23,6 @@ export function coreLint(files: string[], fix?: boolean): TaskFunction { 'verify-lint', 'eslint', condition('prettier-check', () => !fix), - condition('prettier-fix', () => !!fix), + condition('prettier-fix', () => !!fix) ); } diff --git a/tools/core-build-tasks/src/tasks/helpers/copyFiles.ts b/tools/core-build-tasks/src/tasks/helpers/copyFiles.ts new file mode 100644 index 0000000..c26f4b0 --- /dev/null +++ b/tools/core-build-tasks/src/tasks/helpers/copyFiles.ts @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { FileSystem } from '@rushstack/node-core-library'; +import path from 'path'; + +export function copyFiles(originPaths: string[], outputPath: string) { + let destinationPath = path.resolve(outputPath); + for (const originPath of originPaths) { + const inputPath = path.resolve(originPath); + const pathStats = FileSystem.getLinkStatistics(inputPath); + if (pathStats.isDirectory()) { + console.log(`Copying folder ${inputPath} to ${destinationPath}`); + } else { + const filename = path.parse(inputPath).base; + destinationPath = path.resolve(destinationPath, filename); + console.log(`Copying file ${inputPath} to ${destinationPath}`); + } + + FileSystem.copyFiles({ + sourcePath: inputPath, + destinationPath: destinationPath, + }); + } +} diff --git a/tools/core-build-tasks/src/tasks/helpers/getGameDeploymentRootPaths.ts b/tools/core-build-tasks/src/tasks/helpers/getGameDeploymentRootPaths.ts new file mode 100644 index 0000000..35edec8 --- /dev/null +++ b/tools/core-build-tasks/src/tasks/helpers/getGameDeploymentRootPaths.ts @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { MinecraftProduct } from '../../platforms'; +import path, { resolve } from 'path'; +import { getOrThrowFromProcess } from './getOrThrowFromProcess'; + +export function getGameDeploymentRootPaths(): Record { + const localAppDataPath = process.env['LOCALAPPDATA']; + const customDeploymentPath = process.env['CUSTOM_DEPLOYMENT_PATH']; + return { + BedrockUWP: localAppDataPath + ? resolve(localAppDataPath, 'Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang/') + : undefined, + PreviewUWP: localAppDataPath + ? resolve( + localAppDataPath, + 'Packages/Microsoft.MinecraftWindowsBeta_8wekyb3d8bbwe/LocalState/games/com.mojang/' + ) + : undefined, + Custom: customDeploymentPath ? customDeploymentPath : undefined, + }; +} + +export function getTargetWorldPath(): string { + let deploymentPath: string | undefined = undefined; + let product: MinecraftProduct; + try { + product = getOrThrowFromProcess('MINECRAFT_PRODUCT'); + deploymentPath = getGameDeploymentRootPaths()[product]; + } catch (_) { + throw new Error('Unable to get deployment path. Make sure to configure package root correctly.'); + } + + if (deploymentPath === undefined) { + throw new Error('Deployment path is undefined. Make sure to configure package root correctly.'); + } + + const projectName = getOrThrowFromProcess('PROJECT_NAME'); + const worldsFolderName = product == MinecraftProduct.Custom ? 'worlds' : 'minecraftWorlds'; + const activeWorldFolderName = product == MinecraftProduct.Custom ? 'Bedrock level' : `${projectName}world`; + return path.join(deploymentPath, worldsFolderName, activeWorldFolderName); +} diff --git a/tools/core-build-tasks/src/tasks/helpers/getOrThrowFromProcess.ts b/tools/core-build-tasks/src/tasks/helpers/getOrThrowFromProcess.ts new file mode 100644 index 0000000..2663dd8 --- /dev/null +++ b/tools/core-build-tasks/src/tasks/helpers/getOrThrowFromProcess.ts @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * Checks process.env for the desired key and returns the value if it exists, otherwise throws an error. Generic parameter + * is used to ensure the correct type is returned + * + * @param key - The key to query from process env + * @param message - Message to include in thrown error on failure + * @returns Value from process env or throws an error + */ +export function getOrThrowFromProcess(key: string, messageOverride?: string): T { + const value = process.env[key]; + if (!value) { + throw new Error(messageOverride ?? `Missing environment variable ${key}. Make sure to configure project.`); + } + + return value as T; +} diff --git a/tools/core-build-tasks/src/tasks/helpers/index.ts b/tools/core-build-tasks/src/tasks/helpers/index.ts new file mode 100644 index 0000000..4098a84 --- /dev/null +++ b/tools/core-build-tasks/src/tasks/helpers/index.ts @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export * from './copyFiles'; +export * from './getOrThrowFromProcess'; +export * from './getGameDeploymentRootPaths'; diff --git a/tools/core-build-tasks/src/tasks/index.ts b/tools/core-build-tasks/src/tasks/index.ts index fc257ec..aae586e 100644 --- a/tools/core-build-tasks/src/tasks/index.ts +++ b/tools/core-build-tasks/src/tasks/index.ts @@ -1,4 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + export * from './api-extractor'; +export * from './bundle'; export * from './clean'; +export * from './cleanCollateral'; +export * from './copy'; export * from './coreLint'; +export * from './helpers'; export * from './vitest'; +export * from './updateWorld'; +export * from './watch'; +export * from './zip'; diff --git a/tools/core-build-tasks/src/tasks/updateWorld.ts b/tools/core-build-tasks/src/tasks/updateWorld.ts new file mode 100644 index 0000000..f6b4e2e --- /dev/null +++ b/tools/core-build-tasks/src/tasks/updateWorld.ts @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { TaskFunction, condition, series, task } from 'just-scripts'; +import { cleanTask } from './clean'; +import { copyFiles, getTargetWorldPath } from './helpers'; +import { FileSystem } from '@rushstack/node-core-library'; +import path from 'path'; + +export type UpdateWorldParameters = { + /** + * The path to the world backup directory. + */ + backupPath: string; + + /** + * The path to the development world directory. + */ + devWorldPath: string; +}; + +/** + * A just task which updates the world in the game from the development path. Original world is backed up. + */ +export function updateWorldTask(params: UpdateWorldParameters): TaskFunction { + const targetWorldPath = path.resolve(getTargetWorldPath()); + task('clean_localmc_world_backup', cleanTask([params.backupPath])); + task('backup_localmc_world', () => copyFiles([targetWorldPath], params.backupPath)); + task('clean_localmc_world', cleanTask([targetWorldPath])); + task('deploy_localmc_world', () => copyFiles([params.devWorldPath], targetWorldPath)); + return series( + 'clean_localmc_world_backup', + condition('backup_localmc_world', () => FileSystem.exists(targetWorldPath)), + 'clean_localmc_world', + 'deploy_localmc_world' + ); +} diff --git a/tools/core-build-tasks/src/tasks/vitest.ts b/tools/core-build-tasks/src/tasks/vitest.ts index a72ca8e..bfee2e5 100644 --- a/tools/core-build-tasks/src/tasks/vitest.ts +++ b/tools/core-build-tasks/src/tasks/vitest.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + import { execSync } from 'child_process'; export function vitestTask() { diff --git a/tools/core-build-tasks/src/tasks/watch.ts b/tools/core-build-tasks/src/tasks/watch.ts new file mode 100644 index 0000000..b3f105a --- /dev/null +++ b/tools/core-build-tasks/src/tasks/watch.ts @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { argv, series, task, watch, logger, TaskFunction, undertaker, option } from 'just-scripts'; + +const WATCH_TASK_NAME = 'watch-task'; + +option('watch'); + +/** + * If command line parameter `option` is present, watch for changes in the specified files and run the specified task. + * Otherwise, just run the task. + * @param globs The file globs to watch. + * @param taskFunction The task to run when changes are detected. + */ +export function watchTask(globs: string | string[], taskFunction: TaskFunction): TaskFunction { + return () => { + if (!argv().watch) { + return taskFunction; + } + + let taskInProgress = true; + let pendingWork = false; + + const onFinished = (args: any) => { + if (args.name === WATCH_TASK_NAME) { + if (pendingWork) { + logger.info('Processing pending changes...'); + pendingWork = false; + (origTask as any).call(); + } else { + logger.info('Waiting for new changes...'); + taskInProgress = false; + } + } + }; + + undertaker.on('start', function (args: any) { + if (args.name === WATCH_TASK_NAME) { + taskInProgress = true; + } + }); + + undertaker.on('stop', function (args: any) { + onFinished(args); + }); + + undertaker.on('error', function (args: any) { + onFinished(args); + }); + + task(WATCH_TASK_NAME, series(taskFunction)); + let origTask = series(WATCH_TASK_NAME); + + // Start execution. + (origTask as any).call(); + + watch(globs, () => { + if (!taskInProgress) { + (origTask as any).call(); + } else { + pendingWork = true; + } + }); + return Promise.resolve(); + }; +} diff --git a/tools/core-build-tasks/src/tasks/zip.ts b/tools/core-build-tasks/src/tasks/zip.ts new file mode 100644 index 0000000..6aef2ee --- /dev/null +++ b/tools/core-build-tasks/src/tasks/zip.ts @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { FileSystem } from '@rushstack/node-core-library'; +import path from 'path'; +import { CopyTaskParameters } from '.'; +import { Zip } from 'zip-lib'; +import { TaskFunction, parallel, series, task } from 'just-scripts'; + +export type ZipTaskParameters = CopyTaskParameters & { + /** + * The path to the output file to write the zip file to. + */ + outputFile: string; +}; + +export type ZipContent = { + /** + * The contents to add to the zip. + */ + contents: string[]; + /** + * The relative path to the root. In case of provided contents are added into this folder inside the zip. + */ + targetPath?: string; +}; + +function addContentsToZip(zipContents: ZipContent[], zip: Zip) { + for (const content of zipContents) { + for (const originPath of content.contents) { + const inputPath = path.resolve(originPath); + const pathStats = FileSystem.getLinkStatistics(inputPath); + + if (pathStats.isDirectory()) { + console.log(`Adding folder ${inputPath} to package`); + zip.addFolder(inputPath, content.targetPath); + } else { + const metadataPath = content.targetPath + ? path.join(content.targetPath, path.parse(inputPath).base) + : undefined; + console.log(`Adding file ${inputPath} to package`); + zip.addFile(inputPath, metadataPath); + } + } + } +} + +/** + * A just task which compresses files into a specified output file. + */ +export function zipTask(outputFile: string, zipContents: ZipContent[]): ReturnType { + return async function zip() { + if (zipContents.length === 0 || !zipContents.some(content => content.contents.length > 0)) { + process.exitCode = 0; + return Promise.resolve(); + } + + const zip = new Zip(); + + addContentsToZip(zipContents, zip); + + let isSucceeded = true; + let errorMessage = ''; + await zip.archive(outputFile).then( + function () { + console.error(`Compressed file created at ${outputFile}`); + }, + function (err) { + isSucceeded = false; + errorMessage = `Compressed file failed to be created at ${outputFile}: ${err}`; + console.error(errorMessage); + } + ); + + if (isSucceeded) { + process.exitCode = 0; + return Promise.resolve(); + } + + process.exitCode = 1; + return Promise.reject(new Error(errorMessage)); + }; +} + +/** + * A just task which creates the mcaddon file. + */ +export function mcaddonTask(params: ZipTaskParameters): TaskFunction { + const targetFolder = path.parse(params.outputFile).dir; + const outputFileName = path.parse(params.outputFile).name; + const behaviorPackFile = path.join(targetFolder, `${outputFileName}_bp.mcpack`); + const resourcePackFile = path.join(targetFolder, `${outputFileName}_rp.mcpack`); + const mcaddonContents: ZipContent = { contents: [behaviorPackFile] }; + if (params.copyToResourcePacks && params.copyToResourcePacks.length > 0) { + mcaddonContents.contents.push(resourcePackFile); + } + + task( + 'packBP', + zipTask(behaviorPackFile, [ + { contents: params.copyToBehaviorPacks }, + { contents: params.copyToScripts, targetPath: 'scripts' }, + ]) + ); + task('packRP', zipTask(resourcePackFile, [{ contents: params.copyToResourcePacks ?? [] }])); + task('packMcaddon', zipTask(params.outputFile, [mcaddonContents])); + return series(parallel('packBP', 'packRP'), 'packMcaddon'); +} diff --git a/tools/eslint-config-minecraft-scripting/index.js b/tools/eslint-config-minecraft-scripting/index.js index 7245013..29cb07c 100644 --- a/tools/eslint-config-minecraft-scripting/index.js +++ b/tools/eslint-config-minecraft-scripting/index.js @@ -29,7 +29,7 @@ module.exports = { '@typescript-eslint/no-unsafe-assignment': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-call': 'error', - 'header/header': [2, 'line', ' Copyright (c) Mojang AB. All rights reserved.', 1], + 'header/header': [2, 'line', [' Copyright (c) Microsoft Corporation.', ` Licensed under the MIT License.`], 1], 'minecraft-linting/avoid-unnecessary-command': 'error', }, }; diff --git a/tools/eslint-config-minecraft-scripting/package.json b/tools/eslint-config-minecraft-scripting/package.json index bb79761..5f29d73 100644 --- a/tools/eslint-config-minecraft-scripting/package.json +++ b/tools/eslint-config-minecraft-scripting/package.json @@ -20,4 +20,4 @@ "publishConfig": { "access": "public" } -} +} \ No newline at end of file diff --git a/tools/eslint-plugin-minecraft-linting/package.json b/tools/eslint-plugin-minecraft-linting/package.json index 42200b8..c3b1f0b 100644 --- a/tools/eslint-plugin-minecraft-linting/package.json +++ b/tools/eslint-plugin-minecraft-linting/package.json @@ -22,6 +22,7 @@ "@typescript-eslint/parser": "^6.10.0", "@typescript-eslint/typescript-estree": "^6.10.0", "eslint": "^8.53.0", + "eslint-plugin-header": "^3.1.1", "eslint-config-prettier": "^9.0.0", "eslint-plugin-unicorn": "^42.0.0", "just-scripts": "^2.1.3", @@ -30,4 +31,4 @@ "publishConfig": { "access": "public" } -} +} \ No newline at end of file diff --git a/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.test.ts b/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.test.ts index 0d54421..c64ba7c 100644 --- a/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.test.ts +++ b/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.test.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { TSESLint } from '@typescript-eslint/experimental-utils'; import * as path from 'path'; diff --git a/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.ts b/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.ts index 4f2429b..62a2410 100644 --- a/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.ts +++ b/tools/eslint-plugin-minecraft-linting/src/Rules/AvoidUnnecessaryCommand.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. /** * Rule which inspects calls to `runCommand[async]` and recommends using a script API if there diff --git a/tools/eslint-plugin-minecraft-linting/src/Rules/TestProject/estree.ts b/tools/eslint-plugin-minecraft-linting/src/Rules/TestProject/estree.ts index 74e26ff..c041786 100644 --- a/tools/eslint-plugin-minecraft-linting/src/Rules/TestProject/estree.ts +++ b/tools/eslint-plugin-minecraft-linting/src/Rules/TestProject/estree.ts @@ -1,2 +1,3 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. // This file must remain for the test compilation to work successfully diff --git a/tools/eslint-plugin-minecraft-linting/src/index.ts b/tools/eslint-plugin-minecraft-linting/src/index.ts index eb09f8e..6db7af2 100644 --- a/tools/eslint-plugin-minecraft-linting/src/index.ts +++ b/tools/eslint-plugin-minecraft-linting/src/index.ts @@ -1,4 +1,5 @@ -// Copyright (c) Mojang AB. All rights reserved. +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import AvoidUnnecessaryCommand from './Rules/AvoidUnnecessaryCommand';