@portaidentity/cli 0.1.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/dist/auth/browser-flow.d.ts +42 -0
- package/dist/auth/browser-flow.d.ts.map +1 -0
- package/dist/auth/browser-flow.js +193 -0
- package/dist/auth/browser-flow.js.map +1 -0
- package/dist/auth/callback-server.d.ts +81 -0
- package/dist/auth/callback-server.d.ts.map +1 -0
- package/dist/auth/callback-server.js +193 -0
- package/dist/auth/callback-server.js.map +1 -0
- package/dist/auth/metadata.d.ts +43 -0
- package/dist/auth/metadata.d.ts.map +1 -0
- package/dist/auth/metadata.js +66 -0
- package/dist/auth/metadata.js.map +1 -0
- package/dist/auth/pkce.d.ts +42 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +52 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/types.d.ts +72 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +11 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/client-factory.d.ts +29 -0
- package/dist/client-factory.d.ts.map +1 -0
- package/dist/client-factory.js +43 -0
- package/dist/client-factory.js.map +1 -0
- package/dist/commands/app-claim.d.ts +9 -0
- package/dist/commands/app-claim.d.ts.map +1 -0
- package/dist/commands/app-claim.js +128 -0
- package/dist/commands/app-claim.js.map +1 -0
- package/dist/commands/app-module.d.ts +9 -0
- package/dist/commands/app-module.d.ts.map +1 -0
- package/dist/commands/app-module.js +104 -0
- package/dist/commands/app-module.js.map +1 -0
- package/dist/commands/app-permission.d.ts +9 -0
- package/dist/commands/app-permission.d.ts.map +1 -0
- package/dist/commands/app-permission.js +118 -0
- package/dist/commands/app-permission.js.map +1 -0
- package/dist/commands/app-role.d.ts +9 -0
- package/dist/commands/app-role.d.ts.map +1 -0
- package/dist/commands/app-role.js +166 -0
- package/dist/commands/app-role.js.map +1 -0
- package/dist/commands/app.d.ts +12 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +255 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/audit.d.ts +12 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +96 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/bulk.d.ts +12 -0
- package/dist/commands/bulk.d.ts.map +1 -0
- package/dist/commands/bulk.js +77 -0
- package/dist/commands/bulk.js.map +1 -0
- package/dist/commands/client-secret.d.ts +18 -0
- package/dist/commands/client-secret.d.ts.map +1 -0
- package/dist/commands/client-secret.js +126 -0
- package/dist/commands/client-secret.js.map +1 -0
- package/dist/commands/client.d.ts +27 -0
- package/dist/commands/client.d.ts.map +1 -0
- package/dist/commands/client.js +385 -0
- package/dist/commands/client.js.map +1 -0
- package/dist/commands/completion.d.ts +27 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +42 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/config.d.ts +14 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +85 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/doctor.d.ts +25 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +198 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/exports.d.ts +12 -0
- package/dist/commands/exports.d.ts.map +1 -0
- package/dist/commands/exports.js +80 -0
- package/dist/commands/exports.js.map +1 -0
- package/dist/commands/health.d.ts +12 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +53 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/keys.d.ts +14 -0
- package/dist/commands/keys.d.ts.map +1 -0
- package/dist/commands/keys.js +91 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/login.d.ts +36 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +78 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +25 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +43 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/org.d.ts +26 -0
- package/dist/commands/org.d.ts.map +1 -0
- package/dist/commands/org.js +396 -0
- package/dist/commands/org.js.map +1 -0
- package/dist/commands/provision.d.ts +47 -0
- package/dist/commands/provision.d.ts.map +1 -0
- package/dist/commands/provision.js +400 -0
- package/dist/commands/provision.js.map +1 -0
- package/dist/commands/sessions.d.ts +14 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +122 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/stats.d.ts +12 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +46 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/user-claim.d.ts +17 -0
- package/dist/commands/user-claim.d.ts.map +1 -0
- package/dist/commands/user-claim.js +123 -0
- package/dist/commands/user-claim.js.map +1 -0
- package/dist/commands/user-role.d.ts +17 -0
- package/dist/commands/user-role.d.ts.map +1 -0
- package/dist/commands/user-role.js +118 -0
- package/dist/commands/user-role.js.map +1 -0
- package/dist/commands/user.d.ts +26 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +352 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/commands/version.d.ts +25 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +83 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/commands/whoami.d.ts +26 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +66 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/credential-store.d.ts +101 -0
- package/dist/credential-store.d.ts.map +1 -0
- package/dist/credential-store.js +121 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/error-handler.d.ts +47 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +166 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/global-options.d.ts +50 -0
- package/dist/global-options.d.ts.map +1 -0
- package/dist/global-options.js +62 -0
- package/dist/global-options.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +122 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +75 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +100 -0
- package/dist/output.js.map +1 -0
- package/dist/parsers.d.ts +74 -0
- package/dist/parsers.d.ts.map +1 -0
- package/dist/parsers.js +125 -0
- package/dist/parsers.js.map +1 -0
- package/dist/prompt.d.ts +50 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +98 -0
- package/dist/prompt.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI doctor command — diagnostic checks for the CLI environment.
|
|
3
|
+
*
|
|
4
|
+
* Runs a series of checks to verify the CLI setup is correct:
|
|
5
|
+
* 1. Node.js version (>= 22.0.0 required)
|
|
6
|
+
* 2. Credentials file exists and is readable
|
|
7
|
+
* 3. Token validity (not expired)
|
|
8
|
+
* 4. Server reachability (health endpoint)
|
|
9
|
+
* 5. Admin metadata endpoint accessible
|
|
10
|
+
*
|
|
11
|
+
* Useful for troubleshooting authentication or connectivity issues.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* porta doctor # Run all diagnostic checks
|
|
15
|
+
* porta doctor --json # JSON output (machine-readable)
|
|
16
|
+
*
|
|
17
|
+
* @module commands/doctor
|
|
18
|
+
*/
|
|
19
|
+
import { loadCredentials, isTokenExpired, getCredentialsPath, hasCredentials, } from '../credential-store.js';
|
|
20
|
+
import { fetchHealthStatus, fetchAdminMetadata } from '../auth/metadata.js';
|
|
21
|
+
import { printJson, success, warn, error as printError } from '../output.js';
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Diagnostic Checks
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/**
|
|
26
|
+
* Check Node.js version meets the minimum requirement.
|
|
27
|
+
*/
|
|
28
|
+
function checkNodeVersion() {
|
|
29
|
+
const version = process.version;
|
|
30
|
+
const major = parseInt(version.slice(1).split('.')[0], 10);
|
|
31
|
+
if (major >= 22) {
|
|
32
|
+
return { name: 'Node.js version', status: 'pass', message: `${version} (>= 22 required)` };
|
|
33
|
+
}
|
|
34
|
+
return { name: 'Node.js version', status: 'fail', message: `${version} — Node.js >= 22.0.0 is required` };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check credential file existence and validity.
|
|
38
|
+
*/
|
|
39
|
+
function checkCredentials() {
|
|
40
|
+
const path = getCredentialsPath();
|
|
41
|
+
if (!hasCredentials()) {
|
|
42
|
+
return {
|
|
43
|
+
name: 'Credentials',
|
|
44
|
+
status: 'warn',
|
|
45
|
+
message: `Not found at ${path}. Run "porta login" to authenticate.`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const creds = loadCredentials();
|
|
49
|
+
if (!creds) {
|
|
50
|
+
return {
|
|
51
|
+
name: 'Credentials',
|
|
52
|
+
status: 'fail',
|
|
53
|
+
message: `File exists at ${path} but cannot be parsed. Try "porta logout" then "porta login".`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
name: 'Credentials',
|
|
58
|
+
status: 'pass',
|
|
59
|
+
message: `Found at ${path} (user: ${creds.userInfo.email || creds.userInfo.sub})`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check token expiry status.
|
|
64
|
+
*/
|
|
65
|
+
function checkTokenExpiry() {
|
|
66
|
+
const creds = loadCredentials();
|
|
67
|
+
if (!creds) {
|
|
68
|
+
return { name: 'Token validity', status: 'warn', message: 'No credentials — skipped' };
|
|
69
|
+
}
|
|
70
|
+
if (isTokenExpired(creds)) {
|
|
71
|
+
return {
|
|
72
|
+
name: 'Token validity',
|
|
73
|
+
status: 'warn',
|
|
74
|
+
message: `Expired at ${creds.expiresAt}. Run "porta login" to re-authenticate.`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
name: 'Token validity',
|
|
79
|
+
status: 'pass',
|
|
80
|
+
message: `Valid until ${creds.expiresAt}`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check server reachability via health endpoint.
|
|
85
|
+
*/
|
|
86
|
+
async function checkServerHealth(serverUrl) {
|
|
87
|
+
if (!serverUrl) {
|
|
88
|
+
return {
|
|
89
|
+
name: 'Server health',
|
|
90
|
+
status: 'warn',
|
|
91
|
+
message: 'No server configured — skipped',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const health = await fetchHealthStatus(serverUrl);
|
|
95
|
+
if (!health) {
|
|
96
|
+
return {
|
|
97
|
+
name: 'Server health',
|
|
98
|
+
status: 'fail',
|
|
99
|
+
message: `Cannot reach ${serverUrl}/health`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (health.status === 'ok') {
|
|
103
|
+
const services = health.services
|
|
104
|
+
? Object.entries(health.services).map(([k, v]) => `${k}=${v}`).join(', ')
|
|
105
|
+
: '';
|
|
106
|
+
return {
|
|
107
|
+
name: 'Server health',
|
|
108
|
+
status: 'pass',
|
|
109
|
+
message: `${serverUrl} — OK${services ? ` (${services})` : ''}`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
name: 'Server health',
|
|
114
|
+
status: 'warn',
|
|
115
|
+
message: `${serverUrl} — status: ${health.status}`,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check admin metadata endpoint accessibility.
|
|
120
|
+
*/
|
|
121
|
+
async function checkMetadata(serverUrl) {
|
|
122
|
+
if (!serverUrl) {
|
|
123
|
+
return {
|
|
124
|
+
name: 'Admin metadata',
|
|
125
|
+
status: 'warn',
|
|
126
|
+
message: 'No server configured — skipped',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const metadata = await fetchAdminMetadata(serverUrl);
|
|
131
|
+
return {
|
|
132
|
+
name: 'Admin metadata',
|
|
133
|
+
status: 'pass',
|
|
134
|
+
message: `Org: ${metadata.orgSlug}, Client: ${metadata.clientId.slice(0, 8)}...`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
return {
|
|
139
|
+
name: 'Admin metadata',
|
|
140
|
+
status: 'fail',
|
|
141
|
+
message: err instanceof Error ? err.message : 'Unknown error',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// Command Definition
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
/**
|
|
149
|
+
* The doctor command module — runs diagnostic checks.
|
|
150
|
+
*/
|
|
151
|
+
export const doctorCommand = {
|
|
152
|
+
command: 'doctor',
|
|
153
|
+
describe: 'Run diagnostic checks on CLI configuration',
|
|
154
|
+
handler: async (argv) => {
|
|
155
|
+
// Handle --insecure flag before any HTTP calls
|
|
156
|
+
if (argv.insecure) {
|
|
157
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
158
|
+
}
|
|
159
|
+
// Resolve server URL for network checks
|
|
160
|
+
const creds = loadCredentials();
|
|
161
|
+
const serverUrl = argv.server || process.env.PORTA_SERVER || creds?.server;
|
|
162
|
+
// Run all checks
|
|
163
|
+
const results = [
|
|
164
|
+
checkNodeVersion(),
|
|
165
|
+
checkCredentials(),
|
|
166
|
+
checkTokenExpiry(),
|
|
167
|
+
await checkServerHealth(serverUrl),
|
|
168
|
+
await checkMetadata(serverUrl),
|
|
169
|
+
];
|
|
170
|
+
// Output
|
|
171
|
+
if (argv.json) {
|
|
172
|
+
printJson(results);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log('\nPorta CLI Diagnostics\n');
|
|
176
|
+
for (const check of results) {
|
|
177
|
+
const icon = check.status === 'pass' ? '✅' : check.status === 'warn' ? '⚠️' : '❌';
|
|
178
|
+
console.log(` ${icon} ${check.name}: ${check.message}`);
|
|
179
|
+
}
|
|
180
|
+
console.log('');
|
|
181
|
+
const failures = results.filter((r) => r.status === 'fail');
|
|
182
|
+
const warnings = results.filter((r) => r.status === 'warn');
|
|
183
|
+
if (failures.length > 0) {
|
|
184
|
+
printError(`${failures.length} check(s) failed`);
|
|
185
|
+
}
|
|
186
|
+
else if (warnings.length > 0) {
|
|
187
|
+
warn(`All checks passed with ${warnings.length} warning(s)`);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
success('All checks passed');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Exit with failure if any check failed
|
|
194
|
+
const hasFailure = results.some((r) => r.status === 'fail');
|
|
195
|
+
process.exit(hasFailure ? 1 : 0);
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exports command — export data as CSV or JSON.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* download Export entity data to a file or stdout
|
|
6
|
+
*
|
|
7
|
+
* @module commands/exports
|
|
8
|
+
*/
|
|
9
|
+
import type { CommandModule } from 'yargs';
|
|
10
|
+
import type { GlobalOptions } from '../global-options.js';
|
|
11
|
+
export declare const exportsCommand: CommandModule<GlobalOptions, GlobalOptions>;
|
|
12
|
+
//# sourceMappingURL=exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../src/commands/exports.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAqB1D,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,aAAa,EAAE,aAAa,CAsEtE,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exports command — export data as CSV or JSON.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* download Export entity data to a file or stdout
|
|
6
|
+
*
|
|
7
|
+
* @module commands/exports
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import { createClient } from '../client-factory.js';
|
|
11
|
+
import { handleError } from '../error-handler.js';
|
|
12
|
+
import { success, info } from '../output.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Command
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
export const exportsCommand = {
|
|
17
|
+
command: 'exports',
|
|
18
|
+
describe: 'Export data as CSV or JSON',
|
|
19
|
+
builder: (yargs) => yargs
|
|
20
|
+
.command('download', 'Export entity data', (y) => y
|
|
21
|
+
.option('entity-type', {
|
|
22
|
+
type: 'string',
|
|
23
|
+
describe: 'Entity type to export',
|
|
24
|
+
choices: ['organizations', 'applications', 'clients', 'users', 'roles', 'permissions', 'audit'],
|
|
25
|
+
demandOption: true,
|
|
26
|
+
})
|
|
27
|
+
.option('format', {
|
|
28
|
+
type: 'string',
|
|
29
|
+
describe: 'Export format',
|
|
30
|
+
choices: ['csv', 'json'],
|
|
31
|
+
default: 'csv',
|
|
32
|
+
})
|
|
33
|
+
.option('org-id', {
|
|
34
|
+
type: 'string',
|
|
35
|
+
describe: 'Filter by organization ID',
|
|
36
|
+
})
|
|
37
|
+
.option('app-id', {
|
|
38
|
+
type: 'string',
|
|
39
|
+
describe: 'Filter by application ID',
|
|
40
|
+
})
|
|
41
|
+
.option('output', {
|
|
42
|
+
alias: 'o',
|
|
43
|
+
type: 'string',
|
|
44
|
+
describe: 'Output file path (default: stdout)',
|
|
45
|
+
}), async (argv) => {
|
|
46
|
+
try {
|
|
47
|
+
const client = createClient(argv);
|
|
48
|
+
const response = await client.exports.download({
|
|
49
|
+
entityType: argv['entity-type'],
|
|
50
|
+
format: argv.format,
|
|
51
|
+
organizationId: argv['org-id'],
|
|
52
|
+
applicationId: argv['app-id'],
|
|
53
|
+
});
|
|
54
|
+
// The SDK returns a TransportResponse with raw body
|
|
55
|
+
const content = typeof response.body === 'string'
|
|
56
|
+
? response.body
|
|
57
|
+
: JSON.stringify(response.body, null, 2);
|
|
58
|
+
if (argv.output) {
|
|
59
|
+
fs.writeFileSync(argv.output, content, 'utf-8');
|
|
60
|
+
success(`Exported ${argv['entity-type']} to ${argv.output}`);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Write to stdout
|
|
64
|
+
process.stdout.write(content);
|
|
65
|
+
if (!content.endsWith('\n')) {
|
|
66
|
+
process.stdout.write('\n');
|
|
67
|
+
}
|
|
68
|
+
info(`Exported ${argv['entity-type']} (${argv.format})`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
handleError(err, argv.verbose);
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
.demandCommand(1, 'Please specify an exports subcommand: download'),
|
|
76
|
+
handler: () => {
|
|
77
|
+
// No-op — subcommands handle execution
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.js","sourceRoot":"","sources":["../../src/commands/exports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health command — check server health.
|
|
3
|
+
*
|
|
4
|
+
* Makes a simple HTTP GET to /health on the Porta server.
|
|
5
|
+
* Does not require authentication.
|
|
6
|
+
*
|
|
7
|
+
* @module commands/health
|
|
8
|
+
*/
|
|
9
|
+
import type { CommandModule } from 'yargs';
|
|
10
|
+
import type { GlobalOptions } from '../global-options.js';
|
|
11
|
+
export declare const healthCommand: CommandModule<GlobalOptions, GlobalOptions>;
|
|
12
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/commands/health.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAqB1D,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,aAAa,EAAE,aAAa,CAuCrE,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health command — check server health.
|
|
3
|
+
*
|
|
4
|
+
* Makes a simple HTTP GET to /health on the Porta server.
|
|
5
|
+
* Does not require authentication.
|
|
6
|
+
*
|
|
7
|
+
* @module commands/health
|
|
8
|
+
*/
|
|
9
|
+
import { resolveServerUrl } from '../global-options.js';
|
|
10
|
+
import { handleError } from '../error-handler.js';
|
|
11
|
+
import { printJson, success, error as printError } from '../output.js';
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Command
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
export const healthCommand = {
|
|
16
|
+
command: 'health',
|
|
17
|
+
describe: 'Check Porta server health',
|
|
18
|
+
builder: (y) => y,
|
|
19
|
+
handler: async (argv) => {
|
|
20
|
+
try {
|
|
21
|
+
const serverUrl = resolveServerUrl(argv);
|
|
22
|
+
const url = new URL('/health', serverUrl);
|
|
23
|
+
// Use fetch (Node 22 built-in) for unauthenticated health check
|
|
24
|
+
const response = await fetch(url.toString(), {
|
|
25
|
+
method: 'GET',
|
|
26
|
+
headers: { Accept: 'application/json' },
|
|
27
|
+
// Respect --insecure flag for self-signed certs
|
|
28
|
+
...(argv.insecure ? { dispatcher: undefined } : {}),
|
|
29
|
+
});
|
|
30
|
+
const body = (await response.json());
|
|
31
|
+
if (argv.json) {
|
|
32
|
+
printJson(body);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (response.ok && body.status === 'ok') {
|
|
36
|
+
success(`Server is healthy (${serverUrl})`);
|
|
37
|
+
console.log(` Database: ${body.database}`);
|
|
38
|
+
console.log(` Redis: ${body.redis}`);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
printError(`Server is unhealthy (${serverUrl})`);
|
|
42
|
+
console.log(` Status: ${body.status}`);
|
|
43
|
+
console.log(` Database: ${body.database}`);
|
|
44
|
+
console.log(` Redis: ${body.redis}`);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
handleError(err, argv.verbose);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/commands/health.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAcvE,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,CAAC,MAAM,aAAa,GAAgD;IACxE,OAAO,EAAE,QAAQ;IACjB,QAAQ,EAAE,2BAA2B;IACrC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAE1C,gEAAgE;YAChE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;gBAC3C,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;gBACvC,gDAAgD;gBAChD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpD,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;YAEvD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,IAAI,QAAQ,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBACxC,OAAO,CAAC,sBAAsB,SAAS,GAAG,CAAC,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,wBAAwB,SAAS,GAAG,CAAC,CAAC;gBACjD,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;gBACzC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys command — manage signing keys.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* list List all signing keys
|
|
6
|
+
* generate Generate a new ES256 key pair
|
|
7
|
+
* rotate Rotate: generate new + retire current active
|
|
8
|
+
*
|
|
9
|
+
* @module commands/keys
|
|
10
|
+
*/
|
|
11
|
+
import type { CommandModule } from 'yargs';
|
|
12
|
+
import type { GlobalOptions } from '../global-options.js';
|
|
13
|
+
export declare const keysCommand: CommandModule<GlobalOptions, GlobalOptions>;
|
|
14
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAgB1D,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,aAAa,EAAE,aAAa,CAkGnE,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys command — manage signing keys.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* list List all signing keys
|
|
6
|
+
* generate Generate a new ES256 key pair
|
|
7
|
+
* rotate Rotate: generate new + retire current active
|
|
8
|
+
*
|
|
9
|
+
* @module commands/keys
|
|
10
|
+
*/
|
|
11
|
+
import { createClient } from '../client-factory.js';
|
|
12
|
+
import { handleError } from '../error-handler.js';
|
|
13
|
+
import { printTable, printJson, success, warn, formatDate, truncate } from '../output.js';
|
|
14
|
+
import { confirm } from '../prompt.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Command
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
export const keysCommand = {
|
|
19
|
+
command: 'keys',
|
|
20
|
+
describe: 'Manage signing keys',
|
|
21
|
+
builder: (yargs) => yargs
|
|
22
|
+
// ── list ──────────────────────────────────────────────────────────
|
|
23
|
+
.command('list', 'List all signing keys', (y) => y, async (argv) => {
|
|
24
|
+
try {
|
|
25
|
+
const client = createClient(argv);
|
|
26
|
+
const keys = await client.keys.list();
|
|
27
|
+
if (argv.json) {
|
|
28
|
+
printJson(keys);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (keys.length === 0) {
|
|
32
|
+
warn('No signing keys found');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
printTable(['ID', 'KID', 'Algorithm', 'Status', 'Created', 'Rotated'], keys.map((k) => [
|
|
36
|
+
truncate(k.id, 12),
|
|
37
|
+
k.kid,
|
|
38
|
+
k.algorithm,
|
|
39
|
+
k.isActive ? 'active' : 'retired',
|
|
40
|
+
formatDate(k.createdAt),
|
|
41
|
+
formatDate(k.rotatedAt),
|
|
42
|
+
]));
|
|
43
|
+
success(`${keys.length} signing key(s)`);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
handleError(err, argv.verbose);
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
// ── generate ──────────────────────────────────────────────────────
|
|
50
|
+
.command('generate', 'Generate a new ES256 key pair', (y) => y, async (argv) => {
|
|
51
|
+
try {
|
|
52
|
+
const client = createClient(argv);
|
|
53
|
+
const key = await client.keys.generate();
|
|
54
|
+
if (argv.json) {
|
|
55
|
+
printJson(key);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
success(`Generated signing key: ${key.kid} (${truncate(key.id, 12)})`);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
handleError(err, argv.verbose);
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
// ── rotate ────────────────────────────────────────────────────────
|
|
65
|
+
.command('rotate', 'Rotate signing keys (generate new + retire current active)', (y) => y, async (argv) => {
|
|
66
|
+
try {
|
|
67
|
+
if (!argv.force) {
|
|
68
|
+
const ok = await confirm('Rotate signing keys? This will retire the current active key.');
|
|
69
|
+
if (!ok) {
|
|
70
|
+
warn('Aborted');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const client = createClient(argv);
|
|
75
|
+
const key = await client.keys.rotate();
|
|
76
|
+
if (argv.json) {
|
|
77
|
+
printJson(key);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
success(`Rotated signing keys. New active key: ${key.kid}`);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
handleError(err, argv.verbose);
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
.demandCommand(1, 'Please specify a keys subcommand: list, generate, rotate'),
|
|
87
|
+
handler: () => {
|
|
88
|
+
// No-op — subcommands handle execution
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI login command — authenticate with a Porta server.
|
|
3
|
+
*
|
|
4
|
+
* Implements the OIDC Authorization Code + PKCE flow for CLI authentication.
|
|
5
|
+
* This is the same pattern used by `az login`, `gh auth login`, and similar
|
|
6
|
+
* CLI tools that authenticate via browser-based flows.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* porta login # Login to default server
|
|
10
|
+
* porta login --server https://example.com # Login to remote server
|
|
11
|
+
* porta login --no-browser # Manual mode: print URL, paste callback
|
|
12
|
+
* porta login --client-id <id> # Override auto-discovered client ID
|
|
13
|
+
*
|
|
14
|
+
* Docker / headless environments:
|
|
15
|
+
* When running inside a Docker container (auto-detected via /.dockerenv),
|
|
16
|
+
* the command automatically uses manual mode (--no-browser).
|
|
17
|
+
*
|
|
18
|
+
* @module commands/login
|
|
19
|
+
*/
|
|
20
|
+
import type { CommandModule } from 'yargs';
|
|
21
|
+
import type { GlobalOptions } from '../global-options.js';
|
|
22
|
+
/** Options specific to the login command */
|
|
23
|
+
interface LoginOptions extends GlobalOptions {
|
|
24
|
+
server: string;
|
|
25
|
+
'client-id'?: string;
|
|
26
|
+
'no-browser': boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The login command module — authenticates the CLI with a Porta server.
|
|
30
|
+
*
|
|
31
|
+
* Uses OIDC Authorization Code + PKCE flow. Opens a browser for
|
|
32
|
+
* interactive authentication, then stores the tokens locally.
|
|
33
|
+
*/
|
|
34
|
+
export declare const loginCommand: CommandModule<GlobalOptions, LoginOptions>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAiB1D,4CAA4C;AAC5C,UAAU,YAAa,SAAQ,aAAa;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAMD;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,aAAa,EAAE,YAAY,CA+CnE,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI login command — authenticate with a Porta server.
|
|
3
|
+
*
|
|
4
|
+
* Implements the OIDC Authorization Code + PKCE flow for CLI authentication.
|
|
5
|
+
* This is the same pattern used by `az login`, `gh auth login`, and similar
|
|
6
|
+
* CLI tools that authenticate via browser-based flows.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* porta login # Login to default server
|
|
10
|
+
* porta login --server https://example.com # Login to remote server
|
|
11
|
+
* porta login --no-browser # Manual mode: print URL, paste callback
|
|
12
|
+
* porta login --client-id <id> # Override auto-discovered client ID
|
|
13
|
+
*
|
|
14
|
+
* Docker / headless environments:
|
|
15
|
+
* When running inside a Docker container (auto-detected via /.dockerenv),
|
|
16
|
+
* the command automatically uses manual mode (--no-browser).
|
|
17
|
+
*
|
|
18
|
+
* @module commands/login
|
|
19
|
+
*/
|
|
20
|
+
import { executeBrowserFlow } from '../auth/browser-flow.js';
|
|
21
|
+
import { saveCredentials } from '../credential-store.js';
|
|
22
|
+
import { success } from '../output.js';
|
|
23
|
+
import { handleError } from '../error-handler.js';
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Constants
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/** Default Porta server URL for local development */
|
|
28
|
+
const DEFAULT_SERVER = 'https://porta.local:3443';
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Command Definition
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
/**
|
|
33
|
+
* The login command module — authenticates the CLI with a Porta server.
|
|
34
|
+
*
|
|
35
|
+
* Uses OIDC Authorization Code + PKCE flow. Opens a browser for
|
|
36
|
+
* interactive authentication, then stores the tokens locally.
|
|
37
|
+
*/
|
|
38
|
+
export const loginCommand = {
|
|
39
|
+
command: 'login',
|
|
40
|
+
describe: 'Authenticate with a Porta server',
|
|
41
|
+
builder: (yargs) => yargs
|
|
42
|
+
.option('server', {
|
|
43
|
+
type: 'string',
|
|
44
|
+
describe: 'Porta server URL',
|
|
45
|
+
default: DEFAULT_SERVER,
|
|
46
|
+
})
|
|
47
|
+
.option('client-id', {
|
|
48
|
+
type: 'string',
|
|
49
|
+
describe: 'Override admin client ID (normally auto-discovered from server)',
|
|
50
|
+
})
|
|
51
|
+
.option('no-browser', {
|
|
52
|
+
type: 'boolean',
|
|
53
|
+
describe: 'Print login URL instead of opening browser',
|
|
54
|
+
default: false,
|
|
55
|
+
}),
|
|
56
|
+
handler: async (argv) => {
|
|
57
|
+
try {
|
|
58
|
+
// Handle --insecure flag before any HTTP calls
|
|
59
|
+
if (argv.insecure) {
|
|
60
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
61
|
+
}
|
|
62
|
+
// Execute the OIDC browser flow
|
|
63
|
+
const result = await executeBrowserFlow({
|
|
64
|
+
server: argv.server,
|
|
65
|
+
clientId: argv['client-id'],
|
|
66
|
+
noBrowser: argv['no-browser'],
|
|
67
|
+
});
|
|
68
|
+
// Store credentials to disk
|
|
69
|
+
saveCredentials(result);
|
|
70
|
+
success(`Logged in as ${result.userInfo.email || result.userInfo.sub}`);
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
handleError(err, argv.verbose);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,qDAAqD;AACrD,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAalD,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAA+C;IACtE,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,kCAAkC;IAE5C,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,MAAM,CAAC,QAAQ,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,cAAc;KACxB,CAAC;SACD,MAAM,CAAC,WAAW,EAAE;QACnB,IAAI,EAAE,QAAQ;QACd,QAAQ,EACN,iEAAiE;KACpE,CAAC;SACD,MAAM,CAAC,YAAY,EAAE;QACpB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,4CAA4C;QACtD,OAAO,EAAE,KAAK;KACf,CAAC;IAEN,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,+CAA+C;YAC/C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,4BAA4B,GAAG,GAAG,CAAC;YACjD,CAAC;YAED,gCAAgC;YAChC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;gBACtC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;gBAC3B,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;aAC9B,CAAC,CAAC;YAEH,4BAA4B;YAC5B,eAAe,CAAC,MAAM,CAAC,CAAC;YAExB,OAAO,CACL,gBAAgB,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAC/D,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI logout command — clear stored authentication tokens.
|
|
3
|
+
*
|
|
4
|
+
* Removes the ~/.porta/credentials.json file, effectively logging out
|
|
5
|
+
* the CLI user. Does NOT revoke tokens on the server — the access token
|
|
6
|
+
* will expire naturally based on its TTL.
|
|
7
|
+
*
|
|
8
|
+
* This is a local-only operation that does not require a network connection
|
|
9
|
+
* or a running Porta server.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* porta logout
|
|
13
|
+
*
|
|
14
|
+
* @module commands/logout
|
|
15
|
+
*/
|
|
16
|
+
import type { CommandModule } from 'yargs';
|
|
17
|
+
import type { GlobalOptions } from '../global-options.js';
|
|
18
|
+
/**
|
|
19
|
+
* The logout command module — clears stored CLI authentication tokens.
|
|
20
|
+
*
|
|
21
|
+
* Reads existing credentials to show who was logged in, then deletes
|
|
22
|
+
* the credentials file. Safe to run even when not logged in.
|
|
23
|
+
*/
|
|
24
|
+
export declare const logoutCommand: CommandModule<GlobalOptions, GlobalOptions>;
|
|
25
|
+
//# sourceMappingURL=logout.d.ts.map
|