@bitmagic/cli 0.1.83-dev.1 → 0.1.83-dev.3

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 (206) hide show
  1. package/README.md +69 -0
  2. package/assets/skills/publishing-to-steam/SKILL.md +218 -0
  3. package/dist/assets/vxl-summary.d.ts +6 -20
  4. package/dist/assets/vxl-summary.js +9 -100
  5. package/dist/assets/vxl-summary.js.map +1 -1
  6. package/dist/cli.d.ts +1 -0
  7. package/dist/cli.js +2 -0
  8. package/dist/cli.js.map +1 -1
  9. package/dist/commands/check.js +5 -0
  10. package/dist/commands/check.js.map +1 -1
  11. package/dist/commands/forge.js +1 -1
  12. package/dist/commands/forge.js.map +1 -1
  13. package/dist/commands/ios.js +88 -136
  14. package/dist/commands/ios.js.map +1 -1
  15. package/dist/commands/steam-build.d.ts +67 -0
  16. package/dist/commands/steam-build.js +286 -0
  17. package/dist/commands/steam-build.js.map +1 -0
  18. package/dist/commands/steam-portal.d.ts +1 -0
  19. package/dist/commands/steam-portal.js +319 -0
  20. package/dist/commands/steam-portal.js.map +1 -0
  21. package/dist/commands/steam-upload.d.ts +37 -0
  22. package/dist/commands/steam-upload.js +174 -0
  23. package/dist/commands/steam-upload.js.map +1 -0
  24. package/dist/commands/steam.d.ts +1 -0
  25. package/dist/commands/steam.js +504 -0
  26. package/dist/commands/steam.js.map +1 -0
  27. package/dist/commands/verify.js +6 -0
  28. package/dist/commands/verify.js.map +1 -1
  29. package/dist/editor/asset-viewer.js +5 -4
  30. package/dist/editor/asset-viewer.js.map +1 -1
  31. package/dist/editor/server.js +1 -1
  32. package/dist/editor/server.js.map +1 -1
  33. package/dist/editor/shell-page.js +3 -3
  34. package/dist/forge/browser-host.d.ts +1 -1
  35. package/dist/forge/browser-host.js +1 -1
  36. package/dist/forge/browser-host.js.map +1 -1
  37. package/dist/ios/native-overrides.d.ts +27 -0
  38. package/dist/ios/native-overrides.js +87 -0
  39. package/dist/ios/native-overrides.js.map +1 -0
  40. package/dist/ios/record-validate.d.ts +1 -33
  41. package/dist/ios/record-validate.js +2 -100
  42. package/dist/ios/record-validate.js.map +1 -1
  43. package/dist/ios/store-bridge.d.ts +26 -0
  44. package/dist/ios/store-bridge.js +224 -0
  45. package/dist/ios/store-bridge.js.map +1 -0
  46. package/dist/ios/storekit-config.d.ts +15 -0
  47. package/dist/ios/storekit-config.js +106 -0
  48. package/dist/ios/storekit-config.js.map +1 -0
  49. package/dist/ios/xcode-template.d.ts +12 -3
  50. package/dist/ios/xcode-template.js +158 -27
  51. package/dist/ios/xcode-template.js.map +1 -1
  52. package/dist/package/collect-urls.d.ts +1 -1
  53. package/dist/package/collect-urls.js +10 -2
  54. package/dist/package/collect-urls.js.map +1 -1
  55. package/dist/package/offline-payload.d.ts +35 -0
  56. package/dist/package/offline-payload.js +142 -0
  57. package/dist/package/offline-payload.js.map +1 -0
  58. package/dist/package/packaged-check.d.ts +39 -0
  59. package/dist/package/packaged-check.js +104 -0
  60. package/dist/package/packaged-check.js.map +1 -0
  61. package/dist/package/transform.d.ts +4 -4
  62. package/dist/package/transform.js +3 -3
  63. package/dist/project/published-three.d.ts +14 -0
  64. package/dist/project/published-three.js +91 -0
  65. package/dist/project/published-three.js.map +1 -0
  66. package/dist/publish/bundle.js +6 -0
  67. package/dist/publish/bundle.js.map +1 -1
  68. package/dist/scaffold/project-files.js +7 -4
  69. package/dist/scaffold/project-files.js.map +1 -1
  70. package/dist/scaffold/project.js +2 -0
  71. package/dist/scaffold/project.js.map +1 -1
  72. package/dist/scaffold/skill-files.js +3 -1
  73. package/dist/scaffold/skill-files.js.map +1 -1
  74. package/dist/scaffold/steam-skill-files.d.ts +2 -0
  75. package/dist/scaffold/steam-skill-files.js +7 -0
  76. package/dist/scaffold/steam-skill-files.js.map +1 -0
  77. package/dist/steam/art-generate.d.ts +55 -0
  78. package/dist/steam/art-generate.js +174 -0
  79. package/dist/steam/art-generate.js.map +1 -0
  80. package/dist/steam/art-render.d.ts +25 -0
  81. package/dist/steam/art-render.js +157 -0
  82. package/dist/steam/art-render.js.map +1 -0
  83. package/dist/steam/art-use.d.ts +20 -0
  84. package/dist/steam/art-use.js +84 -0
  85. package/dist/steam/art-use.js.map +1 -0
  86. package/dist/steam/art.d.ts +98 -0
  87. package/dist/steam/art.js +243 -0
  88. package/dist/steam/art.js.map +1 -0
  89. package/dist/steam/check.d.ts +21 -0
  90. package/dist/steam/check.js +113 -0
  91. package/dist/steam/check.js.map +1 -0
  92. package/dist/steam/config.d.ts +57 -0
  93. package/dist/steam/config.js +145 -0
  94. package/dist/steam/config.js.map +1 -0
  95. package/dist/steam/electron-cache.d.ts +11 -0
  96. package/dist/steam/electron-cache.js +105 -0
  97. package/dist/steam/electron-cache.js.map +1 -0
  98. package/dist/steam/fuses.d.ts +16 -0
  99. package/dist/steam/fuses.js +75 -0
  100. package/dist/steam/fuses.js.map +1 -0
  101. package/dist/steam/icon-files.d.ts +16 -0
  102. package/dist/steam/icon-files.js +70 -0
  103. package/dist/steam/icon-files.js.map +1 -0
  104. package/dist/steam/image-info.d.ts +16 -0
  105. package/dist/steam/image-info.js +89 -0
  106. package/dist/steam/image-info.js.map +1 -0
  107. package/dist/steam/launch-check.d.ts +12 -0
  108. package/dist/steam/launch-check.js +101 -0
  109. package/dist/steam/launch-check.js.map +1 -0
  110. package/dist/steam/media.d.ts +48 -0
  111. package/dist/steam/media.js +155 -0
  112. package/dist/steam/media.js.map +1 -0
  113. package/dist/steam/package-macos.d.ts +52 -0
  114. package/dist/steam/package-macos.js +268 -0
  115. package/dist/steam/package-macos.js.map +1 -0
  116. package/dist/steam/package-windows.d.ts +23 -0
  117. package/dist/steam/package-windows.js +83 -0
  118. package/dist/steam/package-windows.js.map +1 -0
  119. package/dist/steam/paths.d.ts +35 -0
  120. package/dist/steam/paths.js +44 -0
  121. package/dist/steam/paths.js.map +1 -0
  122. package/dist/steam/playtest-shots.d.ts +18 -0
  123. package/dist/steam/playtest-shots.js +83 -0
  124. package/dist/steam/playtest-shots.js.map +1 -0
  125. package/dist/steam/portal-recipes.d.ts +25 -0
  126. package/dist/steam/portal-recipes.js +61 -0
  127. package/dist/steam/portal-recipes.js.map +1 -0
  128. package/dist/steam/portal.d.ts +58 -0
  129. package/dist/steam/portal.js +340 -0
  130. package/dist/steam/portal.js.map +1 -0
  131. package/dist/steam/raster.d.ts +58 -0
  132. package/dist/steam/raster.js +285 -0
  133. package/dist/steam/raster.js.map +1 -0
  134. package/dist/steam/shell-files.d.ts +17 -0
  135. package/dist/steam/shell-files.js +268 -0
  136. package/dist/steam/shell-files.js.map +1 -0
  137. package/dist/steam/specs.d.ts +61 -0
  138. package/dist/steam/specs.js +103 -0
  139. package/dist/steam/specs.js.map +1 -0
  140. package/dist/steam/steampipe.d.ts +46 -0
  141. package/dist/steam/steampipe.js +170 -0
  142. package/dist/steam/steampipe.js.map +1 -0
  143. package/dist/steam/store-copy.d.ts +88 -0
  144. package/dist/steam/store-copy.js +214 -0
  145. package/dist/steam/store-copy.js.map +1 -0
  146. package/dist/steam/tags.d.ts +9 -0
  147. package/dist/steam/tags.js +52 -0
  148. package/dist/steam/tags.js.map +1 -0
  149. package/dist/steam/trailer.d.ts +34 -0
  150. package/dist/steam/trailer.js +141 -0
  151. package/dist/steam/trailer.js.map +1 -0
  152. package/dist/theme/kernel.d.ts +14 -0
  153. package/dist/theme/kernel.js +15 -0
  154. package/dist/theme/kernel.js.map +1 -0
  155. package/dist/theme/theme-io.js +11 -16
  156. package/dist/theme/theme-io.js.map +1 -1
  157. package/dist/vendor/hud-theme/catalog.js +71 -0
  158. package/dist/vendor/hud-theme/engine/hud/ThemeTokens.js +115 -0
  159. package/dist/{theme/theme-color-math.js → vendor/hud-theme/engine/hud/colorMath.js} +13 -14
  160. package/dist/vendor/hud-theme/engine/hud/decorations.js +179 -0
  161. package/dist/vendor/hud-theme/engine/hud/fonts.js +147 -0
  162. package/dist/vendor/hud-theme/engine/hud/presets.js +80 -0
  163. package/dist/vendor/hud-theme/engine/hud/resolveWorldTheme.js +66 -0
  164. package/dist/vendor/hud-theme/engine/hud/themes/bitmagic.js +29 -0
  165. package/dist/vendor/hud-theme/engine/hud/themes/nexus.js +69 -0
  166. package/dist/vendor/hud-theme/engine/hud/themes/racing.js +57 -0
  167. package/dist/vendor/hud-theme/engine/hud/themes/rift-raider.js +63 -0
  168. package/dist/vendor/hud-theme/engine/hud/themes/simulator.js +55 -0
  169. package/dist/vendor/hud-theme/engine/hud/themes/village-keep.js +108 -0
  170. package/dist/vendor/hud-theme/engine/hud/validateTheme.js +535 -0
  171. package/dist/vendor/hud-theme/index.js +26 -0
  172. package/dist/{theme/theme-merge.js → vendor/hud-theme/merge.js} +0 -1
  173. package/dist/{theme/theme-report.js → vendor/hud-theme/report.js} +8 -9
  174. package/dist/{theme/theme-stored.js → vendor/hud-theme/stored.js} +6 -9
  175. package/dist/{theme/theme-validate.js → vendor/hud-theme/validate-strict.js} +102 -164
  176. package/dist/verify/browser.d.ts +11 -0
  177. package/dist/verify/browser.js +222 -155
  178. package/dist/verify/browser.js.map +1 -1
  179. package/dist/verify/categories.d.ts +1 -1
  180. package/dist/verify/categories.js +1 -0
  181. package/dist/verify/categories.js.map +1 -1
  182. package/dist/verify/classify.d.ts +14 -2
  183. package/dist/verify/classify.js +23 -4
  184. package/dist/verify/classify.js.map +1 -1
  185. package/dist/verify/hud-theme.d.ts +19 -14
  186. package/dist/verify/hud-theme.js +23 -17
  187. package/dist/verify/hud-theme.js.map +1 -1
  188. package/dist/verify/mobile-parity.d.ts +1 -1
  189. package/dist/verify/mobile-parity.js +1 -1
  190. package/dist/verify/start.d.ts +3 -2
  191. package/dist/verify/start.js +1 -1
  192. package/dist/verify/start.js.map +1 -1
  193. package/package.json +8 -6
  194. package/dist/theme/hud-theme-catalog.d.ts +0 -235
  195. package/dist/theme/hud-theme-catalog.js +0 -389
  196. package/dist/theme/hud-theme-catalog.js.map +0 -1
  197. package/dist/theme/theme-color-math.d.ts +0 -21
  198. package/dist/theme/theme-color-math.js.map +0 -1
  199. package/dist/theme/theme-merge.d.ts +0 -36
  200. package/dist/theme/theme-merge.js.map +0 -1
  201. package/dist/theme/theme-report.d.ts +0 -28
  202. package/dist/theme/theme-report.js.map +0 -1
  203. package/dist/theme/theme-stored.d.ts +0 -21
  204. package/dist/theme/theme-stored.js.map +0 -1
  205. package/dist/theme/theme-validate.d.ts +0 -41
  206. package/dist/theme/theme-validate.js.map +0 -1
