@oxprotocol/cli 0.1.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 (104) hide show
  1. package/LICENSE +189 -0
  2. package/README.md +73 -0
  3. package/dist/cli.d.ts +15 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +109 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/create.d.ts +6 -0
  8. package/dist/commands/create.d.ts.map +1 -0
  9. package/dist/commands/create.js +212 -0
  10. package/dist/commands/create.js.map +1 -0
  11. package/dist/commands/dev.d.ts +2 -0
  12. package/dist/commands/dev.d.ts.map +1 -0
  13. package/dist/commands/dev.js +191 -0
  14. package/dist/commands/dev.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +16 -0
  16. package/dist/commands/doctor.d.ts.map +1 -0
  17. package/dist/commands/doctor.js +197 -0
  18. package/dist/commands/doctor.js.map +1 -0
  19. package/dist/commands/install-url.d.ts +20 -0
  20. package/dist/commands/install-url.d.ts.map +1 -0
  21. package/dist/commands/install-url.js +236 -0
  22. package/dist/commands/install-url.js.map +1 -0
  23. package/dist/commands/install.d.ts +13 -0
  24. package/dist/commands/install.d.ts.map +1 -0
  25. package/dist/commands/install.js +411 -0
  26. package/dist/commands/install.js.map +1 -0
  27. package/dist/commands/keygen.d.ts +13 -0
  28. package/dist/commands/keygen.d.ts.map +1 -0
  29. package/dist/commands/keygen.js +40 -0
  30. package/dist/commands/keygen.js.map +1 -0
  31. package/dist/commands/login.d.ts +21 -0
  32. package/dist/commands/login.d.ts.map +1 -0
  33. package/dist/commands/login.js +224 -0
  34. package/dist/commands/login.js.map +1 -0
  35. package/dist/commands/logout.d.ts +17 -0
  36. package/dist/commands/logout.d.ts.map +1 -0
  37. package/dist/commands/logout.js +70 -0
  38. package/dist/commands/logout.js.map +1 -0
  39. package/dist/commands/pack.d.ts +12 -0
  40. package/dist/commands/pack.d.ts.map +1 -0
  41. package/dist/commands/pack.js +94 -0
  42. package/dist/commands/pack.js.map +1 -0
  43. package/dist/commands/protocol-register.d.ts +29 -0
  44. package/dist/commands/protocol-register.d.ts.map +1 -0
  45. package/dist/commands/protocol-register.js +231 -0
  46. package/dist/commands/protocol-register.js.map +1 -0
  47. package/dist/commands/publish.d.ts +17 -0
  48. package/dist/commands/publish.d.ts.map +1 -0
  49. package/dist/commands/publish.js +188 -0
  50. package/dist/commands/publish.js.map +1 -0
  51. package/dist/commands/token.d.ts +17 -0
  52. package/dist/commands/token.d.ts.map +1 -0
  53. package/dist/commands/token.js +110 -0
  54. package/dist/commands/token.js.map +1 -0
  55. package/dist/commands/whoami.d.ts +13 -0
  56. package/dist/commands/whoami.d.ts.map +1 -0
  57. package/dist/commands/whoami.js +77 -0
  58. package/dist/commands/whoami.js.map +1 -0
  59. package/dist/index.d.ts +26 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +22 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/lib/broadcast.d.ts +41 -0
  64. package/dist/lib/broadcast.d.ts.map +1 -0
  65. package/dist/lib/broadcast.js +45 -0
  66. package/dist/lib/broadcast.js.map +1 -0
  67. package/dist/lib/host-adapter.d.ts +72 -0
  68. package/dist/lib/host-adapter.d.ts.map +1 -0
  69. package/dist/lib/host-adapter.js +193 -0
  70. package/dist/lib/host-adapter.js.map +1 -0
  71. package/dist/lib/host-detect.d.ts +60 -0
  72. package/dist/lib/host-detect.d.ts.map +1 -0
  73. package/dist/lib/host-detect.js +479 -0
  74. package/dist/lib/host-detect.js.map +1 -0
  75. package/dist/lib/oxp-url.d.ts +34 -0
  76. package/dist/lib/oxp-url.d.ts.map +1 -0
  77. package/dist/lib/oxp-url.js +74 -0
  78. package/dist/lib/oxp-url.js.map +1 -0
  79. package/dist/lib/vsx-install.d.ts +41 -0
  80. package/dist/lib/vsx-install.d.ts.map +1 -0
  81. package/dist/lib/vsx-install.js +74 -0
  82. package/dist/lib/vsx-install.js.map +1 -0
  83. package/dist/util.d.ts +10 -0
  84. package/dist/util.d.ts.map +1 -0
  85. package/dist/util.js +64 -0
  86. package/dist/util.js.map +1 -0
  87. package/package.json +48 -0
  88. package/templates/hello-code/README.md +39 -0
  89. package/templates/hello-code/oxp.json +14 -0
  90. package/templates/hello-code/package.json +18 -0
  91. package/templates/hello-code/src/extension.ts +17 -0
  92. package/templates/hello-code/tsconfig.json +20 -0
  93. package/templates/hello-html/README.md +18 -0
  94. package/templates/hello-html/oxp.json +14 -0
  95. package/templates/hello-html/ui/index.html +43 -0
  96. package/templates/hello-rust/Cargo.toml +19 -0
  97. package/templates/hello-rust/README.md +50 -0
  98. package/templates/hello-rust/oxp.json +22 -0
  99. package/templates/hello-rust/src/lib.rs +111 -0
  100. package/templates/hello-rust/wit/deps/oxp-host/oxp-host.wit +136 -0
  101. package/templates/hello-rust/wit/extension.wit +71 -0
  102. package/templates/hello-tree/README.md +15 -0
  103. package/templates/hello-tree/oxp.json +14 -0
  104. package/templates/hello-tree/ui/tree.json +27 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * `oxp protocol-register` — register the `oxp://` URL scheme so clicks
