@nano191225/scriptup 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nano191225
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ja.md ADDED
@@ -0,0 +1,182 @@
1
+ [English](README.md) | 日本語
2
+
3
+ # scriptup
4
+
5
+ [![Release](https://img.shields.io/github/v/release/Nano191225/scriptup?display_name=tag)](https://github.com/Nano191225/scriptup/releases)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
8
+
9
+ Minecraft Bedrock ScriptAPI 開発向けの CLI です。
10
+
11
+ scriptup は、@minecraft/\* の更新、ScriptAPI での外部ライブラリ利用、そして ScriptAPI 用ライブラリ作成の初期構築を素早く行えるようにします。
12
+
13
+ ## モチベーション
14
+
15
+ - @minecraft/\* の更新を容易にする
16
+ - ScriptAPI で簡単に外部ライブラリを使えるようにする
17
+ - ScriptAPI 用のライブラリを簡単に作れるようにする
18
+
19
+ ## 主な機能
20
+
21
+ - manifest.json の ScriptAPI 依存バージョン更新と、対応 npm パッケージのインストール
22
+ - development_behavior_packs 直下への新規プロジェクト作成
23
+ - 現在のディレクトリを ScriptAPI プロジェクトとして初期化
24
+ - manifest.json の script entry を出力先として tsdown ビルド
25
+ - 再利用可能ライブラリ作成向けのローカル雛形生成
26
+
27
+ ## 動作要件
28
+
29
+ - Node.js 18 以上
30
+ - アドオンを試すための Minecraft Bedrock 実行環境
31
+ - npm, pnpm, yarn, bun のいずれか
32
+
33
+ ## インストール
34
+
35
+ 好みのパッケージマネージャーで global インストールしてください。
36
+
37
+ ```bash
38
+ npm i -g @nano191225/scriptup
39
+ ```
40
+
41
+ ```bash
42
+ pnpm add -g @nano191225/scriptup
43
+ ```
44
+
45
+ 導入後は scriptup(または sup)で実行できます。
46
+
47
+ ## クイックスタート
48
+
49
+ ### 最新 stable の ScriptAPI モジュールへ更新
50
+
51
+ ```bash
52
+ scriptup stable
53
+ ```
54
+
55
+ ### 新規プロジェクト作成
56
+
57
+ ```bash
58
+ scriptup new my-pack --open
59
+ ```
60
+
61
+ ### ビルド
62
+
63
+ ```bash
64
+ scriptup build
65
+ ```
66
+
67
+ ## コマンド
68
+
69
+ ### scriptup stable
70
+
71
+ 最新の stable な Minecraft バージョンに一致するモジュールをインストールします。
72
+
73
+ ### scriptup preview
74
+
75
+ 最新の preview な Minecraft バージョンに一致するモジュールをインストールします。
76
+
77
+ ### scriptup lts
78
+
79
+ LTS 相当(stable/preview/beta/internal 以外を優先)のモジュールをインストールします。見つからない場合は stable 相当にフォールバックします。
80
+
81
+ ### scriptup <version>
82
+
83
+ 手動バージョン検索モードです。
84
+
85
+ 例:
86
+
87
+ ```bash
88
+ scriptup 1.21.60
89
+ scriptup 2.0.0-beta
90
+ ```
91
+
92
+ ### scriptup init
93
+
94
+ 現在のディレクトリを ScriptAPI プロジェクトとして初期化します。
95
+
96
+ オプション:
97
+
98
+ - --no-workflow: GitHub Actions workflow を生成しない
99
+
100
+ 実行内容:
101
+
102
+ - 主要ファイルを生成(manifest.json, tsconfig.json, src/main.ts など)
103
+ - tsdown.config.ts がなければ作成
104
+ - package.json scripts を更新
105
+ - build: scriptup build --release
106
+ - watch: scriptup build --watch
107
+ - 必要な devDependencies をインストール
108
+
109
+ ### scriptup new <project-name>
110
+
111
+ 新しい ScriptAPI プロジェクトを作成します。
112
+
113
+ オプション:
114
+
115
+ - -o, --open [command]: 作成後にエディタで開く(既定値: code)
116
+ - -p, --preview: Minecraft Bedrock Preview の behavior packs ディレクトリを使う
117
+ - -d, --dir <path>: 指定ディレクトリ配下に作成
118
+ - --lib: package/ 配下にローカルライブラリ雛形を含める
119
+ - --no-link: --dir 使用時の behavior packs へのリンク作成を無効化
120
+ - --no-workflow: GitHub Actions workflow を生成しない
121
+
122
+ 既定の作成先:
123
+
124
+ - Windows stable:
125
+ - %APPDATA%/Minecraft Bedrock/Users/Shared/games/com.mojang/development_behavior_packs
126
+ - Windows preview:
127
+ - %APPDATA%/Minecraft Bedrock Preview/Users/Shared/games/com.mojang/development_behavior_packs
128
+ - Linux (mcpelauncher):
129
+ - ${XDG_DATA_HOME:-~/.local/share}/mcpelauncher/games/com.mojang/development_behavior_packs
130
+
131
+ ### scriptup build
132
+
133
+ tsdown で現在の ScriptAPI プロジェクトをビルドします。
134
+
135
+ オプション:
136
+
137
+ - -b, --bundle: 強制的にバンドル出力
138
+ - -w, --watch: 監視モード
139
+ - -r, --release: リリースビルド(圧縮有効、sourcemap 無効)
140
+
141
+ ビルド挙動の要点:
142
+
143
+ - 出力先は manifest.json の script module entry から決定(例: scripts/main.js)
144
+ - 入力エントリの優先順位
145
+ - src/main.ts
146
+ - src/index.ts
147
+ - tsdown.config.ts の entry
148
+ - release モードでは package/ が存在する場合に package/\*\*/\*.ts も dist/ へ追加ビルド
149
+
150
+ ## 典型的な使い方
151
+
152
+ ### 既存プロジェクト
153
+
154
+ ```bash
155
+ scriptup init
156
+ scriptup stable
157
+ scriptup build
158
+ ```
159
+
160
+ ### 新規アドオン
161
+
162
+ ```bash
163
+ scriptup new my-addon --open
164
+ cd my-addon
165
+ scriptup build --watch
166
+ ```
167
+
168
+ ### ライブラリ前提の新規プロジェクト
169
+
170
+ ```bash
171
+ scriptup new @yourname/your-lib --lib --dir . --open
172
+ ```
173
+
174
+ ## 補足
175
+
176
+ - manifest.json の依存更新と devDependencies のインストールをあわせて実行します
177
+ - packageManager フィールドまたは lockfile からパッケージマネージャーを自動判定します
178
+ - エイリアスとして sup も使えます
179
+
180
+ ## ライセンス
181
+
182
+ MIT
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ English | [日本語](README.ja.md)
2
+
3
+ # scriptup
4
+
5
+ [![Release](https://img.shields.io/github/v/release/Nano191225/scriptup?display_name=tag)](https://github.com/Nano191225/scriptup/releases)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
8
+
9
+ CLI for Minecraft Bedrock ScriptAPI development.
10
+
11
+ scriptup helps you keep @minecraft/\* modules current, use external libraries in ScriptAPI projects, and scaffold projects and library-ready structures quickly.
12
+
13
+ ## Motivation
14
+
15
+ - Make updating @minecraft/\* easier
16
+ - Make it easy to use external libraries in ScriptAPI
17
+ - Make it easy to create libraries for ScriptAPI
18
+
19
+ ## Features
20
+
21
+ - Update ScriptAPI module versions in manifest.json and install matching package versions
22
+ - Create a new ScriptAPI project directly in development_behavior_packs
23
+ - Initialize the current directory as a ScriptAPI project
24
+ - Build ScriptAPI code with tsdown using manifest.json script entry output
25
+ - Optional local library scaffold for creating reusable ScriptAPI packages
26
+
27
+ ## Requirements
28
+
29
+ - Node.js 18+
30
+ - Minecraft Bedrock environment for addon testing
31
+ - One of npm, pnpm, yarn, or bun
32
+
33
+ ## Install
34
+
35
+ Use your preferred package manager and install globally.
36
+
37
+ ```bash
38
+ npm i -g @nano191225/scriptup
39
+ ```
40
+
41
+ ```bash
42
+ pnpm add -g @nano191225/scriptup
43
+ ```
44
+
45
+ After installation, run via scriptup (or sup).
46
+
47
+ ## Quick Start
48
+
49
+ ### Update to latest stable ScriptAPI modules
50
+
51
+ ```bash
52
+ scriptup stable
53
+ ```
54
+
55
+ ### Create a new project
56
+
57
+ ```bash
58
+ scriptup new my-pack --open
59
+ ```
60
+
61
+ ### Build your project
62
+
63
+ ```bash
64
+ scriptup build
65
+ ```
66
+
67
+ ## Commands
68
+
69
+ ### scriptup stable
70
+
71
+ Installs module versions matching the latest stable Minecraft version.
72
+
73
+ ### scriptup preview
74
+
75
+ Installs module versions matching the latest preview Minecraft version.
76
+
77
+ ### scriptup lts
78
+
79
+ Installs LTS-like module versions (non-stable, non-preview, non-beta, non-internal when available), with fallback to stable matching versions.
80
+
81
+ ### scriptup <version>
82
+
83
+ Manual version lookup mode.
84
+
85
+ Example:
86
+
87
+ ```bash
88
+ scriptup 1.21.60
89
+ scriptup 2.0.0-beta
90
+ ```
91
+
92
+ ### scriptup init
93
+
94
+ Initialize the current directory as a ScriptAPI project.
95
+
96
+ Options:
97
+
98
+ - --no-workflow: Do not generate GitHub Actions workflow files
99
+
100
+ What it does:
101
+
102
+ - Scaffolds core project files (manifest.json, tsconfig.json, src/main.ts, etc.)
103
+ - Ensures tsdown.config.ts exists
104
+ - Sets package.json scripts:
105
+ - build: scriptup build --release
106
+ - watch: scriptup build --watch
107
+ - Installs required dev dependencies
108
+
109
+ ### scriptup new <project-name>
110
+
111
+ Create a new ScriptAPI project.
112
+
113
+ Options:
114
+
115
+ - -o, --open [command]: Open project after creation (preset: code)
116
+ - -p, --preview: Use Minecraft Bedrock Preview behavior packs directory
117
+ - -d, --dir <path>: Create under a specific directory
118
+ - --lib: Include local library scaffold under package/
119
+ - --no-link: Do not create behavior-pack link when --dir is used
120
+ - --no-workflow: Do not generate GitHub Actions workflow files
121
+
122
+ Default target directories:
123
+
124
+ - Windows stable:
125
+ - %APPDATA%/Minecraft Bedrock/Users/Shared/games/com.mojang/development_behavior_packs
126
+ - Windows preview:
127
+ - %APPDATA%/Minecraft Bedrock Preview/Users/Shared/games/com.mojang/development_behavior_packs
128
+ - Linux (mcpelauncher):
129
+ - ${XDG_DATA_HOME:-~/.local/share}/mcpelauncher/games/com.mojang/development_behavior_packs
130
+
131
+ ### scriptup build
132
+
133
+ Bundle/build current ScriptAPI project using tsdown.
134
+
135
+ Options:
136
+
137
+ - -b, --bundle: Force bundled output
138
+ - -w, --watch: Watch mode
139
+ - -r, --release: Release build (minified, sourcemap off)
140
+
141
+ Build behavior summary:
142
+
143
+ - Output target is derived from manifest.json script module entry (for example scripts/main.js)
144
+ - Input entry priority:
145
+ - src/main.ts
146
+ - src/index.ts
147
+ - entry in tsdown.config.ts
148
+ - Release mode also builds package/\*\*/\*.ts into dist/ when package/ exists
149
+
150
+ ## Typical Workflows
151
+
152
+ ### Existing project
153
+
154
+ ```bash
155
+ scriptup init
156
+ scriptup stable
157
+ scriptup build
158
+ ```
159
+
160
+ ### New addon project
161
+
162
+ ```bash
163
+ scriptup new my-addon --open
164
+ cd my-addon
165
+ scriptup build --watch
166
+ ```
167
+
168
+ ### New library-ready project
169
+
170
+ ```bash
171
+ scriptup new @yourname/your-lib --lib --dir . --open
172
+ ```
173
+
174
+ ## Notes
175
+
176
+ - scriptup updates versions in manifest.json and installs matching dev dependencies
177
+ - Package manager is auto-detected from packageManager field or lockfile
178
+ - Alias command sup is also available
179
+
180
+ ## License
181
+
182
+ MIT
package/dist/index.js CHANGED
@@ -1,21 +1,23 @@
1
1
  #!/usr/bin/env node
2
- import{Command as e,Option as t}from"commander";import n from"ora";import*as r from"node:fs";import*as i from"node:path";import a from"chalk";import{execSync as o,spawnSync as s}from"node:child_process";import{randomUUID as c}from"node:crypto";import*as l from"node:os";import{build as ee,mergeConfig as u}from"tsdown";import{pathToFileURL as d}from"node:url";function f(e){console.log(`${a.blue(`[INFO]`)} ${e}`)}function p(e){console.log(`${a.gray(`[LOG]`)} ${e}`)}function m(e){console.log(`${a.yellow(`[WARN]`)} ${e}`)}function h(e){console.error(`${a.red(`[ERROR]`)} ${e}`)}function g(e){console.log(`${a.green(`[DONE]`)} ${e}`)}function _(e){return e.type===`script`}function v(e){return`module_name`in e}function y(){let e=i.resolve(`manifest.json`);r.existsSync(e)||(h(`manifest.json not found.`),process.exit(1));let t=r.readFileSync(e,`utf-8`);return JSON.parse(t)}function b(e){let t=i.resolve(`manifest.json`),n=JSON.stringify(e,null,` `);r.writeFileSync(t,n,`utf-8`)}async function x(e){let t=`https://registry.npmjs.org/${e}`,n=await fetch(t);if(!n.ok)throw Error(`Failed to fetch versions for ${e}: ${n.statusText}`);let r=await n.json(),i=Object.keys(r.versions).reverse();return i.sort((e,t)=>{let n=e=>e.includes(`stable`)?0:e.includes(`preview`)?1:2;return n(e)-n(t)}),i}function S(e){let t=e.indexOf(`-`);if(t===-1)return e;let n=e.substring(t).indexOf(`.`);if(n===-1)return e;let r=t+n+1,i=e.substring(r),a=i.indexOf(`-`);return a===-1?i:i.substring(0,a)}function C(e){let t=e.indexOf(`-`);if(t===-1)return e;let n=e.substring(t).indexOf(`.`);return n===-1?e:e.substring(0,t+n)}function w(){let e=process.cwd(),t=i.resolve(e,`package.json`);if(r.existsSync(t)){let e=JSON.parse(r.readFileSync(t,`utf-8`));if(e.packageManager){let t=e.packageManager.split(`@`)[0];if(te(t))return p(`Detected package manager from package.json: ${t}`),t}}return r.existsSync(i.resolve(e,`bun.lockb`))||r.existsSync(i.resolve(e,`bun.lock`))?(p(`Detected package manager from lock file: bun`),`bun`):r.existsSync(i.resolve(e,`pnpm-lock.yaml`))?(p(`Detected package manager from lock file: pnpm`),`pnpm`):r.existsSync(i.resolve(e,`yarn.lock`))?(p(`Detected package manager from lock file: yarn`),`yarn`):r.existsSync(i.resolve(e,`package-lock.json`))?(p(`Detected package manager from lock file: npm`),`npm`):(p(`No lock file found. Defaulting to npm.`),`npm`)}function te(e){return[`npm`,`pnpm`,`yarn`,`bun`].includes(e)}function T(e){return e===`yarn`?`add`:`install`}function E(e){switch(e){case`npm`:return`--save-exact`;case`pnpm`:return`--save-exact`;case`yarn`:return`--exact`;case`bun`:return`--exact`}}function D(e){switch(e){case`npm`:return`--force`;case`pnpm`:return`--force`;case`yarn`:return;case`bun`:return`--force`}}function O(e,t){let n=T(e),r=E(e),i=D(e),a=[e,n,t,e===`yarn`?`--dev`:`--save-dev`,r];i&&a.push(i),o(a.join(` `),{stdio:`pipe`,cwd:process.cwd()})}async function k(){let e=n(`Fetching Minecraft version...`).start(),t=await A();e.succeed(`Install modules for Minecraft version: ${t}`);let r=y();p(`Manifest loaded. Fetching new module versions...`);let i=w(),a=[],o=r.dependencies?.filter(v)??[];for(let e of o){let n=(await x(e.module_name)).find(e=>e.includes(t));n||(h(`No version found for ${e.module_name} matching MC ${t}`),process.exit(1)),e.version=C(n),p(`${e.module_name}: ${n}`),a.push({name:e.module_name,version:n})}b(r),p(`Module versions fetched and manifest updated.`);let s=n(`Installing modules...`).start();for(let e=0;e<a.length;e++){let t=a[e];s.text=`Installing modules... (${e+1}/${a.length}) ${t.name}`;try{O(i,`${t.name}@${t.version}`)}catch(e){s.fail(`Failed to install ${t.name}`),h(e instanceof Error?e.message:String(e)),process.exit(1)}}s.succeed(`All modules installed successfully.`)}async function A(){let e=(await x(`@minecraft/server`)).find(e=>e.includes(`-stable`));return e||(h(`No stable versions found.`),process.exit(1)),S(e)}async function j(){let e=n(`Fetching Minecraft version...`).start(),t=await M();e.succeed(`Install modules for Minecraft version: ${t}`);let r=y();p(`Manifest loaded. Fetching new module versions...`);let i=w(),a=[],o=r.dependencies?.filter(v)??[];for(let e of o){let n=(await x(e.module_name)).find(e=>e.includes(t));n||(h(`No version found for ${e.module_name} matching MC ${t}`),process.exit(1)),e.version=C(n),p(`${e.module_name}: ${n}`),a.push({name:e.module_name,version:n})}b(r),p(`Module versions fetched and manifest updated.`);let s=n(`Installing modules...`).start();for(let e=0;e<a.length;e++){let t=a[e];s.text=`Installing modules... (${e+1}/${a.length}) ${t.name}`;try{O(i,`${t.name}@${t.version}`)}catch(e){s.fail(`Failed to install ${t.name}`),h(e instanceof Error?e.message:String(e)),process.exit(1)}}s.succeed(`All modules installed successfully.`)}async function M(){let e=(await x(`@minecraft/server`)).find(e=>e.includes(`-preview`));return e||(h(`No preview versions found.`),process.exit(1)),S(e)}async function N(){let e=n(`Fetching Minecraft version...`).start(),t=await P();e.succeed(`Install modules for Minecraft version: ${t}`);let r=y();p(`Manifest loaded. Fetching new module versions...`);let i=w(),a=[],o=r.dependencies?.filter(v)??[];for(let e of o){let n=await x(e.module_name),r=n.find(e=>!e.includes(`stable`)&&!e.includes(`preview`)&&!e.includes(`internal`)&&!e.includes(`beta`)&&!e.startsWith(`0.`));r?e.version=r:(m(`No LTS versions found for ${e.module_name}. Falling back to stable.`),r=n.find(e=>e.includes(t)),r||(h(`No version found for ${e.module_name}`),process.exit(1)),e.version=S(r)),p(`${e.module_name}: ${r}`),a.push({name:e.module_name,version:r})}b(r),p(`Module versions fetched and manifest updated.`);let s=n(`Installing modules...`).start();for(let e=0;e<a.length;e++){let t=a[e];s.text=`Installing modules... (${e+1}/${a.length}) ${t.name}`;try{O(i,`${t.name}@${t.version}`)}catch(e){s.fail(`Failed to install ${t.name}`),h(e instanceof Error?e.message:String(e)),process.exit(1)}}s.succeed(`All modules installed successfully.`)}async function P(){let e=(await x(`@minecraft/server`)).find(e=>e.includes(`-stable`));return e||(h(`No stable versions found.`),process.exit(1)),S(e)}async function F(e){let t=await x(`@minecraft/server`),n=t.find(t=>t===e);if(n){f(`Found exact version: ${n}`);return}let r=t.find(t=>t.includes(e));r||(h(`Version not found: ${e}`),process.exit(1));let i=S(r);f(`Found version: ${i}`);let a=(await x(`@minecraft/server`)).find(e=>e.includes(i)),o=(await x(`@minecraft/server-ui`)).find(e=>e.includes(i));a&&f(`Server version: ${a}`),o&&f(`Server UI version: ${o}`)}async function I(e){let t=i.resolve(e.targetDir),n=e.projectName?.trim()||i.basename(t),a=e.workflow!==!1;r.mkdirSync(t,{recursive:!0});let o=B(n,await z(),a),s=0;for(let[e,n]of Object.entries(o)){let a=i.join(t,e);if(r.existsSync(a)){m(`Skipped existing file: ${e}`);continue}r.mkdirSync(i.dirname(a),{recursive:!0}),r.writeFileSync(a,n,`utf-8`),p(`Created ${e}`),s+=1}if(s===0){m(`No files were created.`);return}g(`Project initialized in ${t}`)}function L(e){r.existsSync(e)&&r.readdirSync(e).length>0&&(h(`Target directory is not empty: ${e}`),process.exit(1))}function R(e,t){let n=s(t,[`.`],{cwd:e,shell:!0,stdio:`inherit`});if(n.error)throw n.error;if(n.status!==0)throw Error(`${t} exited with code ${n.status??`unknown`}`)}async function z(){try{let e=(await x(`@minecraft/server`)).find(e=>e.includes(`-stable`));if(!e)throw Error(`No stable @minecraft/server version found.`);let t=S(e),n=t,r=[],i={};for(let e of[`@minecraft/server`,`@minecraft/server-ui`]){let n=(await x(e)).find(e=>e.includes(t));if(!n){m(`Skipped ${e}: no version found for Minecraft ${t}`);continue}let a=C(n);r.push({module_name:e,version:a}),i[e]=n}return{engineVersion:n,dependencies:r,packageDependencies:i}}catch(e){return m(`Failed to resolve latest ScriptAPI dependencies: ${e instanceof Error?e.message:String(e)}`),m(`Creating the project without npm dependencies. You can run scriptup stable later.`),{engineVersion:`1.20.0`,dependencies:[],packageDependencies:{}}}}function B(e,t,n){let r=ne(e,t.engineVersion,t.dependencies),i=V(e,t.packageDependencies),a={".gitignore":`node_modules/
2
+ import{Command as e,Option as t}from"commander";import n from"ora";import*as r from"node:fs";import*as i from"node:path";import a from"chalk";import{execSync as o,spawnSync as s}from"node:child_process";import{randomUUID as c}from"node:crypto";import*as l from"node:os";import{build as u,mergeConfig as d}from"tsdown";import{pathToFileURL as f}from"node:url";function p(e){console.log(`${a.blue(`[INFO]`)} ${e}`)}function m(e){console.log(`${a.gray(`[LOG]`)} ${e}`)}function h(e){console.log(`${a.yellow(`[WARN]`)} ${e}`)}function g(e){console.error(`${a.red(`[ERROR]`)} ${e}`)}function _(e){console.log(`${a.green(`[DONE]`)} ${e}`)}function v(e){return e.type===`script`}function y(e){return`module_name`in e}function b(){let e=i.resolve(`manifest.json`);r.existsSync(e)||(g(`manifest.json not found.`),process.exit(1));let t=r.readFileSync(e,`utf-8`);return JSON.parse(t)}function x(e){let t=i.resolve(`manifest.json`),n=JSON.stringify(e,null,` `);r.writeFileSync(t,n,`utf-8`)}async function S(e){let t=`https://registry.npmjs.org/${e}`,n=await fetch(t);if(!n.ok)throw Error(`Failed to fetch versions for ${e}: ${n.statusText}`);let r=await n.json(),i=Object.keys(r.versions).reverse();return i.sort((e,t)=>{let n=e=>e.includes(`stable`)?0:e.includes(`preview`)?1:2;return n(e)-n(t)}),i}function C(e){let t=e.indexOf(`-`);if(t===-1)return e;let n=e.substring(t).indexOf(`.`);if(n===-1)return e;let r=t+n+1,i=e.substring(r),a=i.indexOf(`-`);return a===-1?i:i.substring(0,a)}function w(e){let t=e.indexOf(`-`);if(t===-1)return e;let n=e.substring(t).indexOf(`.`);return n===-1?e:e.substring(0,t+n)}function T(){let e=process.cwd(),t=i.resolve(e,`package.json`);if(r.existsSync(t)){let e=JSON.parse(r.readFileSync(t,`utf-8`));if(e.packageManager){let t=e.packageManager.split(`@`)[0];if(E(t))return m(`Detected package manager from package.json: ${t}`),t}}return r.existsSync(i.resolve(e,`bun.lockb`))||r.existsSync(i.resolve(e,`bun.lock`))?(m(`Detected package manager from lock file: bun`),`bun`):r.existsSync(i.resolve(e,`pnpm-lock.yaml`))?(m(`Detected package manager from lock file: pnpm`),`pnpm`):r.existsSync(i.resolve(e,`yarn.lock`))?(m(`Detected package manager from lock file: yarn`),`yarn`):r.existsSync(i.resolve(e,`package-lock.json`))?(m(`Detected package manager from lock file: npm`),`npm`):(m(`No lock file found. Defaulting to npm.`),`npm`)}function E(e){return[`npm`,`pnpm`,`yarn`,`bun`].includes(e)}function ee(e){return e===`yarn`?`add`:`install`}function te(e){switch(e){case`npm`:return`--save-exact`;case`pnpm`:return`--save-exact`;case`yarn`:return`--exact`;case`bun`:return`--exact`}}function D(e){switch(e){case`npm`:return`--force`;case`pnpm`:return`--force`;case`yarn`:return;case`bun`:return`--force`}}function O(e,t){let n=ee(e),r=te(e),i=D(e),a=[e,n,t,e===`yarn`?`--dev`:`--save-dev`,r];i&&a.push(i),o(a.join(` `),{stdio:`pipe`,cwd:process.cwd()})}async function k(){let e=n(`Fetching Minecraft version...`).start(),t=await A();e.succeed(`Install modules for Minecraft version: ${t}`);let r=b();m(`Manifest loaded. Fetching new module versions...`);let i=T(),a=[],o=r.dependencies?.filter(y)??[];for(let e of o){let n=(await S(e.module_name)).find(e=>e.includes(t));n||(g(`No version found for ${e.module_name} matching MC ${t}`),process.exit(1)),e.version=w(n),m(`${e.module_name}: ${n}`),a.push({name:e.module_name,version:n})}x(r),m(`Module versions fetched and manifest updated.`);let s=n(`Installing modules...`).start();for(let e=0;e<a.length;e++){let t=a[e];s.text=`Installing modules... (${e+1}/${a.length}) ${t.name}`;try{O(i,`${t.name}@${t.version}`)}catch(e){s.fail(`Failed to install ${t.name}`),g(e instanceof Error?e.message:String(e)),process.exit(1)}}s.succeed(`All modules installed successfully.`)}async function A(){let e=(await S(`@minecraft/server`)).find(e=>e.includes(`-stable`));return e||(g(`No stable versions found.`),process.exit(1)),C(e)}async function j(){let e=n(`Fetching Minecraft version...`).start(),t=await M();e.succeed(`Install modules for Minecraft version: ${t}`);let r=b();m(`Manifest loaded. Fetching new module versions...`);let i=T(),a=[],o=r.dependencies?.filter(y)??[];for(let e of o){let n=(await S(e.module_name)).find(e=>e.includes(t));n||(g(`No version found for ${e.module_name} matching MC ${t}`),process.exit(1)),e.version=w(n),m(`${e.module_name}: ${n}`),a.push({name:e.module_name,version:n})}x(r),m(`Module versions fetched and manifest updated.`);let s=n(`Installing modules...`).start();for(let e=0;e<a.length;e++){let t=a[e];s.text=`Installing modules... (${e+1}/${a.length}) ${t.name}`;try{O(i,`${t.name}@${t.version}`)}catch(e){s.fail(`Failed to install ${t.name}`),g(e instanceof Error?e.message:String(e)),process.exit(1)}}s.succeed(`All modules installed successfully.`)}async function M(){let e=(await S(`@minecraft/server`)).find(e=>e.includes(`-preview`));return e||(g(`No preview versions found.`),process.exit(1)),C(e)}async function N(){let e=n(`Fetching Minecraft version...`).start(),t=await P();e.succeed(`Install modules for Minecraft version: ${t}`);let r=b();m(`Manifest loaded. Fetching new module versions...`);let i=T(),a=[],o=r.dependencies?.filter(y)??[];for(let e of o){let n=await S(e.module_name),r=n.find(e=>!e.includes(`stable`)&&!e.includes(`preview`)&&!e.includes(`internal`)&&!e.includes(`beta`)&&!e.startsWith(`0.`));r?e.version=r:(h(`No LTS versions found for ${e.module_name}. Falling back to stable.`),r=n.find(e=>e.includes(t)),r||(g(`No version found for ${e.module_name}`),process.exit(1)),e.version=C(r)),m(`${e.module_name}: ${r}`),a.push({name:e.module_name,version:r})}x(r),m(`Module versions fetched and manifest updated.`);let s=n(`Installing modules...`).start();for(let e=0;e<a.length;e++){let t=a[e];s.text=`Installing modules... (${e+1}/${a.length}) ${t.name}`;try{O(i,`${t.name}@${t.version}`)}catch(e){s.fail(`Failed to install ${t.name}`),g(e instanceof Error?e.message:String(e)),process.exit(1)}}s.succeed(`All modules installed successfully.`)}async function P(){let e=(await S(`@minecraft/server`)).find(e=>e.includes(`-stable`));return e||(g(`No stable versions found.`),process.exit(1)),C(e)}async function F(e){let t=await S(`@minecraft/server`),n=t.find(t=>t===e);if(n){p(`Found exact version: ${n}`);return}let r=t.find(t=>t.includes(e));r||(g(`Version not found: ${e}`),process.exit(1));let i=C(r);p(`Found version: ${i}`);let a=(await S(`@minecraft/server`)).find(e=>e.includes(i)),o=(await S(`@minecraft/server-ui`)).find(e=>e.includes(i));a&&p(`Server version: ${a}`),o&&p(`Server UI version: ${o}`)}const I=`1.2.0`;async function L(e){let t=i.resolve(e.targetDir),n=e.projectName?.trim()||i.basename(t),a=e.lib===!0,o=e.workflow!==!1;r.mkdirSync(t,{recursive:!0});let s=V(n,await B(),o,a),c=0;for(let[e,n]of Object.entries(s)){let a=i.join(t,e);if(r.existsSync(a)){h(`Skipped existing file: ${e}`);continue}r.mkdirSync(i.dirname(a),{recursive:!0}),r.writeFileSync(a,n,`utf-8`),m(`Created ${e}`),c+=1}if(c===0){h(`No files were created.`);return}_(`Project initialized in ${t}`)}function R(e){r.existsSync(e)&&r.readdirSync(e).length>0&&(g(`Target directory is not empty: ${e}`),process.exit(1))}function z(e,t){let n=s(t,[`.`],{cwd:e,shell:!0,stdio:`inherit`});if(n.error)throw n.error;if(n.status!==0)throw Error(`${t} exited with code ${n.status??`unknown`}`)}async function B(){try{let e=(await S(`@minecraft/server`)).find(e=>e.includes(`-stable`));if(!e)throw Error(`No stable @minecraft/server version found.`);let t=C(e),n=t,r=[],i={};for(let e of[`@minecraft/server`,`@minecraft/server-ui`]){let n=(await S(e)).find(e=>e.includes(t));if(!n){h(`Skipped ${e}: no version found for Minecraft ${t}`);continue}let a=w(n);r.push({module_name:e,version:a}),i[e]=n}return{engineVersion:n,dependencies:r,packageDependencies:i}}catch(e){return h(`Failed to resolve latest ScriptAPI dependencies: ${e instanceof Error?e.message:String(e)}`),h(`Creating the project without npm dependencies. You can run scriptup stable later.`),{engineVersion:`1.20.0`,dependencies:[],packageDependencies:{}}}}function V(e,t,n,r){let i=r?ae(e):null,a=H(e,t.engineVersion,t.dependencies,r),o=U(e,t.packageDependencies,r,i),s={".gitignore":`node_modules/
3
3
  scripts
4
+ dist
4
5
  *.mcpack
5
6
  *.mcaddon
6
- `,".vscode/settings.json":JSON.stringify(U(),null,2)+`
7
- `,".vscode/launch.json":JSON.stringify(W(r),null,2)+`
8
- `,"README.md":K(e),LICENSE:q(),"manifest.json":JSON.stringify(r,null,` `)+`
9
- `,"package.json":JSON.stringify(i,null,2)+`
10
- `,"tsconfig.json":JSON.stringify(H(),null,2)+`
7
+ `,".vscode/settings.json":JSON.stringify(G(),null,2)+`
8
+ `,".vscode/launch.json":JSON.stringify(K(a),null,2)+`
9
+ `,"README.md":ne(e,r,i),LICENSE:oe(),"manifest.json":JSON.stringify(a,null,` `)+`
10
+ `,"package.json":JSON.stringify(o,null,2)+`
11
+ `,"tsconfig.json":JSON.stringify(W(r,i),null,2)+`
11
12
  `,"tsdown.config.ts":[`import { defineConfig } from "tsdown";`,``,`export default defineConfig({});`,``].join(`
12
- `),"src/main.ts":[`import { world } from "@minecraft/server";`,``,`world.afterEvents.worldLoad.subscribe(() => {`,` console.log("Hello world!");`,`});`].join(`
13
- `)+`
14
- `};return n&&(a[`.github/workflows/mcpack.yml`]=G()),a}function ne(e,t,n){return{format_version:3,header:{name:e,description:`${e} (B)`,uuid:c(),version:[1,0,0],min_engine_version:t},metadata:{authors:[`YOUR NAME HERE`],url:`https://example.com/your-project`,generated_with:{scriptup:[`1.0.0`]}},modules:[{type:`data`,uuid:c(),version:[1,0,0]},{type:`script`,uuid:c(),version:[1,0,0],language:`javascript`,entry:`scripts/main.js`}],dependencies:n}}function V(e,t){let n={"@bedrock-apis/env-types":`1.0.0-beta.6`,typescript:`^5.9.3`,tsdown:`^0.21.2`};for(let[e,r]of Object.entries(t))n[e]=r;return{name:J(e),version:`1.0.0`,type:`module`,scripts:{build:`scriptup build --release`,watch:`scriptup build --watch`},devDependencies:n,keywords:[`minecraft`,`minecraft-bedrock`,`minecraft-script-api`,`scriptapi`],files:[`manifest.json`,`scripts`,`LICENSE`,`README.md`]}}function H(){return{include:[`src`],compilerOptions:{strict:!0,noLib:!0,types:[`@bedrock-apis/env-types`],noEmit:!0}}}function U(){return{"json.schemas":[{url:`https://raw.githubusercontent.com/Blockception/Minecraft-bedrock-json-schemas/refs/heads/main/general/manifest.json`,fileMatch:[`manifest.json`]}]}}function W(e){let t=e.modules?.find(e=>e.type===`script`)?.uuid;return t||m(`No script module UUID found in manifest. VSCode launch configuration will not include targetModuleUuid.`),{version:`0.2.0`,configurations:[{type:`minecraft-js`,request:`attach`,name:`Attach to Minecraft`,mode:`listen`,localRoot:"${workspaceFolder}/src",sourceMapRoot:"${workspaceFolder}/scripts",...t?{targetModuleUuid:t}:{},host:`localhost`,port:19144}]}}function G(){return`name: Upload mcpack
13
+ `),"src/main.ts":r?re(i??`@scope/sample`):Z()};return r&&(s[`package/main.ts`]=ie()),n&&(s[`.github/workflows/mcpack.yml`]=q(),s[`.github/workflows/webhook.yml`]=Y(),r&&(s[`.github/workflows/publish.yml`]=J(),s[`.github/workflows/ensure-dts-export.js`]=X())),s}function H(e,t,n,r){let i=r?`-lib`:`-beh`;return{format_version:3,header:{name:`${e}${i}`,description:`${e}${i}`,uuid:c(),version:`0.1.0`,min_engine_version:t},metadata:{authors:[`YOUR NAME HERE`],url:`https://example.com/your-project`,generated_with:{"nano191225-scriptup":[I]}},modules:[{type:`data`,uuid:c(),version:`0.1.0`},{type:`script`,uuid:c(),version:`0.1.0`,language:`javascript`,entry:`scripts/main.js`}],dependencies:n}}function U(e,t,n,r){let i={"@nano191225/scriptup":`^1.0.0`,"@bedrock-apis/env-types":`^1.0.0-beta.6`,typescript:`^5.9.3`,tsdown:`^0.21.2`};for(let[e,n]of Object.entries(t))i[e]=n;let a=n?[`dist`,`LICENSE`,`README.md`]:[`manifest.json`,`scripts`,`LICENSE`,`README.md`];return{name:se(e),version:`0.1.0`,type:`module`,...n?{exports:{".":{types:`./dist/main.d.ts`,default:`./dist/main.js`}},main:`./dist/main.js`,types:`./dist/main.d.ts`,prepublishOnly:`scriptup build --release && node .github/workflows/ensure-dts-export.js`}:{},scripts:{build:`scriptup build --release`,watch:`scriptup build --watch`},dependencies:{},devDependencies:i,keywords:[`minecraft`,`minecraft-bedrock`,`minecraft-script-api`,`scriptapi`],files:a}}function W(e,t){let n={strict:!0,noLib:!0,types:[`@bedrock-apis/env-types`],noEmit:!0};return e&&t&&(n.baseUrl=`.`,n.paths={[t]:[`package/main.ts`]}),{include:e?[`src`,`package`]:[`src`],compilerOptions:n}}function G(){return{"json.schemas":[{url:`https://raw.githubusercontent.com/Blockception/Minecraft-bedrock-json-schemas/refs/heads/main/general/manifest.json`,fileMatch:[`manifest.json`]}]}}function K(e){let t=e.modules?.find(e=>e.type===`script`)?.uuid;return t||h(`No script module UUID found in manifest. VSCode launch configuration will not include targetModuleUuid.`),{version:`0.2.0`,configurations:[{type:`minecraft-js`,request:`attach`,name:`Attach to Minecraft`,mode:`listen`,localRoot:"${workspaceFolder}/src",sourceMapRoot:"${workspaceFolder}/scripts",...t?{targetModuleUuid:t}:{},host:`localhost`,port:19144}]}}function q(){return`name: Upload mcpack
15
14
  on:
16
15
  release:
17
16
  types: [published]
18
17
 
18
+ permissions:
19
+ contents: write
20
+
19
21
  jobs:
20
22
  build:
21
23
  runs-on: ubuntu-latest
@@ -24,23 +26,30 @@ jobs:
24
26
 
25
27
  ##############################
26
28
 
29
+ ### When selected package manager, uncomment below.
30
+
31
+ - name: You have to select a package manager.
32
+ run: exit 1
33
+
27
34
  ### pnpm ###
28
35
 
29
- - name: Install pnpm
30
- uses: pnpm/action-setup@v4
36
+ # - name: Install pnpm
37
+ # uses: pnpm/action-setup@v4
38
+ # with:
39
+ # version: 10
31
40
 
32
- - name: Use Node.js 24
33
- uses: actions/setup-node@v4
34
- with:
35
- node-version: "24"
36
- cache: "pnpm"
41
+ # - name: Use Node.js 24
42
+ # uses: actions/setup-node@v4
43
+ # with:
44
+ # node-version: "24"
45
+ # cache: "pnpm"
37
46
 
38
- - name: Install dependencies
39
- run: |
40
- pnpm i --frozen-lockfile
47
+ # - name: Install dependencies
48
+ # run: |
49
+ # pnpm i --frozen-lockfile
41
50
 
42
- - name: Build
43
- run: pnpm run build
51
+ # - name: Build
52
+ # run: pnpm run build
44
53
 
45
54
  ### npm ###
46
55
 
@@ -58,6 +67,24 @@ jobs:
58
67
  # run: |
59
68
  # npm run build
60
69
 
70
+ ### bun ###
71
+
72
+ # - name: Use Node.js 24
73
+ # uses: actions/setup-node@v4
74
+ # with:
75
+ # node-version: "24"
76
+
77
+ # - name: Install Bun
78
+ # uses: oven-sh/setup-bun@v2
79
+
80
+ # - name: Install dependencies
81
+ # run: |
82
+ # bun i --frozen-lockfile
83
+
84
+ # - name: Build
85
+ # run: |
86
+ # bun run build
87
+
61
88
  ### yarn ###
62
89
 
63
90
  # - name: Use Node.js 24
@@ -82,21 +109,115 @@ jobs:
82
109
  id: get-name
83
110
  run: |
84
111
  name=$(jq -r '.header.name' manifest.json | tr -d '"' | tr ' ' '_')
85
- echo "fileName=$name" >> $GITHUB_OUTPUT
112
+ tag="$GITHUB_REF_NAME"
113
+ echo "fileName=$name-$tag" >> $GITHUB_OUTPUT
86
114
 
87
115
  - name: Make Archive
88
116
  run: |
89
117
  echo "Creating archive: \${{ steps.get-name.outputs.fileName }}"
90
- files=$(jq -r '.files[]' package.json | tr '
91
- ' ' ')
118
+ files="manifest.json scripts $(jq -r '.files[] | select(. != "manifest.json" and . != "scripts")' package.json | tr '\\n' ' ')"
92
119
  zip -r "\${{ steps.get-name.outputs.fileName }}.mcpack" $files
93
120
  cp "\${{ steps.get-name.outputs.fileName }}.mcpack" "\${{ steps.get-name.outputs.fileName }}.zip"
94
121
 
95
122
  - name: Upload Release Asset
96
123
  run: gh release upload "$GITHUB_REF_NAME" "\${{ steps.get-name.outputs.fileName }}.mcpack" "\${{ steps.get-name.outputs.fileName }}.zip" --clobber
97
124
  env:
98
- GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}`}function K(e){return[`# ${e}`,``,`ScriptAPI addon template generated by scriptup.`,``,`## Setup`,``,"```bash",`npm install`,"```",``].join(`
99
- `)}function q(){let e=new Date().getFullYear(),t=`{{author}}`;try{let e=s(`git`,[`config`,`user.name`],{encoding:`utf-8`,shell:!0});if(e.status===0){let n=e.stdout.trim();n&&(t=n)}}catch(e){m(`Failed to get git user.name: ${e instanceof Error?e.message:String(e)}`),m(`Using placeholder author name in LICENSE.`)}return`MIT License
125
+ GITHUB_TOKEN: \${{ github.token }}`}function J(){return`name: Publish library
126
+ # Triggered when a GitHub release is published.
127
+ # Uses npm Trusted Publishers (OIDC) — no NPM_TOKEN secret required.
128
+ # See: https://docs.npmjs.com/trusted-publishers#configuring-trusted-publishing
129
+
130
+ on:
131
+ release:
132
+ types: [published]
133
+
134
+ permissions:
135
+ contents: read
136
+ id-token: write # required for OIDC trusted publishing and provenance
137
+
138
+ jobs:
139
+ publish:
140
+ runs-on: ubuntu-latest
141
+ timeout-minutes: 10
142
+
143
+ steps:
144
+ - name: Checkout
145
+ uses: actions/checkout@v4
146
+
147
+ - name: Install pnpm
148
+ uses: pnpm/action-setup@v4
149
+ with:
150
+ version: 10
151
+
152
+ - name: Use Node.js 24
153
+ uses: actions/setup-node@v4
154
+ with:
155
+ node-version: "24"
156
+ cache: "pnpm"
157
+ registry-url: "https://registry.npmjs.org"
158
+
159
+ - name: Install dependencies
160
+ run: pnpm i --frozen-lockfile
161
+
162
+ - name: Build
163
+ run: pnpm run build
164
+
165
+ - name: Ensure export footer in d.ts
166
+ run: node .github/workflows/ensure-dts-export.js
167
+
168
+ - name: Publish package
169
+ run: pnpm publish --no-git-checks`}function Y(){return`name: Discord release webhook
170
+
171
+ on:
172
+ release:
173
+ types: [published]
174
+
175
+ permissions:
176
+ contents: read
177
+
178
+ jobs:
179
+ notify:
180
+ runs-on: ubuntu-latest
181
+ timeout-minutes: 5
182
+
183
+ steps:
184
+ - name: Post release message to Discord
185
+ env:
186
+ WEBHOOK_URL: \${{ secrets.WEBHOOK_URL }}
187
+ RELEASE_NAME: \${{ github.event.release.name }}
188
+ RELEASE_BODY: \${{ github.event.release.body }}
189
+ RELEASE_URL: \${{ github.event.release.html_url }}
190
+ run: |
191
+ payload=$(jq -n --arg name "$RELEASE_NAME" --arg body "$RELEASE_BODY" --arg url "$RELEASE_URL" '{content: ("## " + $name + "\\n" + $body + "\\n\\n" + $url)}')
192
+ curl -sS -X POST \\
193
+ -H "Content-Type: application/json" \\
194
+ -d "$payload" \\
195
+ "$WEBHOOK_URL"
196
+ `}function X(){return`import { existsSync, readFileSync, writeFileSync } from "node:fs";
197
+
198
+ const filePath = "dist/main.d.ts";
199
+
200
+ if (!existsSync(filePath)) {
201
+ throw new Error(\`Missing file: \${filePath}\`);
202
+ }
203
+
204
+ let content = readFileSync(filePath, "utf8");
205
+ const hasFooter = /\\bexport\\s*\\{\\s*\\};?\\s*$/.test(content);
206
+
207
+ if (!hasFooter) {
208
+ if (!content.endsWith("\\n")) content += "\\n";
209
+ content += "export {};\\n";
210
+ writeFileSync(filePath, content);
211
+ console.log("Appended export {} to dist/main.d.ts");
212
+ } else {
213
+ console.log("dist/main.d.ts already ends with export {}");
214
+ }
215
+ `}function ne(e,t,n){return t?[`# ${e}`,``,`ScriptAPI addon template generated by scriptup.`,``,`## Local library structure`,``,`- package/main.ts: local package source`,`- src/main.ts: sample usage that imports from ${n??`@scope/sample`}`,``,`## Setup`,``,"```bash",`npm install`,"```",``,`## Publish`,``,`### First publish (manual)`,``,`1. Update \`name\` and \`version\` in package.json (current import alias: \`${n??`@scope/sample`}\`).`,`2. Build and publish:`,``,"```bash",`npm run build`,`npm publish --access public`,"```",``,`### Subsequent publishes (automated via GitHub Actions)`,``,`> [!TIP]`,"> Using [npm Trusted Publishers](https://docs.npmjs.com/trusted-publishers#configuring-trusted-publishing) removes the need to manage `NPM_TOKEN` in GitHub secrets.",``,`1. On [npmjs.com](https://www.npmjs.com), open your package → **Settings** → **Trusted Publishers**.`,`2. Add a trusted publisher:`,` - **GitHub Actions** as the provider`,` - Organization or user: Enter your GitHub username or organization name`,` - Repository: Enter the repository name where the package is located`," - Workflow filename: `publish.yml`",` - Environment name: Keep empty`,``,"3. Once configured, **delete** the `NPM_TOKEN` secret from GitHub repository settings (not needed anymore).",``,"4. Bump `version` in package.json, then create a GitHub release → **.github/workflows/publish.yml** runs automatically.",``].join(`
216
+ `):[`# ${e}`,``,`ScriptAPI addon template generated by scriptup.`,``,`## Setup`,``,"```bash",`npm install`,"```",``].join(`
217
+ `)}function Z(){return[`import { world } from "@minecraft/server";`,``,`world.afterEvents.worldLoad.subscribe(() => {`,` console.log("Hello world!");`,`});`,``].join(`
218
+ `)}function re(e){return[`import { world } from "@minecraft/server";`,`import { sum } from "${e}";`,``,`world.afterEvents.worldLoad.subscribe(() => {`,` const result = sum(1, 2);`," console.log(`sum(1, 2) = ${result}`);",`});`,``].join(`
219
+ `)}function ie(){return[`export function sum(a: number, b: number): number {`,` return a + b;`,`}`,``].join(`
220
+ `)}function ae(e){let t=e.trim();return t.length>0?t:`@scope/sample`}function oe(){let e=new Date().getFullYear(),t=`{{author}}`;try{let e=s(`git`,[`config`,`user.name`],{encoding:`utf-8`,shell:!0});if(e.status===0){let n=e.stdout.trim();n&&(t=n)}}catch(e){h(`Failed to get git user.name: ${e instanceof Error?e.message:String(e)}`),h(`Using placeholder author name in LICENSE.`)}return`MIT License
100
221
 
101
222
  Copyright (c) ${e} ${t}
102
223
 
@@ -116,4 +237,6 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
116
237
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
117
238
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
118
239
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
119
- SOFTWARE.`}function J(e){return e.trim().toLowerCase().replace(/[^a-z0-9-_\s]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``)||`scriptapi-addon`}async function Y(e=process.cwd(),t={}){await I({targetDir:e,workflow:t.workflow}),f(`Initialization complete.`)}const X=[`code`,`code-insiders`];async function Z(e,t){let n=ie(t.preview),r=re(e,t,n);if(L(r),await I({targetDir:r,projectName:e,workflow:t.workflow}),t.dir&&t.link!==!1&&ae(r,i.join(n,e)),t.open){if(!X.includes(t.open))return h(`Unsupported editor: ${t.open}`);f(`Opening project with ${t.open}...`);try{R(r,t.open)}catch(e){h(`Failed to open project: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}}function re(e,t,n){return t.dir?i.resolve(t.dir,e):i.join(n,e)}function ie(e=!1){if(process.platform===`win32`){let t=process.env.APPDATA;t||(h(`APPDATA is not available. Use --dir to specify the destination manually.`),process.exit(1));let n=e?`Minecraft Bedrock Preview`:`Minecraft Bedrock`;return i.join(t,n,`Users`,`Shared`,`games`,`com.mojang`,`development_behavior_packs`)}let t=process.env.XDG_DATA_HOME??i.join(l.homedir(),`.local`,`share`);return i.join(t,`mcpelauncher`,`games`,`com.mojang`,`development_behavior_packs`)}function ae(e,t){let n=i.resolve(e),a=i.resolve(t);if(n===a)return;if(r.mkdirSync(i.dirname(a),{recursive:!0}),r.existsSync(a)){m(`Link path already exists, skipping link creation: ${a}`);return}let o=process.platform===`win32`?`junction`:`dir`;r.symlinkSync(n,a,o),p(`Linked behavior pack: ${a} -> ${n}`)}async function oe(e={}){let t=y().modules?.filter(_).find(e=>typeof e.entry==`string`&&e.entry.length>0);t?.entry||(h(`No script module entry found in manifest.json.`),process.exit(1));let n=await le(i.resolve(`tsdown.config.ts`)),r=Q(n);r||(h(`Source entry not found. Expected src/main.ts, src/index.ts, or tsdown.config.ts entry.`),process.exit(1));let a=i.resolve(t.entry),o=i.dirname(a),s=ue(i.resolve(`package.json`)),c=e.bundle===!0,l=e.watch===!0,d=e.release===!0,p=u({config:!1,entry:i.relative(process.cwd(),r),outDir:i.relative(process.cwd(),o),format:`esm`,target:`es2024`,platform:`neutral`,sourcemap:!d,clean:!l,tsconfig:i.relative(process.cwd(),i.resolve(`tsconfig.json`)),outExtensions:()=>({js:`.js`}),deps:{neverBundle:/^@minecraft\/(?!math(?:\/|$)|vanilla-data(?:\/|$))/,alwaysBundle:s,onlyBundle:!1},unbundle:!d&&!c,watch:l,minify:d},n);f(`Bundling addon scripts with tsdown...`);try{await ee(p)}catch(e){h(e instanceof Error?e.message:String(e)),process.exit(1)}l||se(a),g(`Build complete: ${i.relative(process.cwd(),a)}`)}function se(e){r.existsSync(e)||(h(`Expected build output was not found: ${e}`),process.exit(1))}function Q(e){let t=i.resolve(`src/main.ts`);if(r.existsSync(t))return t;let n=i.resolve(`src/index.ts`);if(r.existsSync(n))return n;let a=ce(e.entry);if(!a)return null;let o=i.resolve(a);return r.existsSync(o)?o:null}function ce(e){return typeof e==`string`?e:Array.isArray(e)&&typeof e[0]==`string`?e[0]:null}async function le(e){if(!r.existsSync(e))return{};let t=r.readFileSync(e,`utf-8`);if(!t.includes(`export default`)||!t.includes(`defineConfig`))return m(`tsdown.config.ts was found but could not be parsed. Using internal build defaults.`),{};try{let t=(await import(d(e).href)).default;return!t||typeof t!=`object`||Array.isArray(t)?(m(`tsdown.config.ts should export a single config object. Using internal build defaults.`),{}):t}catch(e){return m(`Failed to import tsdown.config.ts: ${e instanceof Error?e.message:String(e)}`),m(`Using internal build defaults.`),{}}}function ue(e){if(!r.existsSync(e))return m(`package.json was not found. Skipping deps.alwaysBundle.`),[];try{let t=r.readFileSync(e,`utf-8`),n=JSON.parse(t);return Object.keys(n.dependencies??{})}catch(e){return m(`Failed to parse package.json dependencies: ${e instanceof Error?e.message:String(e)}`),m(`Skipping deps.alwaysBundle.`),[]}}const $=new e;$.name(`scriptup`).description(`ScriptAPI version updater for Minecraft Bedrock`).version(`1.0.0`).argument(`[version]`,`Manually specify a version to look up`),$.command(`stable`).description(`Install the latest stable version modules`).action(async()=>{await k()}),$.command(`preview`).description(`Install the latest preview version modules`).action(async()=>{await j()}),$.command(`lts`).description(`Install the latest LTS version modules`).action(async()=>{await N()}),$.command(`build`).description(`Bundle the current ScriptAPI project with tsdown`).option(`-b, --bundle`,`Bundle the output into a single file`).option(`-w, --watch`,`Build in watch mode`).option(`-r, --release`,`Build for release (minified, sourcemap off)`).action(async e=>{await oe(e)}),$.command(`init`).description(`Initialize a ScriptAPI project in the current directory`).option(`--no-workflow`,`Do not create the GitHub Actions workflow files`).action(async e=>{await Y(void 0,e)}),$.command(`new`).description(`Create a new ScriptAPI project`).argument(`<project-name>`,`Directory name for the new project`).addOption(new t(`-o, --open [command]`,`Open the project after creation`).preset(`code`)).option(`-p, --preview`,`Create the project in the Minecraft Bedrock Preview behavior packs directory`).option(`-d, --dir <path>`,`Create the project under a specific directory`).option(`--no-link`,`Do not create a link in the behavior packs directory when --dir is used`).option(`--no-workflow`,`Do not create the GitHub Actions workflow files`).action(async(e,t)=>{await Z(e,t)}),$.action(async e=>{e?await F(e):$.help()}),$.parse();export{};
240
+ SOFTWARE.`}function se(e){return e.trim().toLowerCase().replace(/[^a-z0-9-_\s]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``)||`scriptapi-addon`}async function ce(e=process.cwd(),t={}){let n=i.resolve(e);await L({targetDir:n,workflow:t.workflow}),le(n),ue(n),de(n),p(`Initialization complete.`)}function le(e){let t=i.join(e,`tsdown.config.ts`);if(!r.existsSync(t)){let e=[`import { defineConfig } from "tsdown";`,``,`export default defineConfig(/* */);`,``].join(`
241
+ `);r.writeFileSync(t,e,`utf-8`),m(`Created tsdown.config.ts`);return}let n=r.readFileSync(t,`utf-8`),a=n.replace(/defineConfig\({([^;]*)}\);/s,(e,t)=>{let n=t.trim();return n.length===0?`defineConfig({ /* */ });`:`defineConfig({\n /* ${n} */\n});`});if(a===n){h(`Could not find defineConfig(...) in tsdown.config.ts. File was left unchanged.`);return}r.writeFileSync(t,a,`utf-8`),m(`Updated tsdown.config.ts`)}function ue(e){let t=i.join(e,`package.json`),n=JSON.parse(r.readFileSync(t,`utf-8`));n.scripts??={},n.scripts.build=`scriptup build --release`,n.scripts.watch=`scriptup build --watch`,r.writeFileSync(t,JSON.stringify(n,null,2)+`
242
+ `,`utf-8`),m(`Updated package.json scripts: build, watch`)}function de(e){let t=process.cwd();try{process.chdir(e),o(fe(T(),[`@nano191225/scriptup`,`tsdown`,`typescript`,`@bedrock-apis/env-types`]),{stdio:`inherit`,cwd:e}),m(`Installed required dev dependencies`)}catch(e){g(`Failed to install dependencies: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}finally{process.chdir(t)}}function fe(e,t){let n=t.join(` `);switch(e){case`npm`:return`npm install --save-dev ${n}`;case`pnpm`:return`pnpm add --save-dev ${n}`;case`yarn`:return`yarn add --dev ${n}`;case`bun`:return`bun add --save-dev ${n}`}}const pe=[`code`,`code-insiders`];async function me(e,t){let n=ge(t.preview),r=he(e),a=Q(r,t,n);if(R(a),await L({targetDir:a,projectName:e,lib:t.lib,workflow:t.workflow}),t.dir&&t.link!==!1&&_e(a,i.join(n,r)),t.open){if(!pe.includes(t.open))return g(`Unsupported editor: ${t.open}`);p(`Opening project with ${t.open}...`);try{z(a,t.open)}catch(e){g(`Failed to open project: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}}function Q(e,t,n){return t.dir?i.resolve(t.dir,e):i.join(n,e)}function he(e){let t=e.trim().replace(/[\\/]+/g,`$`).replace(/[^A-Za-z0-9@$-_.]/g,``);return t.length===0&&(g(`Project name is empty after sanitizing. Use at least one of A-Z, a-z, 0-9, @, $, -, _, or .`),process.exit(1)),t}function ge(e=!1){if(process.platform===`win32`){let t=process.env.APPDATA;t||(g(`APPDATA is not available. Use --dir to specify the destination manually.`),process.exit(1));let n=e?`Minecraft Bedrock Preview`:`Minecraft Bedrock`;return i.join(t,n,`Users`,`Shared`,`games`,`com.mojang`,`development_behavior_packs`)}let t=process.env.XDG_DATA_HOME??i.join(l.homedir(),`.local`,`share`);return i.join(t,`mcpelauncher`,`games`,`com.mojang`,`development_behavior_packs`)}function _e(e,t){let n=i.resolve(e),a=i.resolve(t);if(n===a)return;if(r.mkdirSync(i.dirname(a),{recursive:!0}),r.existsSync(a)){h(`Link path already exists, skipping link creation: ${a}`);return}let o=process.platform===`win32`?`junction`:`dir`;r.symlinkSync(n,a,o),m(`Linked behavior pack: ${a} -> ${n}`)}async function ve(e={}){let t=b().modules?.filter(v).find(e=>typeof e.entry==`string`&&e.entry.length>0);t?.entry||(g(`No script module entry found in manifest.json.`),process.exit(1));let n=await Se(i.resolve(`tsdown.config.ts`)),r=be(n);r||(g(`Source entry not found. Expected src/main.ts, src/index.ts, or tsdown.config.ts entry.`),process.exit(1));let a=i.resolve(t.entry),o=i.dirname(a),s=e.bundle===!0,c=e.watch===!0,l=e.release===!0,f=d({config:!1,entry:i.relative(process.cwd(),r),outDir:i.relative(process.cwd(),o),format:`esm`,target:`es2024`,platform:`neutral`,sourcemap:!l,clean:!c,tsconfig:i.relative(process.cwd(),i.resolve(`tsconfig.json`)),outExtensions:()=>({js:`.js`}),deps:{neverBundle:/^@minecraft\/(?!math(?:\/|$)|vanilla-data(?:\/|$))/,alwaysBundle:`**/*`,onlyBundle:!1},unbundle:!l&&!s,watch:c,minify:l},n);p(`Bundling addon scripts with tsdown...`);try{await u(f),l&&await Ce()}catch(e){g(e instanceof Error?e.message:String(e)),process.exit(1)}c||ye(a),_(`Build complete: ${i.relative(process.cwd(),a)}`)}function ye(e){r.existsSync(e)||(g(`Expected build output was not found: ${e}`),process.exit(1))}function be(e){let t=i.resolve(`src/main.ts`);if(r.existsSync(t))return t;let n=i.resolve(`src/index.ts`);if(r.existsSync(n))return n;let a=xe(e.entry);if(!a)return null;let o=i.resolve(a);return r.existsSync(o)?o:null}function xe(e){return typeof e==`string`?e:Array.isArray(e)&&typeof e[0]==`string`?e[0]:null}async function Se(e){if(!r.existsSync(e))return{};let t=r.readFileSync(e,`utf-8`);if(!t.includes(`export default`)||!t.includes(`defineConfig`))return h(`tsdown.config.ts was found but could not be parsed. Using internal build defaults.`),{};try{let t=(await import(f(e).href)).default;return!t||typeof t!=`object`||Array.isArray(t)?(h(`tsdown.config.ts should export a single config object. Using internal build defaults.`),{}):t}catch(e){return h(`Failed to import tsdown.config.ts: ${e instanceof Error?e.message:String(e)}`),h(`Using internal build defaults.`),{}}}async function Ce(){let e=we(i.resolve(`package`));e.length!==0&&(p(`Building local package sources into dist/... `),await u({config:!1,entry:e.map(e=>i.relative(process.cwd(),e)),outDir:i.relative(process.cwd(),i.resolve(`dist`)),format:`esm`,target:`es2024`,platform:`neutral`,clean:!0,tsconfig:i.relative(process.cwd(),i.resolve(`tsconfig.json`)),outExtensions:()=>({js:`.js`}),unbundle:!0,dts:!0,deps:{neverBundle:/^@minecraft\/(?!math(?:\/|$)|vanilla-data(?:\/|$))/}}))}function we(e){if(!r.existsSync(e))return[];let t=[],n=[e];for(;n.length>0;){let e=n.pop();if(!e)continue;let a=r.readdirSync(e,{withFileTypes:!0});for(let r of a){if(r.name===`node_modules`||r.name.startsWith(`.`))continue;let a=i.join(e,r.name);if(r.isDirectory()){n.push(a);continue}r.isFile()&&a.endsWith(`.ts`)&&!a.endsWith(`.d.ts`)&&t.push(a)}}return t.sort()}const $=new e;$.name(`scriptup`).description(`ScriptAPI version updater for Minecraft Bedrock`).version(I).argument(`[version]`,`Manually specify a version to look up`),$.command(`stable`).description(`Install the latest stable version modules`).action(async()=>{await k()}),$.command(`preview`).description(`Install the latest preview version modules`).action(async()=>{await j()}),$.command(`lts`).description(`Install the latest LTS version modules`).action(async()=>{await N()}),$.command(`build`).description(`Bundle the current ScriptAPI project with tsdown`).option(`-b, --bundle`,`Bundle the output into a single file`).option(`-w, --watch`,`Build in watch mode`).option(`-r, --release`,`Build for release (minified, sourcemap off)`).action(async e=>{await ve(e)}),$.command(`init`).description(`Initialize a ScriptAPI project in the current directory`).option(`--no-workflow`,`Do not create the GitHub Actions workflow files`).action(async e=>{await ce(void 0,e)}),$.command(`new`).description(`Create a new ScriptAPI project`).argument(`<project-name>`,`Directory name for the new project`).addOption(new t(`-o, --open [command]`,`Open the project after creation`).preset(`code`)).option(`-p, --preview`,`Create the project in the Minecraft Bedrock Preview behavior packs directory`).option(`-d, --dir <path>`,`Create the project under a specific directory`).option(`--lib`,`Include local library scaffolding under package/`).option(`--no-link`,`Do not create a link in the behavior packs directory when --dir is used`).option(`--no-workflow`,`Do not create the GitHub Actions workflow files`).action(async(e,t)=>{await me(e,t)}),$.action(async e=>{e?await F(e):$.help()}),$.parse();export{};
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "@nano191225/scriptup",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "ScriptAPI version updater for Minecraft Bedrock",
5
- "main": "dist/index.js",
6
- "bin": {
7
- "scriptup": "dist/index.js"
8
- },
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/Nano191225/scriptup.git"
5
+ "license": "MIT",
6
+ "author": "Nano191225",
7
+ "homepage": "https://github.com/Nano191225/scriptup#readme",
8
+ "repository": "https://github.com/Nano191225/scriptup.git",
9
+ "bugs": {
10
+ "url": "https://github.com/Nano191225/scriptup/issues"
12
11
  },
13
12
  "keywords": [
14
13
  "minecraft",
@@ -16,18 +15,22 @@
16
15
  "minecraft-script-api",
17
16
  "scriptapi"
18
17
  ],
19
- "author": "Nano191225",
20
- "license": "MIT",
21
- "bugs": {
22
- "url": "https://github.com/Nano191225/scriptup/issues"
23
- },
24
- "homepage": "https://github.com/Nano191225/scriptup#readme",
25
- "publishConfig": {
26
- "access": "public"
18
+ "type": "module",
19
+ "main": "dist/index.js",
20
+ "bin": {
21
+ "scriptup": "dist/index.js",
22
+ "sup": "dist/index.js"
27
23
  },
28
24
  "files": [
29
25
  "dist"
30
26
  ],
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "registry": "https://registry.npmjs.org"
33
+ },
31
34
  "dependencies": {
32
35
  "chalk": "^5.4.1",
33
36
  "commander": "^13.1.0",
@@ -38,10 +41,6 @@
38
41
  "@types/node": "^22.13.0",
39
42
  "typescript": "^5.7.0"
40
43
  },
41
- "engines": {
42
- "node": ">=18.0.0"
43
- },
44
- "type": "module",
45
44
  "scripts": {
46
45
  "build": "tsdown",
47
46
  "dev": "tsdown --watch"