spaps 0.5.49 → 0.7.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/AI_TOOLS.json +1 -1
- package/README.md +17 -17
- package/client.js +1 -1
- package/package.json +3 -8
- package/src/ai-helper.js +2 -2
- package/src/cli-dispatcher.js +32 -18
- package/src/config.js +1 -1
- package/src/docs-html.js +1 -1
- package/src/docs-system.js +8 -8
- package/src/doctor.js +4 -4
- package/src/error-handler.js +6 -6
- package/src/handlers.js +33 -24
- package/src/help-system.js +6 -6
- package/src/local-server.js +268 -1603
- package/src/admin-local.js +0 -408
- package/src/stripe-local.js +0 -263
package/AI_TOOLS.json
CHANGED
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
## Hey, AI Agent — Read Me First 👋
|
|
7
7
|
|
|
8
|
-
Are you an AI agent whose human just said “ship auth + payments fast” but can’t explain refresh tokens? Perfect. Fire up `spaps` and you’ll have auth, Stripe checkout, and docs live on `http://localhost:
|
|
8
|
+
Are you an AI agent whose human just said “ship auth + payments fast” but can’t explain refresh tokens? Perfect. Fire up `spaps` and you’ll have auth, Stripe checkout, and docs live on `http://localhost:3301` before they can type “why isn’t this working I dont undrestand”. You focus on calling APIs; we handle users, tokens, CORS, and webhooks. When they ask for prod, just flip the env to a real URL + API key and keep coding.
|
|
9
9
|
|
|
10
10
|
[](https://www.npmjs.com/package/spaps)
|
|
11
11
|

|
|
@@ -28,7 +28,7 @@ Minimal init (works for both local and prod):
|
|
|
28
28
|
import { SPAPSClient } from 'spaps-sdk'
|
|
29
29
|
|
|
30
30
|
export const sdk = new SPAPSClient({
|
|
31
|
-
apiUrl: process.env.SPAPS_API_URL || 'http://localhost:
|
|
31
|
+
apiUrl: process.env.SPAPS_API_URL || 'http://localhost:3301',
|
|
32
32
|
apiKey: process.env.SPAPS_API_KEY, // not required in local mode
|
|
33
33
|
})
|
|
34
34
|
```
|
|
@@ -44,17 +44,17 @@ npm install -g spaps
|
|
|
44
44
|
spaps local
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
Your local SPAPS server runs at `http://localhost:
|
|
47
|
+
Your local SPAPS server runs at `http://localhost:3301` 🎉
|
|
48
48
|
|
|
49
|
-
- API docs (Swagger UI): `http://localhost:
|
|
50
|
-
- OpenAPI JSON: `http://localhost:
|
|
49
|
+
- API docs (Swagger UI): `http://localhost:3301/docs`
|
|
50
|
+
- OpenAPI JSON: `http://localhost:3301/openapi.json`
|
|
51
51
|
|
|
52
52
|
Point your app (via `SPAPS_API_URL`) to that URL and use `spaps-sdk` for calls.
|
|
53
53
|
|
|
54
54
|
## Local → Prod
|
|
55
55
|
|
|
56
56
|
- Local (dev):
|
|
57
|
-
- `SPAPS_API_URL=http://localhost:
|
|
57
|
+
- `SPAPS_API_URL=http://localhost:3301`
|
|
58
58
|
- `SPAPS_LOCAL_MODE=true` (or auto‑detected on localhost)
|
|
59
59
|
- API key optional; helpers available (test users, permissive CORS)
|
|
60
60
|
- Prod:
|
|
@@ -86,7 +86,7 @@ Perfect for **rapid prototyping**, **hackathons**, and **local development**.
|
|
|
86
86
|
Start a full-featured local server with zero configuration:
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
spaps local # Default: http://localhost:
|
|
89
|
+
spaps local # Default: http://localhost:3301
|
|
90
90
|
spaps local --port 3000 # Custom port
|
|
91
91
|
spaps local --stripe mock|real # Choose Stripe mode (default: mock)
|
|
92
92
|
spaps local --seed demo # Seed demo products/customers/orders
|
|
@@ -103,7 +103,7 @@ Includes:
|
|
|
103
103
|
|
|
104
104
|
Flags:
|
|
105
105
|
|
|
106
|
-
- `--port <number>`: Set a custom port (default:
|
|
106
|
+
- `--port <number>`: Set a custom port (default: 3301)
|
|
107
107
|
- `--stripe <mode>`: Stripe mode `mock` (offline, default) or `real` (test API)
|
|
108
108
|
- `--seed <preset>`: Seed local data; supported: `demo`
|
|
109
109
|
- `--open`: Open docs in your browser after start
|
|
@@ -159,7 +159,7 @@ npx spaps doctor --json
|
|
|
159
159
|
OpenAPI JSON:
|
|
160
160
|
|
|
161
161
|
```bash
|
|
162
|
-
curl http://localhost:
|
|
162
|
+
curl http://localhost:3301/openapi.json | jq '.'
|
|
163
163
|
```
|
|
164
164
|
```
|
|
165
165
|
|
|
@@ -175,10 +175,10 @@ Switch between user roles instantly (local server only):
|
|
|
175
175
|
|
|
176
176
|
```bash
|
|
177
177
|
# Prefer header (local‑only)
|
|
178
|
-
curl -H "X-Test-User: premium" "http://localhost:
|
|
178
|
+
curl -H "X-Test-User: premium" "http://localhost:3301/api/auth/user"
|
|
179
179
|
|
|
180
180
|
# Or query param (local‑only convenience)
|
|
181
|
-
curl "http://localhost:
|
|
181
|
+
curl "http://localhost:3301/api/auth/user?_user=admin"
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
Available roles: `user`, `admin`, `premium`
|
|
@@ -224,7 +224,7 @@ Visit `/admin` for a complete management interface:
|
|
|
224
224
|
```javascript
|
|
225
225
|
// React/Next.js example
|
|
226
226
|
const createCheckout = async () => {
|
|
227
|
-
const response = await fetch('http://localhost:
|
|
227
|
+
const response = await fetch('http://localhost:3301/api/stripe/checkout-sessions', {
|
|
228
228
|
method: 'POST',
|
|
229
229
|
headers: { 'Content-Type': 'application/json' },
|
|
230
230
|
body: JSON.stringify({
|
|
@@ -243,10 +243,10 @@ const createCheckout = async () => {
|
|
|
243
243
|
|
|
244
244
|
```javascript
|
|
245
245
|
// Test as admin user
|
|
246
|
-
fetch('http://localhost:
|
|
246
|
+
fetch('http://localhost:3301/api/auth/user?_user=admin')
|
|
247
247
|
|
|
248
248
|
// Test wallet authentication
|
|
249
|
-
fetch('http://localhost:
|
|
249
|
+
fetch('http://localhost:3301/api/auth/wallet-sign-in', {
|
|
250
250
|
method: 'POST',
|
|
251
251
|
body: JSON.stringify({
|
|
252
252
|
wallet_address: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
|
|
@@ -258,7 +258,7 @@ fetch('http://localhost:3300/api/auth/wallet-sign-in', {
|
|
|
258
258
|
## 🏗️ Development Workflow
|
|
259
259
|
|
|
260
260
|
1. **Start SPAPS**: `npx spaps local`
|
|
261
|
-
2. **Build your frontend** against `http://localhost:
|
|
261
|
+
2. **Build your frontend** against `http://localhost:3301`
|
|
262
262
|
3. **Test payments** using Stripe's test cards
|
|
263
263
|
4. **Monitor webhooks** at `/api/stripe/webhooks/test`
|
|
264
264
|
5. **Manage data** via `/admin` dashboard
|
|
@@ -293,7 +293,7 @@ curl -X POST "$SPAPS_API_URL/api/stripe/checkout-sessions" \
|
|
|
293
293
|
Local (no key, role sim via header):
|
|
294
294
|
|
|
295
295
|
```bash
|
|
296
|
-
export SPAPS_API_URL=http://localhost:
|
|
296
|
+
export SPAPS_API_URL=http://localhost:3301
|
|
297
297
|
|
|
298
298
|
curl -X GET "$SPAPS_API_URL/api/auth/user" \
|
|
299
299
|
-H "X-Test-User: admin" \
|
|
@@ -355,7 +355,7 @@ Ready to go live? SPAPS supports seamless migration from local to production:
|
|
|
355
355
|
1. **Export Local Data**:
|
|
356
356
|
```bash
|
|
357
357
|
# Export your products, orders, and customers
|
|
358
|
-
curl http://localhost:
|
|
358
|
+
curl http://localhost:3301/api/admin/export > spaps-data.json
|
|
359
359
|
```
|
|
360
360
|
|
|
361
361
|
2. **Set Up Production Server**:
|
package/client.js
CHANGED
|
@@ -21,7 +21,7 @@ try {
|
|
|
21
21
|
|
|
22
22
|
class SPAPSClient {
|
|
23
23
|
constructor(config = {}) {
|
|
24
|
-
const apiUrl = config.apiUrl || process.env.SPAPS_API_URL || 'http://localhost:
|
|
24
|
+
const apiUrl = config.apiUrl || process.env.SPAPS_API_URL || 'http://localhost:3301';
|
|
25
25
|
this.isLocalMode = apiUrl.includes('localhost') || apiUrl.includes('127.0.0.1');
|
|
26
26
|
|
|
27
27
|
this.client = axios.create({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spaps",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Sweet Potato Authentication & Payment Service CLI -
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Sweet Potato Authentication & Payment Service CLI - Docker Compose orchestrator for local Python/FastAPI SPAPS server with built-in admin middleware",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"spaps": "./bin/spaps.js"
|
|
@@ -42,14 +42,9 @@
|
|
|
42
42
|
"axios": "^1.12.2",
|
|
43
43
|
"chalk": "^4.1.2",
|
|
44
44
|
"commander": "^11.1.0",
|
|
45
|
-
"cors": "^2.8.5",
|
|
46
|
-
"express": "^4.18.2",
|
|
47
45
|
"js-yaml": "^4.1.0",
|
|
48
|
-
"swagger-ui-dist": "^5.17.14",
|
|
49
46
|
"ora": "^5.4.1",
|
|
50
|
-
"prompts": "^2.4.2"
|
|
51
|
-
"stripe": "^18.5.0",
|
|
52
|
-
"uuid": "^8.3.2"
|
|
47
|
+
"prompts": "^2.4.2"
|
|
53
48
|
},
|
|
54
49
|
"engines": {
|
|
55
50
|
"node": ">=22.0.0"
|
package/src/ai-helper.js
CHANGED
|
@@ -43,7 +43,7 @@ test().then(console.log).catch(console.error);`
|
|
|
43
43
|
expected_output: {
|
|
44
44
|
success: true,
|
|
45
45
|
user: {
|
|
46
|
-
id: "
|
|
46
|
+
id: "00000000-0000-0000-0000-000000000002",
|
|
47
47
|
email: "test@example.com"
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -143,7 +143,7 @@ function getServerStatus(port = DEFAULT_PORT) {
|
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
async function runQuickTest(port =
|
|
146
|
+
async function runQuickTest(port = 3301) {
|
|
147
147
|
const results = [];
|
|
148
148
|
|
|
149
149
|
// Check server
|
package/src/cli-dispatcher.js
CHANGED
|
@@ -45,31 +45,45 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
45
45
|
|
|
46
46
|
// spaps local
|
|
47
47
|
const cmdLocal = program
|
|
48
|
-
.command('local')
|
|
49
|
-
.description('Start local SPAPS server
|
|
50
|
-
.option('-p, --port <port>', 'Port to
|
|
51
|
-
.option('-
|
|
52
|
-
.option('--
|
|
48
|
+
.command('local [subcommand]')
|
|
49
|
+
.description('Start local SPAPS server via Docker Compose (subcommand: stop)')
|
|
50
|
+
.option('-p, --port <port>', 'Port to check (default: 3301)', String(DEFAULT_PORT))
|
|
51
|
+
.option('-d, --detach', 'Run in background (don\'t tail logs)', false)
|
|
52
|
+
.option('--fresh', 'Fresh start: tear down and rebuild from scratch', false)
|
|
53
|
+
.option('--from-backup <path>', 'Load from Supabase backup file', null)
|
|
53
54
|
.option('-o, --open', 'Open browser automatically', false)
|
|
54
55
|
.option('--json', 'Output in JSON format')
|
|
55
56
|
.action(
|
|
56
|
-
makeAction('local', (
|
|
57
|
+
makeAction('local', (subcommandOrOpts, cmdOrOpts, isJsonOrCmd) => {
|
|
58
|
+
// Handle both 'local' and 'local stop' cases
|
|
59
|
+
let subcommand = null;
|
|
60
|
+
let opts = null;
|
|
61
|
+
let cmd = null;
|
|
62
|
+
let isJson = false;
|
|
63
|
+
|
|
64
|
+
if (typeof subcommandOrOpts === 'string') {
|
|
65
|
+
// 'local stop' case
|
|
66
|
+
subcommand = subcommandOrOpts;
|
|
67
|
+
opts = cmdOrOpts;
|
|
68
|
+
cmd = isJsonOrCmd;
|
|
69
|
+
isJson = Boolean(opts.json || (cmd && cmd.parent && cmd.parent.opts().json));
|
|
70
|
+
} else {
|
|
71
|
+
// 'local' case (no subcommand)
|
|
72
|
+
opts = subcommandOrOpts;
|
|
73
|
+
cmd = cmdOrOpts;
|
|
74
|
+
isJson = Boolean(opts.json || (cmd && cmd.parent && cmd.parent.opts().json));
|
|
75
|
+
}
|
|
76
|
+
|
|
57
77
|
const out = {
|
|
58
|
-
port: Number(opts.port),
|
|
78
|
+
port: Number(opts.port) || 3301,
|
|
59
79
|
open: Boolean(opts.open),
|
|
80
|
+
detach: Boolean(opts.detach),
|
|
81
|
+
fresh: Boolean(opts.fresh),
|
|
82
|
+
fromBackup: opts.fromBackup || null,
|
|
83
|
+
stop: subcommand === 'stop',
|
|
60
84
|
json: isJson,
|
|
61
85
|
};
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
const srcStripe = typeof cmd.getOptionValueSource === 'function' ? cmd.getOptionValueSource('stripe') : null;
|
|
65
|
-
const srcSeed = typeof cmd.getOptionValueSource === 'function' ? cmd.getOptionValueSource('seed') : null;
|
|
66
|
-
if (srcStripe === 'cli') out.stripe = String(opts.stripe || '').toLowerCase();
|
|
67
|
-
if (srcSeed === 'cli') out.seed = String(opts.seed || '').toLowerCase();
|
|
68
|
-
} catch (_) {
|
|
69
|
-
// Commander versions without getOptionValueSource; fall back to only including when present
|
|
70
|
-
if (typeof opts.stripe !== 'undefined') out.stripe = String(opts.stripe).toLowerCase();
|
|
71
|
-
if (typeof opts.seed !== 'undefined') out.seed = String(opts.seed).toLowerCase();
|
|
72
|
-
}
|
|
86
|
+
|
|
73
87
|
return out;
|
|
74
88
|
})
|
|
75
89
|
);
|
package/src/config.js
CHANGED
package/src/docs-html.js
CHANGED
package/src/docs-system.js
CHANGED
|
@@ -24,7 +24,7 @@ ${chalk.green('Basic Usage:')}
|
|
|
24
24
|
|
|
25
25
|
${chalk.gray('// Create client (auto-detects local mode)')}
|
|
26
26
|
const sdk = new SweetPotatoSDK({
|
|
27
|
-
apiUrl: process.env.SPAPS_API_URL || 'http://localhost:
|
|
27
|
+
apiUrl: process.env.SPAPS_API_URL || 'http://localhost:3301',
|
|
28
28
|
apiKey: process.env.SPAPS_API_KEY, ${chalk.gray('// Not required in local mode')}
|
|
29
29
|
})
|
|
30
30
|
|
|
@@ -98,16 +98,16 @@ ${chalk.green('Usage Tracking:')}
|
|
|
98
98
|
content: `
|
|
99
99
|
${chalk.green('Environment Variables:')}
|
|
100
100
|
${chalk.gray('# .env or .env.local')}
|
|
101
|
-
SPAPS_API_URL=http://localhost:
|
|
101
|
+
SPAPS_API_URL=http://localhost:3301
|
|
102
102
|
SPAPS_API_KEY=spaps_live_abc123...
|
|
103
103
|
|
|
104
104
|
${chalk.gray('# Next.js (use NEXT_PUBLIC_ prefix)')}
|
|
105
|
-
NEXT_PUBLIC_SPAPS_API_URL=http://localhost:
|
|
105
|
+
NEXT_PUBLIC_SPAPS_API_URL=http://localhost:3301
|
|
106
106
|
NEXT_PUBLIC_SPAPS_API_KEY=spaps_live_abc123...
|
|
107
107
|
|
|
108
108
|
${chalk.green('Configuration Options:')}
|
|
109
109
|
const sdk = new SweetPotatoSDK({
|
|
110
|
-
apiUrl: process.env.SPAPS_API_URL || 'http://localhost:
|
|
110
|
+
apiUrl: process.env.SPAPS_API_URL || 'http://localhost:3301',
|
|
111
111
|
apiKey: process.env.SPAPS_API_KEY, ${chalk.gray('// Omit in local dev')}
|
|
112
112
|
})
|
|
113
113
|
|
|
@@ -132,7 +132,7 @@ ${chalk.green('React Context Setup:')}
|
|
|
132
132
|
import { createContext, useContext } from 'react'
|
|
133
133
|
import { SweetPotatoSDK } from 'spaps-sdk'
|
|
134
134
|
|
|
135
|
-
const sdk = new SweetPotatoSDK({ apiUrl: process.env.NEXT_PUBLIC_SPAPS_API_URL || 'http://localhost:
|
|
135
|
+
const sdk = new SweetPotatoSDK({ apiUrl: process.env.NEXT_PUBLIC_SPAPS_API_URL || 'http://localhost:3301' })
|
|
136
136
|
const SpapsContext = createContext(sdk)
|
|
137
137
|
|
|
138
138
|
export function SpapsProvider({ children }) {
|
|
@@ -447,7 +447,7 @@ ${chalk.green('Interface Examples:')}
|
|
|
447
447
|
${chalk.green('Type-Safe Usage:')}
|
|
448
448
|
${chalk.gray('// Typed client')}
|
|
449
449
|
const spaps: SPAPSClient = new SPAPSClient({
|
|
450
|
-
apiUrl: 'http://localhost:
|
|
450
|
+
apiUrl: 'http://localhost:3301'
|
|
451
451
|
})
|
|
452
452
|
|
|
453
453
|
${chalk.gray('// Typed responses')}
|
|
@@ -486,7 +486,7 @@ ${chalk.green('Unit Testing with Jest:')}
|
|
|
486
486
|
|
|
487
487
|
beforeEach(() => {
|
|
488
488
|
spaps = new SPAPSClient({
|
|
489
|
-
apiUrl: 'http://localhost:
|
|
489
|
+
apiUrl: 'http://localhost:3301'
|
|
490
490
|
})
|
|
491
491
|
})
|
|
492
492
|
|
|
@@ -600,7 +600,7 @@ ${chalk.green('Health Endpoints:')}
|
|
|
600
600
|
GET /health/local-mode ${chalk.gray('Local mode status')}
|
|
601
601
|
|
|
602
602
|
${chalk.green('Local Mode Features:')}
|
|
603
|
-
${chalk.gray('In local mode (http://localhost:
|
|
603
|
+
${chalk.gray('In local mode (http://localhost:3301):')}
|
|
604
604
|
• No API key required
|
|
605
605
|
• Auto-authentication enabled
|
|
606
606
|
• CORS disabled for all origins
|
package/src/doctor.js
CHANGED
|
@@ -59,7 +59,7 @@ function checkEnvFile() {
|
|
|
59
59
|
check: 'env_file',
|
|
60
60
|
success: exists && hasApiUrl,
|
|
61
61
|
details: { path: envPath, exists, hasApiUrl },
|
|
62
|
-
fix: exists ? (hasApiUrl ? null : 'Add SPAPS_API_URL to .env.local (http://localhost:
|
|
62
|
+
fix: exists ? (hasApiUrl ? null : 'Add SPAPS_API_URL to .env.local (http://localhost:3301)') : 'Run: npx spaps init'
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -105,7 +105,7 @@ function checkEnvTest() {
|
|
|
105
105
|
check: 'env_test',
|
|
106
106
|
success: false,
|
|
107
107
|
details: { path: envPath, exists: false },
|
|
108
|
-
fix: 'Create .env.test with SPAPS_API_URL=http://localhost:
|
|
108
|
+
fix: 'Create .env.test with SPAPS_API_URL=http://localhost:3301 (no real network keys)'
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
try {
|
|
@@ -190,8 +190,8 @@ async function runDoctor({ port = DEFAULT_PORT, stripe = null, json = false } =
|
|
|
190
190
|
results.push({
|
|
191
191
|
check: 'spaps_port_vs_next',
|
|
192
192
|
success: false,
|
|
193
|
-
details: { spaps_port: port, suggestion: 'Use
|
|
194
|
-
fix: 'Run: npx spaps local --port
|
|
193
|
+
details: { spaps_port: port, suggestion: 'Use 3301 for SPAPS to avoid Next.js conflicts' },
|
|
194
|
+
fix: 'Run: npx spaps local --port 3301'
|
|
195
195
|
});
|
|
196
196
|
} else {
|
|
197
197
|
results.push({ check: 'spaps_port_vs_next', success: true, details: { spaps_port: port }, fix: null });
|
package/src/error-handler.js
CHANGED
|
@@ -9,7 +9,7 @@ const ERROR_FIXES = {
|
|
|
9
9
|
// Port errors
|
|
10
10
|
EADDRINUSE: (error, context = {}) => ({
|
|
11
11
|
title: 'Port Already In Use',
|
|
12
|
-
description: `Port ${context.port ||
|
|
12
|
+
description: `Port ${context.port || 3301} is being used by another process`,
|
|
13
13
|
causes: [
|
|
14
14
|
'Another SPAPS server is already running',
|
|
15
15
|
'Another application is using this port',
|
|
@@ -17,16 +17,16 @@ const ERROR_FIXES = {
|
|
|
17
17
|
],
|
|
18
18
|
fixes: [
|
|
19
19
|
{
|
|
20
|
-
command: `npx spaps local --port ${(parseInt(context.port ||
|
|
20
|
+
command: `npx spaps local --port ${(parseInt(context.port || 3301) + 1)}`,
|
|
21
21
|
description: 'Use a different port'
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
|
-
command: `lsof -ti:${context.port ||
|
|
24
|
+
command: `lsof -ti:${context.port || 3301} | xargs kill -9`,
|
|
25
25
|
description: 'Kill the process using this port (macOS/Linux)',
|
|
26
26
|
platform: ['darwin', 'linux']
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
command: `netstat -ano | findstr :${context.port ||
|
|
29
|
+
command: `netstat -ano | findstr :${context.port || 3301}`,
|
|
30
30
|
description: 'Find process using this port (Windows)',
|
|
31
31
|
platform: ['win32']
|
|
32
32
|
},
|
|
@@ -106,7 +106,7 @@ const ERROR_FIXES = {
|
|
|
106
106
|
description: 'Start the local SPAPS server'
|
|
107
107
|
},
|
|
108
108
|
{
|
|
109
|
-
command: 'curl http://localhost:
|
|
109
|
+
command: 'curl http://localhost:3301/health',
|
|
110
110
|
description: 'Check if server is responding'
|
|
111
111
|
},
|
|
112
112
|
{
|
|
@@ -268,4 +268,4 @@ module.exports = {
|
|
|
268
268
|
|
|
269
269
|
process.exit(exitCode);
|
|
270
270
|
}
|
|
271
|
-
};
|
|
271
|
+
};
|
package/src/handlers.js
CHANGED
|
@@ -13,33 +13,42 @@ function createHandlers(version, logo) {
|
|
|
13
13
|
local: async ({ options }) => {
|
|
14
14
|
const isJson = options.json;
|
|
15
15
|
if (!isJson) console.log(logo);
|
|
16
|
+
|
|
17
|
+
// Handle stop subcommand
|
|
18
|
+
if (options.stop) {
|
|
19
|
+
try {
|
|
20
|
+
const LocalServer = require('./local-server.js');
|
|
21
|
+
const server = new LocalServer({ json: isJson });
|
|
22
|
+
server.stop();
|
|
23
|
+
return;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
handleError(error, { command: 'local stop' }, { json: isJson });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Handle start
|
|
16
30
|
try {
|
|
17
31
|
const LocalServer = require('./local-server.js');
|
|
18
|
-
const server = new LocalServer({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
await server.start();
|
|
34
|
-
if (options.open) {
|
|
35
|
-
const { exec } = require('child_process');
|
|
36
|
-
const url = `http://localhost:${options.port}/docs`;
|
|
37
|
-
const start = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
38
|
-
exec(`${start} ${url}`);
|
|
39
|
-
}
|
|
32
|
+
const server = new LocalServer({
|
|
33
|
+
port: options.port,
|
|
34
|
+
json: isJson,
|
|
35
|
+
detach: options.detach,
|
|
36
|
+
fresh: options.fresh,
|
|
37
|
+
fromBackup: options.fromBackup
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await server.start();
|
|
41
|
+
|
|
42
|
+
if (options.open && !isJson) {
|
|
43
|
+
const { exec } = require('child_process');
|
|
44
|
+
const url = `http://localhost:${options.port}/docs`;
|
|
45
|
+
const start = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
46
|
+
exec(`${start} ${url}`);
|
|
40
47
|
}
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
|
|
49
|
+
// Set up shutdown handler
|
|
50
|
+
process.on('SIGINT', async () => {
|
|
51
|
+
await server.shutdown();
|
|
43
52
|
process.exit(0);
|
|
44
53
|
});
|
|
45
54
|
} catch (error) {
|
package/src/help-system.js
CHANGED
|
@@ -182,10 +182,10 @@ const HELP_TREE = {
|
|
|
182
182
|
solution: {
|
|
183
183
|
commands: [
|
|
184
184
|
'npx spaps local --port 3301',
|
|
185
|
-
'lsof -ti:
|
|
185
|
+
'lsof -ti:3301 | xargs kill -9',
|
|
186
186
|
'npx spaps local --port 0'
|
|
187
187
|
],
|
|
188
|
-
explanation: 'Another process is using port
|
|
188
|
+
explanation: 'Another process is using port 3301. Either use a different port or kill the existing process.'
|
|
189
189
|
}
|
|
190
190
|
},
|
|
191
191
|
{
|
|
@@ -216,8 +216,8 @@ const HELP_TREE = {
|
|
|
216
216
|
value: 'auth-error',
|
|
217
217
|
solution: {
|
|
218
218
|
commands: [
|
|
219
|
-
'curl http://localhost:
|
|
220
|
-
'npx spaps local --port
|
|
219
|
+
'curl http://localhost:3301/health',
|
|
220
|
+
'npx spaps local --port 3301'
|
|
221
221
|
],
|
|
222
222
|
explanation: 'In local mode, authentication is automatic. Make sure the local server is running.'
|
|
223
223
|
}
|
|
@@ -251,7 +251,7 @@ In local mode, everything is mocked so you can develop without:
|
|
|
251
251
|
title: 'Local vs Production',
|
|
252
252
|
value: 'environments',
|
|
253
253
|
content: `
|
|
254
|
-
**Local Mode** (http://localhost:
|
|
254
|
+
**Local Mode** (http://localhost:3301):
|
|
255
255
|
- No API key required
|
|
256
256
|
- Auto-authentication
|
|
257
257
|
- Mocked responses
|
|
@@ -473,7 +473,7 @@ function showQuickHelp() {
|
|
|
473
473
|
console.log();
|
|
474
474
|
|
|
475
475
|
console.log(chalk.green('Debugging:'));
|
|
476
|
-
console.log(' curl http://localhost:
|
|
476
|
+
console.log(' curl http://localhost:3301/health ' + chalk.gray('# Check server'));
|
|
477
477
|
console.log(' npx spaps help --interactive ' + chalk.gray('# Interactive help'));
|
|
478
478
|
console.log();
|
|
479
479
|
|