import * as plugins from './plugins.js'; import { IdpCli } from './classes.idpcli.js'; export { IdpCli } from './classes.idpcli.js'; const DEFAULT_IDP_URL = 'https://idp.global'; /** * Run the CLI */ export const runCli = async () => { const smartcliInstance = new plugins.smartcli.Smartcli(); smartcliInstance.addVersion('1.0.0'); const getIdpClient = () => { const idpUrl = process.env.IDP_URL || DEFAULT_IDP_URL; return new IdpCli({ idpBaseUrl: idpUrl }); }; // ============================================ // Help // ============================================ smartcliInstance.addHelp({ helpText: ` idp - CLI for idp.global identity provider USAGE: idp [options] COMMANDS: login Login with email and password login-token Login with API token logout Logout and clear credentials whoami Show current user information orgs List organizations orgs-create Create a new organization members List organization members invite Invite a user to organization sessions List active sessions revoke Revoke a session admin-check Check if current user is global admin admin-apps List global apps (admin only) admin-suspend Suspend a user (admin only) help Show this help message ENVIRONMENT: IDP_URL Override IDP server URL (default: https://idp.global) EXAMPLES: idp login idp whoami idp orgs idp members --org idp invite --org --email user@example.com `, }); // ============================================ // Login Commands // ============================================ smartcliInstance.addCommand('login').subscribe(async (argv) => { const client = getIdpClient(); const interact = new plugins.smartinteract.SmartInteract(); const emailAnswer = await interact.askQuestion({ type: 'input', name: 'email', message: 'Email:', default: '', }); const passwordAnswer = await interact.askQuestion({ type: 'password', name: 'password', message: 'Password:', default: '', }); await client.loginWithPassword(emailAnswer.value as string, passwordAnswer.value as string); await client.disconnect(); }); smartcliInstance.addCommand('login-token').subscribe(async (argv) => { const client = getIdpClient(); const interact = new plugins.smartinteract.SmartInteract(); const tokenAnswer = await interact.askQuestion({ type: 'password', name: 'token', message: 'API Token:', default: '', }); await client.loginWithApiToken(tokenAnswer.value as string); await client.disconnect(); }); smartcliInstance.addCommand('logout').subscribe(async (argv) => { const client = getIdpClient(); await client.logout(); await client.disconnect(); }); // ============================================ // User Commands // ============================================ smartcliInstance.addCommand('whoami').subscribe(async (argv) => { const client = getIdpClient(); const user = await client.whoami(); if (user) { console.log('\nUser Information:'); console.log(` ID: ${user.id}`); console.log(` Name: ${user.data?.name || 'N/A'}`); console.log(` Username: ${user.data?.username || 'N/A'}`); console.log(` Email: ${user.data?.email || 'N/A'}`); console.log(` Status: ${user.data?.status || 'N/A'}`); console.log(` Global Admin: ${user.data?.isGlobalAdmin ? 'Yes' : 'No'}`); } await client.disconnect(); }); smartcliInstance.addCommand('sessions').subscribe(async (argv) => { const client = getIdpClient(); const sessions = await client.getSessions(); if (sessions) { console.log('\nActive Sessions:'); for (const session of sessions) { console.log(` - ${session.id}`); console.log(` Device: ${session.deviceName || 'Unknown'}`); console.log(` Browser: ${session.browser || 'Unknown'}`); console.log(` OS: ${session.os || 'Unknown'}`); console.log(` Last Active: ${new Date(session.lastActive).toLocaleString()}`); console.log(` Current: ${session.isCurrent ? 'Yes' : 'No'}`); console.log(''); } } await client.disconnect(); }); smartcliInstance.addCommand('revoke').subscribe(async (argv) => { const client = getIdpClient(); const sessionId = argv.session || argv.s || argv._[1]; if (!sessionId) { console.error('Please provide a session ID: idp revoke --session '); return; } const success = await client.revokeSession(sessionId); if (success) { console.log('Session revoked successfully.'); } else { console.error('Failed to revoke session.'); } await client.disconnect(); }); // ============================================ // Organization Commands // ============================================ smartcliInstance.addCommand('orgs').subscribe(async (argv) => { const client = getIdpClient(); const result = await client.getOrganizations(); if (result) { console.log('\nOrganizations:'); for (const org of result.organizations) { const role = result.roles.find((r) => r.data?.organizationId === org.id); console.log(` - ${org.data?.name} (${org.id})`); console.log(` Slug: ${org.data?.slug}`); console.log(` Roles: ${role?.data?.roles?.join(', ') || 'Unknown'}`); console.log(''); } } await client.disconnect(); }); smartcliInstance.addCommand('orgs-create').subscribe(async (argv) => { const client = getIdpClient(); const interact = new plugins.smartinteract.SmartInteract(); const nameAnswer = await interact.askQuestion({ type: 'input', name: 'name', message: 'Organization Name:', default: '', }); const slugAnswer = await interact.askQuestion({ type: 'input', name: 'slug', message: 'Organization Slug:', default: '', }); // First check availability const checkResult = await client.createOrganization( nameAnswer.value as string, slugAnswer.value as string, 'checkAvailability' ); if (!checkResult?.nameAvailable) { console.error('Organization name or slug is not available.'); await client.disconnect(); return; } // Then create const result = await client.createOrganization( nameAnswer.value as string, slugAnswer.value as string, 'manifest' ); if (result?.resultingOrganization) { console.log('\nOrganization created successfully!'); console.log(` ID: ${result.resultingOrganization.id}`); console.log(` Name: ${result.resultingOrganization.data?.name}`); } await client.disconnect(); }); // ============================================ // Member Commands // ============================================ smartcliInstance.addCommand('members').subscribe(async (argv) => { const client = getIdpClient(); const orgId = argv.org || argv.o || argv._[1]; if (!orgId) { console.error('Please provide an organization ID: idp members --org '); return; } const members = await client.getOrgMembers(orgId); if (members) { console.log('\nOrganization Members:'); for (const member of members) { console.log(` - ${member.user.data?.name || 'Unknown'}`); console.log(` Email: ${member.user.data?.email || 'N/A'}`); console.log(` Roles: ${member.role.data?.roles?.join(', ') || 'Unknown'}`); console.log(''); } } await client.disconnect(); }); smartcliInstance.addCommand('invite').subscribe(async (argv) => { const client = getIdpClient(); const orgId = argv.org || argv.o; const email = argv.email || argv.e || argv._[1]; if (!orgId || !email) { console.error('Please provide organization ID and email:'); console.error(' idp invite --org --email user@example.com'); return; } const result = await client.inviteMember(orgId, email); if (result?.success) { console.log(`Invitation sent to ${email}`); } else { console.error(`Failed to send invitation: ${result?.message || 'Unknown error'}`); } await client.disconnect(); }); // ============================================ // Admin Commands // ============================================ smartcliInstance.addCommand('admin-check').subscribe(async (argv) => { const client = getIdpClient(); const isAdmin = await client.checkGlobalAdmin(); if (isAdmin) { console.log('You are a global admin.'); } else { console.log('You are not a global admin.'); } await client.disconnect(); }); smartcliInstance.addCommand('admin-apps').subscribe(async (argv) => { const client = getIdpClient(); const apps = await client.getGlobalAppStats(); if (apps) { console.log('\nGlobal Apps:'); for (const appInfo of apps) { console.log(` - ${appInfo.app.data?.name}`); console.log(` ID: ${appInfo.app.id}`); console.log(` Connections: ${appInfo.connectionCount}`); console.log(''); } } await client.disconnect(); }); smartcliInstance.addCommand('admin-suspend').subscribe(async (argv) => { const client = getIdpClient(); const userId = argv.user || argv.u || argv._[1]; if (!userId) { console.error('Please provide a user ID: idp admin-suspend --user '); return; } const interact = new plugins.smartinteract.SmartInteract(); const confirmAnswer = await interact.askQuestion({ type: 'confirm', name: 'confirm', message: `Are you sure you want to suspend user ${userId}?`, default: false, }); if (confirmAnswer.value) { const success = await client.suspendUser(userId); if (success) { console.log('User suspended successfully.'); } else { console.error('Failed to suspend user.'); } } else { console.log('Operation cancelled.'); } await client.disconnect(); }); // ============================================ // Default/Standard command // ============================================ smartcliInstance.standardCommand().subscribe(async (argv) => { // If no command specified, show help smartcliInstance.triggerCommand('help', argv); }); // Start parsing smartcliInstance.startParse(); }; // Auto-run if this is the main module runCli().catch(console.error);