@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,89 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { readConfig, CONFIG_PATH } from "../config/store.js";
3
+ import { probeDylib } from "../steam/client.js";
4
+ function detectSteamRunning() {
5
+ // Best-effort check on macOS — pgrep -x Steam returns 0 if found.
6
+ // execFileSync (not execSync) — no shell interpretation, no injection risk.
7
+ try {
8
+ execFileSync("pgrep", ["-x", "Steam"], { stdio: "ignore" });
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ export function runDoctor(opts) {
16
+ const checks = [];
17
+ // 1. Config exists
18
+ const cfg = readConfig();
19
+ if (!cfg) {
20
+ checks.push({
21
+ name: "config",
22
+ ok: false,
23
+ detail: `not found at ${CONFIG_PATH} — run \`riu init\``,
24
+ });
25
+ }
26
+ else {
27
+ checks.push({ name: "config", ok: true, detail: CONFIG_PATH });
28
+ }
29
+ // 2. Steam SDK / dylib
30
+ if (cfg) {
31
+ const probe = probeDylib(cfg.steamSdkPath);
32
+ if (probe.ok) {
33
+ checks.push({ name: "steamSdk", ok: true, detail: probe.dylibPath });
34
+ }
35
+ else {
36
+ checks.push({ name: "steamSdk", ok: false, detail: probe.reason });
37
+ }
38
+ }
39
+ else {
40
+ checks.push({ name: "steamSdk", ok: false, detail: "skipped — config missing" });
41
+ }
42
+ // 3. Steam client running (best effort, macOS only)
43
+ const steamRunning = detectSteamRunning();
44
+ checks.push({
45
+ name: "steamRunning",
46
+ ok: steamRunning,
47
+ detail: steamRunning
48
+ ? "pgrep found Steam process"
49
+ : "pgrep did not find a Steam process — start Steam before running upload",
50
+ });
51
+ // 4. Author SteamID format (we already validate at write time, but reverify)
52
+ if (cfg) {
53
+ const looksValid = /^7656\d{13}$/.test(cfg.authorId);
54
+ checks.push({
55
+ name: "authorId",
56
+ ok: looksValid,
57
+ detail: looksValid ? cfg.authorId : `invalid SteamID64: ${cfg.authorId}`,
58
+ });
59
+ }
60
+ // 5. Steam app ID
61
+ if (cfg) {
62
+ checks.push({
63
+ name: "steamAppId",
64
+ ok: cfg.steamAppId > 0,
65
+ detail: cfg.steamAppId === 252490 ? "252490 (Rust)" : String(cfg.steamAppId),
66
+ });
67
+ }
68
+ const failed = checks.filter((c) => !c.ok).length;
69
+ const status = failed === 0 ? "ok" : "fail";
70
+ const result = { status, checks };
71
+ if (opts.json) {
72
+ process.stdout.write(JSON.stringify(result) + "\n");
73
+ process.exit(failed > 0 ? 1 : 0);
74
+ }
75
+ process.stdout.write("riu doctor\n");
76
+ for (const c of checks) {
77
+ const icon = c.ok ? "✓" : "✗";
78
+ process.stdout.write(` ${icon} ${c.name.padEnd(14)} ${c.detail ?? ""}\n`);
79
+ }
80
+ if (failed > 0) {
81
+ process.stdout.write(`\n${failed} check(s) failed — fix the issues above before running upload.\n`);
82
+ process.exit(1);
83
+ }
84
+ else {
85
+ process.stdout.write("\nall checks passed\n");
86
+ process.exit(0);
87
+ }
88
+ }
89
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from "ink";
3
+ import { ZodError } from "zod";
4
+ import { ConfigInputSchema, } from "../config/schema.js";
5
+ import { hasConfig, readConfig, writeConfig, buildConfig, probeSteamSdk, CONFIG_PATH, } from "../config/store.js";
6
+ import { findSteamLibraries } from "../sdk/locator.js";
7
+ import { installFromSource, isSdkInstalled, getManagedSdkDir, } from "../sdk/installer.js";
8
+ import { InitWizard } from "../ui/InitWizard.js";
9
+ // Try to auto-resolve a steamSdkPath. Returns the managed path if a local
10
+ // Steam game install was found and the dylib was successfully installed,
11
+ // otherwise undefined.
12
+ function tryAutoInstallSdk() {
13
+ if (isSdkInstalled()) {
14
+ return { source: "already-installed", managedDir: getManagedSdkDir() };
15
+ }
16
+ const candidates = findSteamLibraries();
17
+ if (candidates.length === 0)
18
+ return undefined;
19
+ const result = installFromSource(candidates[0]);
20
+ if (!result.ok)
21
+ return undefined;
22
+ return { source: candidates[0].game, managedDir: getManagedSdkDir() };
23
+ }
24
+ function emit(opts, result, exitCode) {
25
+ if (opts.jsonFlag) {
26
+ process.stdout.write(JSON.stringify(result) + "\n");
27
+ }
28
+ else {
29
+ if (result.status === "error") {
30
+ process.stderr.write(`error: ${result.error?.message}${result.error?.field ? ` (field: ${result.error.field})` : ""}\n`);
31
+ }
32
+ else if (result.status === "skipped") {
33
+ process.stdout.write("init skipped — config already exists (use --force to overwrite)\n");
34
+ }
35
+ else if (result.config) {
36
+ const c = result.config;
37
+ const heading = result.mode === "shown"
38
+ ? `current config (${result.configPath})`
39
+ : result.mode === "dry-run"
40
+ ? `dry-run — would write to ${result.configPath}`
41
+ : `config saved to ${result.configPath}`;
42
+ process.stdout.write(`✓ ${heading}\n`);
43
+ process.stdout.write(` steamSdkPath: ${c.steamSdkPath}\n`);
44
+ process.stdout.write(` authorId: ${c.authorId}\n`);
45
+ process.stdout.write(` steamAppId: ${c.steamAppId}\n`);
46
+ process.stdout.write(` defaultTags: ${c.defaultTags.join(", ")}\n`);
47
+ process.stdout.write(` cacheDir: ${c.cacheDir}\n`);
48
+ if (result.validatedSdk?.ok) {
49
+ process.stdout.write(`✓ libsteam_api.dylib found at ${result.validatedSdk.dylibPath}\n`);
50
+ }
51
+ else if (result.validatedSdk?.reason) {
52
+ process.stdout.write(`⚠ ${result.validatedSdk.reason}\n`);
53
+ process.stdout.write(" (run \`riu doctor\` to revalidate after installing the SDK)\n");
54
+ }
55
+ }
56
+ }
57
+ process.exit(exitCode);
58
+ }
59
+ function persist(input, opts) {
60
+ // If steamSdkPath is missing or empty, try auto-install before validation
61
+ // would reject the input. This is the "just works" path for users with
62
+ // Rust installed locally.
63
+ let autoInstallInfo;
64
+ if (!input.steamSdkPath || input.steamSdkPath.trim().length === 0) {
65
+ const auto = tryAutoInstallSdk();
66
+ if (auto) {
67
+ input = { ...input, steamSdkPath: auto.managedDir };
68
+ autoInstallInfo = { source: auto.source, path: auto.managedDir };
69
+ }
70
+ }
71
+ // Validate via zod first so we can produce a clean field-level error in JSON mode.
72
+ let parsed;
73
+ try {
74
+ parsed = ConfigInputSchema.parse(input);
75
+ }
76
+ catch (e) {
77
+ if (e instanceof ZodError) {
78
+ const issue = e.issues[0];
79
+ emit(opts, {
80
+ status: "error",
81
+ error: {
82
+ message: issue?.message ?? "validation failed",
83
+ field: issue?.path.join(".") ?? undefined,
84
+ },
85
+ }, 2);
86
+ }
87
+ throw e;
88
+ }
89
+ const sdkProbe = probeSteamSdk(parsed.steamSdkPath);
90
+ if (opts.dryRun) {
91
+ // Build fully-merged config (with defaults) without touching disk.
92
+ const merged = buildConfig(parsed);
93
+ emit(opts, {
94
+ status: "ok",
95
+ mode: "dry-run",
96
+ configPath: CONFIG_PATH,
97
+ validatedSdk: sdkProbe,
98
+ sdkAutoInstalled: autoInstallInfo,
99
+ config: merged,
100
+ }, 0);
101
+ }
102
+ const written = writeConfig(parsed);
103
+ emit(opts, {
104
+ status: "ok",
105
+ mode: "saved",
106
+ config: written,
107
+ configPath: CONFIG_PATH,
108
+ validatedSdk: sdkProbe,
109
+ sdkAutoInstalled: autoInstallInfo,
110
+ }, 0);
111
+ }
112
+ export async function runInit(opts) {
113
+ // --show: print current config and exit
114
+ if (opts.show) {
115
+ const cfg = readConfig();
116
+ if (!cfg) {
117
+ emit(opts, { status: "error", error: { message: "no config found — run `riu init` first" } }, 1);
118
+ }
119
+ emit(opts, { status: "ok", mode: "shown", config: cfg, configPath: CONFIG_PATH }, 0);
120
+ }
121
+ // Refuse to overwrite without --force.
122
+ if (hasConfig() && !opts.force) {
123
+ emit(opts, { status: "skipped", configPath: CONFIG_PATH }, 0);
124
+ }
125
+ // Headless mode: --json '{...}' supplied a payload.
126
+ if (opts.jsonPayload && typeof opts.jsonPayload === "object") {
127
+ persist(opts.jsonPayload, opts);
128
+ }
129
+ // --json flag with no payload is ambiguous for init — refuse.
130
+ if (opts.jsonFlag && !opts.jsonPayload) {
131
+ emit(opts, {
132
+ status: "error",
133
+ error: {
134
+ message: "init in --json mode requires a JSON payload, e.g. --json '{\"steamSdkPath\":\"...\",\"authorId\":\"...\"}'",
135
+ },
136
+ }, 2);
137
+ }
138
+ // Interactive mode: try auto-install first, then launch the Ink wizard
139
+ // with the resolved path pre-filled (so the user just hits enter past it).
140
+ const existing = readConfig();
141
+ let initial = existing ?? {};
142
+ let preDetectedNotice;
143
+ if (!initial.steamSdkPath) {
144
+ const auto = tryAutoInstallSdk();
145
+ if (auto) {
146
+ initial = { ...initial, steamSdkPath: auto.managedDir };
147
+ preDetectedNotice =
148
+ auto.source === "already-installed"
149
+ ? `using existing managed dylib at ${auto.managedDir}`
150
+ : `auto-installed libsteam_api.dylib from ${auto.source} → ${auto.managedDir}`;
151
+ // Print to stderr so the eventual JSON output (if any) stays clean.
152
+ // In interactive mode this surfaces above the wizard render.
153
+ process.stderr.write(`✓ ${preDetectedNotice}\n\n`);
154
+ }
155
+ }
156
+ await new Promise((resolve) => {
157
+ const app = render(_jsx(InitWizard, { initial: initial, onComplete: (input) => {
158
+ // Tear the Ink app down BEFORE we call persist (which exits the process).
159
+ app.unmount();
160
+ // Defer to next tick so Ink finishes its cleanup output.
161
+ setImmediate(() => {
162
+ persist(input, opts);
163
+ resolve();
164
+ });
165
+ } }));
166
+ });
167
+ }
168
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { findSteamLibraries } from "../sdk/locator.js";
4
+ import { installFromPath, installFromSource, isSdkInstalled, SDK_DYLIB_PATH, getManagedSdkDir, } from "../sdk/installer.js";
5
+ import { readConfig, writeConfig, hasConfig } from "../config/store.js";
6
+ function emit(opts, payload, exitCode) {
7
+ if (opts.json) {
8
+ process.stdout.write(JSON.stringify(payload) + "\n");
9
+ }
10
+ else {
11
+ if (payload.status === "error") {
12
+ process.stderr.write(`error: ${payload.error?.message}\n`);
13
+ }
14
+ else if (payload.status === "skipped") {
15
+ process.stdout.write(`✓ SDK already installed at ${payload.installedPath} (use --force to reinstall)\n`);
16
+ }
17
+ else if (payload.mode === "dry-run") {
18
+ process.stdout.write(`[DRY RUN] would install:\n`);
19
+ process.stdout.write(` source: ${payload.source}\n`);
20
+ process.stdout.write(` dest: ${payload.installedPath}\n`);
21
+ if (payload.candidates && payload.candidates.length > 1) {
22
+ process.stdout.write(` other candidates found:\n`);
23
+ for (const c of payload.candidates.slice(1)) {
24
+ process.stdout.write(` - ${c.game}: ${c.path}\n`);
25
+ }
26
+ }
27
+ }
28
+ else {
29
+ process.stdout.write(`✓ installed libsteam_api.dylib (${payload.bytesCopied} bytes)\n`);
30
+ process.stdout.write(` source: ${payload.source}\n`);
31
+ process.stdout.write(` dest: ${payload.installedPath}\n`);
32
+ if (payload.configUpdated) {
33
+ process.stdout.write(` config updated to point at ${getManagedSdkDir()}\n`);
34
+ }
35
+ }
36
+ }
37
+ process.exit(exitCode);
38
+ }
39
+ function updateConfigToManaged() {
40
+ const cfg = readConfig();
41
+ if (!cfg)
42
+ return false;
43
+ if (cfg.steamSdkPath === getManagedSdkDir())
44
+ return false; // already pointing there
45
+ writeConfig({ ...cfg, steamSdkPath: getManagedSdkDir() });
46
+ return true;
47
+ }
48
+ export function runInstallSdk(opts) {
49
+ // 1. Already installed?
50
+ if (isSdkInstalled() && !opts.force && !opts.from) {
51
+ emit(opts, {
52
+ status: "skipped",
53
+ mode: "already-present",
54
+ installedPath: SDK_DYLIB_PATH,
55
+ }, 0);
56
+ }
57
+ // 2. Source: explicit --from path takes priority
58
+ if (opts.from) {
59
+ const src = resolve(opts.from);
60
+ if (!existsSync(src)) {
61
+ emit(opts, { status: "error", error: { message: `--from path not found: ${src}` } }, 2);
62
+ }
63
+ if (opts.dryRun) {
64
+ emit(opts, {
65
+ status: "ok",
66
+ mode: "dry-run",
67
+ installedPath: SDK_DYLIB_PATH,
68
+ source: src,
69
+ }, 0);
70
+ }
71
+ const result = installFromPath(src, "manual (--from)");
72
+ if (!result.ok) {
73
+ emit(opts, { status: "error", error: { message: result.error ?? "install failed" } }, 1);
74
+ }
75
+ const cfgUpdated = hasConfig() ? updateConfigToManaged() : false;
76
+ emit(opts, {
77
+ status: "ok",
78
+ mode: "installed",
79
+ installedPath: result.installedPath,
80
+ source: result.source,
81
+ bytesCopied: result.bytesCopied,
82
+ configUpdated: cfgUpdated,
83
+ }, 0);
84
+ }
85
+ // 3. Auto-locate
86
+ const candidates = findSteamLibraries();
87
+ if (candidates.length === 0) {
88
+ emit(opts, {
89
+ status: "error",
90
+ error: {
91
+ message: "no libsteam_api binary found in any local Steam game install. Install Rust or Spacewar via Steam, or pass --from <path> with a manual location.",
92
+ },
93
+ }, 1);
94
+ }
95
+ const chosen = candidates[0];
96
+ const candidateSummary = candidates.map((c) => ({ path: c.path, game: c.game }));
97
+ if (opts.dryRun) {
98
+ emit(opts, {
99
+ status: "ok",
100
+ mode: "dry-run",
101
+ installedPath: SDK_DYLIB_PATH,
102
+ source: chosen.game + ": " + chosen.path,
103
+ candidates: candidateSummary,
104
+ }, 0);
105
+ }
106
+ const result = installFromSource(chosen);
107
+ if (!result.ok) {
108
+ emit(opts, { status: "error", error: { message: result.error ?? "install failed" } }, 1);
109
+ }
110
+ const cfgUpdated = hasConfig() ? updateConfigToManaged() : false;
111
+ emit(opts, {
112
+ status: "ok",
113
+ mode: "installed",
114
+ installedPath: result.installedPath,
115
+ source: chosen.game,
116
+ bytesCopied: result.bytesCopied,
117
+ candidates: candidateSummary,
118
+ configUpdated: cfgUpdated,
119
+ }, 0);
120
+ }
121
+ //# sourceMappingURL=install-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-sdk.js","sourceRoot":"","sources":["../../src/commands/install-sdk.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { readConfig } from "../config/store.js";
2
+ import { readCache } from "../cache/uploads.js";
3
+ function pad(s, w) {
4
+ if (s.length > w)
5
+ return s.slice(0, w - 1) + "…";
6
+ return s.padEnd(w);
7
+ }
8
+ function formatDate(iso) {
9
+ return iso.slice(0, 10);
10
+ }
11
+ export function runList(opts) {
12
+ const cfg = readConfig();
13
+ if (!cfg) {
14
+ if (opts.json) {
15
+ process.stdout.write(JSON.stringify({ status: "error", error: { message: "no config found — run `riu init` first" } }) + "\n");
16
+ }
17
+ else {
18
+ process.stderr.write("error: no config found — run `riu init` first\n");
19
+ }
20
+ process.exit(1);
21
+ }
22
+ const cache = readCache(cfg.cacheDir);
23
+ let entries = cache.uploads;
24
+ if (!opts.includeDryRun) {
25
+ entries = entries.filter((e) => !e.dryRun);
26
+ }
27
+ if (opts.filter) {
28
+ entries = entries.filter((e) => e.itemType === opts.filter);
29
+ }
30
+ if (opts.json) {
31
+ process.stdout.write(JSON.stringify({
32
+ status: "ok",
33
+ count: entries.length,
34
+ uploads: entries,
35
+ }) + "\n");
36
+ process.exit(0);
37
+ }
38
+ if (entries.length === 0) {
39
+ process.stdout.write("no skins uploaded yet — run `riu upload` to publish one\n");
40
+ process.exit(0);
41
+ }
42
+ // Manual table render — Ink would be overkill for a non-interactive list,
43
+ // and ink-table has version-coupling issues with Ink 5.
44
+ const cols = [
45
+ { header: "FileID", width: 12 },
46
+ { header: "Title", width: 28 },
47
+ { header: "ItemType", width: 14 },
48
+ { header: "Uploaded", width: 12 },
49
+ { header: "URL", width: 60 },
50
+ ];
51
+ const headerRow = cols.map((c) => pad(c.header, c.width)).join(" ");
52
+ const sep = cols.map((c) => "─".repeat(c.width)).join(" ");
53
+ process.stdout.write(headerRow + "\n");
54
+ process.stdout.write(sep + "\n");
55
+ for (const e of entries) {
56
+ process.stdout.write([
57
+ pad(e.publishedFileId, cols[0].width),
58
+ pad(e.title, cols[1].width),
59
+ pad(e.itemType, cols[2].width),
60
+ pad(formatDate(e.uploadedAt), cols[3].width),
61
+ pad(e.url, cols[4].width),
62
+ ].join(" ") + "\n");
63
+ }
64
+ process.stdout.write(`\n${entries.length} upload(s)\n`);
65
+ process.exit(0);
66
+ }
67
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,177 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from "ink";
3
+ import { copyFileSync, mkdirSync, existsSync } from "node:fs";
4
+ import { join, resolve } from "node:path";
5
+ import { z } from "zod";
6
+ import { buildManifest } from "../manifest/builder.js";
7
+ import { writeManifest, manifestPath } from "../manifest/writer.js";
8
+ import { validateIcon } from "../utils/iconValidator.js";
9
+ import { slugify } from "../utils/slugify.js";
10
+ import { readConfig } from "../config/store.js";
11
+ import { NewSkinWizard } from "../ui/NewSkinWizard.js";
12
+ const NewSkinPayloadSchema = z.object({
13
+ itemType: z.string().min(1, "itemType is required"),
14
+ title: z.string().min(1, "title is required").max(128, "title must be ≤128 chars"),
15
+ description: z.string().optional().default(""),
16
+ tags: z.array(z.string().min(1)).optional(),
17
+ iconPath: z.string().min(1, "iconPath is required"),
18
+ outputDir: z.string().optional(),
19
+ allowCustomItemType: z.boolean().optional().default(false),
20
+ });
21
+ function emit(opts, result, exitCode) {
22
+ if (opts.jsonFlag) {
23
+ process.stdout.write(JSON.stringify(result) + "\n");
24
+ }
25
+ else if (result.status === "error") {
26
+ process.stderr.write(`error: ${result.error.message}${result.error.field ? ` (field: ${result.error.field})` : ""}\n`);
27
+ }
28
+ else {
29
+ const heading = result.mode === "dry-run"
30
+ ? `dry-run — would generate skin folder at ${result.skinDir}`
31
+ : `generated skin folder at ${result.skinDir}`;
32
+ process.stdout.write(`✓ ${heading}\n`);
33
+ process.stdout.write(` manifest: ${result.manifestPath}\n`);
34
+ process.stdout.write(` icon: ${result.iconPath}\n`);
35
+ process.stdout.write(` image: ${result.iconMeta.width}x${result.iconMeta.height} ${result.iconMeta.format} (${result.iconMeta.fileSize ?? "?"}b)\n`);
36
+ if (result.warnings.length > 0) {
37
+ for (const w of result.warnings) {
38
+ process.stdout.write(` ⚠ ${w}\n`);
39
+ }
40
+ }
41
+ }
42
+ process.exit(exitCode);
43
+ }
44
+ async function generate(payload, opts) {
45
+ const cfg = readConfig();
46
+ if (!cfg) {
47
+ emit(opts, {
48
+ status: "error",
49
+ error: { message: "no config found — run `riu init` first" },
50
+ }, 1);
51
+ }
52
+ const tags = payload.tags ?? cfg.defaultTags;
53
+ const description = payload.description || cfg.defaultDescription;
54
+ const skinDirRel = payload.outputDir ?? `./skins/${slugify(payload.title)}`;
55
+ const skinDir = resolve(skinDirRel);
56
+ const iconAbs = resolve(payload.iconPath);
57
+ // Step 1: validate icon (always, even in dry-run)
58
+ const iconResult = await validateIcon(iconAbs);
59
+ if (!iconResult.ok) {
60
+ emit(opts, {
61
+ status: "error",
62
+ error: {
63
+ message: `icon validation failed: ${iconResult.errors.join("; ")}`,
64
+ field: "iconPath",
65
+ },
66
+ }, 2);
67
+ }
68
+ // Step 2: build manifest object
69
+ let buildResult;
70
+ try {
71
+ buildResult = buildManifest({
72
+ itemType: payload.itemType,
73
+ authorId: cfg.authorId,
74
+ allowCustomItemType: payload.allowCustomItemType,
75
+ });
76
+ }
77
+ catch (e) {
78
+ emit(opts, {
79
+ status: "error",
80
+ error: { message: e instanceof Error ? e.message : String(e), field: "itemType" },
81
+ }, 2);
82
+ }
83
+ const warnings = [...buildResult.warnings, ...iconResult.warnings];
84
+ const targetIconPath = join(skinDir, "icon.png");
85
+ const targetManifestPath = manifestPath(skinDir);
86
+ // Step 3: dry-run short-circuits before any filesystem mutation
87
+ if (opts.dryRun) {
88
+ emit(opts, {
89
+ status: "ok",
90
+ mode: "dry-run",
91
+ skinDir,
92
+ manifestPath: targetManifestPath,
93
+ iconPath: targetIconPath,
94
+ manifest: buildResult.manifest,
95
+ warnings,
96
+ iconMeta: {
97
+ width: iconResult.width,
98
+ height: iconResult.height,
99
+ format: iconResult.format,
100
+ hasAlpha: iconResult.hasAlpha,
101
+ fileSize: iconResult.fileSize,
102
+ },
103
+ }, 0);
104
+ }
105
+ // Step 4: write manifest + copy icon
106
+ if (existsSync(skinDir) && existsSync(targetManifestPath)) {
107
+ warnings.push(`overwriting existing manifest at ${targetManifestPath}`);
108
+ }
109
+ mkdirSync(skinDir, { recursive: true });
110
+ writeManifest(skinDir, buildResult.manifest, { originalAuthorId: cfg.authorId });
111
+ copyFileSync(iconAbs, targetIconPath);
112
+ emit(opts, {
113
+ status: "ok",
114
+ mode: "written",
115
+ skinDir,
116
+ manifestPath: targetManifestPath,
117
+ iconPath: targetIconPath,
118
+ manifest: buildResult.manifest,
119
+ warnings,
120
+ iconMeta: {
121
+ width: iconResult.width,
122
+ height: iconResult.height,
123
+ format: iconResult.format,
124
+ hasAlpha: iconResult.hasAlpha,
125
+ fileSize: iconResult.fileSize,
126
+ },
127
+ }, 0);
128
+ }
129
+ export async function runNew(opts) {
130
+ // Headless: --json with payload
131
+ if (opts.jsonPayload && typeof opts.jsonPayload === "object") {
132
+ const parsed = NewSkinPayloadSchema.safeParse(opts.jsonPayload);
133
+ if (!parsed.success) {
134
+ const issue = parsed.error.issues[0];
135
+ emit(opts, {
136
+ status: "error",
137
+ error: {
138
+ message: issue?.message ?? "validation failed",
139
+ field: issue?.path.join(".") ?? undefined,
140
+ },
141
+ }, 2);
142
+ }
143
+ await generate(parsed.data, opts);
144
+ return; // unreachable; emit calls process.exit
145
+ }
146
+ if (opts.jsonFlag && !opts.jsonPayload) {
147
+ emit(opts, {
148
+ status: "error",
149
+ error: {
150
+ message: "new in --json mode requires a JSON payload",
151
+ },
152
+ }, 2);
153
+ }
154
+ // Interactive: launch the Ink wizard
155
+ const cfg = readConfig();
156
+ await new Promise((resolve) => {
157
+ const app = render(_jsx(NewSkinWizard, { defaults: {
158
+ description: cfg?.defaultDescription,
159
+ tags: cfg?.defaultTags,
160
+ }, onComplete: (input) => {
161
+ app.unmount();
162
+ setImmediate(() => {
163
+ generate({
164
+ itemType: input.itemType,
165
+ title: input.title,
166
+ description: input.description,
167
+ tags: input.tags,
168
+ iconPath: input.iconPath,
169
+ outputDir: input.outputDir,
170
+ allowCustomItemType: false,
171
+ }, opts);
172
+ resolve();
173
+ });
174
+ } }));
175
+ });
176
+ }
177
+ //# sourceMappingURL=new.js.map