spaps 0.7.6 ā 0.7.8
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 +5566 -38
- package/README.md +67 -13
- package/assets/local-runtime/Dockerfile +13 -0
- package/assets/local-runtime/docker-compose.yml +2 -1
- package/assets/local-runtime/manifest.json +3 -1
- package/bin/spaps.js +34 -8
- package/package.json +3 -4
- package/src/ai-helper.js +44 -10
- package/src/ai-tool-spec.js +19 -4
- package/src/auth/env.js +5 -0
- package/src/cli-dispatcher.js +365 -91
- package/src/docs-quick.js +37 -0
- package/src/docs-system.js +1 -31
- package/src/doctor.js +58 -1
- package/src/domain-cli.js +79 -0
- package/src/domains.js +193 -0
- package/src/fixture-kernel.js +898 -29
- package/src/handlers.js +535 -29
- package/src/help-quick.js +42 -0
- package/src/help-system.js +1 -36
- package/src/home-view.js +200 -0
- package/src/local-runtime.js +19 -4
- package/src/local-server.js +30 -1
package/src/cli-dispatcher.js
CHANGED
|
@@ -44,6 +44,38 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function allowDryRun(command) {
|
|
48
|
+
if (!dryRun) return command;
|
|
49
|
+
command.allowUnknownOption(true);
|
|
50
|
+
if (typeof command.allowExcessArguments === 'function') {
|
|
51
|
+
command.allowExcessArguments(true);
|
|
52
|
+
}
|
|
53
|
+
return command;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function addRemoteCommandOptions(command) {
|
|
57
|
+
return command
|
|
58
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
59
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
60
|
+
.option('--json', 'Output in JSON format');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// spaps home
|
|
64
|
+
const cmdHome = program
|
|
65
|
+
.command('home')
|
|
66
|
+
.description('Show operator, app, and runtime state')
|
|
67
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
68
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
69
|
+
.option('--json', 'Output in JSON format')
|
|
70
|
+
.action(
|
|
71
|
+
makeAction('home', (opts, _cmd, isJson) => ({
|
|
72
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
73
|
+
serverUrl: opts.serverUrl || null,
|
|
74
|
+
json: isJson,
|
|
75
|
+
}))
|
|
76
|
+
);
|
|
77
|
+
allowDryRun(cmdHome);
|
|
78
|
+
|
|
47
79
|
// spaps local
|
|
48
80
|
const cmdLocal = program
|
|
49
81
|
.command('local [subcommand]')
|
|
@@ -58,7 +90,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
58
90
|
)
|
|
59
91
|
.option('-d, --detach', 'Run in background (don\'t tail logs)', false)
|
|
60
92
|
.option('--fresh', 'Fresh start: tear down and rebuild from scratch', false)
|
|
61
|
-
.option('--from-backup <path>', 'Load from
|
|
93
|
+
.option('--from-backup <path>', 'Load from database dump file', null)
|
|
62
94
|
.option('-o, --open', 'Open browser automatically', false)
|
|
63
95
|
.option('--json', 'Output in JSON format')
|
|
64
96
|
.action(
|
|
@@ -80,12 +112,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
80
112
|
return out;
|
|
81
113
|
})
|
|
82
114
|
);
|
|
83
|
-
|
|
84
|
-
cmdLocal.allowUnknownOption(true);
|
|
85
|
-
if (typeof cmdLocal.allowExcessArguments === 'function') {
|
|
86
|
-
cmdLocal.allowExcessArguments(true);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
115
|
+
allowDryRun(cmdLocal);
|
|
89
116
|
|
|
90
117
|
// spaps quickstart
|
|
91
118
|
const cmdQuick = program
|
|
@@ -94,12 +121,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
94
121
|
.option('-p, --port <port>', 'Port to check', String(DEFAULT_PORT))
|
|
95
122
|
.option('--json', 'Output in JSON format')
|
|
96
123
|
.action(makeAction('quickstart', (opts, _cmd, isJson) => ({ port: Number(opts.port), json: isJson })));
|
|
97
|
-
|
|
98
|
-
cmdQuick.allowUnknownOption(true);
|
|
99
|
-
if (typeof cmdQuick.allowExcessArguments === 'function') {
|
|
100
|
-
cmdQuick.allowExcessArguments(true);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
124
|
+
allowDryRun(cmdQuick);
|
|
103
125
|
|
|
104
126
|
// spaps status
|
|
105
127
|
const cmdStatus = program
|
|
@@ -108,12 +130,24 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
108
130
|
.option('-p, --port <port>', 'Port to check', String(DEFAULT_PORT))
|
|
109
131
|
.option('--json', 'Output in JSON format')
|
|
110
132
|
.action(makeAction('status', (opts, _cmd, isJson) => ({ port: Number(opts.port), json: isJson })));
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
133
|
+
allowDryRun(cmdStatus);
|
|
134
|
+
|
|
135
|
+
// spaps verify
|
|
136
|
+
const cmdVerify = program
|
|
137
|
+
.command('verify')
|
|
138
|
+
.alias('test')
|
|
139
|
+
.description('Run a quick SPAPS verification')
|
|
140
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
141
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
142
|
+
.option('--json', 'Output in JSON format')
|
|
143
|
+
.action(
|
|
144
|
+
makeAction('verify', (opts, _cmd, isJson) => ({
|
|
145
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
146
|
+
serverUrl: opts.serverUrl || null,
|
|
147
|
+
json: isJson,
|
|
148
|
+
}))
|
|
149
|
+
);
|
|
150
|
+
allowDryRun(cmdVerify);
|
|
117
151
|
|
|
118
152
|
// spaps init
|
|
119
153
|
const cmdInit = program
|
|
@@ -121,12 +155,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
121
155
|
.description('Initialize SPAPS in current project')
|
|
122
156
|
.option('--json', 'Output in JSON format')
|
|
123
157
|
.action(makeAction('init', (_opts, _cmd, isJson) => ({ json: isJson })));
|
|
124
|
-
|
|
125
|
-
cmdInit.allowUnknownOption(true);
|
|
126
|
-
if (typeof cmdInit.allowExcessArguments === 'function') {
|
|
127
|
-
cmdInit.allowExcessArguments(true);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
158
|
+
allowDryRun(cmdInit);
|
|
130
159
|
|
|
131
160
|
// spaps create <name>
|
|
132
161
|
const cmdCreate = program
|
|
@@ -147,24 +176,14 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
147
176
|
json: isJson,
|
|
148
177
|
}))
|
|
149
178
|
);
|
|
150
|
-
|
|
151
|
-
cmdCreate.allowUnknownOption(true);
|
|
152
|
-
if (typeof cmdCreate.allowExcessArguments === 'function') {
|
|
153
|
-
cmdCreate.allowExcessArguments(true);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
179
|
+
allowDryRun(cmdCreate);
|
|
156
180
|
|
|
157
181
|
// spaps types
|
|
158
182
|
const cmdTypes = program
|
|
159
183
|
.command('types')
|
|
160
184
|
.description('Generate TypeScript types (coming soon)')
|
|
161
185
|
.action(makeAction('types', () => ({})));
|
|
162
|
-
|
|
163
|
-
cmdTypes.allowUnknownOption(true);
|
|
164
|
-
if (typeof cmdTypes.allowExcessArguments === 'function') {
|
|
165
|
-
cmdTypes.allowExcessArguments(true);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
186
|
+
allowDryRun(cmdTypes);
|
|
168
187
|
|
|
169
188
|
// spaps help
|
|
170
189
|
const cmdHelp = program
|
|
@@ -175,12 +194,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
175
194
|
.action(
|
|
176
195
|
makeAction('help', (opts) => ({ interactive: Boolean(opts.interactive), quick: Boolean(opts.quick) }))
|
|
177
196
|
);
|
|
178
|
-
|
|
179
|
-
cmdHelp.allowUnknownOption(true);
|
|
180
|
-
if (typeof cmdHelp.allowExcessArguments === 'function') {
|
|
181
|
-
cmdHelp.allowExcessArguments(true);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
197
|
+
allowDryRun(cmdHelp);
|
|
184
198
|
|
|
185
199
|
// spaps docs
|
|
186
200
|
const cmdDocs = program
|
|
@@ -192,12 +206,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
192
206
|
.action(
|
|
193
207
|
makeAction('docs', (opts, _cmd, isJson) => ({ interactive: Boolean(opts.interactive), search: opts.search || null, json: isJson }))
|
|
194
208
|
);
|
|
195
|
-
|
|
196
|
-
cmdDocs.allowUnknownOption(true);
|
|
197
|
-
if (typeof cmdDocs.allowExcessArguments === 'function') {
|
|
198
|
-
cmdDocs.allowExcessArguments(true);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
209
|
+
allowDryRun(cmdDocs);
|
|
201
210
|
|
|
202
211
|
// spaps tools
|
|
203
212
|
const cmdTools = program
|
|
@@ -209,12 +218,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
209
218
|
.action(
|
|
210
219
|
makeAction('tools', (opts, _cmd, isJson) => ({ port: Number(opts.port), format: String(opts.format || 'openai'), json: isJson }))
|
|
211
220
|
);
|
|
212
|
-
|
|
213
|
-
cmdTools.allowUnknownOption(true);
|
|
214
|
-
if (typeof cmdTools.allowExcessArguments === 'function') {
|
|
215
|
-
cmdTools.allowExcessArguments(true);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
221
|
+
allowDryRun(cmdTools);
|
|
218
222
|
|
|
219
223
|
// spaps fixtures
|
|
220
224
|
const cmdFixtures = program
|
|
@@ -223,7 +227,8 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
223
227
|
.option('--dir <dir>', 'Target repo directory (defaults to current working directory)')
|
|
224
228
|
.option('-p, --port <port>', 'Port to inspect for SPAPS runtime hints', String(DEFAULT_PORT))
|
|
225
229
|
.option('--base-url <url>', 'Browser app base URL for generated storage-state files')
|
|
226
|
-
.option('--persona <persona>', 'Persona code to target for storage-state export')
|
|
230
|
+
.option('--persona <persona>', 'Persona code to target for apply or storage-state export')
|
|
231
|
+
.option('--seed', 'Run persona-declared seed requests against the local SPAPS server', false)
|
|
227
232
|
.option('-f, --format <format>', 'Artifact format (playwright)', 'playwright')
|
|
228
233
|
.option('--force', 'Overwrite fixture files during init', false)
|
|
229
234
|
.option('--json', 'Output in JSON format')
|
|
@@ -235,18 +240,14 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
235
240
|
port: Number(opts.port) || DEFAULT_PORT,
|
|
236
241
|
baseUrl: opts.baseUrl || null,
|
|
237
242
|
persona: opts.persona || null,
|
|
243
|
+
seed: Boolean(opts.seed),
|
|
238
244
|
format: String(opts.format || 'playwright'),
|
|
239
245
|
force: Boolean(opts.force),
|
|
240
246
|
json: isJson,
|
|
241
247
|
};
|
|
242
248
|
})
|
|
243
249
|
);
|
|
244
|
-
|
|
245
|
-
cmdFixtures.allowUnknownOption(true);
|
|
246
|
-
if (typeof cmdFixtures.allowExcessArguments === 'function') {
|
|
247
|
-
cmdFixtures.allowExcessArguments(true);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
+
allowDryRun(cmdFixtures);
|
|
250
251
|
|
|
251
252
|
// spaps doctor
|
|
252
253
|
const cmdDoctor = program
|
|
@@ -258,16 +259,12 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
258
259
|
.action(
|
|
259
260
|
makeAction('doctor', (opts, _cmd, isJson) => ({ port: Number(opts.port), stripe: opts.stripe || null, json: isJson }))
|
|
260
261
|
);
|
|
261
|
-
|
|
262
|
-
cmdDoctor.allowUnknownOption(true);
|
|
263
|
-
if (typeof cmdDoctor.allowExcessArguments === 'function') {
|
|
264
|
-
cmdDoctor.allowExcessArguments(true);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
262
|
+
allowDryRun(cmdDoctor);
|
|
267
263
|
|
|
268
264
|
// spaps login
|
|
269
265
|
const cmdLogin = program
|
|
270
266
|
.command('login')
|
|
267
|
+
.alias('connect')
|
|
271
268
|
.description('Authenticate with a SPAPS server (RFC 8628 device flow)')
|
|
272
269
|
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
273
270
|
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
@@ -281,12 +278,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
281
278
|
json: isJson,
|
|
282
279
|
}))
|
|
283
280
|
);
|
|
284
|
-
|
|
285
|
-
cmdLogin.allowUnknownOption(true);
|
|
286
|
-
if (typeof cmdLogin.allowExcessArguments === 'function') {
|
|
287
|
-
cmdLogin.allowExcessArguments(true);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
281
|
+
allowDryRun(cmdLogin);
|
|
290
282
|
|
|
291
283
|
// spaps logout
|
|
292
284
|
const cmdLogout = program
|
|
@@ -302,12 +294,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
302
294
|
json: isJson,
|
|
303
295
|
}))
|
|
304
296
|
);
|
|
305
|
-
|
|
306
|
-
cmdLogout.allowUnknownOption(true);
|
|
307
|
-
if (typeof cmdLogout.allowExcessArguments === 'function') {
|
|
308
|
-
cmdLogout.allowExcessArguments(true);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
297
|
+
allowDryRun(cmdLogout);
|
|
311
298
|
|
|
312
299
|
// spaps whoami
|
|
313
300
|
const cmdWhoami = program
|
|
@@ -323,12 +310,7 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
323
310
|
json: isJson,
|
|
324
311
|
}))
|
|
325
312
|
);
|
|
326
|
-
|
|
327
|
-
cmdWhoami.allowUnknownOption(true);
|
|
328
|
-
if (typeof cmdWhoami.allowExcessArguments === 'function') {
|
|
329
|
-
cmdWhoami.allowExcessArguments(true);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
313
|
+
allowDryRun(cmdWhoami);
|
|
332
314
|
|
|
333
315
|
// spaps token (print access token for piping to curl or env vars)
|
|
334
316
|
const cmdToken = program
|
|
@@ -344,12 +326,304 @@ function defineProgram({ handlers = {}, dryRun = false, version = '0.0.0', logo
|
|
|
344
326
|
json: isJson,
|
|
345
327
|
}))
|
|
346
328
|
);
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
329
|
+
allowDryRun(cmdToken);
|
|
330
|
+
|
|
331
|
+
// spaps dayrate <subcommand>
|
|
332
|
+
const cmdDayrate = program
|
|
333
|
+
.command('dayrate <subcommand>')
|
|
334
|
+
.description('Dayrate domain commands (subcommand: config)')
|
|
335
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
336
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
337
|
+
.option('--json', 'Output in JSON format')
|
|
338
|
+
.action(
|
|
339
|
+
makeAction('dayrate', (opts, cmd, isJson) => ({
|
|
340
|
+
subcommand: cmd.args[0],
|
|
341
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
342
|
+
serverUrl: opts.serverUrl || null,
|
|
343
|
+
json: isJson,
|
|
344
|
+
}))
|
|
345
|
+
);
|
|
346
|
+
allowDryRun(cmdDayrate);
|
|
347
|
+
|
|
348
|
+
// spaps email
|
|
349
|
+
const cmdEmail = program
|
|
350
|
+
.command('email')
|
|
351
|
+
.description('Email domain commands')
|
|
352
|
+
.showHelpAfterError()
|
|
353
|
+
.showSuggestionAfterError()
|
|
354
|
+
.addHelpText('after', '\nUse `spaps email <verb> --help` for verb-specific flags.\n');
|
|
355
|
+
if (!dryRun) {
|
|
356
|
+
cmdEmail.action(() => {
|
|
357
|
+
cmdEmail.outputHelp();
|
|
358
|
+
});
|
|
352
359
|
}
|
|
360
|
+
allowDryRun(cmdEmail);
|
|
361
|
+
|
|
362
|
+
function addEmailSubcommand(name, description, addOptions, shape) {
|
|
363
|
+
const command = cmdEmail.command(name).description(description);
|
|
364
|
+
if (typeof addOptions === 'function') addOptions(command);
|
|
365
|
+
addRemoteCommandOptions(command);
|
|
366
|
+
command.action(
|
|
367
|
+
makeAction('email', (opts, _cmd, isJson) => ({
|
|
368
|
+
subcommand: name,
|
|
369
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
370
|
+
serverUrl: opts.serverUrl || null,
|
|
371
|
+
...shape(opts),
|
|
372
|
+
json: isJson,
|
|
373
|
+
}))
|
|
374
|
+
);
|
|
375
|
+
allowDryRun(command);
|
|
376
|
+
return command;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
addEmailSubcommand(
|
|
380
|
+
'send',
|
|
381
|
+
'Send a transactional email by template key',
|
|
382
|
+
(command) =>
|
|
383
|
+
command
|
|
384
|
+
.requiredOption('--template-key <key>', 'Template key')
|
|
385
|
+
.requiredOption('--to <email>', 'Recipient email address')
|
|
386
|
+
.option('--context <json>', 'Template context as JSON')
|
|
387
|
+
.option('--user-id <id>', 'User id for log attribution')
|
|
388
|
+
.option('--owner-id <id>', 'Owner id for log attribution')
|
|
389
|
+
.option('--subject-override <text>', 'Subject override')
|
|
390
|
+
.option('--body-override <text>', 'Body override'),
|
|
391
|
+
(opts) => ({
|
|
392
|
+
templateKey: opts.templateKey || null,
|
|
393
|
+
to: opts.to || null,
|
|
394
|
+
context: opts.context || null,
|
|
395
|
+
userId: opts.userId || null,
|
|
396
|
+
ownerId: opts.ownerId || null,
|
|
397
|
+
subjectOverride: opts.subjectOverride || null,
|
|
398
|
+
bodyOverride: opts.bodyOverride || null,
|
|
399
|
+
})
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
addEmailSubcommand(
|
|
403
|
+
'get-template',
|
|
404
|
+
'Fetch one email template by key',
|
|
405
|
+
(command) => command.requiredOption('--template-key <key>', 'Template key'),
|
|
406
|
+
(opts) => ({
|
|
407
|
+
templateKey: opts.templateKey || null,
|
|
408
|
+
})
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
addEmailSubcommand(
|
|
412
|
+
'preview',
|
|
413
|
+
'Render a template preview using sample or custom context',
|
|
414
|
+
(command) =>
|
|
415
|
+
command
|
|
416
|
+
.requiredOption('--template-key <key>', 'Template key')
|
|
417
|
+
.option('--context <json>', 'Template context as JSON'),
|
|
418
|
+
(opts) => ({
|
|
419
|
+
templateKey: opts.templateKey || null,
|
|
420
|
+
context: opts.context || null,
|
|
421
|
+
})
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
addEmailSubcommand(
|
|
425
|
+
'logs',
|
|
426
|
+
'List email logs filtered by owner or user',
|
|
427
|
+
(command) =>
|
|
428
|
+
command
|
|
429
|
+
.option('--owner-id <id>', 'Owner id for log attribution')
|
|
430
|
+
.option('--user-id <id>', 'User id for log attribution')
|
|
431
|
+
.option('--limit <n>', 'Pagination limit')
|
|
432
|
+
.option('--offset <n>', 'Pagination offset'),
|
|
433
|
+
(opts) => ({
|
|
434
|
+
ownerId: opts.ownerId || null,
|
|
435
|
+
userId: opts.userId || null,
|
|
436
|
+
limit: opts.limit ? Number(opts.limit) : null,
|
|
437
|
+
offset: opts.offset ? Number(opts.offset) : null,
|
|
438
|
+
})
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
addEmailSubcommand(
|
|
442
|
+
'list-templates',
|
|
443
|
+
'List all templates for the active application',
|
|
444
|
+
null,
|
|
445
|
+
() => ({})
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
addEmailSubcommand(
|
|
449
|
+
'create-template',
|
|
450
|
+
'Create a new template',
|
|
451
|
+
(command) =>
|
|
452
|
+
command
|
|
453
|
+
.requiredOption('--template-key <key>', 'Template key')
|
|
454
|
+
.requiredOption('--name <name>', 'Template display name')
|
|
455
|
+
.requiredOption('--subject <text>', 'Template subject')
|
|
456
|
+
.requiredOption('--html-body <html>', 'Template HTML body')
|
|
457
|
+
.option('--text-body <text>', 'Template text body')
|
|
458
|
+
.option('--description <text>', 'Template description')
|
|
459
|
+
.option('--from-email <email>', 'From email address')
|
|
460
|
+
.option('--from-name <name>', 'From display name')
|
|
461
|
+
.option('--reply-to <email>', 'Reply-to address')
|
|
462
|
+
.option('--variables <json>', 'Template variables JSON')
|
|
463
|
+
.option('--sample-context <json>', 'Sample context JSON')
|
|
464
|
+
.option('--is-active <bool>', 'Template active state')
|
|
465
|
+
.option('--category <category>', 'Template category'),
|
|
466
|
+
(opts) => ({
|
|
467
|
+
templateKey: opts.templateKey || null,
|
|
468
|
+
name: opts.name || null,
|
|
469
|
+
subject: opts.subject || null,
|
|
470
|
+
htmlBody: opts.htmlBody || null,
|
|
471
|
+
textBody: opts.textBody || null,
|
|
472
|
+
description: opts.description || null,
|
|
473
|
+
fromEmail: opts.fromEmail || null,
|
|
474
|
+
fromName: opts.fromName || null,
|
|
475
|
+
replyTo: opts.replyTo || null,
|
|
476
|
+
variables: opts.variables || null,
|
|
477
|
+
sampleContext: opts.sampleContext || null,
|
|
478
|
+
isActive: opts.isActive === undefined ? null : opts.isActive,
|
|
479
|
+
category: opts.category || null,
|
|
480
|
+
})
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
addEmailSubcommand(
|
|
484
|
+
'update-template',
|
|
485
|
+
'Update an existing template',
|
|
486
|
+
(command) =>
|
|
487
|
+
command
|
|
488
|
+
.requiredOption('--template-key <key>', 'Template key')
|
|
489
|
+
.option('--name <name>', 'Template display name')
|
|
490
|
+
.option('--subject <text>', 'Template subject')
|
|
491
|
+
.option('--html-body <html>', 'Template HTML body')
|
|
492
|
+
.option('--text-body <text>', 'Template text body')
|
|
493
|
+
.option('--description <text>', 'Template description')
|
|
494
|
+
.option('--from-email <email>', 'From email address')
|
|
495
|
+
.option('--from-name <name>', 'From display name')
|
|
496
|
+
.option('--reply-to <email>', 'Reply-to address')
|
|
497
|
+
.option('--variables <json>', 'Template variables JSON')
|
|
498
|
+
.option('--sample-context <json>', 'Sample context JSON')
|
|
499
|
+
.option('--is-active <bool>', 'Template active state')
|
|
500
|
+
.option('--category <category>', 'Template category'),
|
|
501
|
+
(opts) => ({
|
|
502
|
+
templateKey: opts.templateKey || null,
|
|
503
|
+
name: opts.name || null,
|
|
504
|
+
subject: opts.subject || null,
|
|
505
|
+
htmlBody: opts.htmlBody || null,
|
|
506
|
+
textBody: opts.textBody || null,
|
|
507
|
+
description: opts.description || null,
|
|
508
|
+
fromEmail: opts.fromEmail || null,
|
|
509
|
+
fromName: opts.fromName || null,
|
|
510
|
+
replyTo: opts.replyTo || null,
|
|
511
|
+
variables: opts.variables || null,
|
|
512
|
+
sampleContext: opts.sampleContext || null,
|
|
513
|
+
isActive: opts.isActive === undefined ? null : opts.isActive,
|
|
514
|
+
category: opts.category || null,
|
|
515
|
+
})
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
addEmailSubcommand(
|
|
519
|
+
'get-override',
|
|
520
|
+
'Fetch the current override for a template',
|
|
521
|
+
(command) => command.requiredOption('--template-key <key>', 'Template key'),
|
|
522
|
+
(opts) => ({
|
|
523
|
+
templateKey: opts.templateKey || null,
|
|
524
|
+
})
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
addEmailSubcommand(
|
|
528
|
+
'set-override',
|
|
529
|
+
'Create or update an override for a template',
|
|
530
|
+
(command) =>
|
|
531
|
+
command
|
|
532
|
+
.requiredOption('--template-key <key>', 'Template key')
|
|
533
|
+
.option('--subject-override <text>', 'Subject override')
|
|
534
|
+
.option('--body-override <text>', 'Body override'),
|
|
535
|
+
(opts) => ({
|
|
536
|
+
templateKey: opts.templateKey || null,
|
|
537
|
+
subjectOverride: opts.subjectOverride || null,
|
|
538
|
+
bodyOverride: opts.bodyOverride || null,
|
|
539
|
+
})
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
addEmailSubcommand(
|
|
543
|
+
'clear-override',
|
|
544
|
+
'Delete an override for a template',
|
|
545
|
+
(command) => command.requiredOption('--template-key <key>', 'Template key'),
|
|
546
|
+
(opts) => ({
|
|
547
|
+
templateKey: opts.templateKey || null,
|
|
548
|
+
})
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
// spaps policy <subcommand>
|
|
552
|
+
const cmdPolicy = program
|
|
553
|
+
.command('policy <subcommand>')
|
|
554
|
+
.description('Policies domain commands (subcommand: list|create|delete)')
|
|
555
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
556
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
557
|
+
.option('--name <name>', 'Policy name (create)')
|
|
558
|
+
.option('--effect <effect>', 'Policy effect: allow|deny (create)')
|
|
559
|
+
.option('--conditions <json>', 'Policy conditions as JSON (create)')
|
|
560
|
+
.option('--description <text>', 'Policy description (create)')
|
|
561
|
+
.option('--priority <n>', 'Policy priority (create)')
|
|
562
|
+
.option('--id <id>', 'Policy id (delete)')
|
|
563
|
+
.option('--is-active <bool>', 'Filter by is_active (list)')
|
|
564
|
+
.option('--limit <n>', 'Limit (list)')
|
|
565
|
+
.option('--json', 'Output in JSON format')
|
|
566
|
+
.action(
|
|
567
|
+
makeAction('policy', (opts, cmd, isJson) => ({
|
|
568
|
+
subcommand: cmd.args[0],
|
|
569
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
570
|
+
serverUrl: opts.serverUrl || null,
|
|
571
|
+
name: opts.name || null,
|
|
572
|
+
effect: opts.effect || null,
|
|
573
|
+
conditions: opts.conditions || null,
|
|
574
|
+
description: opts.description || null,
|
|
575
|
+
priority: opts.priority ? Number(opts.priority) : 0,
|
|
576
|
+
id: opts.id || null,
|
|
577
|
+
isActive: opts.isActive === undefined ? null : opts.isActive,
|
|
578
|
+
limit: opts.limit ? Number(opts.limit) : null,
|
|
579
|
+
json: isJson,
|
|
580
|
+
}))
|
|
581
|
+
);
|
|
582
|
+
allowDryRun(cmdPolicy);
|
|
583
|
+
|
|
584
|
+
// spaps webhook <subcommand>
|
|
585
|
+
const cmdWebhook = program
|
|
586
|
+
.command('webhook <subcommand>')
|
|
587
|
+
.description('Webhooks domain commands (subcommand: list|register)')
|
|
588
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
589
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
590
|
+
.option('--url <url>', 'Destination URL (register)')
|
|
591
|
+
.option('--events <csv>', 'Comma-separated event keys (register)')
|
|
592
|
+
.option('--json', 'Output in JSON format')
|
|
593
|
+
.action(
|
|
594
|
+
makeAction('webhook', (opts, cmd, isJson) => ({
|
|
595
|
+
subcommand: cmd.args[0],
|
|
596
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
597
|
+
serverUrl: opts.serverUrl || null,
|
|
598
|
+
url: opts.url || null,
|
|
599
|
+
events: opts.events || null,
|
|
600
|
+
json: isJson,
|
|
601
|
+
}))
|
|
602
|
+
);
|
|
603
|
+
allowDryRun(cmdWebhook);
|
|
604
|
+
|
|
605
|
+
// spaps issue-reports <subcommand>
|
|
606
|
+
const cmdIssueReports = program
|
|
607
|
+
.command('issue-reports <subcommand>')
|
|
608
|
+
.description('Issue reporting commands (subcommand: list-mine)')
|
|
609
|
+
.option('-p, --port <port>', 'Port (default: 3301)', String(DEFAULT_PORT))
|
|
610
|
+
.option('--server-url <url>', 'Full server URL (overrides --port and SPAPS_API_URL)')
|
|
611
|
+
.option('--status <status>', 'Filter by status')
|
|
612
|
+
.option('--limit <n>', 'Pagination limit')
|
|
613
|
+
.option('--offset <n>', 'Pagination offset')
|
|
614
|
+
.option('--json', 'Output in JSON format')
|
|
615
|
+
.action(
|
|
616
|
+
makeAction('issue-reports', (opts, cmd, isJson) => ({
|
|
617
|
+
subcommand: cmd.args[0],
|
|
618
|
+
port: Number(opts.port) || DEFAULT_PORT,
|
|
619
|
+
serverUrl: opts.serverUrl || null,
|
|
620
|
+
status: opts.status || null,
|
|
621
|
+
limit: opts.limit ? Number(opts.limit) : null,
|
|
622
|
+
offset: opts.offset ? Number(opts.offset) : null,
|
|
623
|
+
json: isJson,
|
|
624
|
+
}))
|
|
625
|
+
);
|
|
626
|
+
allowDryRun(cmdIssueReports);
|
|
353
627
|
|
|
354
628
|
return { program, getIntents: () => intents };
|
|
355
629
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
function showQuickReference() {
|
|
4
|
+
const output = [
|
|
5
|
+
'',
|
|
6
|
+
chalk.yellow('š SPAPS SDK Quick Reference'),
|
|
7
|
+
'',
|
|
8
|
+
chalk.green('Installation:'),
|
|
9
|
+
' npm install spaps-sdk',
|
|
10
|
+
'',
|
|
11
|
+
chalk.green('Basic Setup:'),
|
|
12
|
+
chalk.gray(` import { SPAPSClient } from 'spaps-sdk'`),
|
|
13
|
+
chalk.gray(` const spaps = new SPAPSClient()`),
|
|
14
|
+
'',
|
|
15
|
+
chalk.green('Common Methods:'),
|
|
16
|
+
' await spaps.login(email, password)',
|
|
17
|
+
' await spaps.register(email, password)',
|
|
18
|
+
' await spaps.getUser()',
|
|
19
|
+
' await spaps.createCheckoutSession(priceId, successUrl)',
|
|
20
|
+
' await spaps.getSubscription()',
|
|
21
|
+
' await spaps.getUsageBalance()',
|
|
22
|
+
'',
|
|
23
|
+
chalk.green('Helper Methods:'),
|
|
24
|
+
` spaps.isAuthenticated() ${chalk.gray('// Check auth status')}`,
|
|
25
|
+
` spaps.isLocalMode() ${chalk.gray('// Check if local mode')}`,
|
|
26
|
+
` spaps.getAccessToken() ${chalk.gray('// Get current token')}`,
|
|
27
|
+
'',
|
|
28
|
+
chalk.blue('š Full docs: npx spaps docs --interactive'),
|
|
29
|
+
'',
|
|
30
|
+
].join('\n');
|
|
31
|
+
|
|
32
|
+
process.stdout.write(`${output}\n`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
showQuickReference,
|
|
37
|
+
};
|
package/src/docs-system.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
const chalk = require('chalk');
|
|
7
7
|
const prompts = require('prompts');
|
|
8
|
+
const { showQuickReference } = require('./docs-quick');
|
|
8
9
|
|
|
9
10
|
const SDK_DOCS = {
|
|
10
11
|
quickstart: {
|
|
@@ -676,37 +677,6 @@ async function showInteractiveDocs() {
|
|
|
676
677
|
}
|
|
677
678
|
}
|
|
678
679
|
|
|
679
|
-
function showQuickReference() {
|
|
680
|
-
console.log(chalk.yellow('\nš SPAPS SDK Quick Reference\n'));
|
|
681
|
-
|
|
682
|
-
console.log(chalk.green('Installation:'));
|
|
683
|
-
console.log(' npm install spaps-sdk');
|
|
684
|
-
console.log();
|
|
685
|
-
|
|
686
|
-
console.log(chalk.green('Basic Setup:'));
|
|
687
|
-
console.log(chalk.gray(` import { SPAPSClient } from 'spaps-sdk'`));
|
|
688
|
-
console.log(chalk.gray(` const spaps = new SPAPSClient()`));
|
|
689
|
-
console.log();
|
|
690
|
-
|
|
691
|
-
console.log(chalk.green('Common Methods:'));
|
|
692
|
-
console.log(' await spaps.login(email, password)');
|
|
693
|
-
console.log(' await spaps.register(email, password)');
|
|
694
|
-
console.log(' await spaps.getUser()');
|
|
695
|
-
console.log(' await spaps.createCheckoutSession(priceId, successUrl)');
|
|
696
|
-
console.log(' await spaps.getSubscription()');
|
|
697
|
-
console.log(' await spaps.getUsageBalance()');
|
|
698
|
-
console.log();
|
|
699
|
-
|
|
700
|
-
console.log(chalk.green('Helper Methods:'));
|
|
701
|
-
console.log(' spaps.isAuthenticated() ' + chalk.gray('// Check auth status'));
|
|
702
|
-
console.log(' spaps.isLocalMode() ' + chalk.gray('// Check if local mode'));
|
|
703
|
-
console.log(' spaps.getAccessToken() ' + chalk.gray('// Get current token'));
|
|
704
|
-
console.log();
|
|
705
|
-
|
|
706
|
-
console.log(chalk.blue('š Full docs: npx spaps docs --interactive'));
|
|
707
|
-
console.log();
|
|
708
|
-
}
|
|
709
|
-
|
|
710
680
|
function searchDocs(query) {
|
|
711
681
|
const results = [];
|
|
712
682
|
const searchTerm = query.toLowerCase();
|