@blackasteroid/riu 0.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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +371 -0
  3. package/dist/cache/uploads.js +48 -0
  4. package/dist/cache/uploads.js.map +1 -0
  5. package/dist/cli.js +196 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/doctor.js +89 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/init.js +168 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/install-sdk.js +121 -0
  12. package/dist/commands/install-sdk.js.map +1 -0
  13. package/dist/commands/list.js +67 -0
  14. package/dist/commands/list.js.map +1 -0
  15. package/dist/commands/new.js +177 -0
  16. package/dist/commands/new.js.map +1 -0
  17. package/dist/commands/update.js +116 -0
  18. package/dist/commands/update.js.map +1 -0
  19. package/dist/commands/upgrade.js +93 -0
  20. package/dist/commands/upgrade.js.map +1 -0
  21. package/dist/commands/upload-all.js +250 -0
  22. package/dist/commands/upload-all.js.map +1 -0
  23. package/dist/commands/upload.js +205 -0
  24. package/dist/commands/upload.js.map +1 -0
  25. package/dist/config/schema.js +76 -0
  26. package/dist/config/schema.js.map +1 -0
  27. package/dist/config/store.js +70 -0
  28. package/dist/config/store.js.map +1 -0
  29. package/dist/manifest/builder.js +84 -0
  30. package/dist/manifest/builder.js.map +1 -0
  31. package/dist/manifest/itemTypes.js +44 -0
  32. package/dist/manifest/itemTypes.js.map +1 -0
  33. package/dist/manifest/writer.js +38 -0
  34. package/dist/manifest/writer.js.map +1 -0
  35. package/dist/sdk/installer.js +59 -0
  36. package/dist/sdk/installer.js.map +1 -0
  37. package/dist/sdk/locator.js +160 -0
  38. package/dist/sdk/locator.js.map +1 -0
  39. package/dist/steam/client.js +163 -0
  40. package/dist/steam/client.js.map +1 -0
  41. package/dist/steam/mock.js +51 -0
  42. package/dist/steam/mock.js.map +1 -0
  43. package/dist/steam/types.js +7 -0
  44. package/dist/steam/types.js.map +1 -0
  45. package/dist/ui/BulkUploadProgress.js +21 -0
  46. package/dist/ui/BulkUploadProgress.js.map +1 -0
  47. package/dist/ui/InitWizard.js +67 -0
  48. package/dist/ui/InitWizard.js.map +1 -0
  49. package/dist/ui/NewSkinWizard.js +52 -0
  50. package/dist/ui/NewSkinWizard.js.map +1 -0
  51. package/dist/ui/UploadProgress.js +46 -0
  52. package/dist/ui/UploadProgress.js.map +1 -0
  53. package/dist/utils/iconValidator.js +68 -0
  54. package/dist/utils/iconValidator.js.map +1 -0
  55. package/dist/utils/slugify.js +13 -0
  56. package/dist/utils/slugify.js.map +1 -0
  57. package/dist/utils/updateCheck.js +93 -0
  58. package/dist/utils/updateCheck.js.map +1 -0
  59. package/dist/version.js +9 -0
  60. package/dist/version.js.map +1 -0
  61. package/package.json +67 -0
