From ded34dca82d16d045e72decfb14fc7b00ec04fea Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Aug 2026 05:27:11 +0000 Subject: [PATCH] refactor: Rename snake_case identifiers and enable the camelcase rule The `camelcase` ESLint rule was disabled for `src/bin` and `src/lib` because local identifiers mirrored the snake_case parameter names of the Seam API. Rename those identifiers and drop the override. Where a name is only a local binding, it is renamed outright. Where the name also has to leave the process, the snake_case key is kept and only the binding is renamed: - `seam.accessCodes.list({ device_id })`, `seam.acs.users.list({ acs_system_id })` and `seam.actionAttempts.get({ action_attempt_id })` keep their request keys. - `interactForAccessCode` keeps `device_id` as its destructuring key, since callers pass the blueprint params bag through as `args.params as any` and the cast hides a mismatch from the type checker. - The `use_remote_api_defs` config key stays snake_case so existing installs keep reading their stored setting. - `getOutput().data({ action_attempt })` keeps its output key. The three `prompt()` answer keys are internal to a single function each, so their `name` and binding are renamed together. `no-console` stays off; its TODO is unrelated. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_017BkuFhVWgKzWQYTDpz4w9Y --- eslint.config.ts | 3 -- src/bin/cli.ts | 8 ++--- src/lib/interact-for-access-code.ts | 10 +++--- src/lib/interact-for-acs-user.ts | 4 +-- src/lib/interact-for-action-attempt-poll.ts | 18 +++++----- src/lib/interact-for-blueprint-object.ts | 14 ++++---- src/lib/interact-for-custom-metadata.ts | 38 ++++++++++----------- src/lib/interact-for-use-remote-api-defs.ts | 8 ++--- 8 files changed, 49 insertions(+), 54 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index 2ba7ae8f..30f25915 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -19,9 +19,6 @@ export default [ { files: ['src/bin/**/*.ts', 'src/lib/**/*.ts'], rules: { - // TODO: Rename the identifiers that mirror the snake_case parameter names - // of the Seam API so that everything here is camelCase. - camelcase: 'off', // TODO: Replace the console calls with a logger wrapper. 'no-console': 'off', }, diff --git a/src/bin/cli.ts b/src/bin/cli.ts index 5fd2395b..8c2cf4a0 100644 --- a/src/bin/cli.ts +++ b/src/bin/cli.ts @@ -126,10 +126,10 @@ async function cli(args: ParsedArgs) { args[k.toLowerCase().replace(/-/g, '_')] = args[k] } - const use_remote_api_defs = + const useRemoteApiDefs = args['remote_api_defs'] ?? config.get('use_remote_api_defs') - const blueprint = await getApiBlueprint(use_remote_api_defs ?? false, { + const blueprint = await getApiBlueprint(useRemoteApiDefs ?? false, { update, }) @@ -287,10 +287,10 @@ const toCommandWord = (arg: string): string => arg.toLowerCase().replace(/_/g, '-') const handleConnectWebviewResponse = async ( - connect_webview: any, + connectWebview: any, interactivity: Interactivity, ) => { - const url = connect_webview.url + const url = connectWebview.url if ( interactivity !== 'non-interactive' && diff --git a/src/lib/interact-for-access-code.ts b/src/lib/interact-for-access-code.ts index 6ad7bd59..caa707ba 100644 --- a/src/lib/interact-for-access-code.ts +++ b/src/lib/interact-for-access-code.ts @@ -3,19 +3,21 @@ import { interactForDevice } from './interact-for-device.js' import { interactForResource } from './interact-for-resource.js' export const interactForAccessCode = async ({ - device_id, + // The key is a Seam API parameter name: callers pass the blueprint params + // bag through as-is, so only the binding may be camelCase. + device_id: deviceId, }: { device_id?: string }) => { const seam = await getSeam() - if (!device_id) { - device_id = await interactForDevice() + if (!deviceId) { + deviceId = await interactForDevice() } return interactForResource({ resourceName: 'access_code', - fetchResources: () => seam.accessCodes.list({ device_id }), + fetchResources: () => seam.accessCodes.list({ device_id: deviceId }), toChoice: (accessCode) => ({ title: accessCode.name ?? '', value: accessCode.access_code_id, diff --git a/src/lib/interact-for-acs-user.ts b/src/lib/interact-for-acs-user.ts index 09cb5a9d..bfb49d15 100644 --- a/src/lib/interact-for-acs-user.ts +++ b/src/lib/interact-for-acs-user.ts @@ -5,13 +5,13 @@ import { interactForResource } from './interact-for-resource.js' export const interactForAcsUser = async () => { const seam = await getSeam() - const acs_system_id = await interactForAcsSystem( + const acsSystemId = await interactForAcsSystem( 'What acs_system does the acs_user belong to?', ) return interactForResource({ resourceName: 'ACS user', - fetchResources: () => seam.acs.users.list({ acs_system_id }), + fetchResources: () => seam.acs.users.list({ acs_system_id: acsSystemId }), toChoice: (user) => ({ title: `${user.display_name} ${user.email_address}`, value: user.acs_user_id, diff --git a/src/lib/interact-for-action-attempt-poll.ts b/src/lib/interact-for-action-attempt-poll.ts index cfcaaa47..7f3c5ad1 100644 --- a/src/lib/interact-for-action-attempt-poll.ts +++ b/src/lib/interact-for-action-attempt-poll.ts @@ -6,11 +6,11 @@ import { prompt } from './util/prompt.js' import { withLoading } from './util/with-loading.js' export const interactForActionAttemptPoll = async ( - action_attempt: ActionAttemptsGetResponse['action_attempt'], + actionAttempt: ActionAttemptsGetResponse['action_attempt'], ) => { - if (action_attempt.status === 'pending') { - const { poll_for_action_attempt } = await prompt({ - name: 'poll_for_action_attempt', + if (actionAttempt.status === 'pending') { + const { pollForActionAttempt } = await prompt({ + name: 'pollForActionAttempt', message: "Would you like to poll the action attempt until it's ready?", type: 'toggle', initial: true, @@ -18,19 +18,19 @@ export const interactForActionAttemptPoll = async ( inactive: 'no', }) - if (poll_for_action_attempt) { + if (pollForActionAttempt) { const seam = await getSeam() - const { action_attempt_id } = action_attempt + const { action_attempt_id: actionAttemptId } = actionAttempt - const updated_action_attempt = await withLoading( + const updatedActionAttempt = await withLoading( 'Polling action attempt...', () => seam.actionAttempts.get( - { action_attempt_id }, + { action_attempt_id: actionAttemptId }, { waitForActionAttempt: { pollingInterval: 240, timeout: 10_000 } }, ), ) - getOutput().data({ action_attempt: updated_action_attempt }) + getOutput().data({ action_attempt: updatedActionAttempt }) } } } diff --git a/src/lib/interact-for-blueprint-object.ts b/src/lib/interact-for-blueprint-object.ts index 63f363f8..84429ea7 100644 --- a/src/lib/interact-for-blueprint-object.ts +++ b/src/lib/interact-for-blueprint-object.ts @@ -51,11 +51,11 @@ export const interactForBlueprintObject = async ( const cmdPath = `/${args.command.join('/').replace(/-/g, '_')}` - const should_auto_submit = + const shouldAutoSubmit = ctx.interactivity !== 'interactive' && haveAllRequiredParams && !args.isSubProperty - if (should_auto_submit) { + if (shouldAutoSubmit) { return args.params } @@ -160,18 +160,16 @@ export const interactForBlueprintObject = async ( args.params[paramToEdit] = await interactForAccessCode(args.params as any) return interactForBlueprintObject(args, ctx) } else if (paramToEdit === 'connected_account_id') { - const connected_account_id = await interactForConnectedAccount() - args.params[paramToEdit] = connected_account_id + const connectedAccountId = await interactForConnectedAccount() + args.params[paramToEdit] = connectedAccountId return interactForBlueprintObject(args, ctx) } else if ( paramToEdit === 'user_identity_id' || paramToEdit === 'user_identity_ids' ) { - const user_identity_id = await interactForUserIdentity() + const userIdentityId = await interactForUserIdentity() args.params[paramToEdit] = - paramToEdit === 'user_identity_ids' - ? [user_identity_id] - : user_identity_id + paramToEdit === 'user_identity_ids' ? [userIdentityId] : userIdentityId return interactForBlueprintObject(args, ctx) } else if (paramToEdit.endsWith('acs_system_id')) { args.params[paramToEdit] = await interactForAcsSystem() diff --git a/src/lib/interact-for-custom-metadata.ts b/src/lib/interact-for-custom-metadata.ts index f08d1c5c..eb823c2f 100644 --- a/src/lib/interact-for-custom-metadata.ts +++ b/src/lib/interact-for-custom-metadata.ts @@ -10,16 +10,16 @@ type UpdatedCustomMetadata = { } export const interactForCustomMetadata = async ( - custom_metadata: CustomMetadata, + customMetadata: CustomMetadata, ) => { - const updated_custom_metadata: UpdatedCustomMetadata = { ...custom_metadata } + const updatedCustomMetadata: UpdatedCustomMetadata = { ...customMetadata } const output = getOutput() const displayCurrentCustomMetadata = () => { output.info('custom_metadata:') - if (Object.keys(updated_custom_metadata).length > 0) { - Object.keys(updated_custom_metadata).forEach((key, index) => { - output.info(`${index + 1}: ${key}: ${updated_custom_metadata[key]}`) + if (Object.keys(updatedCustomMetadata).length > 0) { + Object.keys(updatedCustomMetadata).forEach((key, index) => { + output.info(`${index + 1}: ${key}: ${updatedCustomMetadata[key]}`) }) } else { output.info('The custom metadata param is empty.') @@ -61,31 +61,29 @@ export const interactForCustomMetadata = async ( newValue = Boolean(newValue) } if (newValue === 'null') { - updated_custom_metadata[newKey] = null + updatedCustomMetadata[newKey] = null } else { - updated_custom_metadata[newKey] = newValue + updatedCustomMetadata[newKey] = newValue } } } else if (action === 'remove') { - const { custom_key_to_remove } = await prompt({ + const { customKeyToRemove } = await prompt({ type: 'select', - name: 'custom_key_to_remove', + name: 'customKeyToRemove', message: 'Choose a key-value pair to remove from params:', - choices: Object.keys(updated_custom_metadata).map( - (custom_metadata_key) => { - return { - title: `${custom_metadata_key}: ${updated_custom_metadata[custom_metadata_key]}`, - value: custom_metadata_key, - } - }, - ), + choices: Object.keys(updatedCustomMetadata).map((customMetadataKey) => { + return { + title: `${customMetadataKey}: ${updatedCustomMetadata[customMetadataKey]}`, + value: customMetadataKey, + } + }), }) - if (custom_key_to_remove) { - delete custom_metadata[custom_key_to_remove] + if (customKeyToRemove) { + delete customMetadata[customKeyToRemove] } } } while (action !== 'done') - return updated_custom_metadata + return updatedCustomMetadata } diff --git a/src/lib/interact-for-use-remote-api-defs.ts b/src/lib/interact-for-use-remote-api-defs.ts index 71009dd4..678d67a2 100644 --- a/src/lib/interact-for-use-remote-api-defs.ts +++ b/src/lib/interact-for-use-remote-api-defs.ts @@ -3,10 +3,10 @@ import { getOutput } from './output/get-output.js' import { prompt } from './util/prompt.js' export async function interactForUseRemoteApiDefs() { - const { use_remote_api_defs } = await prompt([ + const { useRemoteApiDefs } = await prompt([ { type: 'select', - name: 'use_remote_api_defs', + name: 'useRemoteApiDefs', message: 'Always use remote API Definitions?', choices: [ { @@ -22,6 +22,6 @@ export async function interactForUseRemoteApiDefs() { ]) const config = getConfigStore() - config.set('use_remote_api_defs', use_remote_api_defs) - getOutput().info(`Use remote API Definitions: ${use_remote_api_defs}`) + config.set('use_remote_api_defs', useRemoteApiDefs) + getOutput().info(`Use remote API Definitions: ${useRemoteApiDefs}`) }