diff --git a/docs/commands.md b/docs/commands.md index d57c4bc..ed165dd 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -489,6 +489,7 @@ dm properties export --body '{"locations": [...]}' --mobile-only --json | `--mobile-only` | Only include wireless phone numbers | | `--landline-only` | Only include landline phone numbers | | `--scrub-dnc` | Exclude contacts on the Do Not Call registry | +| `--active-phones-only` | Exclude phone numbers with inactive or unknown reported activity | | `--json` | Output as JSON | --- @@ -1280,3 +1281,5 @@ node dist/index.js mycommand --json ### Used By The **Playbook** at `packages/playbooks/playbook/` uses `dm` commands to execute property intelligence workflows. The CLI is the primary interface through which the Playbook interacts with DealMachine data. Agents can load the bundled Playbook directly with `dm agents playbook`. + +Both `dm properties export` and `dm people export` accept `--active-phones-only`. It combines with existing phone-type and Do Not Call controls. diff --git a/npm-alias/package.json b/npm-alias/package.json index 5865b95..c4d76df 100644 --- a/npm-alias/package.json +++ b/npm-alias/package.json @@ -1,6 +1,6 @@ { "name": "dealmachine", - "version": "0.4.0-rc.1", + "version": "0.4.0-rc.4", "description": "Short install alias for the DealMachine property intelligence CLI", "author": "DealMachine", "license": "MIT", @@ -23,7 +23,7 @@ "LICENSE" ], "dependencies": { - "@dealmachine/cli": "0.4.0-rc.1" + "@dealmachine/cli": "0.4.0-rc.4" }, "engines": { "node": ">=18" diff --git a/package-lock.json b/package-lock.json index dfad486..225166d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dealmachine/cli", - "version": "0.4.0-rc.1", + "version": "0.4.0-rc.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dealmachine/cli", - "version": "0.4.0-rc.1", + "version": "0.4.0-rc.4", "license": "MIT", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index 76c938b..bdc592b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dealmachine/cli", - "version": "0.4.0-rc.1", + "version": "0.4.0-rc.4", "description": "DealMachine CLI for property intelligence, people lookup, and enrichment through the public API", "author": "DealMachine", "license": "MIT", diff --git a/src/commands/lists.ts b/src/commands/lists.ts index 2ba2178..9f71018 100644 --- a/src/commands/lists.ts +++ b/src/commands/lists.ts @@ -314,7 +314,7 @@ export async function listsBuild( 'Progress': `${l.progress}%`, }); console.log(); - console.log(chalk.dim(' Poll with: dm lists get ' + listId)); + console.log(chalk.dim(' Poll with: dm lists get ' + l.list_id)); console.log(); } @@ -366,7 +366,7 @@ export async function listsImport( 'Progress': `${l.progress}%`, }); console.log(); - console.log(chalk.dim(' Poll with: dm lists get ' + listId)); + console.log(chalk.dim(' Poll with: dm lists get ' + l.list_id)); console.log(); } diff --git a/src/commands/people.ts b/src/commands/people.ts index c72ffe0..1e52f29 100644 --- a/src/commands/people.ts +++ b/src/commands/people.ts @@ -353,6 +353,7 @@ export async function peopleExport( mobileOnly?: boolean; landlineOnly?: boolean; scrubDnc?: boolean; + activePhonesOnly?: boolean; } & SearchProtocolCliOptions ): Promise { const requestBody = await parseRequestBody(options); @@ -364,6 +365,7 @@ export async function peopleExport( if (options.mobileOnly) requestBody.mobile_only = true; if (options.landlineOnly) requestBody.landline_only = true; if (options.scrubDnc) requestBody.scrub_dnc = true; + if (options.activePhonesOnly) requestBody.active_phones_only = true; const spinner = createSpinner('Exporting people (this may take 30-60 seconds)...').start(); const data = await apiRequest('/people/export', { diff --git a/src/commands/properties.ts b/src/commands/properties.ts index 1b6ac8a..42b68d9 100644 --- a/src/commands/properties.ts +++ b/src/commands/properties.ts @@ -329,6 +329,7 @@ export async function propertiesExport( mobileOnly?: boolean; landlineOnly?: boolean; scrubDnc?: boolean; + activePhonesOnly?: boolean; contactAudience?: string; anchor?: string; } & SearchProtocolCliOptions @@ -349,6 +350,7 @@ export async function propertiesExport( if (options.mobileOnly) requestBody.mobile_only = true; if (options.landlineOnly) requestBody.landline_only = true; if (options.scrubDnc) requestBody.scrub_dnc = true; + if (options.activePhonesOnly) requestBody.active_phones_only = true; const spinner = createSpinner('Exporting properties (this may take 30-60 seconds)...').start(); const data = await apiRequest('/properties/export', { diff --git a/src/index.ts b/src/index.ts index 69cac75..a1ba8b2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -774,6 +774,10 @@ propertiesCmd .option('--mobile-only', 'Only include wireless phone numbers') .option('--landline-only', 'Only include landline phone numbers') .option('--scrub-dnc', 'Exclude contacts on the Do Not Call registry') + .option( + '--active-phones-only', + 'Only include phone numbers with active reported phone activity (inactive/unknown excluded)' + ) .option('--json', 'Output as JSON') .addHelpText( 'after', @@ -1164,6 +1168,10 @@ peopleCmd .option('--mobile-only', 'Only include wireless phone numbers') .option('--landline-only', 'Only include landline phone numbers') .option('--scrub-dnc', 'Exclude contacts on the Do Not Call registry') + .option( + '--active-phones-only', + 'Only include phone numbers with active reported phone activity (inactive/unknown excluded)' + ) .option('--json', 'Output as JSON') .addHelpText( 'after', diff --git a/src/version.ts b/src/version.ts index 1d20963..9978a3a 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,2 +1,2 @@ -export const CLI_VERSION = '0.4.0-rc.1'; +export const CLI_VERSION = '0.4.0-rc.4'; export const CLI_USER_AGENT = `dm-cli/${CLI_VERSION}`; diff --git a/tests/commands/publicApiExtensions.test.ts b/tests/commands/publicApiExtensions.test.ts index 6fab6d2..9551903 100644 --- a/tests/commands/publicApiExtensions.test.ts +++ b/tests/commands/publicApiExtensions.test.ts @@ -31,8 +31,8 @@ vi.mock('../../src/lib/output.js', () => ({ })); import { printJson, printTable } from '../../src/lib/output.js'; -import { peopleGet, peopleIds, peopleSearch } from '../../src/commands/people.js'; -import { propertiesGet, propertiesIds, propertiesSearch } from '../../src/commands/properties.js'; +import { peopleGet, peopleIds, peopleSearch, peopleExport } from '../../src/commands/people.js'; +import { propertiesGet, propertiesIds, propertiesSearch, propertiesExport } from '../../src/commands/properties.js'; import { enrichAddress, enrichApn, @@ -571,3 +571,22 @@ describe('CLI phone carrier (DEA-2144)', () => { }); }); + + +describe.each([ + ['people', peopleExport], + ['properties', propertiesExport], +] as const)('%s active phone exports', (source, exportRecords) => { + it.each([true, undefined])('preserves active phone selection %s at the API boundary', async (activePhonesOnly) => { + mockParseRequestBody.mockResolvedValue({ fields: ['phone_1'] }); + await exportRecords({ activePhonesOnly, json: true }); + expect(mockApiRequest).toHaveBeenCalledWith(`/${source}/export`, { + method: 'POST', + body: { + fields: ['phone_1'], + ...(source === 'properties' ? { anchor: 'person', contact_audience: 'owners' } : {}), + ...(activePhonesOnly ? { active_phones_only: true } : {}), + }, + }); + }); +});