3
+ * in the browser open `oxp install --from <url>` automatically.
4
+ *
5
+ * Per-OS strategy:
6
+ *
7
+ * macOS Generate a tiny `.app` bundle at
8
+ * `~/Applications/OXP Helper.app` whose Info.plist declares
9
+ * the `oxp` scheme. Its main binary is a shell script that
10
+ * runs `oxp install --from "$1"`. Then ask Launch Services
11
+ * to register it.
12
+ *
13
+ * Linux Drop a `.desktop` file in
14
+ * `~/.local/share/applications/oxp-handler.desktop` with
15
+ * `MimeType=x-scheme-handler/oxp;` and run `xdg-mime default`.
16
+ *
17
+ * Windows Write registry keys under `HKCU\Software\Classes\oxp`
18
+ * pointing at the `oxp.cmd` shim.
19
+ *
20
+ * The command is **idempotent**: running it twice is safe and silent.
21
+ * It's also reversible — `oxp protocol-register --uninstall` removes
22
+ * everything it created.
23
+ *
24
+ * No network calls, no admin/sudo prompt. The handler simply re-invokes
25
+ * the user's installed `oxp` binary, so security stays inside the
26
+ * existing install pipeline (signature, TOFU, permission prompt).
27
+ */
28
+ import { promises as fs } from "node:fs";
29
+ import { execFile } from "node:child_process";
30
+ import { promisify } from "node:util";
31
+ import { homedir, platform } from "node:os";
32
+ import { join } from "node:path";
33
+ import { fail, info } from "../util.js";
34
+ const exec = promisify(execFile);
35
+ const MAC_APP_NAME = "OXP Helper.app";
36
+ const LINUX_DESKTOP_NAME = "oxp-handler.desktop";
37
+ const HELP = `oxp protocol-register Register the oxp:// URL scheme on this machine
38
+
39
+ Flags:
40
+ --uninstall Remove the registration
41
+ --oxp-bin <path> Path to the oxp binary to invoke (default: detected)
42
+ `;
43
+ function parseArgs(args) {
44
+ let uninstall = false;
45
+ let oxpBin;
46
+ for (let i = 0; i < args.length; i++) {
47
+ const a = args[i];
48
+ if (a === undefined)
49
+ continue;
50
+ if (a === "--uninstall")
51
+ uninstall = true;
52
+ else if (a === "--oxp-bin") {
53
+ oxpBin = args[++i];
54
+ if (!oxpBin)
55
+ fail("--oxp-bin requires a path");
56
+ }
57
+ else if (a.startsWith("--oxp-bin=")) {
58
+ oxpBin = a.slice("--oxp-bin=".length);
59
+ }
60
+ else if (a === "-h" || a === "--help") {
61
+ process.stdout.write(HELP);
62
+ process.exit(0);
63
+ }
64
+ else
65
+ fail(`unknown flag: ${a}`);
66
+ }
67
+ return { uninstall, oxpBin };
68
+ }
69
+ export async function protocolRegister(args) {
70
+ const opts = parseArgs(args);
71
+ const bin = opts.oxpBin ?? (await detectOxpBin());
72
+ if (!bin)
73
+ fail("could not locate oxp binary — pass --oxp-bin <path>");
74
+ switch (platform()) {
75
+ case "darwin":
76
+ return opts.uninstall ? unregisterMac() : registerMac(bin);
77
+ case "linux":
78
+ return opts.uninstall ? unregisterLinux() : registerLinux(bin);
79
+ case "win32":
80
+ return opts.uninstall ? unregisterWindows() : registerWindows(bin);
81
+ default:
82
+ fail(`unsupported platform: ${platform()}`);
83
+ }
84
+ }
85
+ async function detectOxpBin() {
86
+ // The CLI is most often launched via npx / pnpm dlx, which puts a
87
+ // shim on PATH. Prefer that. Fall back to argv[0] (process.execPath)
88
+ // when nothing matches.
89
+ try {
90
+ const { stdout } = await exec(platform() === "win32" ? "where" : "command", platform() === "win32" ? ["oxp"] : ["-v", "oxp"], { shell: platform() !== "win32", timeout: 1500 });
91
+ const first = stdout.split(/\r?\n/).find((s) => s.trim().length > 0);
92
+ if (first?.trim())
93
+ return first.trim();
94
+ }
95
+ catch {
96
+ // ignore
97
+ }
98
+ return process.execPath;
99
+ }
100
+ /* -------------------------------------------------------------------------- */
101
+ /* macOS */
102
+ /* -------------------------------------------------------------------------- */
103
+ async function registerMac(oxpBin) {
104
+ const root = join(homedir(), "Applications", MAC_APP_NAME);
105
+ const contents = join(root, "Contents");
106
+ const macOS = join(contents, "MacOS");
107
+ await fs.mkdir(macOS, { recursive: true });
108
+ const launcher = join(macOS, "oxp-helper");
109
+ const script = "#!/bin/sh\n" +
110
+ "# OXP url scheme handler. Auto-generated by `oxp protocol-register`.\n" +
111
+ `exec ${shQuote(oxpBin)} install --from "$1"\n`;
112
+ await fs.writeFile(launcher, script, { mode: 0o755 });
113
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
114
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
115
+ <plist version="1.0">
116
+ <dict>
117
+ <key>CFBundleName</key> <string>OXP Helper</string>
118
+ <key>CFBundleIdentifier</key> <string>dev.oxp.helper</string>
119
+ <key>CFBundleVersion</key> <string>1</string>
120
+ <key>CFBundleShortVersionString</key><string>1.0</string>
121
+ <key>CFBundlePackageType</key> <string>APPL</string>
122
+ <key>CFBundleExecutable</key> <string>oxp-helper</string>
123
+ <key>LSUIElement</key> <true/>
124
+ <key>CFBundleURLTypes</key>
125
+ <array>
126
+ <dict>
127
+ <key>CFBundleURLName</key> <string>OXP Install</string>
128
+ <key>CFBundleURLSchemes</key>
129
+ <array><string>oxp</string></array>
130
+ </dict>
131
+ </array>
132
+ </dict>
133
+ </plist>
134
+ `;
135
+ await fs.writeFile(join(contents, "Info.plist"), plist);
136
+ // Tell Launch Services to (re)scan the bundle so the URL scheme takes
137
+ // effect immediately. Failure here isn't fatal — the OS will pick the
138
+ // app up on next login.
139
+ try {
140
+ await exec("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", root], { timeout: 5000 });
141
+ }
142
+ catch {
143
+ // ignore
144
+ }
145
+ info(`✓ registered oxp:// scheme via ${root}`);
146
+ info(` test: open 'oxp://install/@oxprotocol/example'`);
147
+ return 0;
148
+ }
149
+ async function unregisterMac() {
150
+ const root = join(homedir(), "Applications", MAC_APP_NAME);
151
+ await fs.rm(root, { recursive: true, force: true });
152
+ info(`✓ removed ${root}`);
153
+ return 0;
154
+ }
155
+ /* -------------------------------------------------------------------------- */
156
+ /* Linux */
157
+ /* -------------------------------------------------------------------------- */
158
+ async function registerLinux(oxpBin) {
159
+ const dir = join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "applications");
160
+ await fs.mkdir(dir, { recursive: true });
161
+ const file = join(dir, LINUX_DESKTOP_NAME);
162
+ const desktop = "[Desktop Entry]\n" +
163
+ "Type=Application\n" +
164
+ "Name=OXP Install Helper\n" +
165
+ `Exec=${shQuote(oxpBin)} install --from %u\n` +
166
+ "NoDisplay=true\n" +
167
+ "MimeType=x-scheme-handler/oxp;\n" +
168
+ "Categories=Development;\n" +
169
+ "Terminal=false\n";
170
+ await fs.writeFile(file, desktop);
171
+ try {
172
+ await exec("update-desktop-database", [dir], { timeout: 5000 });
173
+ }
174
+ catch {
175
+ // not all distros ship update-desktop-database; that's fine
176
+ }
177
+ try {
178
+ await exec("xdg-mime", ["default", LINUX_DESKTOP_NAME, "x-scheme-handler/oxp"], { timeout: 5000 });
179
+ }
180
+ catch {
181
+ info(`note: xdg-mime not available — install xdg-utils to finalize`);
182
+ }
183
+ info(`✓ registered oxp:// scheme via ${file}`);
184
+ return 0;
185
+ }
186
+ async function unregisterLinux() {
187
+ const dir = join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "applications");
188
+ const file = join(dir, LINUX_DESKTOP_NAME);
189
+ await fs.rm(file, { force: true });
190
+ info(`✓ removed ${file}`);
191
+ return 0;
192
+ }
193
+ /* -------------------------------------------------------------------------- */
194
+ /* Windows */
195
+ /* -------------------------------------------------------------------------- */
196
+ async function registerWindows(oxpBin) {
197
+ // Use `reg add` rather than touching the registry via FFI — it's
198
+ // built in and supports HKCU writes without elevation.
199
+ const cmd = `"${oxpBin}" install --from "%1"`;
200
+ const ops = [
201
+ ["HKCU\\Software\\Classes\\oxp", "", "REG_SZ", "URL:OXP Install Protocol"],
202
+ ["HKCU\\Software\\Classes\\oxp", "URL Protocol", "REG_SZ", ""],
203
+ ["HKCU\\Software\\Classes\\oxp\\shell\\open\\command", "", "REG_SZ", cmd],
204
+ ];
205
+ for (const [key, name, type, value] of ops) {
206
+ const args = ["add", key];
207
+ if (name)
208
+ args.push("/v", name);
209
+ else
210
+ args.push("/ve");
211
+ args.push("/t", type, "/d", value, "/f");
212
+ await exec("reg", args, { timeout: 5000 });
213
+ }
214
+ info(`✓ registered oxp:// scheme in HKCU\\Software\\Classes\\oxp`);
215
+ return 0;
216
+ }
217
+ async function unregisterWindows() {
218
+ await exec("reg", ["delete", "HKCU\\Software\\Classes\\oxp", "/f"], {
219
+ timeout: 5000,
220
+ });
221
+ info(`✓ removed HKCU\\Software\\Classes\\oxp`);
222
+ return 0;
223
+ }
224
+ /* -------------------------------------------------------------------------- */
225
+ /* helpers */
226
+ /* -------------------------------------------------------------------------- */
227
+ function shQuote(s) {
228
+ // Just enough to survive paths with spaces — we control the input.
229
+ return `"${s.replace(/"/g, '\\"')}"`;
230
+ }
231
+ //# sourceMappingURL=protocol-register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-register.js","sourceRoot":"","sources":["../../src/commands/protocol-register.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `oxp publish [bundle] [--dry-run] [--json] [--no-prepublish]` — POST a
3
+ * `.oxp` + signature to the registry.
4
+ *
5
+ * If <bundle> is omitted, the most recent `dist/*.oxp` in the current project
6
+ * is used.
7
+ *
8
+ * Flags:
9
+ * --dry-run Validate everything (bundle exists, signature + public
10
+ * key files exist, manifest parses, target URL resolves)
11
+ * but do NOT send the POST. Useful in CI to catch broken
12
+ * bundles before they consume publish-rate budget.
13
+ * --json Emit a single-line JSON record instead of human prose.
14
+ * --no-prepublish Skip running `oxp.json#scripts.prepublish` (default: run it).
15
+ */
16
+ export declare function publish(args: string[]): Promise<number>;
17
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6H7D"}
@@ -0,0 +1,188 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { spawn } from "node:child_process";
3
+ import { basename, join, resolve } from "node:path";
4
+ import { unpackBundle } from "@oxprotocol/bundle";
5
+ import { mkdtemp, rm } from "node:fs/promises";
6
+ import { tmpdir } from "node:os";
7
+ import { fail, info, readCredentials, registryUrl, findProjectRoot, } from "../util.js";
8
+ /**
9
+ * `oxp publish [bundle] [--dry-run] [--json] [--no-prepublish]` — POST a
10
+ * `.oxp` + signature to the registry.
11
+ *
12
+ * If <bundle> is omitted, the most recent `dist/*.oxp` in the current project
13
+ * is used.
14
+ *
15
+ * Flags:
16
+ * --dry-run Validate everything (bundle exists, signature + public
17
+ * key files exist, manifest parses, target URL resolves)
18
+ * but do NOT send the POST. Useful in CI to catch broken
19
+ * bundles before they consume publish-rate budget.
20
+ * --json Emit a single-line JSON record instead of human prose.
21
+ * --no-prepublish Skip running `oxp.json#scripts.prepublish` (default: run it).
22
+ */
23
+ export async function publish(args) {
24
+ const dryRun = args.includes("--dry-run");
25
+ const json = args.includes("--json");
26
+ const noPrepublish = args.includes("--no-prepublish");
27
+ const positional = args.filter((a) => !a.startsWith("--"));
28
+ // --dry-run does not require credentials — it never talks to the registry.
29
+ const token = dryRun ? null : await readCredentials();
30
+ if (!dryRun && !token)
31
+ fail("not logged in. run `oxp login` first");
32
+ const bundlePath = await resolveBundle(positional[0]);
33
+ const sigPath = bundlePath.replace(/\.oxp$/, ".sig.json");
34
+ const pubPath = bundlePath.replace(/\.oxp$/, ".pub.pem");
35
+ const [oxpBytes, sigText, pubText] = await Promise.all([
36
+ fs.readFile(bundlePath),
37
+ fs.readFile(sigPath, "utf8"),
38
+ fs.readFile(pubPath, "utf8"),
39
+ ]);
40
+ // Read the manifest out of the bundle to learn id + version → URL path.
41
+ const tmp = await mkdtemp(join(tmpdir(), "oxp-publish-"));
42
+ let publisher;
43
+ let slug;
44
+ let version;
45
+ try {
46
+ const u = await unpackBundle(oxpBytes, tmp);
47
+ publisher = u.manifest.publisher;
48
+ const idSlug = u.manifest.id.split("/")[1];
49
+ if (!idSlug)
50
+ fail(`bad manifest id: ${u.manifest.id}`);
51
+ slug = idSlug;
52
+ version = u.manifest.version;
53
+ }
54
+ finally {
55
+ await rm(tmp, { recursive: true, force: true });
56
+ }
57
+ const url = `${registryUrl()}/api/v1/extensions/${publisher}/${slug}/versions`;
58
+ if (dryRun) {
59
+ const summary = {
60
+ ok: true,
61
+ dryRun: true,
62
+ bundle: bundlePath,
63
+ bytes: oxpBytes.length,
64
+ target: url,
65
+ manifest: { publisher, slug, version },
66
+ };
67
+ if (json) {
68
+ process.stdout.write(JSON.stringify(summary) + "\n");
69
+ }
70
+ else {
71
+ info(`✓ dry-run for @${publisher}/${slug}@${version}`);
72
+ info(` bundle: ${bundlePath} (${oxpBytes.length} bytes)`);
73
+ info(` signature: ${sigPath}`);
74
+ info(` pubkey: ${pubPath}`);
75
+ info(` target: ${url}`);
76
+ info(` (no network request was made)`);
77
+ }
78
+ return 0;
79
+ }
80
+ // Run scripts.prepublish (if set) after a successful pack and before upload.
81
+ if (!noPrepublish) {
82
+ const root = await findProjectRoot(process.cwd());
83
+ if (root) {
84
+ const cmd = await readPrepublishScript(root);
85
+ if (cmd) {
86
+ if (!json)
87
+ info(`▶ scripts.prepublish: ${cmd}`);
88
+ const code = await runShell(cmd, root);
89
+ if (code !== 0) {
90
+ fail(`scripts.prepublish exited with code ${code}`);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ const form = new FormData();
96
+ form.append("bundle", new Blob([new Uint8Array(oxpBytes)], {
97
+ type: "application/vnd.oxp.bundle.v1.tar+zstd",
98
+ }), basename(bundlePath));
99
+ form.append("signature", sigText);
100
+ form.append("publicKey", pubText);
101
+ if (!json)
102
+ info(`POST ${url}`);
103
+ const res = await fetch(url, {
104
+ method: "POST",
105
+ headers: { authorization: `Bearer ${token}` },
106
+ body: form,
107
+ });
108
+ const body = await res.text();
109
+ if (!res.ok) {
110
+ if (json) {
111
+ process.stdout.write(JSON.stringify({
112
+ ok: false,
113
+ status: res.status,
114
+ statusText: res.statusText,
115
+ body,
116
+ }) + "\n");
117
+ }
118
+ else {
119
+ process.stderr.write(`oxp: ${res.status} ${res.statusText}\n${body}\n`);
120
+ }
121
+ return 1;
122
+ }
123
+ if (json) {
124
+ let parsed = body;
125
+ try {
126
+ parsed = JSON.parse(body);
127
+ }
128
+ catch {
129
+ /* keep as string */
130
+ }
131
+ process.stdout.write(JSON.stringify({ ok: true, publisher, slug, version, response: parsed }) +
132
+ "\n");
133
+ }
134
+ else {
135
+ info(`✓ published @${publisher}/${slug}@${version}`);
136
+ info(body);
137
+ }
138
+ return 0;
139
+ }
140
+ async function resolveBundle(arg) {
141
+ if (arg)
142
+ return resolve(arg);
143
+ const root = await findProjectRoot(process.cwd());
144
+ if (!root)
145
+ fail("not inside an OXP project. pass a bundle path explicitly");
146
+ const distDir = join(root, "dist");
147
+ let entries;
148
+ try {
149
+ entries = (await fs.readdir(distDir)).filter((n) => n.endsWith(".oxp"));
150
+ }
151
+ catch {
152
+ fail(`no dist/ directory in ${root}. run \`oxp pack\` first`);
153
+ }
154
+ if (entries.length === 0)
155
+ fail("no .oxp files in dist/. run `oxp pack` first");
156
+ const stats = await Promise.all(entries.map(async (n) => ({
157
+ name: n,
158
+ mtime: (await fs.stat(join(distDir, n))).mtimeMs,
159
+ })));
160
+ stats.sort((a, b) => b.mtime - a.mtime);
161
+ return join(distDir, stats[0].name);
162
+ }
163
+ async function readPrepublishScript(root) {
164
+ try {
165
+ const txt = await fs.readFile(join(root, "oxp.json"), "utf8");
166
+ const parsed = JSON.parse(txt);
167
+ const cmd = parsed.scripts?.prepublish;
168
+ return typeof cmd === "string" && cmd.trim().length > 0 ? cmd.trim() : null;
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ function runShell(cmd, cwd) {
175
+ return new Promise((resolveExit) => {
176
+ const child = spawn("sh", ["-c", cmd], {
177
+ cwd,
178
+ stdio: "inherit",
179
+ env: process.env,
180
+ });
181
+ child.on("exit", (code) => resolveExit(code ?? 1));
182
+ child.on("error", (err) => {
183
+ process.stderr.write(`oxp publish: prepublish hook failed to start: ${err.message}\n`);
184
+ resolveExit(1);
185
+ });
186
+ });
187
+ }
188
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `oxp token` — manage the bearer token stored in `~/.oxp/credentials`.
3
+ *
4
+ * Subcommands:
5
+ * oxp token rotate [--days N] [--name "label"] [--scope publish:@a/b ...]
6
+ *
7
+ * `rotate` POSTs to /api/v1/tokens/rotate with the current token, then
8
+ * overwrites `~/.oxp/credentials` with the new secret returned by the
9
+ * registry. The previous token continues to work for ROTATION_GRACE_MS
10
+ * (5 min server-side) so a publish in flight does not break.
11
+ *
12
+ * If `--scope` is passed one or more times, the new token is NARROWED
13
+ * to that subset. Without it the new token inherits all scopes from
14
+ * the current token.
15
+ */
16
+ export declare function token(args: string[]): Promise<number>;
17
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuCH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAO3D"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * `oxp token` — manage the bearer token stored in `~/.oxp/credentials`.
3
+ *
4
+ * Subcommands:
5
+ * oxp token rotate [--days N] [--name "label"] [--scope publish:@a/b ...]
6
+ *
7
+ * `rotate` POSTs to /api/v1/tokens/rotate with the current token, then
8
+ * overwrites `~/.oxp/credentials` with the new secret returned by the
9
+ * registry. The previous token continues to work for ROTATION_GRACE_MS
10
+ * (5 min server-side) so a publish in flight does not break.
11
+ *
12
+ * If `--scope` is passed one or more times, the new token is NARROWED
13
+ * to that subset. Without it the new token inherits all scopes from
14
+ * the current token.
15
+ */
16
+ import { readCredentials, writeCredentials, registryUrl, info, } from "../util.js";
17
+ function parseRotate(args) {
18
+ const out = {};
19
+ for (let i = 0; i < args.length; i++) {
20
+ const a = args[i];
21
+ if (a === "--days") {
22
+ const v = args[++i];
23
+ const n = Number(v);
24
+ if (!Number.isFinite(n) || n <= 0)
25
+ return { error: "--days must be a positive number" };
26
+ out.days = Math.floor(n);
27
+ }
28
+ else if (a === "--name") {
29
+ const v = args[++i];
30
+ if (!v)
31
+ return { error: "--name requires a value" };
32
+ out.name = v;
33
+ }
34
+ else if (a === "--scope") {
35
+ const v = args[++i];
36
+ if (!v)
37
+ return { error: "--scope requires a value" };
38
+ (out.scopes ??= []).push(v);
39
+ }
40
+ else {
41
+ return { error: `unknown flag: ${a}` };
42
+ }
43
+ }
44
+ return out;
45
+ }
46
+ export async function token(args) {
47
+ const [sub, ...rest] = args;
48
+ if (sub === "rotate")
49
+ return rotate(rest);
50
+ process.stderr.write("usage:\n oxp token rotate [--days N] [--name LABEL] [--scope publish:@h/s ...]\n");
51
+ return 2;
52
+ }
53
+ async function rotate(args) {
54
+ const parsed = parseRotate(args);
55
+ if ("error" in parsed) {
56
+ process.stderr.write(`oxp: ${parsed.error}\n`);
57
+ return 2;
58
+ }
59
+ const current = await readCredentials();
60
+ if (!current) {
61
+ process.stderr.write("oxp: no credentials on disk; run `oxp login` first\n");
62
+ return 1;
63
+ }
64
+ const url = registryUrl();
65
+ info(`Rotating token at ${url}…`);
66
+ const body = {};
67
+ if (parsed.days !== undefined)
68
+ body.ttlDays = parsed.days;
69
+ if (parsed.name !== undefined)
70
+ body.name = parsed.name;
71
+ if (parsed.scopes !== undefined)
72
+ body.scopes = parsed.scopes;
73
+ let res;
74
+ try {
75
+ res = await fetch(`${url}/api/v1/tokens/rotate`, {
76
+ method: "POST",
77
+ headers: {
78
+ Authorization: `Bearer ${current}`,
79
+ "Content-Type": "application/json",
80
+ },
81
+ body: JSON.stringify(body),
82
+ });
83
+ }
84
+ catch (e) {
85
+ process.stderr.write(`oxp: rotation request failed: ${e.message}\n`);
86
+ return 1;
87
+ }
88
+ let payload;
89
+ try {
90
+ payload = (await res.json());
91
+ }
92
+ catch {
93
+ process.stderr.write(`oxp: rotation returned ${res.status} with non-JSON body\n`);
94
+ return 1;
95
+ }
96
+ if (!res.ok || !payload.ok || !payload.token) {
97
+ process.stderr.write(`oxp: rotation failed (${res.status}): ${payload.error ?? "unknown error"}\n`);
98
+ return 1;
99
+ }
100
+ await writeCredentials(payload.token);
101
+ info("✓ new token saved to ~/.oxp/credentials");
102
+ if (payload.scopes)
103
+ info(` scopes: ${payload.scopes.join(", ")}`);
104
+ if (payload.expiresAt)
105
+ info(` expires: ${payload.expiresAt}`);
106
+ if (payload.previousExpiresAt)
107
+ info(` old token valid until: ${payload.previousExpiresAt}`);
108
+ return 0;
109
+ }
110
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,IAAI,GACL,MAAM,YAAY,CAAC;AAQpB,SAAS,WAAW,CAAC,IAAc;IACjC,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;YACxF,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;YACpD,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;YACrD,CAAC,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAAE,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAc;IACxC,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5B,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mFAAmF,CACpF,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAc;IAClC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,eAAe,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sDAAsD,CACvD,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,CAAC,qBAAqB,GAAG,GAAG,CAAC,CAAC;IAElC,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1D,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACvD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAE7D,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,uBAAuB,EAAE;YAC/C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,OAAO,EAAE;gBAClC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAkC,CAAW,CAAC,OAAO,IAAI,CAAC,CAAC;QAChF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,OAQH,CAAC;IACF,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,GAAG,CAAC,MAAM,uBAAuB,CAC5D,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,yBAAyB,GAAG,CAAC,MAAM,MAAM,OAAO,CAAC,KAAK,IAAI,eAAe,IAAI,CAC9E,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,aAAa,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnE,IAAI,OAAO,CAAC,SAAS;QAAE,IAAI,CAAC,cAAc,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,iBAAiB;QAC3B,IAAI,CAAC,4BAA4B,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `oxp whoami [--json]` — print the identity behind the local credentials.
3
+ *
4
+ * Hits GET /api/v1/auth/whoami with the stored bearer token and prints
5
+ * handle, email, scopes, and expiry. Prints nothing sensitive (the token
6
+ * itself is never echoed back).
7
+ *
8
+ * Exit codes:
9
+ * 0 authenticated
10
+ * 1 not logged in / token invalid / network error
11
+ */
12
+ export declare function whoami(args: string[]): Promise<number>;
13
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkBH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0E5D"}