From 4d072edd132f7c2d3e896905e223ac3582f10ab0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 12 Jul 2026 11:30:47 +0000 Subject: [PATCH] chore(deps): bump @photon-ai/dashboard-api to 1.6.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Syncs the CLI with dashboard@v1.6.8. This release is a security hardening pass on the phone-OTP flow (dashboard#241) and does not republish @photon-ai/dashboard-api — 1.6.1 remains the latest. main was pinned to @photon-ai/dashboard-api@1.2.0, so this catches the CLI up to the current public API surface. The 1.6.x bundled .d.ts exposes route response bodies as `Record` (index signature only), which makes `.map((p) => ...)` implicitly-any. Fix pattern: define typed Project and SpectrumUser DTOs in src/lib/types.ts and cast at the API boundary in the two list commands. - projects list: (data ?? []) as Project[] - spectrum users list: (data?.users ?? []) as SpectrumUser[] - dropped the local SpectrumUser interface in favor of the shared one bun run check is green. Co-authored-by: citron --- bun.lock | 5 +++-- package.json | 2 +- src/commands/projects.ts | 3 ++- src/commands/spectrum/users.ts | 11 ++--------- src/lib/types.ts | 35 +++++++++++++++++++++++++++++++++- 5 files changed, 42 insertions(+), 14 deletions(-) diff --git a/bun.lock b/bun.lock index 748dba3..fdc61ff 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "dashboard-cli", @@ -15,7 +16,7 @@ "update-notifier": "^7.3.1", }, "devDependencies": { - "@photon-ai/dashboard-api": "1.2.0", + "@photon-ai/dashboard-api": "1.6.1", "@types/bun": "latest", "@types/node": "^25.6.2", "@types/update-notifier": "^6.0.8", @@ -49,7 +50,7 @@ "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], - "@photon-ai/dashboard-api": ["@photon-ai/dashboard-api@1.2.0", "", { "peerDependencies": { "@elysiajs/eden": "^1.4.9", "elysia": "^1.4.28" } }, "sha512-ZQ4OVaGQMFVMa2/bL2OfRxMaQDABwi+tHUFQHmQOH39N7pCXC6vQ8m32+Its2FxQ5VwU+dyvqmyv0ccxCmK8hw=="], + "@photon-ai/dashboard-api": ["@photon-ai/dashboard-api@1.6.1", "", { "peerDependencies": { "@elysiajs/eden": "^1.4.9", "elysia": "^1.4.28" } }, "sha512-6wgtxR3/6PXxckhkkCWKSGaRBZviaxLrhtCid5WlD3NimPj4V8S0ODvgeF4kH5vDgmOvvr6QIDLY/dGZKl2fQg=="], "@pnpm/config.env-replace": ["@pnpm/config.env-replace@1.1.0", "", {}, "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w=="], diff --git a/package.json b/package.json index afb9a76..8ffd9db 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "prepublishOnly": "bun run typecheck && bun run build" }, "devDependencies": { - "@photon-ai/dashboard-api": "1.2.0", + "@photon-ai/dashboard-api": "1.6.1", "@types/bun": "latest", "@types/node": "^25.6.2", "@types/update-notifier": "^6.0.8", diff --git a/src/commands/projects.ts b/src/commands/projects.ts index 0722690..25a45a3 100644 --- a/src/commands/projects.ts +++ b/src/commands/projects.ts @@ -20,6 +20,7 @@ import { SessionExpiredError } from "~/lib/errors.ts"; import { confirmDestructive } from "~/lib/interactive.ts"; import { c, die, formatApiError, printJson, printTable } from "~/lib/output.ts"; import { isInteractive } from "~/lib/tty.ts"; +import type { Project } from "~/lib/types.ts"; /** Platforms accepted by `projects create` (mirrors the API's create body). */ const PLATFORMS = ["imessage", "whatsapp_business", "voice"] as const; @@ -65,7 +66,7 @@ function registerListCommand(projects: Command): void { die(`Failed to list projects: ${formatApiError(error)}`); } - const list = data ?? []; + const list = (data ?? []) as Project[]; if (opts.json) { printJson(list); return; diff --git a/src/commands/spectrum/users.ts b/src/commands/spectrum/users.ts index 8fc8ad1..d52406b 100644 --- a/src/commands/spectrum/users.ts +++ b/src/commands/spectrum/users.ts @@ -6,6 +6,7 @@ import { SessionExpiredError } from "~/lib/errors.ts"; import { confirmDestructive } from "~/lib/interactive.ts"; import { c, die, formatApiError, printJson, printTable } from "~/lib/output.ts"; import { isInteractive } from "~/lib/tty.ts"; +import type { SpectrumUser } from "~/lib/types.ts"; export function registerSpectrumUsers(spectrum: Command): void { const users = spectrum @@ -37,7 +38,7 @@ export function registerSpectrumUsers(spectrum: Command): void { if (status === 401) throw new SessionExpiredError(resolved.name); if (error) die(`Failed to list users: ${formatApiError(error)}`); - const list = data?.users ?? []; + const list = (data?.users ?? []) as SpectrumUser[]; if (opts.json) return printJson(list); if (list.length === 0) { console.log(c.dim("No Spectrum users yet.")); @@ -142,14 +143,6 @@ export function registerSpectrumUsers(spectrum: Command): void { }); } -interface SpectrumUser { - id: string; - firstName?: string | null; - lastName?: string | null; - email?: string | null; - phoneNumber?: string | null; -} - interface FilledAdd { firstName: string; lastName: string; diff --git a/src/lib/types.ts b/src/lib/types.ts index 179f417..cfe3636 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -9,4 +9,37 @@ * in command logic. */ -export {}; +/** + * Project row as returned by `GET /api/projects` and `GET /api/projects/:id`. + * The upstream `.d.ts` for 1.6.x publishes these bodies as `Record` + * (index-signature only), so we cast to this shape at the boundary to get typed + * field access in list/show/delete commands. + */ +export interface Project { + id: string; + name: string; + location: string; + status: string; + platforms: string[]; + isOwner: boolean; + template: boolean; + observability: boolean; + slackChannelId?: string | null; + slackTeamId?: string | null; + projectSecret?: string | null; + createdAt: string; + updatedAt: string; +} + +/** + * Spectrum user row as returned by `GET /api/projects/:id/spectrum/users` + * and echoed back by `POST` on the same route. Same rationale as `Project`: + * the 1.6.x published response type is a bare index signature. + */ +export interface SpectrumUser { + id: string; + firstName?: string | null; + lastName?: string | null; + email?: string | null; + phoneNumber?: string | null; +}