@nexusmods/vortex-api 1.0.0 → 2.2.0-beta.1

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.
@@ -0,0 +1,370 @@
1
+ # Migration Guide
2
+
3
+ This guide covers the changes extension developers need to make when migrating from Vortex 1.16 to Vortex 2.0. The Vortex API surface is largely unchanged, so most extensions will not require source code modifications - the migration is primarily about build tooling and dependency management.
4
+
5
+ ## Overview of Changes
6
+
7
+ | Area | 1.16 | 2.0 |
8
+ | --------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
9
+ | Bundler | webpack | webpack (still supported) or Rolldown |
10
+ | Runtime dependencies | Manually listed as `devDependencies` | Automatically installed via `vortex-api` peer dependencies (registry packages); git-based packages listed manually |
11
+ | Development Vortex plugins folder | `%APPDATA%/vortex_devel/plugins` | `%APPDATA%/@vortex/main/plugins` |
12
+
13
+ ## Choose Your Migration Path
14
+
15
+ Switching to pnpm is recommended but optional. Most of Vortex's runtime packages are declared as `peerDependencies` of `vortex-api` and are auto-installed by pnpm, npm 7+, and Yarn Berry. A small number of git-based packages must be added manually (see [Step 2](#step-2-update-dependencies)).
16
+
17
+ ### Path A: Switch to pnpm (recommended)
18
+
19
+ Switching to pnpm aligns your tooling with Vortex's own build system. See [Step 1: Switch to pnpm](#step-1-switch-to-pnpm-path-a-only) below.
20
+
21
+ ### Path B: Keep your current package manager
22
+
23
+ npm (7+) and Yarn Berry (v2+) also auto-install peer dependencies - just skip Step 1 and go to [Step 2: Update Dependencies](#step-2-update-dependencies).
24
+
25
+ > **Note:** Yarn Classic (v1) does **not** auto-install peer dependencies. If you stay on Yarn Classic, you'll need to **manually maintain** your `devDependencies` to match the versions Vortex ships at runtime. The correct versions can be found in Vortex's [`pnpm-workspace.yaml`](https://github.com/Nexus-Mods/Vortex/blob/master/pnpm-workspace.yaml) under the `catalog:` section.
26
+
27
+ ---
28
+
29
+ ## Step 1: Switch to pnpm (Path A only)
30
+
31
+ ### 1a. Update `packageManager` field
32
+
33
+ In your `package.json`, replace:
34
+
35
+ ```diff
36
+ - "packageManager": "yarn@1.22.19"
37
+ + "packageManager": "pnpm@10.31.0"
38
+ ```
39
+
40
+ ### 1b. Generate `pnpm-lock.yaml`
41
+
42
+ pnpm can import your existing lockfile to preserve resolved versions, then you can remove the old one:
43
+
44
+ ```bash
45
+ pnpm import # generates pnpm-lock.yaml from yarn.lock (or package-lock.json)
46
+ rm yarn.lock # remove the old lockfile
47
+ pnpm install # verify everything resolves correctly
48
+ ```
49
+
50
+ See [`pnpm import`](https://pnpm.io/cli/import) for details.
51
+
52
+ ### 1c. Replace Yarn commands in build scripts
53
+
54
+ If you have custom build scripts (e.g., a `build.js`), update all Yarn commands:
55
+
56
+ | Yarn | pnpm |
57
+ | -------------------------- | ------------------------------------ |
58
+ | `yarn install` | `pnpm install` |
59
+ | `yarn add <pkg>` | `pnpm add <pkg>` |
60
+ | `yarn remove <pkg>` | `pnpm remove <pkg>` |
61
+ | `yarn run <script>` | `pnpm run <script>` |
62
+ | `yarn pack --filename <f>` | `pnpm pack --pack-destination <dir>` |
63
+ | `npx <cmd>` | `pnpm exec <cmd>` |
64
+
65
+ > **Note:** `pnpm pack` produces a filename based on the package scope and version (e.g., `scope-name-1.0.0.tgz`), not a user-specified filename. If your build scripts rely on a specific `.tgz` filename, you'll need to rename the output after packing.
66
+
67
+ ### 1d. Allow package install scripts
68
+
69
+ pnpm blocks lifecycle scripts (e.g., `postinstall`) by default for security. During `pnpm install`, it will prompt you to approve packages that need to run install scripts. You can approve them interactively or use `pnpm approve-builds` to review and approve pending packages:
70
+
71
+ ```bash
72
+ pnpm approve-builds
73
+ ```
74
+
75
+ This saves the approved list to `pnpm-workspace.yaml` under `allowBuilds`:
76
+
77
+ ```yaml
78
+ allowBuilds:
79
+ my-native-addon: true
80
+ # Add other packages that need install scripts
81
+ ```
82
+
83
+ > **Tip:** You can also pre-configure `allowBuilds` manually before running `pnpm install` if you already know which packages need build scripts (typically native addons).
84
+
85
+ ### 1e. Adapt `resolutions`
86
+
87
+ The Yarn `resolutions` field is not supported by pnpm. Resolutions that pinned Vortex-provided packages (e.g., `@types/react`, `@types/react-dom`) can be removed entirely - those versions are now enforced by `vortex-api` peer dependencies.
88
+
89
+ If your extension has its own resolutions for **non-Vortex packages**, migrate them to pnpm `overrides` in `package.json`:
90
+
91
+ ```diff
92
+ - "resolutions": {
93
+ - "node-gyp": "^10.0.0",
94
+ - "@types/react": "16.14.66",
95
+ - "@types/react-dom": "16.9.25",
96
+ - "some-transitive-dep": "^2.0.0"
97
+ - },
98
+ + "pnpm": {
99
+ + "overrides": {
100
+ + "some-transitive-dep": "^2.0.0"
101
+ + }
102
+ + },
103
+ ```
104
+
105
+ > **Note:** Yarn `resolutions` and pnpm `overrides` have slightly different syntax for scoped overrides. See the [pnpm overrides documentation](https://pnpm.io/package_json#pnpmoverrides) for details.
106
+
107
+ ## Step 2: Update Dependencies
108
+
109
+ Vortex 2.0 ships `vortex-api` with `peerDependencies` that declare most packages Vortex provides at runtime (React, Redux, Lodash, Bluebird, etc.) along with their type definitions. When you install `vortex-api` with pnpm, npm 7+, or Yarn Berry, these peer dependencies are installed automatically.
110
+
111
+ You can **remove most Vortex runtime packages** from your `devDependencies`.
112
+
113
+ > The following example shows a subset of Vortex packages - your extension may use more or fewer. The principle is the same: any package covered by `vortex-api` peer dependencies can be removed.
114
+
115
+ #### Example: Before (1.16)
116
+
117
+ ```json
118
+ {
119
+ "devDependencies": {
120
+ "vortex-api": "git+https://github.com/Nexus-Mods/vortex-api.git",
121
+ "@nexusmods/nexus-api": "git+https://github.com/Nexus-Mods/node-nexus-api.git",
122
+ "@types/bluebird": "3.5.20",
123
+ "@types/lodash": "^4.14.149",
124
+ "@types/node": "^22.0.0",
125
+ "@types/react": "16.14.66",
126
+ "@types/react-redux": "^7.1.9",
127
+ "bluebird": "^3.7.2",
128
+ "i18next": "^19.0.1",
129
+ "react": "^16.12.0",
130
+ "react-bootstrap": "^0.33.0",
131
+ "react-dom": "^16.12.0",
132
+ "react-i18next": "^11.11.0",
133
+ "react-redux": "^7.1.3",
134
+ "redux": "^4.0.4",
135
+ "redux-act": "^1.7.7",
136
+ "webpack": "^5.94.0",
137
+ "webpack-cli": "^5.1.4"
138
+ }
139
+ }
140
+ ```
141
+
142
+ #### Example: After (2.0)
143
+
144
+ ```json
145
+ {
146
+ "devDependencies": {
147
+ "vortex-api": "git+https://github.com/Nexus-Mods/vortex-api.git",
148
+ "@nexusmods/nexus-api": "git+https://github.com/Nexus-Mods/node-nexus-api#4192c0c9f34306c2167e258dd4fef773af406161",
149
+ "typescript": "5.9.3"
150
+ }
151
+ }
152
+ ```
153
+
154
+ Only keep dependencies that are:
155
+
156
+ - **Your extension's own dependencies** (listed in `dependencies`, bundled into your output)
157
+ - **Build tools** you use directly (TypeScript, your bundler, ESLint, Prettier, etc.)
158
+ - **Git-based Vortex packages** your extension imports directly (see below)
159
+ - **Type packages not covered by** `vortex-api` (e.g., `@types/react-bootstrap` if your extension uses it and it's not in the peer dependency list)
160
+
161
+ ### Git-based packages (manual)
162
+
163
+ Some Vortex runtime packages are hosted on GitHub and not published to npm. These cannot be included in `vortex-api`'s `peerDependencies`, so you must add them to your `devDependencies` manually if your extension imports them.
164
+
165
+ **Important:** The commit hashes below must match the version Vortex ships. When Vortex updates these packages, you must update the hashes in your `devDependencies` to match. The authoritative source is the `catalog:` section in Vortex's [`pnpm-workspace.yaml`](https://github.com/Nexus-Mods/Vortex/blob/master/pnpm-workspace.yaml).
166
+
167
+ The full list of git-based packages:
168
+
169
+ ```json
170
+ {
171
+ "@nexusmods/nexus-api": "git+https://github.com/Nexus-Mods/node-nexus-api#4192c0c9f34306c2167e258dd4fef773af406161",
172
+ "bbcode-to-react": "git+https://github.com/TanninOne/bbcode-to-react#c67356006470e5066ea447e04a3968dca367339d",
173
+ "crash-dump": "git+https://github.com/Nexus-Mods/node-crash-dump#7fc76dabdc9117a7f238d7bf5e5fb7841a374804",
174
+ "diskusage": "git+https://github.com/TanninOne/node-diskusage#eb52fd176b2c311dd3ae5f0e68ff7488c08a179d",
175
+ "drivelist": "git+https://github.com/TanninOne/drivelist#720d1890db11482ec05fc0f6aa176cfa6e6844dd",
176
+ "electron-redux": "git+https://github.com/TanninOne/electron-redux#66bbd9d389579806e8c4ebd87bd513a668cc64a8",
177
+ "exe-version": "git+https://github.com/Nexus-Mods/node-exe-version#eded60fc0a0f3c234e1d586d2eb9952401945406",
178
+ "json-socket": "git+https://github.com/foi/node-json-socket#d56c8e2938fa4284c4001b815d9b6e4a92b5c07b",
179
+ "modmeta-db": "git+https://github.com/Nexus-Mods/modmeta-db#daa8935b6e38e255ec192c908adfce35d47c0336",
180
+ "native-errors": "git+https://github.com/Nexus-Mods/node-native-errors#51913db07e4c9b68a96ba7fcf741b32796758f18",
181
+ "node-7z": "git+https://github.com/Nexus-Mods/node-7z#3d98d2ba40906f8afa9de52d2ceb6a44f7143198",
182
+ "permissions": "git+https://github.com/Nexus-Mods/node-permissions#7c1b6f1d6437f2238be51316de823b0fbd63e4c0",
183
+ "rimraf": "git+https://github.com/TanninOne/rimraf#7b8b70d4e8783cd233fca3283cf1f930af4e39c2",
184
+ "simple-vdf": "git+https://github.com/Nexus-Mods/vdf-parser#df279ff89cb480597544d3029e12f90cb8c79464",
185
+ "turbowalk": "git+https://github.com/Nexus-Mods/node-turbowalk#3502f6ffc3f9eb55fe1c9c097b4e4772edce0c0f",
186
+ "vortex-parse-ini": "git+https://github.com/Nexus-Mods/vortex-parse-ini#2425af99d1cff2331ccf3aacfa892c314e99e18d",
187
+ "vortexmt": "git+https://github.com/Nexus-Mods/node-vortexmt#5251ea012ce856742aeaf73a583073497aff773a",
188
+ "wholocks": "git+https://github.com/Nexus-Mods/node-wholocks#28da3bcf312312e577d7c636799a59011998b4af",
189
+ "winapi-bindings": "git+https://github.com/Nexus-Mods/node-winapi-bindings#faa92afe3320731e98abc15b3f5f19c60896d7c1"
190
+ }
191
+ ```
192
+
193
+ You only need to add the ones your extension actually imports. For example, if your extension uses `@nexusmods/nexus-api` and `turbowalk`, add just those two.
194
+
195
+ ## Step 3: Update Build Configuration
196
+
197
+ ### Webpack (still works)
198
+
199
+ If your extension uses the `vortex-api`-provided webpack helper (`api/bin/webpack.js`), no changes are needed - it handles externals automatically.
200
+
201
+ If you use a custom webpack config, you can simplify your externals by reading from `vortex-api`:
202
+
203
+ ```js
204
+ // webpack.config.js
205
+ const { peerDependencies } = require("vortex-api/package.json");
206
+ module.exports = {
207
+ // ...
208
+ externals: [...Object.keys(peerDependencies || {}), "electron", "vortex-api"].reduce(
209
+ (acc, dep) => {
210
+ acc[dep] = `commonjs ${dep}`;
211
+ return acc;
212
+ },
213
+ {},
214
+ ),
215
+ };
216
+ ```
217
+
218
+ ### Rolldown (optional migration)
219
+
220
+ Vortex 2.0 uses [Rolldown](https://rolldown.rs/) internally. You can optionally migrate your extension to Rolldown as well.
221
+
222
+ #### Install Rolldown
223
+
224
+ Add Rolldown and remove webpack-related packages you no longer need:
225
+
226
+ ```bash
227
+ # If using pnpm:
228
+ pnpm add -D rolldown
229
+ pnpm remove webpack webpack-cli # also remove any webpack plugins/loaders you were using,
230
+ # e.g. ts-loader, copy-webpack-plugin, native-addon-loader,
231
+ # webpack-node-externals
232
+ # If using yarn:
233
+ yarn add -D rolldown
234
+ yarn remove webpack webpack-cli # same as above
235
+ ```
236
+
237
+ #### Create `rolldown.config.mjs`
238
+
239
+ ```js
240
+ import { defineConfig } from "rolldown";
241
+ import { builtinModules, createRequire } from "node:module";
242
+ const require = createRequire(import.meta.url);
243
+ const { peerDependencies } = require("vortex-api/package.json");
244
+ function getExternals() {
245
+ const builtins = builtinModules.filter((m) => !m.startsWith("_"));
246
+ return [
247
+ ...new Set([...builtins, ...Object.keys(peerDependencies || {}), "electron", "vortex-api"]),
248
+ ];
249
+ }
250
+ export default defineConfig({
251
+ input: "src/index.ts",
252
+ output: {
253
+ file: "dist/index.js",
254
+ format: "cjs",
255
+ sourcemap: true,
256
+ exports: "auto",
257
+ },
258
+ external: getExternals(),
259
+ platform: "node",
260
+ resolve: {
261
+ extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
262
+ tsconfigFilename: "tsconfig.json",
263
+ },
264
+ plugins: [
265
+ // Add custom plugins as needed (e.g., for native addons, asset copying)
266
+ ],
267
+ });
268
+ ```
269
+
270
+ #### Update your build command
271
+
272
+ ```diff
273
+ - "build": "npx webpack --config webpack.config.js"
274
+ + "build": "pnpm exec rolldown --config rolldown.config.mjs"
275
+ ```
276
+
277
+ ## Step 4: Collections Type Declarations
278
+
279
+ The `collections` extension is now part of the Vortex monorepo and its type declarations are not yet distributed via the `vortex-api` package. If your extension imports types from `collections` (e.g., `ICollection`, `IExtendedInterfaceProps`, `IExtensionFeature`), you have two options:
280
+
281
+ ### Option A: Add local type declarations
282
+
283
+ Create a `typings.custom/collections/` directory with the type definitions your extension needs, and add a `paths` mapping in `tsconfig.json`:
284
+
285
+ ```json
286
+ {
287
+ "compilerOptions": {
288
+ "paths": {
289
+ "collections/*": ["./typings.custom/collections/*"]
290
+ }
291
+ }
292
+ }
293
+ ```
294
+
295
+ ### Option B: Wait for `vortex-api` to include them
296
+
297
+ These types will be included in a future `vortex-api` release. If your extension doesn't need them immediately, you can skip this step.
298
+
299
+ ## Step 5: Replace `VORTEX_VERSION` Constant
300
+
301
+ The `VORTEX_VERSION` constant from `@vortex/shared` is no longer available to extensions. Read the version from Redux state instead:
302
+
303
+ ```diff
304
+ - import { VORTEX_VERSION } from "@vortex/shared";
305
+ - const version = VORTEX_VERSION;
306
+ + const state = context.api.getState();
307
+ + const version = state.app.appVersion;
308
+ ```
309
+
310
+ ## Step 6: Update Dev Deployment Path (dev builds only)
311
+
312
+ > Most extension developers don't use a dev build of Vortex and can skip this step.
313
+
314
+ If your build scripts copy the extension to Vortex's dev plugins folder, update the path:
315
+
316
+ ```diff
317
+ - const deployPath = "vortex_devel/plugins";
318
+ + const deployPath = "@vortex/main/plugins";
319
+ ```
320
+
321
+ The production path (`Vortex/plugins`) remains unchanged.
322
+
323
+ ## Step 7: Update Main Page Priorities
324
+
325
+ If your extension registers custom main pages for load order or save game management, update their `priority` values to match Vortex 2.0's page ordering:
326
+
327
+ | Page type | Priority |
328
+ | ----------------------- | -------- |
329
+ | Custom Load Order pages | `30` |
330
+ | Custom Save pages | `50` |
331
+
332
+ Additionally, page names should use **sentence case** (e.g., "Load order") rather than Title Case (e.g., "Load Order").
333
+
334
+ ```js
335
+ context.registerMainPage("sort-none", "Load order", MyLoadOrderPage, {
336
+ priority: 30,
337
+ id: "my-loadorder",
338
+ group: "per-game",
339
+ // ...
340
+ });
341
+
342
+ context.registerMainPage("savegame", "Save games", MySavegamePage, {
343
+ priority: 50,
344
+ id: "my-savegames",
345
+ group: "per-game",
346
+ // ...
347
+ });
348
+ ```
349
+
350
+ ## Quick Checklist
351
+
352
+ ### All extensions
353
+
354
+ - [ ] Remove registry runtime packages from `devDependencies` (now provided by `vortex-api` peer dependencies)
355
+ - [ ] Add git-based packages your extension uses to `devDependencies` with correct commit hashes
356
+ - [ ] If using a custom webpack config, simplify externals to read from `vortex-api/package.json` (or optionally migrate to Rolldown)
357
+ - [ ] Add local `collections` type declarations if needed
358
+ - [ ] Replace `VORTEX_VERSION` imports with `state.app.appVersion`
359
+ - [ ] Update `priority` for custom Load Order pages to `30` and Save pages to `50`
360
+ - [ ] If using a dev build of Vortex, update dev deployment path from `vortex_devel/plugins` to `@vortex/main/plugins`
361
+ - [ ] If using ESLint, add `typings.custom/**` to ignores (if applicable)
362
+ - [ ] Verify your extension builds and loads correctly
363
+
364
+ ### If switching to pnpm (Path A)
365
+
366
+ - [ ] Replace `yarn.lock` with `pnpm-lock.yaml`
367
+ - [ ] Update `packageManager` field in `package.json`
368
+ - [ ] Replace `yarn`/`npx` commands with `pnpm`/`pnpm exec` in build scripts
369
+ - [ ] Remove runtime packages from `devDependencies` (now provided by `vortex-api` peer dependencies)
370
+ - [ ] Adapt `resolutions` field from `package.json`