From a991801a14a28320365232ccbdeda60c5ac5ca61 Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 9 Feb 2026 16:46:29 -0800 Subject: [PATCH] removed unused route --- apps/sim/app/api/tools/jira/issue/route.ts | 111 --------------- .../tools/onepassword/create-item/route.ts | 9 +- .../tools/onepassword/replace-item/route.ts | 5 +- .../tools/onepassword/update-item/route.ts | 19 +-- apps/sim/app/api/tools/onepassword/utils.ts | 134 +++++++++++++++--- 5 files changed, 134 insertions(+), 144 deletions(-) delete mode 100644 apps/sim/app/api/tools/jira/issue/route.ts diff --git a/apps/sim/app/api/tools/jira/issue/route.ts b/apps/sim/app/api/tools/jira/issue/route.ts deleted file mode 100644 index 3c837de04..000000000 --- a/apps/sim/app/api/tools/jira/issue/route.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { createLogger } from '@sim/logger' -import { type NextRequest, NextResponse } from 'next/server' -import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' -import { validateJiraCloudId, validateJiraIssueKey } from '@/lib/core/security/input-validation' -import { getJiraCloudId } from '@/tools/jira/utils' - -export const dynamic = 'force-dynamic' - -const logger = createLogger('JiraIssueAPI') - -export async function POST(request: NextRequest) { - try { - const auth = await checkSessionOrInternalAuth(request) - if (!auth.success || !auth.userId) { - return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) - } - - const { domain, accessToken, issueId, cloudId: providedCloudId } = await request.json() - if (!domain) { - logger.error('Missing domain in request') - return NextResponse.json({ error: 'Domain is required' }, { status: 400 }) - } - - if (!accessToken) { - logger.error('Missing access token in request') - return NextResponse.json({ error: 'Access token is required' }, { status: 400 }) - } - - if (!issueId) { - logger.error('Missing issue ID in request') - return NextResponse.json({ error: 'Issue ID is required' }, { status: 400 }) - } - - const cloudId = providedCloudId || (await getJiraCloudId(domain, accessToken)) - logger.info('Using cloud ID:', cloudId) - - const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId') - if (!cloudIdValidation.isValid) { - return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 }) - } - - const issueIdValidation = validateJiraIssueKey(issueId, 'issueId') - if (!issueIdValidation.isValid) { - return NextResponse.json({ error: issueIdValidation.error }, { status: 400 }) - } - - const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${issueId}` - - logger.info('Fetching Jira issue from:', url) - - const response = await fetch(url, { - method: 'GET', - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: 'application/json', - }, - }) - - if (!response.ok) { - logger.error('Jira API error:', { - status: response.status, - statusText: response.statusText, - }) - - let errorMessage - try { - const errorData = await response.json() - logger.error('Error details:', errorData) - errorMessage = errorData.message || `Failed to fetch issue (${response.status})` - } catch (_e) { - errorMessage = `Failed to fetch issue: ${response.status} ${response.statusText}` - } - return NextResponse.json({ error: errorMessage }, { status: response.status }) - } - - const data = await response.json() - logger.info('Successfully fetched issue:', data.key) - - const issueInfo: any = { - id: data.key, - name: data.fields.summary, - mimeType: 'jira/issue', - url: `https://${domain}/browse/${data.key}`, - modifiedTime: data.fields.updated, - webViewLink: `https://${domain}/browse/${data.key}`, - status: data.fields.status?.name, - description: data.fields.description, - priority: data.fields.priority?.name, - assignee: data.fields.assignee?.displayName, - reporter: data.fields.reporter?.displayName, - project: { - key: data.fields.project?.key, - name: data.fields.project?.name, - }, - } - - return NextResponse.json({ - issue: issueInfo, - cloudId, - }) - } catch (error) { - logger.error('Error processing request:', error) - return NextResponse.json( - { - error: 'Failed to retrieve Jira issue', - details: (error as Error).message, - }, - { status: 500 } - ) - } -} diff --git a/apps/sim/app/api/tools/onepassword/create-item/route.ts b/apps/sim/app/api/tools/onepassword/create-item/route.ts index bd5ebfab8..dae8cbffa 100644 --- a/apps/sim/app/api/tools/onepassword/create-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/create-item/route.ts @@ -1,4 +1,5 @@ import { randomUUID } from 'crypto' +import type { ItemCreateParams } from '@1password/sdk' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' @@ -62,15 +63,13 @@ export async function POST(request: NextRequest) { })) : undefined - // Cast to any because toSdkCategory/toSdkFieldType return string literals - // that match SDK enum values but TypeScript can't verify this at compile time const item = await client.items.create({ vaultId: params.vaultId, - category: toSdkCategory(params.category) as any, + category: toSdkCategory(params.category), title: params.title || '', tags: parsedTags, - fields: parsedFields as any, - }) + fields: parsedFields, + } as ItemCreateParams) return NextResponse.json(normalizeSdkItem(item)) } diff --git a/apps/sim/app/api/tools/onepassword/replace-item/route.ts b/apps/sim/app/api/tools/onepassword/replace-item/route.ts index d45dac20b..3fc198d62 100644 --- a/apps/sim/app/api/tools/onepassword/replace-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/replace-item/route.ts @@ -1,4 +1,5 @@ import { randomUUID } from 'crypto' +import type { Item } from '@1password/sdk' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' @@ -79,9 +80,9 @@ export async function POST(request: NextRequest) { autofillBehavior: 'AnywhereOnWebsite' as const, })) : existing.websites, - } + } as Item - const result = await client.items.put(sdkItem as any) + const result = await client.items.put(sdkItem) return NextResponse.json(normalizeSdkItem(result)) } diff --git a/apps/sim/app/api/tools/onepassword/update-item/route.ts b/apps/sim/app/api/tools/onepassword/update-item/route.ts index 5482dd6b9..543b5f052 100644 --- a/apps/sim/app/api/tools/onepassword/update-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/update-item/route.ts @@ -35,11 +35,7 @@ export async function POST(request: NextRequest) { const body = await request.json() const params = UpdateItemSchema.parse(body) const creds = resolveCredentials(params) - const ops = JSON.parse(params.operations) as Array<{ - op: string - path: string - value?: unknown - }> + const ops = JSON.parse(params.operations) as JsonPatchOperation[] logger.info( `[${requestId}] Updating item ${params.itemId} in vault ${params.vaultId} (${creds.mode} mode)` @@ -48,7 +44,6 @@ export async function POST(request: NextRequest) { if (creds.mode === 'service_account') { const client = await createOnePasswordClient(creds.serviceAccountToken!) - // SDK doesn't support PATCH — fetch, apply patches, then put const item = await client.items.get(params.vaultId, params.itemId) for (const op of ops) { @@ -89,8 +84,15 @@ export async function POST(request: NextRequest) { } } -/** Apply a single RFC6902 JSON Patch operation to a mutable SDK Item. */ -function applyPatch(item: Record, op: { op: string; path: string; value?: unknown }) { +interface JsonPatchOperation { + op: 'add' | 'remove' | 'replace' + path: string + value?: unknown +} + +/** Apply a single RFC6902 JSON Patch operation to a mutable object. */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function applyPatch(item: Record, op: JsonPatchOperation) { const segments = op.path.split('/').filter(Boolean) if (segments.length === 1) { @@ -103,7 +105,6 @@ function applyPatch(item: Record, op: { op: string; path: string; v return } - // Navigate to parent of target let target = item for (let i = 0; i < segments.length - 1; i++) { const seg = segments[i] diff --git a/apps/sim/app/api/tools/onepassword/utils.ts b/apps/sim/app/api/tools/onepassword/utils.ts index fbf6042b7..ce052f15b 100644 --- a/apps/sim/app/api/tools/onepassword/utils.ts +++ b/apps/sim/app/api/tools/onepassword/utils.ts @@ -1,12 +1,112 @@ +import type { + Item, + ItemCategory, + ItemField, + ItemFieldType, + ItemOverview, + ItemSection, + VaultOverview, + Website, +} from '@1password/sdk' import { createLogger } from '@sim/logger' const logger = createLogger('OnePasswordRouteUtils') +/** Connect-format field type strings returned by normalization. */ +type ConnectFieldType = + | 'STRING' + | 'CONCEALED' + | 'EMAIL' + | 'URL' + | 'OTP' + | 'PHONE' + | 'DATE' + | 'MONTH_YEAR' + | 'MENU' + | 'ADDRESS' + | 'REFERENCE' + | 'SSHKEY' + | 'CREDIT_CARD_NUMBER' + | 'CREDIT_CARD_TYPE' + +/** Connect-format category strings returned by normalization. */ +type ConnectCategory = + | 'LOGIN' + | 'PASSWORD' + | 'API_CREDENTIAL' + | 'SECURE_NOTE' + | 'SERVER' + | 'DATABASE' + | 'CREDIT_CARD' + | 'IDENTITY' + | 'SSH_KEY' + | 'DOCUMENT' + | 'SOFTWARE_LICENSE' + | 'EMAIL_ACCOUNT' + | 'MEMBERSHIP' + | 'PASSPORT' + | 'REWARD_PROGRAM' + | 'DRIVER_LICENSE' + | 'BANK_ACCOUNT' + | 'MEDICAL_RECORD' + | 'OUTDOOR_LICENSE' + | 'WIRELESS_ROUTER' + | 'SOCIAL_SECURITY_NUMBER' + | 'CUSTOM' + +/** Normalized vault shape matching the Connect API response. */ +export interface NormalizedVault { + id: string + name: string + description: null + attributeVersion: number + contentVersion: number + items: number + type: string + createdAt: string | null + updatedAt: string | null +} + +/** Normalized item overview shape matching the Connect API response. */ +export interface NormalizedItemOverview { + id: string + title: string + vault: { id: string } + category: ConnectCategory + urls: Array<{ href: string; label: string | null; primary: boolean }> + favorite: boolean + tags: string[] + version: number + state: string | null + createdAt: string | null + updatedAt: string | null + lastEditedBy: null +} + +/** Normalized field shape matching the Connect API response. */ +export interface NormalizedField { + id: string + label: string + type: ConnectFieldType + purpose: string + value: string | null + section: { id: string } | null + generate: boolean + recipe: null + entropy: null +} + +/** Normalized full item shape matching the Connect API response. */ +export interface NormalizedItem extends NormalizedItemOverview { + fields: NormalizedField[] + sections: Array<{ id: string; label: string }> +} + /** * SDK field type string values → Connect field type mapping. * Uses string literals instead of enum imports to avoid loading the WASM module at build time. */ -const SDK_TO_CONNECT_FIELD_TYPE: Record = { +const SDK_TO_CONNECT_FIELD_TYPE: Record = { Text: 'STRING', Concealed: 'CONCEALED', Email: 'EMAIL', @@ -24,7 +124,7 @@ const SDK_TO_CONNECT_FIELD_TYPE: Record = { } /** SDK category string values → Connect category mapping. */ -const SDK_TO_CONNECT_CATEGORY: Record = { +const SDK_TO_CONNECT_CATEGORY: Record = { Login: 'LOGIN', Password: 'PASSWORD', ApiCredentials: 'API_CREDENTIAL', @@ -52,7 +152,7 @@ const SDK_TO_CONNECT_CATEGORY: Record = { } /** Connect category → SDK category string mapping. */ -const CONNECT_TO_SDK_CATEGORY: Record = { +const CONNECT_TO_SDK_CATEGORY: Record = { LOGIN: 'Login', PASSWORD: 'Password', API_CREDENTIAL: 'ApiCredentials', @@ -77,7 +177,7 @@ const CONNECT_TO_SDK_CATEGORY: Record = { } /** Connect field type → SDK field type string mapping. */ -const CONNECT_TO_SDK_FIELD_TYPE: Record = { +const CONNECT_TO_SDK_FIELD_TYPE: Record = { STRING: 'Text', CONCEALED: 'Concealed', EMAIL: 'Email', @@ -98,10 +198,10 @@ const CONNECT_TO_SDK_FIELD_TYPE: Record = { export type ConnectionMode = 'service_account' | 'connect' export interface CredentialParams { - connectionMode?: ConnectionMode - serviceAccountToken?: string - serverUrl?: string - apiKey?: string + connectionMode?: ConnectionMode | null + serviceAccountToken?: string | null + serverUrl?: string | null + apiKey?: string | null } export interface ResolvedCredentials { @@ -172,7 +272,7 @@ export async function connectRequest(options: { } /** Normalize an SDK VaultOverview to match Connect API vault shape. */ -export function normalizeSdkVault(vault: Record) { +export function normalizeSdkVault(vault: VaultOverview): NormalizedVault { return { id: vault.id, name: vault.title, @@ -189,13 +289,13 @@ export function normalizeSdkVault(vault: Record) { } /** Normalize an SDK ItemOverview to match Connect API item summary shape. */ -export function normalizeSdkItemOverview(item: Record) { +export function normalizeSdkItemOverview(item: ItemOverview): NormalizedItemOverview { return { id: item.id, title: item.title, vault: { id: item.vaultId }, category: SDK_TO_CONNECT_CATEGORY[item.category] ?? 'CUSTOM', - urls: (item.websites ?? []).map((w: Record) => ({ + urls: item.websites.map((w: Website) => ({ href: w.url, label: w.label ?? null, primary: false, @@ -213,13 +313,13 @@ export function normalizeSdkItemOverview(item: Record) { } /** Normalize a full SDK Item to match Connect API FullItem shape. */ -export function normalizeSdkItem(item: Record) { +export function normalizeSdkItem(item: Item): NormalizedItem { return { id: item.id, title: item.title, vault: { id: item.vaultId }, category: SDK_TO_CONNECT_CATEGORY[item.category] ?? 'CUSTOM', - urls: (item.websites ?? []).map((w: Record) => ({ + urls: item.websites.map((w: Website) => ({ href: w.url, label: w.label ?? null, primary: false, @@ -228,7 +328,7 @@ export function normalizeSdkItem(item: Record) { tags: item.tags ?? [], version: item.version ?? 0, state: null, - fields: (item.fields ?? []).map((field: Record) => ({ + fields: item.fields.map((field: ItemField) => ({ id: field.id, label: field.title, type: SDK_TO_CONNECT_FIELD_TYPE[field.fieldType] ?? 'STRING', @@ -239,7 +339,7 @@ export function normalizeSdkItem(item: Record) { recipe: null, entropy: null, })), - sections: (item.sections ?? []).map((section: Record) => ({ + sections: item.sections.map((section: ItemSection) => ({ id: section.id, label: section.title, })), @@ -252,11 +352,11 @@ export function normalizeSdkItem(item: Record) { } /** Convert a Connect-style category string to the SDK category string. */ -export function toSdkCategory(category: string): string { +export function toSdkCategory(category: string): `${ItemCategory}` { return CONNECT_TO_SDK_CATEGORY[category] ?? 'Login' } /** Convert a Connect-style field type string to the SDK field type string. */ -export function toSdkFieldType(type: string): string { +export function toSdkFieldType(type: string): `${ItemFieldType}` { return CONNECT_TO_SDK_FIELD_TYPE[type] ?? 'Text' }