phewsh 0.5.0 → 0.5.2

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/commands/login.js CHANGED
@@ -53,6 +53,37 @@ async function main() {
53
53
  return;
54
54
  }
55
55
 
56
+ // --token: paste a JWT obtained from phewsh.com/intent settings
57
+ if (args.includes('--token')) {
58
+ const tokenIdx = args.indexOf('--token');
59
+ const jwt = args[tokenIdx + 1];
60
+ if (!jwt) {
61
+ console.log('\n Usage: phewsh login --token <jwt-from-web>\n');
62
+ console.log(' Get your token at phewsh.com/intent → Settings → CLI Access\n');
63
+ process.exit(1);
64
+ }
65
+ // Decode JWT payload (no verification needed — Supabase will validate on API calls)
66
+ try {
67
+ const payload = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString());
68
+ const config = loadConfig() || {};
69
+ saveConfig({
70
+ ...config,
71
+ userId: payload.sub,
72
+ email: payload.email || config.email || '',
73
+ supabaseUserId: payload.sub,
74
+ supabaseAccessToken: jwt,
75
+ supabaseRefreshToken: config.supabaseRefreshToken || null,
76
+ });
77
+ console.log(`\n ✓ Logged in as ${payload.email || payload.sub}`);
78
+ console.log(' ✓ Cloud sync enabled\n');
79
+ console.log(' Note: web tokens expire in ~1 hour. Run `phewsh login --refresh` if sync fails.\n');
80
+ } catch {
81
+ console.error('\n Invalid token. Copy it from phewsh.com/intent → Settings → CLI Access.\n');
82
+ process.exit(1);
83
+ }
84
+ return;
85
+ }
86
+
56
87
  if (args.includes('--set-key')) {
57
88
  const config = loadConfig() || {};
58
89
  const { ask, close } = createPrompter();
@@ -109,16 +140,26 @@ async function main() {
109
140
  process.exit(1);
110
141
  }
111
142
 
112
- console.log(` Check ${email} for a 6-digit code.\n`);
113
- const token = await ask(' Verification code\n > ');
143
+ console.log(` Check ${email} — look for a 6-digit code.`);
144
+ console.log(` (It may arrive as a link — if so, visit phewsh.com/intent to log in there first,`);
145
+ console.log(` then run: phewsh login --from-web to save that session.)\n`);
146
+ const token = await ask(' 6-digit code\n > ');
114
147
  console.log('');
115
148
 
149
+ if (!token || token.length < 4) {
150
+ close();
151
+ console.log('\n No code entered. If you received a link, log in at phewsh.com/intent\n then run `phewsh login --status` after logging in via web.\n');
152
+ process.exit(1);
153
+ }
154
+
116
155
  let session;
117
156
  try {
118
157
  session = await verifyOtp(email, token);
119
158
  } catch (err) {
120
159
  close();
121
- console.error('\n Verification failed:', err.message, '\n');
160
+ console.error('\n Verification failed:', err.message);
161
+ console.error(' If you received a link instead of a code, ask your admin to enable');
162
+ console.error(' Email OTP in the Supabase dashboard (Authentication → Email).\n');
122
163
  process.exit(1);
123
164
  }
124
165
 
package/lib/supabase.js CHANGED
@@ -20,9 +20,14 @@ async function req(path, options = {}, accessToken = null) {
20
20
 
21
21
  // Send magic link / OTP to email
22
22
  async function sendOtp(email) {
23
+ // redirect_to ensures magic links (if project uses them) land on /intent, not root
23
24
  const res = await req('/auth/v1/otp', {
24
25
  method: 'POST',
25
- body: JSON.stringify({ email, create_user: true }),
26
+ body: JSON.stringify({
27
+ email,
28
+ create_user: true,
29
+ options: { redirect_to: 'https://phewsh.com/intent' },
30
+ }),
26
31
  });
27
32
  return res.ok;
28
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phewsh",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Turn intent into action. Structure your thinking, execute your next step.",
5
5
  "bin": {
6
6
  "phewsh": "bin/phewsh.js"