@xbrowser/cli 0.14.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 (55) hide show
  1. package/README.md +858 -0
  2. package/dist/admin-6UTU2RZ2.js +281 -0
  3. package/dist/admin-MDGF4CET.js +285 -0
  4. package/dist/admin-RPJJ5CAF.js +282 -0
  5. package/dist/browser-GWBH6OJK.js +46 -0
  6. package/dist/browser-I2HJZ7IP.js +48 -0
  7. package/dist/browser-R7B255ML.js +46 -0
  8. package/dist/chunk-2ONMTDLK.js +2050 -0
  9. package/dist/chunk-3RG5ZIWI.js +10 -0
  10. package/dist/chunk-43VX3TYN.js +83 -0
  11. package/dist/chunk-ATFTAKMN.js +267 -0
  12. package/dist/chunk-DESA2KMG.js +77 -0
  13. package/dist/chunk-DTJRVA76.js +206 -0
  14. package/dist/chunk-F3ZWFCJJ.js +2051 -0
  15. package/dist/chunk-FF5WHQHN.js +135 -0
  16. package/dist/chunk-HINTG75P.js +77 -0
  17. package/dist/chunk-KDYXFLAC.js +1503 -0
  18. package/dist/chunk-KTSQU4QT.js +29 -0
  19. package/dist/chunk-L53IDAWK.js +68 -0
  20. package/dist/chunk-M7CMBPCA.js +100 -0
  21. package/dist/chunk-NFGO7J2I.js +29 -0
  22. package/dist/chunk-OLB6UJ25.js +438 -0
  23. package/dist/chunk-OPRXFZVE.js +52 -0
  24. package/dist/chunk-RS6YYWTK.js +685 -0
  25. package/dist/chunk-VEDJ5XSQ.js +196 -0
  26. package/dist/chunk-VEKPHQBR.js +47 -0
  27. package/dist/chunk-VUJDJCIN.js +437 -0
  28. package/dist/chunk-YEN2ODUI.js +14 -0
  29. package/dist/chunk-ZZ2TFWIV.js +1382 -0
  30. package/dist/cli.js +11012 -0
  31. package/dist/convert-4DUWZIKH.js +205 -0
  32. package/dist/convert-EKQVHKB4.js +11 -0
  33. package/dist/daemon-client-3IJD6X4B.js +59 -0
  34. package/dist/daemon-client-GX2UYIW4.js +241 -0
  35. package/dist/daemon-client-XWSSQBEA.js +58 -0
  36. package/dist/daemon-main.js +9910 -0
  37. package/dist/extract-EGRXZSSK.js +67 -0
  38. package/dist/extract-JUOQQX4V.js +11 -0
  39. package/dist/filter-OLAE26HN.js +51 -0
  40. package/dist/filter-VID2GGZ7.js +9 -0
  41. package/dist/human-interaction-QPHNDD76.js +8 -0
  42. package/dist/index.d.ts +2313 -0
  43. package/dist/index.js +13839 -0
  44. package/dist/marketplace-FCVN5OTZ.js +706 -0
  45. package/dist/marketplace-FPT5YLKB.js +351 -0
  46. package/dist/marketplace-W545W4FR.js +706 -0
  47. package/dist/network-store-2S5HATEV.js +194 -0
  48. package/dist/network-store-BN6QEZ7R.js +196 -0
  49. package/dist/network-store-YAF5OIBH.js +12 -0
  50. package/dist/parse-action-dsl-DRSPBALP.js +72 -0
  51. package/dist/parse-action-dsl-T3DYC33D.js +74 -0
  52. package/dist/proxy-WKGUCH2C.js +7 -0
  53. package/dist/session-recorder-ILSSV2UC.js +6 -0
  54. package/dist/session-recorder-XET3DNML.js +7 -0
  55. package/package.json +111 -0
