Skip to content
Merged
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
4 changes: 2 additions & 2 deletions npm-alias/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dealmachine",
"version": "0.4.1-rc.1",
"version": "0.4.1-rc.2",
"description": "Short install alias for the DealMachine property intelligence CLI",
"author": "DealMachine",
"license": "MIT",
Expand All @@ -23,7 +23,7 @@
"LICENSE"
],
"dependencies": {
"@dealmachine/cli": "0.4.1-rc.1"
"@dealmachine/cli": "0.4.1-rc.2"
},
"engines": {
"node": ">=18"
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dealmachine/cli",
"version": "0.4.1-rc.1",
"version": "0.4.1-rc.2",
"description": "DealMachine CLI for property intelligence, people lookup, and enrichment through the public API",
"author": "DealMachine",
"license": "MIT",
Expand Down
19 changes: 18 additions & 1 deletion src/commands/prospects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type Prospect = {
record_id: string;
lifecycle: string;
favorite: boolean;
/** Read only: hot, warm, cold, follow_up, do_not_contact, or null. */
status?: string | null;
source: string;
record: {
address?: string | null;
Expand Down Expand Up @@ -56,16 +58,29 @@ function recordLabel(prospect: Prospect): string {
return place ? `${main} (${place})` : String(main);
}

const STATUS_LABELS: Record<string, string> = {
hot: 'Hot',
warm: 'Warm',
cold: 'Cold',
follow_up: 'Follow up',
do_not_contact: 'Do Not Contact',
};

function statusLabel(prospect: Prospect): string {
return prospect.status ? (STATUS_LABELS[prospect.status] ?? prospect.status) : 'None';
}

function printProspectRows(prospects: Prospect[]) {
const rows = prospects.map((p) => ({
id: p.id,
record: truncate(recordLabel(p), 44),
lifecycle: p.lifecycle,
fav: p.favorite ? '★' : '',
status: statusLabel(p),
tags: truncate(p.tags.map((tag) => tag.name).join(', ') || '—', 24),
added: formatDate(p.created_at),
}));
printTable(rows, ['id', 'record', 'lifecycle', 'fav', 'tags', 'added']);
printTable(rows, ['id', 'record', 'lifecycle', 'fav', 'status', 'tags', 'added']);
}

function printPagination(p: Pagination) {
Expand Down Expand Up @@ -138,6 +153,7 @@ export async function prospectsGet(id: string, options: { json?: boolean }): Pro
Type: p.record_type,
Lifecycle: p.lifecycle,
Favorite: p.favorite ? 'Yes' : 'No',
Status: statusLabel(p),
Source: p.source,
Tags: p.tags.map((tag) => `${tag.name} (${tag.id})`).join(', ') || '—',
Notes: String(p.note_count ?? 0),
Expand Down Expand Up @@ -173,6 +189,7 @@ export async function prospectsGetByRecord(options: {
Type: p.record_type,
Lifecycle: p.lifecycle,
Favorite: p.favorite ? 'Yes' : 'No',
Status: statusLabel(p),
Source: p.source,
Tags: p.tags.map((tag) => `${tag.name} (${tag.id})`).join(', ') || '—',
Added: formatDate(p.created_at),
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1642,7 +1642,7 @@ prospectsCmd
.option('--source <source>', 'Filter by source, e.g. driving, import, api, cli, or mcp')
.option('--favorites', 'Only starred prospects')
.option('--list <listId>', 'Only members of this list')
.option('--tag <tagId>', 'Only prospects with this tag, e.g. tag_5')
.option('--tag <tagId>', 'Only prospects with this tag, e.g. tag_31')
.option('--search <term>', 'Address words for properties; name or city for people')
.option('--sort <order>', 'newest (default) or oldest')
.option('-p, --page <n>', 'Page number')
Expand All @@ -1654,7 +1654,7 @@ prospectsCmd
Examples:
dm prospects list
dm prospects list --source driving
dm prospects list --lifecycle opportunity --tag tag_1
dm prospects list --lifecycle opportunity --tag tag_31
dm prospects list --record-type person --search "austin" --json`
)
.action(async (options) => {
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const CLI_VERSION = '0.4.1-rc.1';
export const CLI_VERSION = '0.4.1-rc.2';
export const CLI_USER_AGENT = `dm-cli/${CLI_VERSION}`;
22 changes: 21 additions & 1 deletion tests/commands/prospects.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { prospectsArchive, prospectsReactivate } from '../../src/commands/prospects.js';
import { prospectsArchive, prospectsReactivate, prospectsGet } from '../../src/commands/prospects.js';

vi.mock('../../src/lib/config.js', () => ({
readConfig: () => ({ apiKey: 'fixture-only', apiEnvironment: 'staging' }),
Expand Down Expand Up @@ -134,3 +134,23 @@ describe('dm prospects reactivate', () => {
expect(log.mock.calls.flat().join('\n')).toContain('Prospects Restored');
});
});

// Public output remains usable with both the additive field and older API responses.
describe('dm prospects status display', () => {
it.each([
['do_not_contact', 'Do Not Contact'],
['follow_up', 'Follow up'],
[null, 'None'],
[undefined, 'None'],
])('shows status %s on the prospect detail', async (status, label) => {
fetchMock.mockResolvedValue(jsonResponse(200, { data: {
id: 'prospect_8812', record_type: 'property', record_id: 'prop_1',
lifecycle: 'active', favorite: false, status, source: 'api',
record: { address: '123 Main St' }, tags: [], created_at: '2026-10-13T00:00:00Z',
} }));
await prospectsGet('prospect_8812', {});
const printed = log.mock.calls.flat().join('\n');
expect(printed).toContain('Status');
expect(printed).toContain(label);
});
});
Loading