peekable 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -13,11 +13,18 @@ npm install -g peekable
13
13
  ## First Run
14
14
 
15
15
  ```bash
16
- peekable register --name "Your Name" --email "you@example.com" --invite-code "your-invite-code"
16
+ peekable register your-invite-code
17
17
  peekable init
18
18
  peekable create "My first review"
19
19
  ```
20
20
 
21
+ Got your invite code some other way (support, a paid plan) and it isn't tied to an
22
+ email on file? Use the legacy form:
23
+
24
+ ```bash
25
+ peekable register --name "Your Name" --email "you@example.com" --invite-code "your-invite-code"
26
+ ```
27
+
21
28
  `peekable create` prints a session ID and share URL. Use the session ID with one
22
29
  of the publish commands below.
23
30
 
@@ -3,14 +3,29 @@ import { writeConfig, readConfig, DEFAULT_SERVER_URL } from "../config.js";
3
3
  import { apiNoAuth } from "../api.js";
4
4
  import { CommandFailure, printCommandError } from "../command-error.js";
5
5
  import { runWithTelemetry } from "../telemetry.js";
6
+ const USAGE_FORMS = [
7
+ ` peekable register <code>`,
8
+ ` peekable register --name "Your Name" --email "you@example.com" --invite-code "your-invite-code"`,
9
+ ].join("\n");
6
10
  export const registerCommand = new Command("register")
7
11
  .description("Register for an API key")
8
- .requiredOption("--name <name>", "Your display name")
9
- .requiredOption("--email <email>", "Your email address")
12
+ .argument("[code]", "Invite code from your email")
13
+ .option("--name <name>", "Your display name")
14
+ .option("--email <email>", "Your email address")
10
15
  .option("--invite-code <code>", "Beta invite code")
11
16
  .option("--url <url>", "Server URL", DEFAULT_SERVER_URL)
12
17
  .option("--json", "Output JSON")
13
- .action(async (opts) => {
18
+ .addHelpText("after", `
19
+ Examples:
20
+ peekable register your-invite-code
21
+ peekable register --invite-code your-invite-code
22
+ peekable register --name "Your Name" --email "you@example.com" --invite-code "your-invite-code"
23
+
24
+ The invite code may also come from PEEKABLE_INVITE_CODE. --email is required
25
+ only when no invite code is given (or when your code needs an email on file,
26
+ e.g. codes issued by support or paid checkout).
27
+ `)
28
+ .action(async (code, opts) => {
14
29
  await runWithTelemetry("register", async () => {
15
30
  const existing = readConfig();
16
31
  if (existing) {
@@ -23,38 +38,64 @@ export const registerCommand = new Command("register")
23
38
  }
24
39
  throw new CommandFailure("Already registered.");
25
40
  }
41
+ const flagCode = typeof opts.inviteCode === "string" ? opts.inviteCode : undefined;
42
+ if (code && flagCode && code !== flagCode) {
43
+ const message = `Conflicting invite codes: got "${code}" positionally and "${flagCode}" via --invite-code. Pass the code once.`;
44
+ if (opts.json) {
45
+ console.log(JSON.stringify({ error: message }));
46
+ }
47
+ else {
48
+ console.error(message);
49
+ }
50
+ throw new CommandFailure("Conflicting invite codes.");
51
+ }
52
+ const inviteCode = code ?? flagCode ?? process.env.PEEKABLE_INVITE_CODE;
53
+ if (!inviteCode && !opts.email) {
54
+ const message = "An invite code or --email is required.";
55
+ if (opts.json) {
56
+ console.log(JSON.stringify({ error: message }));
57
+ }
58
+ else {
59
+ console.error(message);
60
+ console.error("");
61
+ console.error("Usage:");
62
+ console.error(USAGE_FORMS);
63
+ }
64
+ throw new CommandFailure("Missing invite code or email.");
65
+ }
26
66
  try {
27
- const inviteCode = typeof opts.inviteCode === "string"
28
- ? opts.inviteCode
29
- : process.env.PEEKABLE_INVITE_CODE;
30
- const body = {
31
- name: opts.name,
32
- email: opts.email,
33
- };
34
- if (inviteCode) {
67
+ const body = {};
68
+ if (opts.name)
69
+ body.name = opts.name;
70
+ if (opts.email)
71
+ body.email = opts.email;
72
+ if (inviteCode)
35
73
  body.invite_code = inviteCode;
36
- }
37
- const data = await apiNoAuth(opts.url, "POST", "/register", {
38
- ...body,
39
- });
74
+ const data = await apiNoAuth(opts.url, "POST", "/register", body);
40
75
  writeConfig({
41
76
  url: opts.url,
42
77
  api_key: data.api_key,
43
- name: opts.name,
78
+ name: data.name,
44
79
  });
45
80
  if (opts.json) {
46
81
  console.log(JSON.stringify({
47
82
  api_key: data.api_key,
48
83
  url: opts.url,
49
- name: opts.name,
84
+ name: data.name,
50
85
  plan_state: data.plan_state ?? null,
51
86
  trial_ends_at: data.trial_ends_at ?? null,
52
87
  days_remaining: data.days_remaining ?? null,
53
88
  invite_source: data.invite_source ?? null,
89
+ email_masked: data.email_masked ?? null,
54
90
  }));
55
91
  }
56
92
  else {
57
- console.log(`Registered as ${opts.name}.`);
93
+ if (data.email_masked) {
94
+ console.log(`Registered as ${data.name} (${data.email_masked}).`);
95
+ }
96
+ else {
97
+ console.log(`Registered as ${data.name}.`);
98
+ }
58
99
  console.log(`API key saved to ~/.peekable/config.json`);
59
100
  console.log("Peekable CLI sends anonymous usage/failure telemetry to improve reliability. Opt out: PEEKABLE_NO_TELEMETRY=1");
60
101
  if (data.invite_source === "trial") {
package/dist/index.js CHANGED
File without changes
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "0.3.0";
1
+ export declare const CLI_VERSION = "0.4.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = "0.3.0";
1
+ export const CLI_VERSION = "0.4.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peekable",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Share HTML mockups with collaborators — CLI for peekable-server",
6
6
  "bin": {