diff --git a/bun.lock b/bun.lock index 42fe4e1..556028f 100644 --- a/bun.lock +++ b/bun.lock @@ -88,6 +88,15 @@ "vitest": "^4", }, }, + "plugins/steam-workshop": { + "name": "@game-ci/steam-workshop", + "version": "0.0.1", + "devDependencies": { + "@types/node": "^17.0.23", + "typescript": "4.7.4", + "vitest": "^4", + }, + }, "plugins/unity": { "name": "@game-ci/unity-engine-core", "version": "0.1.0", @@ -353,6 +362,8 @@ "@game-ci/steam-deploy": ["@game-ci/steam-deploy@workspace:plugins/steam-deploy"], + "@game-ci/steam-workshop": ["@game-ci/steam-workshop@workspace:plugins/steam-workshop"], + "@game-ci/unity-engine-core": ["@game-ci/unity-engine-core@workspace:plugins/unity"], "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="], @@ -1583,6 +1594,8 @@ "@game-ci/steam-deploy/typescript": ["typescript@4.7.4", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="], + "@game-ci/steam-workshop/typescript": ["typescript@4.7.4", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="], + "@game-ci/unity-engine-core/@types/node": ["@types/node@20.19.43", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA=="], "@kubernetes/client-node/@types/node": ["@types/node@10.17.60", "", {}, "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="], diff --git a/plugins/steam-workshop/README.md b/plugins/steam-workshop/README.md new file mode 100644 index 0000000..7ae56b8 --- /dev/null +++ b/plugins/steam-workshop/README.md @@ -0,0 +1,35 @@ +# @game-ci/steam-workshop (draft) + +Steam Workshop / mod-publishing plugin. **Not functional yet** - structural +skeleton only. Mirrors `@game-ci/steam-deploy`'s `deploy ` dispatch +shape, so it reuses core's existing `deploy` command registration rather +than needing a new one. + +## Why this, distinct from steam-deploy + +`@game-ci/steam-deploy` uploads a full game build via `appbuild.vdf`. This +uploads a Workshop _item_ (a mod, map, or asset pack) via SteamCMD's +separate `workshop_build_item.vdf` format and `+workshop_build_item` +command - a genuinely different upload target and VDF schema, not a +variation of the same thing. Real demand: any Workshop-integrated game +currently has zero game-ci coverage for this. + +## What's real vs. TODO + +- Plugin/command registration shape: real, mirrors `steam-deploy`. +- `execute()`: throws immediately, pointing here. + +## Remaining work before this is real + +1. Verify the exact `workshop_build_item.vdf` schema (`appid`, + `contentfolder`, `previewfile`, `vdfpath`/`publishedfileid` for + updates vs. new items, `visibility`) against real SteamCMD Workshop + docs/behavior. +2. Handle the new-item vs. update-existing-item distinction - a new item + has no `publishedfileid` yet and one needs to be captured from + SteamCMD's output and surfaced as a command output (the same way + `steam-deploy` captures `steam_build_id`). +3. Reuse `@game-ci/steam-deploy`'s SteamCMD local/Docker execution and + output-parsing infrastructure rather than duplicating it, if a shared + `@game-ci/steam-shared` package ends up making sense once both exist. +4. Tests once the above is real. diff --git a/plugins/steam-workshop/package.json b/plugins/steam-workshop/package.json new file mode 100644 index 0000000..c5aff18 --- /dev/null +++ b/plugins/steam-workshop/package.json @@ -0,0 +1,32 @@ +{ + "name": "@game-ci/steam-workshop", + "version": "0.0.1", + "description": "Steam Workshop / mod-publishing plugin (draft). Wraps SteamCMD's workshop_build_item.vdf upload path for mods/maps/asset packs - a distinct target and VDF schema from a full game build (see @game-ci/steam-deploy).", + "license": "MIT", + "repository": "git@github.com:game-ci/cli.git", + "files": [ + "dist" + ], + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "bun": "./src/index.ts", + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "scripts": { + "build": "tsc", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "@types/node": "^17.0.23", + "typescript": "4.7.4", + "vitest": "^4" + }, + "engines": { + "node": ">=18.x" + } +} diff --git a/plugins/steam-workshop/src/index.ts b/plugins/steam-workshop/src/index.ts new file mode 100644 index 0000000..59b09e9 --- /dev/null +++ b/plugins/steam-workshop/src/index.ts @@ -0,0 +1,44 @@ +/** + * Steam Workshop / mod-publishing plugin - DRAFT. + * + * Plan: `game-ci deploy steam-workshop --appId --itemId` + * wraps SteamCMD's workshop_build_item.vdf upload path - a genuinely + * different VDF schema and upload target from @game-ci/steam-deploy's + * full-game appbuild.vdf. This is for mods, maps, and asset packs, not a + * whole game build. + * + * NOTE: mirrors steam-deploy's `deploy ` dispatch shape (already + * registered in core - see game-ci/cli#123), so this doesn't need a new + * core command registration, unlike most of the other drafts. + */ + +export const steamWorkshopPlugin = { + name: "steam-workshop", + version: "0.0.1", + + commands: [ + { + engine: "*", + createCommand(command: string, subCommands: string[]) { + if (command === "deploy" && subCommands[0] === "steam-workshop") { + return { + name: "Deploy steam workshop", + async configureOptions() { + // TODO: register --appId, --itemId (omit to publish a new item), + // --title, --description, --changeNote, --visibility, --previewImage. + }, + async execute(): Promise { + throw new Error( + "Steam Workshop publishing is not implemented yet (draft plugin). " + + "See plugins/steam-workshop/README.md for the planned workshop_build_item.vdf shape.", + ); + }, + }; + } + return null; + }, + }, + ], +}; + +export default steamWorkshopPlugin; diff --git a/plugins/steam-workshop/tsconfig.json b/plugins/steam-workshop/tsconfig.json new file mode 100644 index 0000000..fb2218a --- /dev/null +++ b/plugins/steam-workshop/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2022", + "lib": ["es2022"], + "module": "commonjs", + "moduleResolution": "node", + "declaration": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "noImplicitAny": false, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "**/*.test.ts", "dist"] +}