peekable 0.2.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 +8 -1
- package/dist/command-error.js +3 -2
- package/dist/commands/doctor.js +6 -7
- package/dist/commands/register.js +60 -19
- package/dist/commands/upgrade.js +11 -1
- package/dist/index.js +0 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,11 +13,18 @@ npm install -g peekable
|
|
|
13
13
|
## First Run
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
peekable register
|
|
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
|
|
package/dist/command-error.js
CHANGED
|
@@ -25,9 +25,10 @@ export function getErrorMessage(err) {
|
|
|
25
25
|
return getErrorMessage(err.cause);
|
|
26
26
|
return err.message;
|
|
27
27
|
}
|
|
28
|
+
// Neutralized under Early Access: the server no longer emits this code, but
|
|
29
|
+
// keep the branch inert-but-safe in case an old server still sends it.
|
|
28
30
|
if (err instanceof ApiError && err.details.code === "trial_expired") {
|
|
29
|
-
|
|
30
|
-
return `Your Peekable trial has ended. Run \`peekable upgrade\` to keep pushing.${upgradeUrl ? ` Upgrade: ${upgradeUrl}` : ""}`;
|
|
31
|
+
return "This request was blocked. Run `peekable doctor` for details.";
|
|
31
32
|
}
|
|
32
33
|
if (err instanceof Error)
|
|
33
34
|
return err.message;
|
package/dist/commands/doctor.js
CHANGED
|
@@ -198,14 +198,13 @@ export function formatDoctorReport(report) {
|
|
|
198
198
|
return lines.join("\n");
|
|
199
199
|
}
|
|
200
200
|
function formatPlan(report) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (report.planState === "
|
|
204
|
-
|
|
205
|
-
|
|
201
|
+
// trial* plan_states are all served for free during Early Access; collapse
|
|
202
|
+
// them to one display string and drop the upgrade nudge.
|
|
203
|
+
if (report.planState === "trial_registered"
|
|
204
|
+
|| report.planState === "trial_active"
|
|
205
|
+
|| report.planState === "trial_expired") {
|
|
206
|
+
return "early access";
|
|
206
207
|
}
|
|
207
|
-
if (report.planState === "trial_expired")
|
|
208
|
-
return "trial expired — run `peekable upgrade`";
|
|
209
208
|
if (report.planState === "paid")
|
|
210
209
|
return "paid";
|
|
211
210
|
return "free";
|
|
@@ -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
|
-
.
|
|
9
|
-
.
|
|
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
|
-
.
|
|
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,42 +38,68 @@ 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
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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") {
|
|
61
|
-
console.log("
|
|
102
|
+
console.log("Ready — run `peekable init` to get started.");
|
|
62
103
|
}
|
|
63
104
|
else {
|
|
64
105
|
console.log(`\nNext step: run \`peekable init\` to complete setup.`);
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -5,7 +5,7 @@ import { CommandFailure, printCommandError } from "../command-error.js";
|
|
|
5
5
|
import { requireConfig } from "../config.js";
|
|
6
6
|
import { runWithTelemetry } from "../telemetry.js";
|
|
7
7
|
export const upgradeCommand = new Command("upgrade")
|
|
8
|
-
.description("Upgrade a Peekable
|
|
8
|
+
.description("Upgrade a paid Peekable account through Stripe Checkout")
|
|
9
9
|
.option("--json", "Output JSON")
|
|
10
10
|
.action(async (opts) => {
|
|
11
11
|
await runWithTelemetry("upgrade", async () => {
|
|
@@ -25,6 +25,16 @@ export const upgradeCommand = new Command("upgrade")
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
catch (err) {
|
|
28
|
+
if (err instanceof ApiError && err.details.code === "early_access_no_billing") {
|
|
29
|
+
const message = "Peekable is free during Early Access — nothing to upgrade yet.";
|
|
30
|
+
if (opts.json) {
|
|
31
|
+
console.log(JSON.stringify({ error: message, code: "early_access_no_billing" }));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(message);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
28
38
|
if (!opts.json
|
|
29
39
|
&& err instanceof ApiError
|
|
30
40
|
&& (err.details.code === "billing_account_exists"
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.
|
|
1
|
+
export declare const CLI_VERSION = "0.4.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = "0.
|
|
1
|
+
export const CLI_VERSION = "0.4.0";
|