spaps 0.2.4 → 0.2.5

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/bin/spaps.js CHANGED
@@ -13,6 +13,7 @@ const { spawn } = require('child_process');
13
13
  const path = require('path');
14
14
  const fs = require('fs');
15
15
  const { handleError } = require('../src/error-handler');
16
+ const { showInteractiveHelp, showQuickHelp } = require('../src/help-system');
16
17
 
17
18
  const version = require('../package.json').version;
18
19
 
@@ -176,6 +177,23 @@ program
176
177
  console.log(chalk.yellow(`🚧 'spaps types' coming in v0.4.0!`));
177
178
  });
178
179
 
180
+ // Help command - Interactive help system
181
+ program
182
+ .command('help')
183
+ .description('Show help and guides')
184
+ .option('-i, --interactive', 'Interactive help mode')
185
+ .option('-q, --quick', 'Quick reference')
186
+ .action(async (options) => {
187
+ if (options.interactive) {
188
+ await showInteractiveHelp();
189
+ } else if (options.quick) {
190
+ showQuickHelp();
191
+ } else {
192
+ // Default to quick help
193
+ showQuickHelp();
194
+ }
195
+ });
196
+
179
197
  // Help command enhancement
180
198
  program.on('--help', () => {
181
199
  console.log();
@@ -192,6 +210,8 @@ program.on('--help', () => {
192
210
  if (!process.argv.slice(2).length) {
193
211
  console.log(logo);
194
212
  program.outputHelp();
213
+ console.log();
214
+ console.log(chalk.yellow('šŸ’” Try: npx spaps help --interactive'));
195
215
  }
196
216
 
197
217
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spaps",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Sweet Potato Authentication & Payment Service CLI - Zero-config local development and project scaffolding",
5
5
  "main": "bin/spaps.js",
6
6
  "bin": {
@@ -0,0 +1,487 @@
1
+ /**
2
+ * SPAPS CLI Interactive Help System
3
+ * Decision trees and structured guidance for developers
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const prompts = require('prompts');
8
+
9
+ const HELP_TREE = {
10
+ root: {
11
+ question: 'What would you like to do?',
12
+ options: [
13
+ {
14
+ title: 'šŸš€ Start developing locally',
15
+ value: 'local-dev',
16
+ description: 'Run SPAPS on your machine'
17
+ },
18
+ {
19
+ title: 'šŸ“¦ Set up a new project',
20
+ value: 'new-project',
21
+ description: 'Create a new app with SPAPS'
22
+ },
23
+ {
24
+ title: 'šŸ”§ Add SPAPS to existing project',
25
+ value: 'existing-project',
26
+ description: 'Integrate SPAPS into your app'
27
+ },
28
+ {
29
+ title: 'šŸ› Debug an issue',
30
+ value: 'debug',
31
+ description: 'Troubleshoot problems'
32
+ },
33
+ {
34
+ title: 'šŸ“š Learn about SPAPS',
35
+ value: 'learn',
36
+ description: 'Understand concepts and features'
37
+ }
38
+ ]
39
+ },
40
+
41
+ 'local-dev': {
42
+ question: 'How do you want to run SPAPS locally?',
43
+ options: [
44
+ {
45
+ title: 'Quick start (default settings)',
46
+ value: 'quick-start',
47
+ command: 'npx spaps local',
48
+ description: 'Start on port 3300'
49
+ },
50
+ {
51
+ title: 'Custom port',
52
+ value: 'custom-port',
53
+ command: 'npx spaps local --port 3001',
54
+ description: 'Choose your own port'
55
+ },
56
+ {
57
+ title: 'Open browser automatically',
58
+ value: 'auto-open',
59
+ command: 'npx spaps local --open',
60
+ description: 'Opens docs in browser'
61
+ },
62
+ {
63
+ title: 'JSON mode (for CI/CD)',
64
+ value: 'json-mode',
65
+ command: 'npx spaps local --json',
66
+ description: 'Machine-readable output'
67
+ }
68
+ ]
69
+ },
70
+
71
+ 'new-project': {
72
+ question: 'What type of project?',
73
+ options: [
74
+ {
75
+ title: 'Next.js App',
76
+ value: 'nextjs',
77
+ command: 'npx spaps create my-app --template nextjs',
78
+ description: 'Full-stack React framework',
79
+ available: 'v0.3.0'
80
+ },
81
+ {
82
+ title: 'React + Vite',
83
+ value: 'react',
84
+ command: 'npx spaps create my-app --template react',
85
+ description: 'Fast, modern React setup',
86
+ available: 'v0.3.0'
87
+ },
88
+ {
89
+ title: 'Node.js API',
90
+ value: 'node',
91
+ command: 'npx spaps create my-api --template node',
92
+ description: 'Express.js backend',
93
+ available: 'v0.3.0'
94
+ },
95
+ {
96
+ title: 'Vanilla JavaScript',
97
+ value: 'vanilla',
98
+ command: 'npx spaps create my-app --template vanilla',
99
+ description: 'No framework, just JS',
100
+ available: 'v0.3.0'
101
+ }
102
+ ]
103
+ },
104
+
105
+ 'existing-project': {
106
+ question: 'What framework are you using?',
107
+ options: [
108
+ {
109
+ title: 'Next.js',
110
+ value: 'integrate-nextjs',
111
+ steps: [
112
+ 'npm install spaps-sdk',
113
+ 'npx spaps init',
114
+ 'Add to your app:',
115
+ '',
116
+ '// app/providers.tsx',
117
+ 'import { SPAPSClient } from "spaps-sdk"',
118
+ 'const spaps = new SPAPSClient()'
119
+ ]
120
+ },
121
+ {
122
+ title: 'React',
123
+ value: 'integrate-react',
124
+ steps: [
125
+ 'npm install spaps-sdk',
126
+ 'npx spaps init',
127
+ 'Create a context:',
128
+ '',
129
+ '// src/contexts/SpapsContext.tsx',
130
+ 'import { SPAPSClient } from "spaps-sdk"',
131
+ 'const spaps = new SPAPSClient()',
132
+ 'export const SpapsContext = React.createContext(spaps)'
133
+ ]
134
+ },
135
+ {
136
+ title: 'Node.js/Express',
137
+ value: 'integrate-node',
138
+ steps: [
139
+ 'npm install spaps-sdk',
140
+ 'npx spaps init',
141
+ 'Add middleware:',
142
+ '',
143
+ '// server.js',
144
+ 'const { SPAPSClient } = require("spaps-sdk")',
145
+ 'const spaps = new SPAPSClient()',
146
+ '',
147
+ 'app.use(async (req, res, next) => {',
148
+ ' req.spaps = spaps',
149
+ ' next()',
150
+ '})'
151
+ ]
152
+ },
153
+ {
154
+ title: 'Other/Vanilla',
155
+ value: 'integrate-other',
156
+ steps: [
157
+ 'npm install spaps-sdk',
158
+ 'npx spaps init',
159
+ 'Import in your code:',
160
+ '',
161
+ '// Using ES6 modules',
162
+ 'import { SPAPSClient } from "spaps-sdk"',
163
+ '',
164
+ '// Using CommonJS',
165
+ 'const { SPAPSClient } = require("spaps-sdk")',
166
+ '',
167
+ '// Using CDN',
168
+ '<script src="https://unpkg.com/spaps-sdk"></script>'
169
+ ]
170
+ }
171
+ ]
172
+ },
173
+
174
+ 'debug': {
175
+ question: 'What issue are you experiencing?',
176
+ options: [
177
+ {
178
+ title: 'Port already in use',
179
+ value: 'port-error',
180
+ solution: {
181
+ commands: [
182
+ 'npx spaps local --port 3301',
183
+ 'lsof -ti:3300 | xargs kill -9',
184
+ 'npx spaps local --port 0'
185
+ ],
186
+ explanation: 'Another process is using port 3300. Either use a different port or kill the existing process.'
187
+ }
188
+ },
189
+ {
190
+ title: 'Module not found',
191
+ value: 'module-error',
192
+ solution: {
193
+ commands: [
194
+ 'npm install',
195
+ 'rm -rf node_modules package-lock.json && npm install',
196
+ 'npm install spaps-sdk'
197
+ ],
198
+ explanation: 'Dependencies are missing. Reinstall packages to fix this.'
199
+ }
200
+ },
201
+ {
202
+ title: 'CORS errors',
203
+ value: 'cors-error',
204
+ solution: {
205
+ commands: [
206
+ 'npx spaps local',
207
+ 'Check your API URL: process.env.SPAPS_API_URL'
208
+ ],
209
+ explanation: 'CORS is automatically handled in local mode. Make sure your client is pointing to the local server.'
210
+ }
211
+ },
212
+ {
213
+ title: 'Authentication failing',
214
+ value: 'auth-error',
215
+ solution: {
216
+ commands: [
217
+ 'curl http://localhost:3300/health',
218
+ 'npx spaps local --port 3300'
219
+ ],
220
+ explanation: 'In local mode, authentication is automatic. Make sure the local server is running.'
221
+ }
222
+ }
223
+ ]
224
+ },
225
+
226
+ 'learn': {
227
+ question: 'What would you like to learn about?',
228
+ options: [
229
+ {
230
+ title: 'How SPAPS works',
231
+ value: 'how-it-works',
232
+ content: `
233
+ SPAPS (Sweet Potato Authentication & Payment Service) provides:
234
+
235
+ 1. **Authentication**: Email/password, magic links, and wallet-based auth
236
+ 2. **Payments**: Stripe subscriptions and wallet-based payments
237
+ 3. **Local Development**: Zero-config local mode with auto-auth
238
+ 4. **Type Safety**: Full TypeScript support with generated types
239
+ 5. **Multi-tenant**: API key-based app isolation
240
+
241
+ In local mode, everything is mocked so you can develop without:
242
+ - API keys
243
+ - Database setup
244
+ - External services
245
+ - Configuration files
246
+ `
247
+ },
248
+ {
249
+ title: 'Local vs Production',
250
+ value: 'environments',
251
+ content: `
252
+ **Local Mode** (http://localhost:3300):
253
+ - No API key required
254
+ - Auto-authentication
255
+ - Mocked responses
256
+ - CORS disabled
257
+ - Perfect for development
258
+
259
+ **Production Mode** (https://api.yourapp.com):
260
+ - API key required
261
+ - Real authentication
262
+ - Database persistence
263
+ - Stripe integration
264
+ - Rate limiting
265
+
266
+ The SDK auto-detects which mode to use based on the URL!
267
+ `
268
+ },
269
+ {
270
+ title: 'Authentication methods',
271
+ value: 'auth-methods',
272
+ content: `
273
+ SPAPS supports multiple authentication methods:
274
+
275
+ **Traditional Auth**:
276
+ - Email/password login
277
+ - Magic link (passwordless)
278
+ - Social logins (coming soon)
279
+
280
+ **Wallet Auth**:
281
+ - Solana wallets
282
+ - Ethereum wallets
283
+ - Bitcoin (coming soon)
284
+ - Base chain (coming soon)
285
+
286
+ **Code Examples**:
287
+ \`\`\`javascript
288
+ // Email/password
289
+ await spaps.login(email, password)
290
+
291
+ // Wallet
292
+ await spaps.walletSignIn(address, signature, message, 'solana')
293
+ \`\`\`
294
+ `
295
+ },
296
+ {
297
+ title: 'Payment integration',
298
+ value: 'payments',
299
+ content: `
300
+ SPAPS handles two payment types:
301
+
302
+ **Stripe Subscriptions**:
303
+ - Monthly/annual plans
304
+ - Usage-based billing
305
+ - Customer portal
306
+ - Webhook handling
307
+
308
+ **Wallet Payments**:
309
+ - Direct crypto payments
310
+ - Usage credits
311
+ - Instant settlement
312
+ - Multi-chain support
313
+
314
+ **Code Example**:
315
+ \`\`\`javascript
316
+ // Create Stripe checkout
317
+ const session = await spaps.createCheckoutSession(priceId, successUrl)
318
+
319
+ // Check subscription
320
+ const sub = await spaps.getSubscription()
321
+ \`\`\`
322
+ `
323
+ }
324
+ ]
325
+ }
326
+ };
327
+
328
+ async function showInteractiveHelp() {
329
+ console.log(chalk.yellow('\nšŸ  SPAPS Interactive Help\n'));
330
+
331
+ let currentNode = 'root';
332
+ const history = [];
333
+
334
+ while (true) {
335
+ const node = HELP_TREE[currentNode];
336
+
337
+ if (!node) {
338
+ // Leaf node - show result
339
+ break;
340
+ }
341
+
342
+ const choices = node.options.map(opt => ({
343
+ title: opt.title,
344
+ description: opt.description || '',
345
+ value: opt.value
346
+ }));
347
+
348
+ // Add back option if not at root
349
+ if (currentNode !== 'root') {
350
+ choices.push({
351
+ title: chalk.gray('← Back'),
352
+ value: '__back__'
353
+ });
354
+ }
355
+
356
+ choices.push({
357
+ title: chalk.gray('āœ• Exit'),
358
+ value: '__exit__'
359
+ });
360
+
361
+ const response = await prompts({
362
+ type: 'select',
363
+ name: 'choice',
364
+ message: node.question,
365
+ choices: choices
366
+ });
367
+
368
+ if (!response.choice || response.choice === '__exit__') {
369
+ console.log(chalk.gray('\nGoodbye! šŸ‘‹\n'));
370
+ process.exit(0);
371
+ }
372
+
373
+ if (response.choice === '__back__') {
374
+ currentNode = history.pop() || 'root';
375
+ continue;
376
+ }
377
+
378
+ // Find the selected option
379
+ const selected = node.options.find(opt => opt.value === response.choice);
380
+
381
+ if (selected) {
382
+ // Show immediate result if available
383
+ if (selected.command) {
384
+ console.log(chalk.green('\n✨ Run this command:\n'));
385
+ console.log(chalk.bgBlack.white(` $ ${selected.command}`));
386
+
387
+ if (selected.available) {
388
+ console.log(chalk.yellow(`\n āš ļø Available in ${selected.available}`));
389
+ }
390
+ console.log();
391
+ }
392
+
393
+ if (selected.steps) {
394
+ console.log(chalk.green('\nšŸ“ Follow these steps:\n'));
395
+ selected.steps.forEach((step, i) => {
396
+ if (step.startsWith('//') || step.startsWith('#')) {
397
+ console.log(chalk.gray(step));
398
+ } else if (step === '') {
399
+ console.log();
400
+ } else if (step.includes('npm') || step.includes('npx')) {
401
+ console.log(chalk.bgBlack.white(` $ ${step}`));
402
+ } else {
403
+ console.log(` ${step}`);
404
+ }
405
+ });
406
+ console.log();
407
+ }
408
+
409
+ if (selected.solution) {
410
+ console.log(chalk.green('\nšŸ’” Solution:\n'));
411
+ console.log(chalk.white(selected.solution.explanation));
412
+ console.log(chalk.green('\nTry these commands:\n'));
413
+ selected.solution.commands.forEach(cmd => {
414
+ console.log(chalk.bgBlack.white(` $ ${cmd}`));
415
+ });
416
+ console.log();
417
+ }
418
+
419
+ if (selected.content) {
420
+ console.log(chalk.green('\nšŸ“š Information:\n'));
421
+ console.log(selected.content);
422
+ }
423
+
424
+ // Navigate to next level if exists
425
+ if (HELP_TREE[response.choice]) {
426
+ history.push(currentNode);
427
+ currentNode = response.choice;
428
+ } else {
429
+ // Ask to continue or exit
430
+ const cont = await prompts({
431
+ type: 'confirm',
432
+ name: 'continue',
433
+ message: 'Continue exploring help?',
434
+ initial: true
435
+ });
436
+
437
+ if (!cont.continue) {
438
+ console.log(chalk.gray('\nGoodbye! šŸ‘‹\n'));
439
+ process.exit(0);
440
+ }
441
+
442
+ // Go back to previous menu
443
+ currentNode = history.pop() || 'root';
444
+ }
445
+ }
446
+ }
447
+ }
448
+
449
+ function showQuickHelp() {
450
+ console.log(chalk.yellow('\nšŸ  SPAPS Quick Reference\n'));
451
+
452
+ console.log(chalk.green('Common Commands:'));
453
+ console.log(' npx spaps local ' + chalk.gray('# Start local server'));
454
+ console.log(' npx spaps init ' + chalk.gray('# Initialize in project'));
455
+ console.log(' npx spaps create <name> ' + chalk.gray('# Create new project (v0.3.0)'));
456
+ console.log(' npx spaps types ' + chalk.gray('# Generate types (v0.4.0)'));
457
+ console.log();
458
+
459
+ console.log(chalk.green('Local Development:'));
460
+ console.log(' npx spaps local --port 3001 ' + chalk.gray('# Custom port'));
461
+ console.log(' npx spaps local --open ' + chalk.gray('# Open browser'));
462
+ console.log(' npx spaps local --json ' + chalk.gray('# JSON output'));
463
+ console.log();
464
+
465
+ console.log(chalk.green('SDK Usage:'));
466
+ console.log(' npm install spaps-sdk ' + chalk.gray('# Install SDK'));
467
+ console.log();
468
+ console.log(chalk.gray(' import { SPAPSClient } from "spaps-sdk"'));
469
+ console.log(chalk.gray(' const spaps = new SPAPSClient()'));
470
+ console.log(chalk.gray(' await spaps.login(email, password)'));
471
+ console.log();
472
+
473
+ console.log(chalk.green('Debugging:'));
474
+ console.log(' curl http://localhost:3300/health ' + chalk.gray('# Check server'));
475
+ console.log(' npx spaps help --interactive ' + chalk.gray('# Interactive help'));
476
+ console.log();
477
+
478
+ console.log(chalk.blue('šŸ“š Docs: https://sweetpotato.dev'));
479
+ console.log(chalk.blue('šŸ’¬ Discord: https://discord.gg/sweetpotato'));
480
+ console.log();
481
+ }
482
+
483
+ module.exports = {
484
+ showInteractiveHelp,
485
+ showQuickHelp,
486
+ HELP_TREE
487
+ };