From 0ca1a4576ea980d30aa84270e0ba965e109d7a93 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Wed, 26 Nov 2025 23:32:13 +0700 Subject: [PATCH] fix: api --- .../src/services/core/AliasService.ts | 5 +++-- .../src/services/core/ImageService.ts | 4 ++-- tests/api/03-flows.ts | 16 ++++++-------- tests/api/05-live.ts | 21 +++++++++---------- tests/api/utils.ts | 13 +++++++++++- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/apps/api-service/src/services/core/AliasService.ts b/apps/api-service/src/services/core/AliasService.ts index 5cd5ef2..ff842ef 100644 --- a/apps/api-service/src/services/core/AliasService.ts +++ b/apps/api-service/src/services/core/AliasService.ts @@ -117,12 +117,13 @@ export class AliasService { alias: string, projectId: string ): Promise { + // Project aliases can exist on images with or without flowId + // Per spec: images with project alias should be resolvable at project level const image = await db.query.images.findFirst({ where: and( eq(images.projectId, projectId), eq(images.alias, alias), - isNull(images.deletedAt), - isNull(images.flowId) + isNull(images.deletedAt) ), }); diff --git a/apps/api-service/src/services/core/ImageService.ts b/apps/api-service/src/services/core/ImageService.ts index 76e6542..dfbe2c3 100644 --- a/apps/api-service/src/services/core/ImageService.ts +++ b/apps/api-service/src/services/core/ImageService.ts @@ -272,6 +272,7 @@ export class ImageService { projectId: string ): Promise { // Step 1: Clear alias from any existing image with this alias + // Project aliases can exist on images with or without flowId await db .update(images) .set({ @@ -282,8 +283,7 @@ export class ImageService { and( eq(images.projectId, projectId), eq(images.alias, alias), - isNull(images.deletedAt), - isNull(images.flowId) + isNull(images.deletedAt) ) ); diff --git a/tests/api/03-flows.ts b/tests/api/03-flows.ts index 732cc00..f99682a 100644 --- a/tests/api/03-flows.ts +++ b/tests/api/03-flows.ts @@ -34,19 +34,15 @@ async function main() { testContext.firstGenId = generation.id; }); - // Test 2: Lazy flow - verify flow doesn't exist yet + // Test 2: Lazy flow - verify flow doesn't exist yet (Section 4.1) await runTest('Lazy flow - verify flow not created yet', async () => { - try { - await api(`${endpoints.flows}/${testContext.lazyFlowId}`, { - expectError: true, - }); + const result = await api(`${endpoints.flows}/${testContext.lazyFlowId}`, { + expectError: true, + }); + if (result.status !== 404) { throw new Error('Flow should not exist yet (lazy creation)'); - } catch (error: any) { - if (error.message.includes('should not exist')) { - throw error; - } - log.detail('Flow correctly does not exist', '✓'); } + log.detail('Flow correctly does not exist', '✓'); }); // Test 3: Lazy flow - second use creates flow diff --git a/tests/api/05-live.ts b/tests/api/05-live.ts index a4d8aff..525d5d0 100644 --- a/tests/api/05-live.ts +++ b/tests/api/05-live.ts @@ -91,7 +91,9 @@ async function main() { }), }); - const result = await api(endpoints.live, { + // Live endpoint requires prompt query parameter + const testPrompt = encodeURIComponent('A simple blue square on white background'); + const result = await api(`${endpoints.live}?prompt=${testPrompt}`, { method: 'GET', }); @@ -117,18 +119,15 @@ async function main() { method: 'DELETE', }); - // Verify deleted - try { - await api(`${endpoints.live}/scopes/test-scope`, { - expectError: true, - }); + // Verify deleted - check for 404 status + const result = await api(`${endpoints.live}/scopes/test-scope`, { + expectError: true, + }); + + if (result.status !== 404) { throw new Error('Scope should be deleted'); - } catch (error: any) { - if (error.message.includes('should be deleted')) { - throw error; - } - log.detail('Scope deleted', '✓'); } + log.detail('Scope deleted', '✓'); }); log.section('LIVE URL & SCOPE TESTS COMPLETED'); diff --git a/tests/api/utils.ts b/tests/api/utils.ts index debaf98..0031402 100644 --- a/tests/api/utils.ts +++ b/tests/api/utils.ts @@ -313,11 +313,22 @@ export async function resolveAlias( const result = await api(endpoint); const image = result.data.data; + // Determine scope based on alias type and context + const technicalAliases = ['@last', '@first', '@upload']; + let scope: string; + if (technicalAliases.includes(alias)) { + scope = 'technical'; + } else if (flowId) { + scope = 'flow'; + } else { + scope = 'project'; + } + // Adapt response to match old /resolve/ format for test compatibility return { imageId: image.id, alias: image.alias || alias, - scope: image.flowId ? 'flow' : 'project', + scope, flowId: image.flowId, image, };