@@ -0,0 +1,340 @@
1
+ /**
2
+ * The Steamworks website, driven in a Chrome window the creator logs in to.
3
+ *
4
+ * Valve has no API for store pages, graphical assets or most app settings — only the website. So
5
+ * `bitmagic steam portal open` starts the creator's own Chrome on a dedicated profile under
6
+ * `~/.bitmagic/steam-portal/` (their everyday profile is never touched), the CREATOR logs in
7
+ * there, and every later `steam portal` command attaches to that same window over the DevTools
8
+ * protocol to look at the page, fill a field, upload a file or click a button. The window outlives
9
+ * each command, so a login lasts across a whole session, and the profile keeps it between them.
10
+ *
11
+ * Two lines this module will not cross, whatever the caller asks:
12
+ * - credentials: it never types into a password field or a login page — logging in, Steam Guard
13
+ * codes and payment are the creator's;
14
+ * - commitments: a click on a button that submits for review, publishes, releases, pays or
15
+ * deletes is refused unless the caller passes `approved`, which the skill reserves for after
16
+ * the creator has said yes to that specific step.
17
+ *
18
+ * Navigation is limited to Valve's own sites.
19
+ */
20
+ import { spawn } from 'child_process';
21
+ import * as fs from 'fs';
22
+ import * as os from 'os';
23
+ import * as path from 'path';
24
+ import { chromium } from 'playwright-core';
25
+ import { readJsonFile, writeJsonAtomic } from '../atomic-json.js';
26
+ import { CliError } from '../errors.js';
27
+ export const STEAMWORKS_HOME = 'https://partner.steamgames.com/';
28
+ const VALVE_HOSTS = [
29
+ 'partner.steamgames.com',
30
+ 'store.steampowered.com',
31
+ 'steamcommunity.com',
32
+ 'help.steampowered.com',
33
+ 'login.steampowered.com',
34
+ 'checkout.steampowered.com',
35
+ ];
36
+ export function portalDir(baseDir = path.join(os.homedir(), '.bitmagic')) {
37
+ return path.join(baseDir, 'steam-portal');
38
+ }
39
+ function sessionPath(dir) {
40
+ return path.join(dir, 'session.json');
41
+ }
42
+ function readSession(dir) {
43
+ const parsed = readJsonFile(sessionPath(dir));
44
+ if (parsed === null || typeof parsed.port !== 'number' || typeof parsed.pid !== 'number')
45
+ return null;
46
+ return { port: parsed.port, pid: parsed.pid, startedAt: String(parsed.startedAt ?? '') };
47
+ }
48
+ export function isValveUrl(url) {
49
+ try {
50
+ const host = new URL(url).hostname;
51
+ return VALVE_HOSTS.some((allowed) => host === allowed || host.endsWith(`.${allowed}`));
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ /** The system Chrome binary for this OS, or null when none is installed where Chrome installs. */
58
+ export function findChromeExecutable(env = process.env) {
59
+ const candidates = [];
60
+ if (process.platform === 'darwin') {
61
+ candidates.push('/Applications/Google Chrome.app/Contents/MacOS/Google Chrome');
62
+ candidates.push(path.join(os.homedir(), 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'));
63
+ }
64
+ else if (process.platform === 'win32') {
65
+ for (const base of [env.PROGRAMFILES, env['PROGRAMFILES(X86)'], env.LOCALAPPDATA]) {
66
+ if (base)
67
+ candidates.push(path.join(base, 'Google', 'Chrome', 'Application', 'chrome.exe'));
68
+ }
69
+ }
70
+ else {
71
+ candidates.push('/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/opt/google/chrome/chrome');
72
+ }
73
+ return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;
74
+ }
75
+ async function endpointAlive(port) {
76
+ try {
77
+ const response = await fetch(`http://127.0.0.1:${port}/json/version`, { signal: AbortSignal.timeout(1500) });
78
+ return response.ok;
79
+ }
80
+ catch {
81
+ return false;
82
+ }
83
+ }
84
+ /** Chrome writes the port it chose for `--remote-debugging-port=0` into this file. */
85
+ async function waitForDevToolsPort(profileDir, timeoutMs) {
86
+ const file = path.join(profileDir, 'DevToolsActivePort');
87
+ const deadline = Date.now() + timeoutMs;
88
+ while (Date.now() < deadline) {
89
+ try {
90
+ const port = Number(fs.readFileSync(file, 'utf-8').split('\n')[0]);
91
+ if (Number.isInteger(port) && port > 0 && await endpointAlive(port))
92
+ return port;
93
+ }
94
+ catch {
95
+ // Not written yet.
96
+ }
97
+ await new Promise((resolve) => setTimeout(resolve, 250));
98
+ }
99
+ throw new CliError('Chrome started but did not open its DevTools port. Close any Chrome window using the Steam profile and try again.');
100
+ }
101
+ /** Start the Steamworks window, or reuse the one already open. */
102
+ export async function openPortal(options = {}) {
103
+ const dir = options.dir ?? portalDir();
104
+ const existing = readSession(dir);
105
+ if (existing !== null && await endpointAlive(existing.port)) {
106
+ if (options.url !== undefined) {
107
+ const { browser, page } = await attachPortal({ dir });
108
+ try {
109
+ await page.goto(options.url, { waitUntil: 'domcontentloaded' });
110
+ await page.bringToFront();
111
+ }
112
+ finally {
113
+ await detach(browser);
114
+ }
115
+ }
116
+ return { reused: true, port: existing.port };
117
+ }
118
+ const chrome = findChromeExecutable();
119
+ if (chrome === null) {
120
+ throw new CliError('`bitmagic steam portal` drives Google Chrome, and none is installed. Install it from https://www.google.com/chrome/.', 3);
121
+ }
122
+ const profileDir = path.join(dir, 'profile');
123
+ fs.mkdirSync(profileDir, { recursive: true });
124
+ fs.rmSync(path.join(profileDir, 'DevToolsActivePort'), { force: true });
125
+ const child = spawn(chrome, [
126
+ `--user-data-dir=${profileDir}`,
127
+ '--remote-debugging-port=0',
128
+ '--remote-debugging-address=127.0.0.1',
129
+ '--no-first-run',
130
+ '--no-default-browser-check',
131
+ '--disable-features=ChromeWhatsNewUI',
132
+ options.url ?? STEAMWORKS_HOME,
133
+ ], { detached: true, stdio: 'ignore' });
134
+ child.unref();
135
+ const port = await waitForDevToolsPort(profileDir, 20_000);
136
+ writeJsonAtomic(sessionPath(dir), { port, pid: child.pid ?? 0, startedAt: new Date().toISOString() });
137
+ return { reused: false, port };
138
+ }
139
+ /** Disconnect from the window without closing it. */
140
+ export async function detach(browser) {
141
+ try {
142
+ await browser.close();
143
+ }
144
+ catch {
145
+ // Already gone.
146
+ }
147
+ }
148
+ /** Attach to the open window and pick the tab to work in: the newest Valve tab, else any tab. */
149
+ export async function attachPortal(options = {}) {
150
+ const dir = options.dir ?? portalDir();
151
+ const session = readSession(dir);
152
+ if (session === null || !await endpointAlive(session.port)) {
153
+ throw new CliError('No Steamworks window is open. Run `bitmagic steam portal open` and log in there.', 3);
154
+ }
155
+ const browser = await chromium.connectOverCDP(`http://127.0.0.1:${session.port}`);
156
+ const context = browser.contexts()[0];
157
+ const pages = (context?.pages() ?? []).filter((page) => !page.url().startsWith('devtools://'));
158
+ const valve = pages.filter((page) => isValveUrl(page.url()));
159
+ const page = valve[valve.length - 1] ?? pages[pages.length - 1] ?? await context?.newPage();
160
+ if (page === undefined) {
161
+ await detach(browser);
162
+ throw new CliError('The Steamworks window has no tab to work in.');
163
+ }
164
+ return { browser, page };
165
+ }
166
+ /** Close the window and forget the session. The profile (and its login) stays for next time. */
167
+ export async function closePortal(options = {}) {
168
+ const dir = options.dir ?? portalDir();
169
+ const session = readSession(dir);
170
+ fs.rmSync(sessionPath(dir), { force: true });
171
+ if (session === null || !await endpointAlive(session.port))
172
+ return false;
173
+ const browser = await chromium.connectOverCDP(`http://127.0.0.1:${session.port}`);
174
+ try {
175
+ const cdp = await browser.newBrowserCDPSession();
176
+ await cdp.send('Browser.close');
177
+ }
178
+ catch {
179
+ // Closing tears the connection down under us.
180
+ }
181
+ return true;
182
+ }
183
+ /**
184
+ * Number every control on the page (`data-bm-ref`), and describe each the way a person would
185
+ * name it — its label, the table row it sits in, its placeholder, its name. Runs in the page.
186
+ */
187
+ const LOOK_SCRIPT = `(() => {
188
+ const clean = (s) => (s || '').replace(/\\s+/g, ' ').trim();
189
+ const short = (s, n) => { s = clean(s); return s.length > n ? s.slice(0, n - 1) + '…' : s; };
190
+ const visible = (el) => {
191
+ const r = el.getBoundingClientRect();
192
+ const cs = getComputedStyle(el);
193
+ return r.width > 0 && r.height > 0 && cs.visibility !== 'hidden' && cs.display !== 'none';
194
+ };
195
+ const labelOf = (el) => {
196
+ const aria = el.getAttribute('aria-label');
197
+ if (aria) return aria;
198
+ const by = el.getAttribute('aria-labelledby');
199
+ if (by) { const t = by.split(' ').map((id) => document.getElementById(id)?.innerText || '').join(' '); if (clean(t)) return t; }
200
+ if (el.labels && el.labels.length) return Array.from(el.labels).map((l) => l.innerText).join(' ');
201
+ const tag = el.tagName.toLowerCase();
202
+ if (tag === 'button' || tag === 'a' || el.getAttribute('role') === 'button' || el.getAttribute('role') === 'tab') {
203
+ const t = el.innerText || el.value || el.title || el.getAttribute('alt');
204
+ if (clean(t)) return t;
205
+ const img = el.querySelector('img[alt]');
206
+ if (img) return img.getAttribute('alt');
207
+ }
208
+ if (el.placeholder) return el.placeholder;
209
+ const row = el.closest('tr');
210
+ if (row && row.cells && row.cells.length > 1 && !row.cells[0].contains(el)) return row.cells[0].innerText;
211
+ let prev = el.previousElementSibling;
212
+ for (let i = 0; prev && i < 3; i++, prev = prev.previousElementSibling) { if (clean(prev.innerText)) return prev.innerText; }
213
+ const parentText = el.parentElement ? clean(el.parentElement.innerText) : '';
214
+ if (parentText && parentText.length < 120) return parentText;
215
+ return el.name || el.id || el.title || '';
216
+ };
217
+ document.querySelectorAll('[data-bm-ref]').forEach((el) => el.removeAttribute('data-bm-ref'));
218
+ const out = [];
219
+ let n = 0;
220
+ const selector = 'a[href], button, input, textarea, select, [role=button], [role=checkbox], [role=tab], [role=menuitem], [contenteditable="true"]';
221
+ for (const el of document.querySelectorAll(selector)) {
222
+ const tag = el.tagName.toLowerCase();
223
+ const type = (el.getAttribute('type') || '').toLowerCase();
224
+ if (type === 'hidden') continue;
225
+ if (!visible(el) && type !== 'file') continue;
226
+ const ref = 'e' + (++n);
227
+ el.setAttribute('data-bm-ref', ref);
228
+ const role = tag === 'input' ? (type || 'text') : tag === 'a' ? 'link' : (el.getAttribute('role') || tag);
229
+ const entry = { ref, role, label: short(labelOf(el), 90) };
230
+ if (role === 'link' && !entry.label) { el.removeAttribute('data-bm-ref'); n--; continue; }
231
+ if (el.name) entry.label += entry.label ? ' [' + el.name + ']' : el.name;
232
+ if (tag === 'textarea' || (tag === 'input' && !['checkbox', 'radio', 'file', 'submit', 'button', 'image'].includes(type))) entry.value = short(el.value, 120);
233
+ if (tag === 'select') entry.value = short(el.selectedOptions && el.selectedOptions[0] ? el.selectedOptions[0].text : '', 80);
234
+ if (type === 'checkbox' || type === 'radio') entry.checked = el.checked;
235
+ if (el.getAttribute('role') === 'checkbox') entry.checked = el.getAttribute('aria-checked') === 'true';
236
+ if (el.disabled) entry.disabled = true;
237
+ out.push(entry);
238
+ if (n >= 600) break;
239
+ }
240
+ const headings = Array.from(document.querySelectorAll('h1, h2, h3')).filter(visible).map((h) => short(h.innerText, 100)).filter(Boolean).slice(0, 60);
241
+ const notices = Array.from(document.querySelectorAll('.error, .errors, .warning, .notice, .success, [role=alert], .formErrors, .msg')).filter(visible).map((e) => short(e.innerText, 300)).filter(Boolean).slice(0, 12);
242
+ const loggedIn = !!document.querySelector('a[href*="logout"], a[href*="Logout"], form[action*="logout"]');
243
+ return { url: location.href, title: document.title, headings, elements: out, notices, loggedIn };
244
+ })()`;
245
+ export async function lookAtPage(page) {
246
+ await page.waitForLoadState('domcontentloaded');
247
+ return page.evaluate(LOOK_SCRIPT);
248
+ }
249
+ /** The visible text of the page, for reading what it says. */
250
+ export async function pageText(page, maxChars = 20_000) {
251
+ const text = await page.evaluate('document.body ? document.body.innerText : ""');
252
+ return text.length > maxChars ? `${text.slice(0, maxChars)}\n…` : text;
253
+ }
254
+ // ============================================================================
255
+ // Acting on it
256
+ // ============================================================================
257
+ /**
258
+ * Button text that commits the creator to something: a review submission, a publish, a release, a
259
+ * payment, a deletion. Matched on the element's own label.
260
+ */
261
+ const COMMITTING = /\b(submit|publish|release|purchase|pay|buy|checkout|delete|remove|retire|set build live|mark as ready|ready for review|agree|accept)\b/i;
262
+ export function isCommittingLabel(label) {
263
+ return COMMITTING.test(label);
264
+ }
265
+ function isLoginUrl(url) {
266
+ return /\/login\b|\/signin\b|openid|\/twofactor/i.test(url);
267
+ }
268
+ export async function resolveRef(page, ref) {
269
+ if (!/^e\d+$/.test(ref))
270
+ throw new CliError(`"${ref}" is not an element ref — run \`bitmagic steam portal look\` and use one of its e-numbers.`);
271
+ const locator = page.locator(`[data-bm-ref="${ref}"]`);
272
+ if (await locator.count() === 0) {
273
+ throw new CliError(`${ref} is not on the page any more (it changed since the last look). Run \`bitmagic steam portal look\` again.`);
274
+ }
275
+ return locator.first();
276
+ }
277
+ async function labelOfLocator(locator) {
278
+ return locator.evaluate((el) => {
279
+ const e = el;
280
+ return [e.innerText, e.getAttribute('aria-label'), e.value, e.getAttribute('title')].filter(Boolean).join(' ');
281
+ });
282
+ }
283
+ export async function clickElement(page, ref, options = {}) {
284
+ const locator = await resolveRef(page, ref);
285
+ const label = (await labelOfLocator(locator)).replace(/\s+/g, ' ').trim();
286
+ if (isCommittingLabel(label) && options.approved !== true) {
287
+ throw new CliError(`"${label}" commits the creator to something (a submission, a publish, a payment or a deletion). `
288
+ + 'Ask the creator, and only after they say yes to this exact step run the click again with --approved.', 6);
289
+ }
290
+ await locator.scrollIntoViewIfNeeded();
291
+ await locator.click();
292
+ await page.waitForLoadState('domcontentloaded').catch(() => undefined);
293
+ return label;
294
+ }
295
+ export async function fillElement(page, ref, value) {
296
+ if (isLoginUrl(page.url())) {
297
+ throw new CliError('This is a login page. Logging in is the creator\'s to do, in the window — nothing is typed here.', 6);
298
+ }
299
+ const locator = await resolveRef(page, ref);
300
+ const type = (await locator.getAttribute('type'))?.toLowerCase();
301
+ if (type === 'password') {
302
+ throw new CliError('That is a password field. Passwords are the creator\'s to type, never the agent\'s.', 6);
303
+ }
304
+ await locator.scrollIntoViewIfNeeded();
305
+ const editable = await locator.getAttribute('contenteditable');
306
+ if (editable === 'true') {
307
+ await locator.click();
308
+ await page.keyboard.press(process.platform === 'darwin' ? 'Meta+A' : 'Control+A');
309
+ await page.keyboard.insertText(value);
310
+ }
311
+ else {
312
+ await locator.fill(value);
313
+ }
314
+ }
315
+ export async function uploadToElement(page, ref, files) {
316
+ const locator = await resolveRef(page, ref);
317
+ if ((await locator.getAttribute('type'))?.toLowerCase() !== 'file') {
318
+ throw new CliError(`${ref} is not a file input. \`look\` lists file inputs with role "file".`);
319
+ }
320
+ for (const file of files) {
321
+ if (!fs.existsSync(file))
322
+ throw new CliError(`No file at ${file}.`);
323
+ }
324
+ await locator.setInputFiles([...files]);
325
+ }
326
+ export async function selectOption(page, ref, option) {
327
+ const locator = await resolveRef(page, ref);
328
+ return locator.selectOption({ label: option }).catch(() => locator.selectOption(option));
329
+ }
330
+ export async function setChecked(page, ref, checked) {
331
+ const locator = await resolveRef(page, ref);
332
+ await locator.setChecked(checked);
333
+ }
334
+ export async function gotoUrl(page, url) {
335
+ const target = /^https?:\/\//.test(url) ? url : new URL(url.replace(/^\//, ''), STEAMWORKS_HOME).toString();
336
+ if (!isValveUrl(target))
337
+ throw new CliError(`${target} is not a Valve site; the Steamworks window only goes to Steamworks and the Steam store.`);
338
+ await page.goto(target, { waitUntil: 'domcontentloaded' });
339
+ }
340
+ //# sourceMappingURL=portal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/steam/portal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { SizedPng } from './icon-files.js';
2
+ export declare function dataUrlFor(bytes: Buffer): string;
3
+ export interface KeyOptions {
4
+ /** The background colour to remove, `#rrggbb`; `auto` reads it off the image's border. */
5
+ keyColor: string;
6
+ /** Colour distance (0-441) at or below which a pixel is fully transparent. */
7
+ tolerance: number;
8
+ /** Width of the soft edge above `tolerance`, in the same units. */
9
+ softness: number;
10
+ }
11
+ export interface KeyedImage {
12
+ png: Buffer;
13
+ width: number;
14
+ height: number;
15
+ /** The colour actually removed, `#rrggbb`. */
16
+ keyColor: string;
17
+ }
18
+ export declare class RasterSession {
19
+ private readonly browser;
20
+ private readonly page;
21
+ private constructor();
22
+ static open(command: string): Promise<RasterSession>;
23
+ close(): Promise<void>;
24
+ /**
25
+ * Lay `html` out at exactly `width`x`height` CSS pixels and capture it. `transparent` keeps the
26
+ * page background clear (the library logo); otherwise the page paints black under the art.
27
+ */
28
+ render(html: string, width: number, height: number, options?: {
29
+ transparent?: boolean;
30
+ format?: 'png' | 'jpeg';
31
+ }): Promise<Buffer>;
32
+ /** Decode any supported image and re-encode it as PNG, with its size. */
33
+ toPng(bytes: Buffer): Promise<{
34
+ png: Buffer;
35
+ width: number;
36
+ height: number;
37
+ }>;
38
+ /**
39
+ * Remove a flat background colour and trim to what is left, plus `pad` pixels. Partially
40
+ * keyed edge pixels are un-mixed from the key colour (c = (observed - (1-a)·key) / a), so an
41
+ * anti-aliased outline keeps its own colour instead of a green or magenta fringe.
42
+ */
43
+ keyAndTrim(bytes: Buffer, options: KeyOptions & {
44
+ pad?: number;
45
+ }): Promise<KeyedImage>;
46
+ /** Trim fully transparent margins off a PNG, keeping `pad` pixels. */
47
+ trimTransparent(png: Buffer, pad?: number): Promise<{
48
+ png: Buffer;
49
+ width: number;
50
+ height: number;
51
+ }>;
52
+ /**
53
+ * Square PNGs of `bytes` at each size, cover-cropped to the centre (or to `focus`, as fractions).
54
+ * Downscaling halves step by step before the last draw — one big drawImage from 1024 to 16 would
55
+ * alias badly even with high-quality smoothing.
56
+ */
57
+ squareIcons(bytes: Buffer, sizes: readonly number[], focus?: readonly [number, number]): Promise<SizedPng[]>;
58
+ }