Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,610 changes: 1,610 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

42 changes: 16 additions & 26 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#!/usr/bin/env node

import { Command as CommanderCommand } from 'commander';
import { existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import type { Argument, CommandSpec } from './types.js';
import { getModule, hasModule } from './lib/registry.js';
import { loadSpecs } from './utils/specs.js';
import { checkForUpdates } from './utils/update-check.js';
import { version } from '../package.json';
Expand All @@ -26,9 +24,6 @@ process.on('uncaughtException', (error) => {
process.exit(1);
});

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const specs = loadSpecs();

/**
Expand All @@ -45,16 +40,12 @@ function isValidCommandName(name: string): boolean {
*/
function hasImplementation(pathParts: string[]): boolean {
if (pathParts.length === 0) return false;

// Try direct file: lib/iam/policies/get.js
const directPath = join(__dirname, 'lib', ...pathParts) + '.js';
if (existsSync(directPath)) return true;

// Try index file: lib/iam/policies/get/index.js
const indexPath = join(__dirname, 'lib', ...pathParts, 'index.js');
if (existsSync(indexPath)) return true;

return false;
const [commandName, ...rest] = pathParts;
if (!commandName) {
return false;
}
const operationName = rest.length > 0 ? rest.join('.') : undefined;
return hasModule(commandName, operationName);
}

function formatArgumentHelp(arg: Argument): string {
Expand Down Expand Up @@ -313,16 +304,15 @@ function camelCase(str: string): string {
async function loadModule(
pathParts: string[]
): Promise<{ module: Record<string, unknown> | null; error: string | null }> {
const paths = [
`./lib/${pathParts.join('/')}.js`,
`./lib/${pathParts.join('/')}/index.js`,
];

for (const path of paths) {
const module = await import(path).catch(() => null);
if (module) {
return { module, error: null };
}
const commandName = pathParts[0];
if (!commandName) {
return { module: null, error: 'Command not found' };
}
const operationName =
pathParts.length > 1 ? pathParts.slice(1).join('.') : undefined;
const module = getModule(commandName, operationName);
if (module) {
return { module, error: null };
}

const cmdDisplay = pathParts.join(' ');
Expand Down
102 changes: 102 additions & 0 deletions src/lib/registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import * as accessKeysAssign from './access-keys/assign.js';
import * as accessKeysCreate from './access-keys/create.js';
import * as accessKeysDelete from './access-keys/delete.js';
import * as accessKeysGet from './access-keys/get.js';
import * as accessKeysList from './access-keys/list.js';
import * as bucketsCreate from './buckets/create.js';
import * as bucketsDelete from './buckets/delete.js';
import * as bucketsGet from './buckets/get.js';
import * as bucketsList from './buckets/list.js';
import * as bucketsSet from './buckets/set.js';
import * as configure from './configure/index.js';
import * as cp from './cp.js';
import * as credentialsTest from './credentials/test.js';
import * as forksCreate from './forks/create.js';
import * as forksList from './forks/list.js';
import * as iamPoliciesCreate from './iam/policies/create.js';
import * as iamPoliciesDelete from './iam/policies/delete.js';
import * as iamPoliciesEdit from './iam/policies/edit.js';
import * as iamPoliciesGet from './iam/policies/get.js';
import * as iamPoliciesList from './iam/policies/list.js';
import * as loginCredentials from './login/credentials.js';
import * as loginOauth from './login/oauth.js';
import * as loginSelect from './login/select.js';
import * as logout from './logout.js';
import * as ls from './ls.js';
import * as mk from './mk.js';
import * as mv from './mv.js';
import * as objectsDelete from './objects/delete.js';
import * as objectsGet from './objects/get.js';
import * as objectsList from './objects/list.js';
import * as objectsPut from './objects/put.js';
import * as objectsSet from './objects/set.js';
import * as organizationsCreate from './organizations/create.js';
import * as organizationsList from './organizations/list.js';
import * as organizationsSelect from './organizations/select.js';
import * as rm from './rm.js';
import * as snapshotsList from './snapshots/list.js';
import * as snapshotsTake from './snapshots/take.js';
import * as stat from './stat.js';
import * as touch from './touch.js';
import * as whoami from './whoami.js';

type CommandModule = Record<string, unknown>;

const registry: Record<string, CommandModule> = {
'access-keys.assign': accessKeysAssign,
'access-keys.create': accessKeysCreate,
'access-keys.delete': accessKeysDelete,
'access-keys.get': accessKeysGet,
'access-keys.list': accessKeysList,
'buckets.create': bucketsCreate,
'buckets.delete': bucketsDelete,
'buckets.get': bucketsGet,
'buckets.list': bucketsList,
'buckets.set': bucketsSet,
configure,
cp,
'credentials.test': credentialsTest,
'forks.create': forksCreate,
'forks.list': forksList,
'iam.policies.list': iamPoliciesList,
'iam.policies.get': iamPoliciesGet,
'iam.policies.create': iamPoliciesCreate,
'iam.policies.edit': iamPoliciesEdit,
'iam.policies.delete': iamPoliciesDelete,
'login.credentials': loginCredentials,
'login.oauth': loginOauth,
'login.select': loginSelect,
logout,
ls,
mk,
mv,
'objects.delete': objectsDelete,
'objects.get': objectsGet,
'objects.list': objectsList,
'objects.put': objectsPut,
'objects.set': objectsSet,
'organizations.create': organizationsCreate,
'organizations.list': organizationsList,
'organizations.select': organizationsSelect,
rm,
'snapshots.list': snapshotsList,
'snapshots.take': snapshotsTake,
stat,
touch,
whoami,
};

export function getModule(
commandName: string,
operationName?: string
): CommandModule | null {
const key = operationName ? `${commandName}.${operationName}` : commandName;
return registry[key] ?? null;
}

export function hasModule(
commandName: string,
operationName?: string
): boolean {
return getModule(commandName, operationName) !== null;
}
Loading