@floomhq/floom 1.0.20 → 1.0.21
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.
- package/README.md +1 -1
- package/dist/cli.js +25 -2
- package/dist/login.js +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ The package is designed for `npx -y @floomhq/floom ...`. Global installs expose
|
|
|
22
22
|
|
|
23
23
|
## Commands
|
|
24
24
|
|
|
25
|
-
- `npx -y @floomhq/floom login` — sign in with Google. New accounts are created on first login. Token stored at `~/.floom/config.json`.
|
|
25
|
+
- `npx -y @floomhq/floom login` — sign in with Google. Use `--provider github` for GitHub. New accounts are created on first login. Token stored at `~/.floom/config.json`.
|
|
26
26
|
- `npx -y @floomhq/floom init [path]` — create a starter skill folder at `<path>/SKILL.md`. Passing an existing-style `file.md` path still creates that Markdown file.
|
|
27
27
|
- `npx -y @floomhq/floom publish <path>` — upload a skill folder or Markdown file. Folder packages use `<slug>/SKILL.md` plus optional `references/`, `examples/`, `scripts/`, and `assets/`. Optional `--public` / `--private` / `--unlisted`, `--type knowledge|instruction|workflow|skill`, `--installs-as <target>`, and `--skill-version <label>`.
|
|
28
28
|
- `npx -y @floomhq/floom share <slug>` — email-share one of your skills. Optional `--add <email>`, `--remove <email>`, and `--list`.
|
package/dist/cli.js
CHANGED
|
@@ -162,6 +162,13 @@ Diagnose auth, API reachability, PATH collisions, MCP setup, and local skills fo
|
|
|
162
162
|
${c.bold("Flags")}
|
|
163
163
|
${c.cyan("--target")} ${c.dim("claude|codex")} Check Claude Code or Codex paths. Default: claude.
|
|
164
164
|
${c.cyan("--json")} Print structured checks for scripts.
|
|
165
|
+
`,
|
|
166
|
+
login: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} login`)} ${c.dim("[flags]")}
|
|
167
|
+
|
|
168
|
+
Sign in through browser OAuth.
|
|
169
|
+
|
|
170
|
+
${c.bold("Flags")}
|
|
171
|
+
${c.cyan("--provider")} ${c.dim("google|github")} OAuth provider. Default: google.
|
|
165
172
|
`,
|
|
166
173
|
publish: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} publish`)} ${c.dim("<path> [flags]")}
|
|
167
174
|
|
|
@@ -255,6 +262,23 @@ function readFlagValue(argv, index, flag) {
|
|
|
255
262
|
throw new FloomError(`Missing value for ${flag}.`);
|
|
256
263
|
return { value, nextIndex: index + 1 };
|
|
257
264
|
}
|
|
265
|
+
function parseLoginArgs(argv) {
|
|
266
|
+
let provider = "google";
|
|
267
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
268
|
+
const a = argv[i] ?? "";
|
|
269
|
+
if (a === "--provider" || a.startsWith("--provider=")) {
|
|
270
|
+
const { value, nextIndex } = readFlagValue(argv, i, "--provider");
|
|
271
|
+
if (value !== "google" && value !== "github") {
|
|
272
|
+
throw new FloomError("Invalid --provider.", "Use google or github.");
|
|
273
|
+
}
|
|
274
|
+
provider = value;
|
|
275
|
+
i = nextIndex;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
throw new FloomError(`Unknown flag or argument: ${a}`, `Try \`${CLI_COMMAND} login --provider github\`.`);
|
|
279
|
+
}
|
|
280
|
+
return { provider };
|
|
281
|
+
}
|
|
258
282
|
function parseFlags(argv) {
|
|
259
283
|
const out = { visibility: "unlisted", update: false, rest: [] };
|
|
260
284
|
let visibilityFlag = null;
|
|
@@ -852,8 +876,7 @@ async function main() {
|
|
|
852
876
|
process.stdout.write(`${CLI_VERSION}\n`);
|
|
853
877
|
return;
|
|
854
878
|
case "login":
|
|
855
|
-
|
|
856
|
-
await login();
|
|
879
|
+
await login(parseLoginArgs(rest).provider);
|
|
857
880
|
return;
|
|
858
881
|
case "logout":
|
|
859
882
|
rejectArgs(rest, `Try \`${CLI_COMMAND} logout\`.`);
|
package/dist/login.js
CHANGED
|
@@ -8,18 +8,19 @@ import { c, header, symbols } from "./ui.js";
|
|
|
8
8
|
import { FloomError, friendlyHttp, friendlyNetwork } from "./errors.js";
|
|
9
9
|
const DEFAULT_PORT = 7456;
|
|
10
10
|
const TIMEOUT_MS = 5 * 60 * 1000;
|
|
11
|
-
export async function login() {
|
|
11
|
+
export async function login(provider = "google") {
|
|
12
12
|
const apiUrl = getApiUrl();
|
|
13
13
|
const port = await pickPort();
|
|
14
|
+
const providerLabel = provider === "github" ? "GitHub" : "Google";
|
|
14
15
|
process.stdout.write(header());
|
|
15
|
-
process.stdout.write(`${symbols.arrow} Opening browser to sign in with
|
|
16
|
+
process.stdout.write(`${symbols.arrow} Opening browser to sign in with ${providerLabel}...\n\n`);
|
|
16
17
|
const spinner = ora({
|
|
17
18
|
text: c.dim("Waiting for sign-in to complete..."),
|
|
18
19
|
color: "yellow",
|
|
19
20
|
}).start();
|
|
20
21
|
let tokens;
|
|
21
22
|
try {
|
|
22
|
-
tokens = await waitForCallback(port);
|
|
23
|
+
tokens = await waitForCallback(port, provider);
|
|
23
24
|
}
|
|
24
25
|
catch (err) {
|
|
25
26
|
spinner.stop();
|
|
@@ -90,7 +91,7 @@ function reserveEphemeralPort() {
|
|
|
90
91
|
});
|
|
91
92
|
});
|
|
92
93
|
}
|
|
93
|
-
function waitForCallback(port) {
|
|
94
|
+
function waitForCallback(port, provider) {
|
|
94
95
|
return new Promise((resolve, reject) => {
|
|
95
96
|
const apiUrl = getApiUrl();
|
|
96
97
|
const state = randomBytes(32).toString("base64url");
|
|
@@ -172,7 +173,7 @@ function waitForCallback(port) {
|
|
|
172
173
|
reject(new FloomError(`Local auth server failed on port ${port}.`, `Is port ${port} already in use? (${err.message})`));
|
|
173
174
|
});
|
|
174
175
|
server.listen(port, "127.0.0.1", () => {
|
|
175
|
-
const target = `${apiUrl}/auth/cli?port=${port}&state=${encodeURIComponent(state)}`;
|
|
176
|
+
const target = `${apiUrl}/auth/cli?port=${port}&provider=${provider}&state=${encodeURIComponent(state)}`;
|
|
176
177
|
open(target).catch((e) => {
|
|
177
178
|
const msg = e instanceof Error ? e.message : String(e);
|
|
178
179
|
process.stdout.write(c.yellow(`Could not auto-open browser (${msg}).\n`) +
|