@@ -0,0 +1,160 @@
1
+ // Locates an existing libsteam_api binary on the user's machine.
2
+ //
3
+ // Strategy: walk every Steam library folder (default + alt libraries from
4
+ // libraryfolders.vdf), look inside each installed game for files matching
5
+ // libsteam_api.{dylib,bundle,so,dll}.
6
+ //
7
+ // On macOS, Unity-built games (Rust included) ship the binary as
8
+ // `Contents/PlugIns/libsteam_api.bundle` — flat Mach-O, just renamed. So
9
+ // we accept the .bundle extension and verify it's a regular file via
10
+ // `statSync` (not a directory bundle).
11
+ //
12
+ // We do NOT auto-download from Valve — the Steamworks SDK is gated. If no
13
+ // local copy exists, the locator returns an empty array and the caller
14
+ // falls back to asking the user.
15
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
16
+ import { homedir, platform } from "node:os";
17
+ import { join } from "node:path";
18
+ const STEAM_LIBRARY_DEFAULT_MAC = join(homedir(), "Library", "Application Support", "Steam");
19
+ // Filenames we accept as valid sources, in order of preference.
20
+ const CANDIDATE_NAMES = [
21
+ "libsteam_api.dylib",
22
+ "libsteam_api.bundle", // Unity convention on macOS
23
+ "libsteam_api.so",
24
+ "steam_api64.dll",
25
+ ];
26
+ function isRegularFile(p) {
27
+ try {
28
+ return statSync(p).isFile();
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ // libraryfolders.vdf format (simplified):
35
+ // "libraryfolders" {
36
+ // "0" { "path" "/Users/pablo/Library/Application Support/Steam" ... }
37
+ // "1" { "path" "/Volumes/External/SteamLibrary" ... }
38
+ // }
39
+ function parseLibraryFoldersVdf(content) {
40
+ const out = [];
41
+ // matchAll → cleaner than the regex.exec loop pattern, no false-positive
42
+ // collisions with child_process.exec name lookups in tooling.
43
+ for (const match of content.matchAll(/"path"\s+"([^"]+)"/g)) {
44
+ if (match[1])
45
+ out.push(match[1]);
46
+ }
47
+ return out;
48
+ }
49
+ function getSteamLibraryRoots() {
50
+ const roots = [];
51
+ if (existsSync(STEAM_LIBRARY_DEFAULT_MAC)) {
52
+ roots.push(STEAM_LIBRARY_DEFAULT_MAC);
53
+ }
54
+ const vdf = join(STEAM_LIBRARY_DEFAULT_MAC, "steamapps", "libraryfolders.vdf");
55
+ if (existsSync(vdf)) {
56
+ try {
57
+ const content = readFileSync(vdf, "utf8");
58
+ for (const p of parseLibraryFoldersVdf(content)) {
59
+ if (existsSync(p) && !roots.includes(p)) {
60
+ roots.push(p);
61
+ }
62
+ }
63
+ }
64
+ catch {
65
+ // Best effort — bail silently if the VDF is unreadable.
66
+ }
67
+ }
68
+ return roots;
69
+ }
70
+ // Walk a single game install dir looking for libsteam_api.* anywhere inside.
71
+ // Caps recursion depth so we don't crawl the entire game's asset tree.
72
+ function* walkForBinary(dir, depth = 0, maxDepth = 5) {
73
+ if (depth > maxDepth)
74
+ return;
75
+ let entries;
76
+ try {
77
+ entries = readdirSync(dir);
78
+ }
79
+ catch {
80
+ return;
81
+ }
82
+ for (const name of entries) {
83
+ const full = join(dir, name);
84
+ if (CANDIDATE_NAMES.includes(name)) {
85
+ if (isRegularFile(full)) {
86
+ yield full;
87
+ }
88
+ continue;
89
+ }
90
+ let isDir = false;
91
+ try {
92
+ isDir = statSync(full).isDirectory();
93
+ }
94
+ catch {
95
+ continue;
96
+ }
97
+ if (isDir) {
98
+ yield* walkForBinary(full, depth + 1, maxDepth);
99
+ }
100
+ }
101
+ }
102
+ export function findSteamLibraries() {
103
+ const sources = [];
104
+ const seen = new Set();
105
+ if (platform() !== "darwin") {
106
+ // We could extend this for Linux/Windows later, but the user is on macOS
107
+ // and that's the only platform with the .bundle/dylib trick. Return empty
108
+ // here so the caller falls back to manual entry.
109
+ return sources;
110
+ }
111
+ for (const root of getSteamLibraryRoots()) {
112
+ const commonDir = join(root, "steamapps", "common");
113
+ if (!existsSync(commonDir))
114
+ continue;
115
+ let games;
116
+ try {
117
+ games = readdirSync(commonDir);
118
+ }
119
+ catch {
120
+ continue;
121
+ }
122
+ for (const game of games) {
123
+ const gameDir = join(commonDir, game);
124
+ try {
125
+ if (!statSync(gameDir).isDirectory())
126
+ continue;
127
+ }
128
+ catch {
129
+ continue;
130
+ }
131
+ for (const found of walkForBinary(gameDir)) {
132
+ if (seen.has(found))
133
+ continue;
134
+ seen.add(found);
135
+ sources.push({
136
+ path: found,
137
+ game,
138
+ destExtension: ".dylib",
139
+ });
140
+ }
141
+ }
142
+ }
143
+ // Sort: Rust first, then Spacewar (the SDK example), then alphabetical.
144
+ sources.sort((a, b) => {
145
+ const rank = (game) => {
146
+ if (game === "Rust")
147
+ return 0;
148
+ if (game === "Spacewar")
149
+ return 1;
150
+ return 2;
151
+ };
152
+ const ra = rank(a.game);
153
+ const rb = rank(b.game);
154
+ if (ra !== rb)
155
+ return ra - rb;
156
+ return a.game.localeCompare(b.game);
157
+ });
158
+ return sources;
159
+ }
160
+ //# sourceMappingURL=locator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locator.js","sourceRoot":"","sources":["../../src/sdk/locator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ // Real Steam client wrapper around steamworks-ffi-node.
2
+ //
3
+ // Lifecycle:
4
+ // 1. setSdkPath() — points the loader at the dir containing libsteam_api.dylib
5
+ // 2. write steam_appid.txt to cwd (Steamworks reads this to know which app
6
+ // to attach as)
7
+ // 3. init() — actually loads the lib + connects to the running Steam client
8
+ // 4. ...do work...
9
+ // 5. shutdown() — releases the FFI handles and removes steam_appid.txt
10
+ //
11
+ // The class is intentionally a thin façade — the heavy lifting is in
12
+ // SteamWorkshopManager (which already promisifies createItem and
13
+ // submitItemUpdate, so we don't need a manual callback pump).
14
+ import { writeFileSync, unlinkSync, existsSync, statSync, } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { RUST_WORKSHOP_URL_PREFIX, } from "./types.js";
17
+ import { MockSteamClient } from "./mock.js";
18
+ const STEAM_APPID_FILENAME = "steam_appid.txt";
19
+ export class SteamSdkMissingError extends Error {
20
+ constructor(reason) {
21
+ super(`Steamworks SDK not ready: ${reason}`);
22
+ this.name = "SteamSdkMissingError";
23
+ }
24
+ }
25
+ export class SteamInitFailedError extends Error {
26
+ constructor(reason) {
27
+ super(`Steam init failed: ${reason}`);
28
+ this.name = "SteamInitFailedError";
29
+ }
30
+ }
31
+ class RealSteamClient {
32
+ isMock = false;
33
+ appId;
34
+ steamAppIdPath;
35
+ steam;
36
+ shutDown = false;
37
+ constructor(steam, appId, steamAppIdPath) {
38
+ this.steam = steam;
39
+ this.appId = appId;
40
+ this.steamAppIdPath = steamAppIdPath;
41
+ }
42
+ isSteamRunning() {
43
+ return this.steam.isSteamRunning();
44
+ }
45
+ async uploadSkin(params) {
46
+ // EWorkshopFileType.Community = 0
47
+ const publishedFileId = (await this.steam.workshop.createItem(this.appId, 0));
48
+ if (!publishedFileId) {
49
+ throw new Error("createItem returned null — check Steam console for details");
50
+ }
51
+ const handle = this.steam.workshop.startItemUpdate(this.appId, publishedFileId);
52
+ const okTitle = this.steam.workshop.setItemTitle(handle, params.title);
53
+ const okDesc = this.steam.workshop.setItemDescription(handle, params.description);
54
+ const okTags = this.steam.workshop.setItemTags(handle, params.tags);
55
+ const okContent = this.steam.workshop.setItemContent(handle, params.skinDir);
56
+ const okPreview = this.steam.workshop.setItemPreview(handle, params.previewPng);
57
+ if (!okTitle || !okDesc || !okTags || !okContent || !okPreview) {
58
+ throw new Error(`failed to set workshop item metadata (title=${okTitle} desc=${okDesc} tags=${okTags} content=${okContent} preview=${okPreview})`);
59
+ }
60
+ const submitted = (await this.steam.workshop.submitItemUpdate(handle, "initial upload via riu"));
61
+ if (!submitted) {
62
+ throw new Error("submitItemUpdate returned false — check Steam console for details");
63
+ }
64
+ const idStr = publishedFileId.toString();
65
+ return {
66
+ publishedFileId: idStr,
67
+ url: `${RUST_WORKSHOP_URL_PREFIX}${idStr}`,
68
+ needsLegalAgreement: false, // we'd need to inspect the result struct to know
69
+ };
70
+ }
71
+ async updateSkinPreview(publishedFileId, params, changeNote) {
72
+ const fileIdBig = BigInt(publishedFileId);
73
+ const handle = this.steam.workshop.startItemUpdate(this.appId, fileIdBig);
74
+ const okPreview = this.steam.workshop.setItemPreview(handle, params.previewPng);
75
+ const okContent = this.steam.workshop.setItemContent(handle, params.skinDir);
76
+ if (!okPreview || !okContent) {
77
+ throw new Error(`failed to set update fields (preview=${okPreview} content=${okContent})`);
78
+ }
79
+ const submitted = (await this.steam.workshop.submitItemUpdate(handle, changeNote));
80
+ if (!submitted) {
81
+ throw new Error("submitItemUpdate returned false during preview update");
82
+ }
83
+ return {
84
+ publishedFileId,
85
+ url: `${RUST_WORKSHOP_URL_PREFIX}${publishedFileId}`,
86
+ needsLegalAgreement: false,
87
+ };
88
+ }
89
+ shutdown() {
90
+ if (this.shutDown)
91
+ return;
92
+ this.shutDown = true;
93
+ try {
94
+ this.steam.shutdown();
95
+ }
96
+ catch {
97
+ // best effort
98
+ }
99
+ if (existsSync(this.steamAppIdPath)) {
100
+ try {
101
+ unlinkSync(this.steamAppIdPath);
102
+ }
103
+ catch {
104
+ // best effort
105
+ }
106
+ }
107
+ }
108
+ }
109
+ // Probe a SDK directory for the macOS dylib. Linux/Windows variants are
110
+ // handled by the steamworks-ffi-node loader itself; this check exists for
111
+ // the doctor command and to bail early on macOS with a clear error.
112
+ export function probeDylib(sdkPath) {
113
+ if (!existsSync(sdkPath))
114
+ return { ok: false, reason: `path does not exist: ${sdkPath}` };
115
+ if (!statSync(sdkPath).isDirectory()) {
116
+ return { ok: false, reason: `not a directory: ${sdkPath}` };
117
+ }
118
+ // Look for the macOS dylib first since that's our primary target. Fall
119
+ // back to checking for any of the supported lib names so we don't fail
120
+ // on Linux/Windows in CI.
121
+ const candidates = ["libsteam_api.dylib", "libsteam_api.so", "steam_api64.dll"];
122
+ for (const name of candidates) {
123
+ const p = join(sdkPath, name);
124
+ if (existsSync(p))
125
+ return { ok: true, dylibPath: p };
126
+ }
127
+ return { ok: false, reason: `no Steam library found in ${sdkPath} (looked for ${candidates.join(", ")})` };
128
+ }
129
+ export async function createSteamClient(opts) {
130
+ if (opts.mock) {
131
+ return new MockSteamClient();
132
+ }
133
+ const probe = probeDylib(opts.sdkPath);
134
+ if (!probe.ok) {
135
+ throw new SteamSdkMissingError(probe.reason ?? "unknown");
136
+ }
137
+ // Drop steam_appid.txt in the current working directory so SteamAPI_Init
138
+ // can read it. We delete it on shutdown.
139
+ const appIdPath = join(process.cwd(), STEAM_APPID_FILENAME);
140
+ writeFileSync(appIdPath, String(opts.appId), "utf8");
141
+ // Lazily import the FFI lib only in real-mode so dry-run paths don't pay
142
+ // the load cost (and don't crash on machines without the SDK).
143
+ const mod = (await import("steamworks-ffi-node"));
144
+ const SteamworksSDK = mod.default ?? mod.SteamworksSDK;
145
+ if (!SteamworksSDK) {
146
+ throw new SteamSdkMissingError("steamworks-ffi-node module did not export SteamworksSDK");
147
+ }
148
+ const steam = SteamworksSDK.getInstance();
149
+ steam.setSdkPath(opts.sdkPath);
150
+ const initialized = steam.init({ appId: opts.appId });
151
+ if (!initialized) {
152
+ // Clean up appid file before throwing
153
+ try {
154
+ unlinkSync(appIdPath);
155
+ }
156
+ catch {
157
+ // ignore
158
+ }
159
+ throw new SteamInitFailedError("Steam init returned false — make sure Steam is running and the account owns the app");
160
+ }
161
+ return new RealSteamClient(steam, opts.appId, appIdPath);
162
+ }
163
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/steam/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ // Fake Steam client used by --dry-run. Does NOT load the FFI library, so it
2
+ // works on any machine without libsteam_api.dylib, Steam running, or a Steam
3
+ // account that owns Rust. Returns synthetic-but-realistic-looking IDs so the
4
+ // rest of the pipeline can be exercised end-to-end.
5
+ import { RUST_WORKSHOP_URL_PREFIX, } from "./types.js";
6
+ let counter = 0;
7
+ function fakeFileId() {
8
+ // Real Rust workshop IDs are 10-digit-ish numbers. Generate something in the
9
+ // same shape so consumers parsing the output get realistic-looking data.
10
+ counter += 1;
11
+ const base = 9_000_000_000 + counter;
12
+ return base.toString();
13
+ }
14
+ export class MockSteamClient {
15
+ isMock = true;
16
+ isSteamRunning() {
17
+ return true;
18
+ }
19
+ async uploadSkin(params) {
20
+ // Validate the same shape we expect a real upload to validate, so dry-run
21
+ // surfaces problems before they happen for real.
22
+ if (!params.title.trim())
23
+ throw new Error("title is required");
24
+ if (params.title.length > 128)
25
+ throw new Error("title must be ≤128 chars");
26
+ if (!params.skinDir)
27
+ throw new Error("skinDir is required");
28
+ if (!params.previewPng)
29
+ throw new Error("previewPng is required");
30
+ // Simulate the async dance with a tiny delay so progress UIs render.
31
+ await new Promise((r) => setTimeout(r, 25));
32
+ const id = fakeFileId();
33
+ return {
34
+ publishedFileId: id,
35
+ url: `${RUST_WORKSHOP_URL_PREFIX}${id}`,
36
+ needsLegalAgreement: false,
37
+ };
38
+ }
39
+ async updateSkinPreview(publishedFileId, _params, _changeNote) {
40
+ await new Promise((r) => setTimeout(r, 25));
41
+ return {
42
+ publishedFileId,
43
+ url: `${RUST_WORKSHOP_URL_PREFIX}${publishedFileId}`,
44
+ needsLegalAgreement: false,
45
+ };
46
+ }
47
+ shutdown() {
48
+ // no-op
49
+ }
50
+ }
51
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/steam/mock.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,oDAAoD;AAEpD,OAAO,EAIL,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,IAAI,OAAO,GAAG,CAAC,CAAC;AAEhB,SAAS,UAAU;IACjB,6EAA6E;IAC7E,yEAAyE;IACzE,OAAO,IAAI,CAAC,CAAC;IACb,MAAM,IAAI,GAAG,aAAa,GAAG,OAAO,CAAC;IACrC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,OAAO,eAAe;IACjB,MAAM,GAAG,IAAI,CAAC;IAEvB,cAAc;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAoB;QACnC,0EAA0E;QAC1E,iDAAiD;QACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAElE,qEAAqE;QACrE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,OAAO;YACL,eAAe,EAAE,EAAE;YACnB,GAAG,EAAE,GAAG,wBAAwB,GAAG,EAAE,EAAE;YACvC,mBAAmB,EAAE,KAAK;SAC3B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,eAAuB,EACvB,OAAqB,EACrB,WAAmB;QAEnB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO;YACL,eAAe;YACf,GAAG,EAAE,GAAG,wBAAwB,GAAG,eAAe,EAAE;YACpD,mBAAmB,EAAE,KAAK;SAC3B,CAAC;IACJ,CAAC;IAED,QAAQ;QACN,QAAQ;IACV,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ // Shared types for the Steam upload layer.
2
+ //
3
+ // These are kept separate from the steamworks-ffi-node types so the rest of
4
+ // the app can import them without dragging in the FFI lib (which is what
5
+ // the mock client takes advantage of).
6
+ export const RUST_WORKSHOP_URL_PREFIX = "https://steamcommunity.com/sharedfiles/filedetails/?id=";
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/steam/types.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,4EAA4E;AAC5E,yEAAyE;AACzE,uCAAuC;AAmDvC,MAAM,CAAC,MAAM,wBAAwB,GACnC,yDAAyD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import Spinner from "ink-spinner";
4
+ function statusIcon(status) {
5
+ switch (status) {
6
+ case "success":
7
+ return _jsx(Text, { color: "green", children: "\u2713" });
8
+ case "skipped":
9
+ return _jsx(Text, { color: "yellow", children: "\u2299" });
10
+ case "failed":
11
+ return _jsx(Text, { color: "red", children: "\u2717" });
12
+ case "uploading":
13
+ return _jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) });
14
+ default:
15
+ return _jsx(Text, { dimColor: true, children: "\u25CB" });
16
+ }
17
+ }
18
+ export function BulkUploadProgress({ total, current, successCount, skippedCount, failedCount, items, isMock, done, }) {
19
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "riu upload-all" }), _jsxs(Text, { dimColor: true, children: [" \u2014 ", current, "/", total] }), isMock && _jsx(Text, { color: "yellow", children: " [DRY RUN]" })] }), items.map((item) => (_jsxs(Box, { children: [_jsx(Box, { marginRight: 1, children: statusIcon(item.status) }), _jsx(Text, { children: item.title }), item.publishedFileId && (_jsxs(Text, { dimColor: true, children: [" \u2192 ", item.publishedFileId] })), item.error && _jsxs(Text, { color: "red", children: [" (", item.error, ")"] })] }, item.index))), done && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { children: [_jsxs(Text, { color: "green", children: ["\u2713 ", successCount, " uploaded"] }), skippedCount > 0 && _jsxs(Text, { color: "yellow", children: [" \u2299 ", skippedCount, " skipped"] }), failedCount > 0 && _jsxs(Text, { color: "red", children: [" \u2717 ", failedCount, " failed"] })] }) }))] }));
20
+ }
21
+ //# sourceMappingURL=BulkUploadProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BulkUploadProgress.js","sourceRoot":"","sources":["../../src/ui/BulkUploadProgress.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,OAAO,MAAM,aAAa,CAAC;AAqBlC,SAAS,UAAU,CAAC,MAAkC;IACpD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,uBAAS,CAAC;QACtC,KAAK,SAAS;YACZ,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,uBAAS,CAAC;QACvC,KAAK,QAAQ;YACX,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,uBAAS,CAAC;QACpC,KAAK,WAAW;YACd,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAC,KAAC,OAAO,IAAC,IAAI,EAAC,MAAM,GAAG,GAAO,CAAC;QAC3D;YACE,OAAO,KAAC,IAAI,IAAC,QAAQ,6BAAS,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,KAAK,EACL,MAAM,EACN,IAAI,GACE;IACN,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aACrC,MAAC,GAAG,IAAC,YAAY,EAAE,CAAC,aAClB,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,MAAM,+BAAsB,EAC7C,MAAC,IAAI,IAAC,QAAQ,+BAAK,OAAO,OAAG,KAAK,IAAQ,EACzC,MAAM,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,2BAAkB,IAC7C,EAEL,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,MAAC,GAAG,eACF,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,YAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAO,EACpD,KAAC,IAAI,cAAE,IAAI,CAAC,KAAK,GAAQ,EACxB,IAAI,CAAC,eAAe,IAAI,CACvB,MAAC,IAAI,IAAC,QAAQ,+BAAK,IAAI,CAAC,eAAe,IAAQ,CAChD,EACA,IAAI,CAAC,KAAK,IAAI,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,mBAAI,IAAI,CAAC,KAAK,SAAS,KAN/C,IAAI,CAAC,KAAK,CAOd,CACP,CAAC,EAED,IAAI,IAAI,CACP,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,YACtC,MAAC,IAAI,eACH,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,wBAAI,YAAY,iBAAiB,EACnD,YAAY,GAAG,CAAC,IAAI,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,0BAAM,YAAY,gBAAgB,EAC1E,WAAW,GAAG,CAAC,IAAI,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,0BAAM,WAAW,eAAe,IAChE,GACH,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, Text, useApp } from "ink";
4
+ import TextInput from "ink-text-input";
5
+ import { FIELD_ORDER, RUST_APP_ID } from "../config/schema.js";
6
+ const initialDefaults = {
7
+ steamAppId: String(RUST_APP_ID),
8
+ defaultTags: "Version3,Skin",
9
+ defaultDescription: "",
10
+ };
11
+ export function InitWizard({ initial, onComplete }) {
12
+ const { exit } = useApp();
13
+ const [step, setStep] = useState(0);
14
+ const [fields, setFields] = useState(() => {
15
+ const out = {};
16
+ for (const f of FIELD_ORDER) {
17
+ const seed = initial[f.key] ??
18
+ initialDefaults[f.key] ??
19
+ "";
20
+ out[f.key] = { raw: typeof seed === "string" ? seed : String(seed) };
21
+ }
22
+ return out;
23
+ });
24
+ const current = FIELD_ORDER[step];
25
+ const value = current ? fields[current.key]?.raw ?? "" : "";
26
+ function setRaw(next) {
27
+ if (!current)
28
+ return;
29
+ setFields((prev) => ({
30
+ ...prev,
31
+ [current.key]: { raw: next },
32
+ }));
33
+ }
34
+ function handleSubmit() {
35
+ if (!current)
36
+ return;
37
+ const trimmed = value.trim();
38
+ if (current.required && trimmed.length === 0) {
39
+ setFields((prev) => ({
40
+ ...prev,
41
+ [current.key]: { raw: trimmed, error: "required" },
42
+ }));
43
+ return;
44
+ }
45
+ if (step + 1 < FIELD_ORDER.length) {
46
+ setStep(step + 1);
47
+ return;
48
+ }
49
+ // Done — coerce raw strings into the typed input shape.
50
+ const input = {
51
+ steamSdkPath: fields["steamSdkPath"]?.raw.trim() ?? "",
52
+ authorId: fields["authorId"]?.raw.trim() ?? "",
53
+ steamAppId: Number(fields["steamAppId"]?.raw.trim() || RUST_APP_ID),
54
+ defaultTags: (fields["defaultTags"]?.raw ?? "Version3,Skin")
55
+ .split(",")
56
+ .map((t) => t.trim())
57
+ .filter(Boolean),
58
+ defaultDescription: fields["defaultDescription"]?.raw ?? "",
59
+ };
60
+ onComplete(input);
61
+ exit();
62
+ }
63
+ if (!current)
64
+ return _jsx(Text, { children: "done" });
65
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "riu init" }), _jsxs(Text, { dimColor: true, children: [" \u2014 step ", step + 1, "/", FIELD_ORDER.length] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { children: [_jsx(Text, { bold: true, children: current.label }), current.required ? _jsx(Text, { color: "red", children: " *" }) : _jsx(Text, { dimColor: true, children: " (optional)" })] }), _jsx(Text, { dimColor: true, children: current.hint })] }), _jsxs(Box, { children: [_jsx(Text, { color: "green", children: "❯ " }), _jsx(TextInput, { value: value, onChange: setRaw, onSubmit: handleSubmit })] }), fields[current.key]?.error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u2717 ", fields[current.key]?.error] }) }))] }));
66
+ }
67
+ //# sourceMappingURL=InitWizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InitWizard.js","sourceRoot":"","sources":["../../src/ui/InitWizard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, Text, useApp } from "ink";
4
+ import TextInput from "ink-text-input";
5
+ import SelectInput from "ink-select-input";
6
+ import { KNOWN_ITEM_TYPES } from "../manifest/itemTypes.js";
7
+ import { slugify } from "../utils/slugify.js";
8
+ const STEPS = ["itemType", "title", "description", "tags", "iconPath", "outputDir", "confirm"];
9
+ const itemTypeItems = KNOWN_ITEM_TYPES.map((t) => ({ label: t, value: t }));
10
+ export function NewSkinWizard({ defaults, onComplete }) {
11
+ const { exit } = useApp();
12
+ const [stepIdx, setStepIdx] = useState(0);
13
+ const [itemType, setItemType] = useState("");
14
+ const [title, setTitle] = useState("");
15
+ const [description, setDescription] = useState(defaults.description ?? "");
16
+ const [tags, setTags] = useState((defaults.tags ?? ["Version3", "Skin"]).join(","));
17
+ const [iconPath, setIconPath] = useState("");
18
+ const [outputDir, setOutputDir] = useState("");
19
+ const step = STEPS[stepIdx];
20
+ function next() {
21
+ if (stepIdx + 1 < STEPS.length) {
22
+ setStepIdx(stepIdx + 1);
23
+ }
24
+ }
25
+ function finish() {
26
+ onComplete({
27
+ itemType,
28
+ title: title.trim(),
29
+ description: description.trim(),
30
+ tags: tags
31
+ .split(",")
32
+ .map((t) => t.trim())
33
+ .filter(Boolean),
34
+ iconPath: iconPath.trim(),
35
+ outputDir: outputDir.trim() || `./skins/${slugify(title)}`,
36
+ });
37
+ exit();
38
+ }
39
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "riu new" }), _jsxs(Text, { dimColor: true, children: [" \u2014 step ", stepIdx + 1, "/", STEPS.length] })] }), step === "itemType" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Item type" }), _jsx(Text, { dimColor: true, children: "which Rust item category does this skin target?" }), _jsx(Box, { marginTop: 1, children: _jsx(SelectInput, { items: itemTypeItems, onSelect: (item) => {
40
+ setItemType(String(item.value));
41
+ next();
42
+ } }) })] })), step === "title" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Title" }), _jsx(Text, { dimColor: true, children: "workshop item title (max 128 chars)" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "green", children: "❯ " }), _jsx(TextInput, { value: title, onChange: setTitle, onSubmit: () => title.trim() && next() })] })] })), step === "description" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Description" }), _jsxs(Text, { dimColor: true, children: ["optional \u2014 defaults to \"", defaults.description ?? "", "\""] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "green", children: "❯ " }), _jsx(TextInput, { value: description, onChange: setDescription, onSubmit: next })] })] })), step === "tags" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Tags" }), _jsx(Text, { dimColor: true, children: "comma-separated" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "green", children: "❯ " }), _jsx(TextInput, { value: tags, onChange: setTags, onSubmit: next })] })] })), step === "iconPath" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Icon path" }), _jsx(Text, { dimColor: true, children: "absolute or relative path to a 512x512 PNG (256/1024/2048 also OK)" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "green", children: "❯ " }), _jsx(TextInput, { value: iconPath, onChange: setIconPath, onSubmit: () => iconPath.trim() && next() })] })] })), step === "outputDir" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Output folder" }), _jsxs(Text, { dimColor: true, children: ["defaults to ./skins/", slugify(title) || "skin"] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "green", children: "❯ " }), _jsx(TextInput, { value: outputDir, onChange: setOutputDir, onSubmit: next })] })] })), step === "confirm" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: "yellow", children: "Review" }), _jsxs(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, children: [_jsxs(Text, { children: [" itemType: ", _jsx(Text, { color: "cyan", children: itemType })] }), _jsxs(Text, { children: [" title: ", _jsx(Text, { color: "cyan", children: title.trim() })] }), _jsxs(Text, { children: [" description: ", _jsx(Text, { color: "cyan", children: description.trim() || "(none)" })] }), _jsxs(Text, { children: [" tags: ", _jsx(Text, { color: "cyan", children: tags })] }), _jsxs(Text, { children: [" iconPath: ", _jsx(Text, { color: "cyan", children: iconPath.trim() })] }), _jsxs(Text, { children: [" outputDir: ", _jsx(Text, { color: "cyan", children: outputDir.trim() || `./skins/${slugify(title)}` })] })] }), _jsx(SelectInput, { items: [
43
+ { label: "✓ Generate skin folder", value: "go" },
44
+ { label: "✗ Cancel", value: "cancel" },
45
+ ], onSelect: (item) => {
46
+ if (item.value === "go")
47
+ finish();
48
+ else
49
+ exit();
50
+ } })] }))] }));
51
+ }
52
+ //# sourceMappingURL=NewSkinWizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NewSkinWizard.js","sourceRoot":"","sources":["../../src/ui/NewSkinWizard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import Spinner from "ink-spinner";
4
+ const STAGES = [
5
+ { key: "validating", label: "validating skin folder" },
6
+ { key: "creating", label: "creating workshop item" },
7
+ { key: "configuring", label: "setting metadata" },
8
+ { key: "uploading", label: "uploading content + preview" },
9
+ { key: "submitting", label: "submitting update" },
10
+ ];
11
+ function stageIndex(stage) {
12
+ return STAGES.findIndex((s) => s.key === stage);
13
+ }
14
+ export function UploadProgress({ title, stage, message, publishedFileId, url, errorMsg, isMock, }) {
15
+ const currentIdx = stageIndex(stage);
16
+ const isError = stage === "error";
17
+ const isDone = stage === "done";
18
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "riu upload" }), _jsxs(Text, { dimColor: true, children: [" \u2014 ", title] }), isMock && _jsx(Text, { color: "yellow", children: " [DRY RUN]" })] }), STAGES.map((s, idx) => {
19
+ const done = idx < currentIdx || isDone;
20
+ const active = idx === currentIdx && !isDone && !isError;
21
+ const pending = idx > currentIdx && !isDone;
22
+ let icon;
23
+ let color;
24
+ if (done) {
25
+ icon = _jsx(Text, { color: "green", children: "\u2713" });
26
+ color = "green";
27
+ }
28
+ else if (active) {
29
+ icon = _jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) });
30
+ color = "cyan";
31
+ }
32
+ else if (pending) {
33
+ icon = _jsx(Text, { dimColor: true, children: "\u25CB" });
34
+ color = undefined;
35
+ }
36
+ else if (isError && idx === currentIdx) {
37
+ icon = _jsx(Text, { color: "red", children: "\u2717" });
38
+ color = "red";
39
+ }
40
+ else {
41
+ icon = _jsx(Text, { dimColor: true, children: "\u25CB" });
42
+ }
43
+ return (_jsxs(Box, { children: [_jsx(Box, { marginRight: 1, children: icon }), _jsx(Text, { color: color, dimColor: pending, children: s.label })] }, s.key));
44
+ }), message && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: message }) })), isDone && publishedFileId && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "green", children: "\u2713 uploaded" }), _jsxs(Text, { children: [" PublishedFileId: ", _jsx(Text, { color: "cyan", children: publishedFileId })] }), url && _jsxs(Text, { children: [" URL: ", _jsx(Text, { color: "cyan", children: url })] })] })), isError && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u2717 ", errorMsg ?? "upload failed"] }) }))] }));
45
+ }
46
+ //# sourceMappingURL=UploadProgress.js.map