@@ -0,0 +1,351 @@
1
+ import {
2
+ createTarball
3
+ } from "./chunk-OLB6UJ25.js";
4
+ import {
5
+ loadAuth,
6
+ saveAuth
7
+ } from "./chunk-KTSQU4QT.js";
8
+ import {
9
+ ensureProxyFetch
10
+ } from "./chunk-VEKPHQBR.js";
11
+ import {
12
+ getRegistryUrl
13
+ } from "./chunk-M7CMBPCA.js";
14
+ import "./chunk-3RG5ZIWI.js";
15
+
16
+ // src/plugin/builtins/marketplace.ts
17
+ import { z } from "zod";
18
+ import { createInterface } from "readline";
19
+ var marketResult = z.object({
20
+ success: z.boolean(),
21
+ data: z.record(z.unknown()).optional(),
22
+ message: z.string().optional()
23
+ });
24
+ function prompt(rl, question, hidden = false) {
25
+ return new Promise((resolve) => {
26
+ if (hidden) {
27
+ const stdin = process.stdin;
28
+ const wasRaw = stdin.isRaw;
29
+ if (stdin.isTTY) stdin.setRawMode(true);
30
+ let input = "";
31
+ process.stdout.write(question);
32
+ const onData = (char) => {
33
+ const c = char.toString();
34
+ switch (c) {
35
+ case "\n":
36
+ case "\r":
37
+ if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
38
+ stdin.removeListener("data", onData);
39
+ console.log();
40
+ resolve(input);
41
+ break;
42
+ case "":
43
+ process.exit();
44
+ break;
45
+ case "\x7F":
46
+ input = input.slice(0, -1);
47
+ break;
48
+ default:
49
+ input += c;
50
+ process.stdout.write("*");
51
+ }
52
+ };
53
+ stdin.on("data", onData);
54
+ } else {
55
+ rl.question(question, resolve);
56
+ }
57
+ });
58
+ }
59
+ function setupMarketplacePlugin(xcli) {
60
+ const site = xcli.createSite({
61
+ name: "marketplace",
62
+ url: "https://xbrowser.dev",
63
+ description: "xbrowser marketplace \u2014 publish, login, register, whoami, logout"
64
+ });
65
+ const cmd = (name, config) => site.command(name, config);
66
+ cmd("publish", {
67
+ description: "Publish a plugin to the marketplace",
68
+ scope: "global",
69
+ parameters: z.object({
70
+ dir: z.string().optional().describe("Plugin directory (defaults to cwd)"),
71
+ registry: z.string().optional().describe("Custom registry URL"),
72
+ dryRun: z.boolean().optional().default(false).describe("Validate without publishing")
73
+ }),
74
+ result: marketResult,
75
+ handler: async (params) => {
76
+ const pluginDir = params.dir || process.cwd();
77
+ const auth = loadAuth();
78
+ if (!auth?.token) {
79
+ return { success: false, message: "Not logged in. Run: xbrowser marketplace login" };
80
+ }
81
+ const registryUrl = getRegistryUrl(params, auth.registry);
82
+ await ensureProxyFetch();
83
+ try {
84
+ const result = await createTarball(pluginDir, {
85
+ registry: registryUrl,
86
+ token: auth.token,
87
+ dryRun: !!params.dryRun
88
+ });
89
+ if (params.dryRun) {
90
+ const lines = [
91
+ "Dry run - validation passed:",
92
+ ` Name: ${result.name}`,
93
+ ` Version: ${result.version}`,
94
+ ` Slug: ${result.slug}`,
95
+ ` Description: ${result.description}`
96
+ ];
97
+ if (result.commands?.length) lines.push(` Commands: ${result.commands.join(", ")}`);
98
+ if (result.tags?.length) lines.push(` Tags: ${result.tags.join(", ")}`);
99
+ if (result.sites?.length) lines.push(` Sites: ${result.sites.join(", ")}`);
100
+ if (result.commandsDocs?.length) {
101
+ lines.push(" Command Docs:");
102
+ for (const c of result.commandsDocs) {
103
+ lines.push(` ${c.name}: ${c.description}`);
104
+ for (const p of c.parameters) {
105
+ const req = p.required ? "required" : "optional";
106
+ const def = p.default !== void 0 ? `, default: ${JSON.stringify(p.default)}` : "";
107
+ lines.push(` - ${p.name} (${p.type}, ${req}${def}): ${p.description}`);
108
+ }
109
+ if (c.examples?.length) {
110
+ for (const ex of c.examples) lines.push(` example: ${ex.cmd} \u2014 ${ex.description}`);
111
+ }
112
+ }
113
+ }
114
+ if (result.readme) {
115
+ const preview = result.readme.slice(0, 200).replace(/\n/g, "\\n");
116
+ lines.push(` README: ${preview.length < result.readme.length ? preview + "..." : preview}`);
117
+ }
118
+ lines.push(` Files: ${result.fileCount} files, ${(result.size / 1024).toFixed(1)}KB`);
119
+ return { success: true, data: { text: lines.join("\n"), name: result.name, version: result.version, slug: result.slug } };
120
+ }
121
+ const response = await fetch(`${registryUrl}/api/plugins/publish`, {
122
+ method: "POST",
123
+ headers: { Authorization: `Bearer ${auth.token}` },
124
+ body: result.formData
125
+ });
126
+ if (!response.ok) {
127
+ const errBody = await response.json().catch(() => ({}));
128
+ const errMsg = errBody.error || response.statusText;
129
+ if (errMsg.includes("R2 storage")) {
130
+ return { success: false, message: "R2 storage unavailable. Cannot publish plugin without source code.\n Please configure R2 bucket or use --storage local" };
131
+ }
132
+ return { success: false, message: `Publish failed (${response.status}): ${errMsg}` };
133
+ }
134
+ const body = await response.json();
135
+ const slug = body.data?.slug || result.slug;
136
+ const text = `
137
+ Published: ${result.name}@${result.version}
138
+ URL: ${registryUrl}/plugins/${slug}`;
139
+ return { success: true, data: { ok: true, name: result.name, version: result.version, slug, text } };
140
+ } catch (e) {
141
+ const msg = e instanceof Error ? e.message : String(e);
142
+ const cause = e instanceof Error && e.cause instanceof Error ? ` (${e.cause.message})` : "";
143
+ return { success: false, message: `Error: ${msg}${cause}` };
144
+ }
145
+ }
146
+ });
147
+ cmd("login", {
148
+ description: "Login to the marketplace",
149
+ scope: "global",
150
+ parameters: z.object({
151
+ email: z.string().optional().describe("Email (skip interactive prompt)"),
152
+ password: z.string().optional().describe("Password (skip interactive prompt)"),
153
+ token: z.string().optional().describe("Auth token (skip interactive login)"),
154
+ registry: z.string().optional().describe("Custom registry URL")
155
+ }),
156
+ result: marketResult,
157
+ handler: async (params) => {
158
+ const registryUrl = getRegistryUrl(params);
159
+ await ensureProxyFetch();
160
+ if (params.token) {
161
+ saveAuth({ token: params.token, registry: registryUrl });
162
+ const auth = loadAuth();
163
+ let username = "unknown";
164
+ if (auth?.token) {
165
+ try {
166
+ const resp = await fetch(`${registryUrl}/api/auth/verify`, {
167
+ headers: { Authorization: `Bearer ${auth.token}` }
168
+ });
169
+ if (resp.ok) {
170
+ const body = await resp.json();
171
+ username = body.data?.username || body.data?.email || "unknown";
172
+ }
173
+ } catch {
174
+ }
175
+ }
176
+ return { success: true, data: { ok: true, text: `Token saved.
177
+ Logged in as ${username}` } };
178
+ }
179
+ let email = params.email;
180
+ let password = params.password;
181
+ if (!email || !password) {
182
+ console.log(`
183
+ Login to ${registryUrl}
184
+ `);
185
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
186
+ if (!email) email = await prompt(rl, "Email: ");
187
+ if (!password) password = await prompt(rl, "Password: ", true);
188
+ rl.close();
189
+ console.log();
190
+ }
191
+ if (!email || !password) {
192
+ return { success: false, message: "Email and password are required" };
193
+ }
194
+ try {
195
+ const res = await fetch(`${registryUrl}/api/auth/login`, {
196
+ method: "POST",
197
+ headers: { "Content-Type": "application/json" },
198
+ body: JSON.stringify({ email, password })
199
+ });
200
+ if (!res.ok) {
201
+ const errBody = await res.json().catch(() => ({}));
202
+ return { success: false, message: `Login failed: ${errBody.error || errBody.message || res.statusText}` };
203
+ }
204
+ const body = await res.json();
205
+ const result = body.data;
206
+ if (!result?.token) {
207
+ return { success: false, message: "No token received from server" };
208
+ }
209
+ saveAuth({ token: result.token, registry: registryUrl });
210
+ const username = result.profile?.username || result.profile?.email || "unknown";
211
+ return { success: true, data: { ok: true, text: `Logged in as ${username}` } };
212
+ } catch (e) {
213
+ return { success: false, message: e instanceof Error ? e.message : String(e) };
214
+ }
215
+ }
216
+ });
217
+ cmd("register", {
218
+ description: "Register a new marketplace account",
219
+ scope: "global",
220
+ parameters: z.object({
221
+ username: z.string().optional().describe("Username (2-50 chars)"),
222
+ email: z.string().optional().describe("Email"),
223
+ password: z.string().optional().describe("Password (min 6 chars)"),
224
+ registry: z.string().optional().describe("Custom registry URL")
225
+ }),
226
+ result: marketResult,
227
+ handler: async (params) => {
228
+ const registryUrl = getRegistryUrl(params);
229
+ await ensureProxyFetch();
230
+ let username = params.username;
231
+ let email = params.email;
232
+ let password = params.password;
233
+ const needsInteractive = !username || !email || !password;
234
+ let confirmPassword = "";
235
+ if (needsInteractive) {
236
+ console.log("\nRegister for xbrowser developer account\n");
237
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
238
+ if (!username) username = await prompt(rl, "Username (2-50 chars): ");
239
+ if (!email) email = await prompt(rl, "Email: ");
240
+ if (!password) password = await prompt(rl, "Password (min 6 chars): ", true);
241
+ confirmPassword = await prompt(rl, "Confirm password: ", true);
242
+ rl.close();
243
+ }
244
+ if (!username || username.length < 2 || username.length > 50) {
245
+ return { success: false, message: "Username must be 2-50 characters" };
246
+ }
247
+ if (!email || !email.includes("@")) {
248
+ return { success: false, message: "Invalid email" };
249
+ }
250
+ if (!password || password.length < 6) {
251
+ return { success: false, message: "Password must be at least 6 characters" };
252
+ }
253
+ if (needsInteractive && password !== confirmPassword) {
254
+ return { success: false, message: "Passwords do not match" };
255
+ }
256
+ try {
257
+ const regRes = await fetch(`${registryUrl}/api/auth/register`, {
258
+ method: "POST",
259
+ headers: { "Content-Type": "application/json" },
260
+ body: JSON.stringify({ username, email, password })
261
+ });
262
+ if (!regRes.ok) {
263
+ const errBody = await regRes.json().catch(() => ({}));
264
+ return { success: false, message: `Registration failed: ${errBody.error || errBody.message || regRes.statusText}` };
265
+ }
266
+ const loginRes = await fetch(`${registryUrl}/api/auth/login`, {
267
+ method: "POST",
268
+ headers: { "Content-Type": "application/json" },
269
+ body: JSON.stringify({ email, password })
270
+ });
271
+ if (!loginRes.ok) {
272
+ return { success: false, message: "Registration succeeded but auto-login failed. Run: xbrowser marketplace login" };
273
+ }
274
+ const loginBody = await loginRes.json();
275
+ const token = loginBody.data?.token;
276
+ const profile = loginBody.data?.profile;
277
+ if (!token) {
278
+ return { success: false, message: "Registration succeeded but no token received. Run: xbrowser marketplace login" };
279
+ }
280
+ saveAuth({ token, registry: registryUrl });
281
+ const text = [
282
+ "\n Registered successfully!",
283
+ ` Username: ${profile?.username || username}`,
284
+ ` Email: ${profile?.email || email}`,
285
+ ` Saved to ~/.xbrowser/auth.json`,
286
+ "\nYou can now publish plugins with: xbrowser marketplace publish"
287
+ ].join("\n");
288
+ return { success: true, data: { ok: true, username: profile?.username, text } };
289
+ } catch (e) {
290
+ return { success: false, message: e instanceof Error ? e.message : String(e) };
291
+ }
292
+ }
293
+ });
294
+ cmd("whoami", {
295
+ description: "Show current logged-in user",
296
+ scope: "global",
297
+ parameters: z.object({
298
+ registry: z.string().optional().describe("Custom registry URL")
299
+ }),
300
+ result: marketResult,
301
+ handler: async (params) => {
302
+ const auth = loadAuth();
303
+ if (!auth?.token) {
304
+ return { success: false, message: "Not logged in. Run: xbrowser marketplace login" };
305
+ }
306
+ const registryUrl = getRegistryUrl(params, auth.registry);
307
+ await ensureProxyFetch();
308
+ try {
309
+ const resp = await fetch(`${registryUrl}/api/auth/verify`, {
310
+ headers: { Authorization: `Bearer ${auth.token}` }
311
+ });
312
+ if (!resp.ok) {
313
+ return { success: false, message: "Token invalid or expired. Run: xbrowser marketplace login" };
314
+ }
315
+ const body = await resp.json();
316
+ return {
317
+ success: true,
318
+ data: {
319
+ username: body.data?.username,
320
+ email: body.data?.email,
321
+ role: body.data?.role,
322
+ registry: registryUrl,
323
+ text: `Username: ${body.data?.username || "unknown"}
324
+ Email: ${body.data?.email || "unknown"}
325
+ Role: ${body.data?.role || "user"}
326
+ Registry: ${registryUrl}`
327
+ }
328
+ };
329
+ } catch (e) {
330
+ return { success: false, message: e instanceof Error ? e.message : String(e) };
331
+ }
332
+ }
333
+ });
334
+ cmd("logout", {
335
+ description: "Logout from the marketplace",
336
+ scope: "global",
337
+ parameters: z.object({}),
338
+ result: marketResult,
339
+ handler: async (_params) => {
340
+ const auth = loadAuth();
341
+ if (!auth?.token) {
342
+ return { success: false, message: "Not logged in" };
343
+ }
344
+ saveAuth({ token: "", registry: "" });
345
+ return { success: true, data: { ok: true, text: "Logged out" } };
346
+ }
347
+ });
348
+ }
349
+ export {
350
+ setupMarketplacePlugin as default
351
+ };