Code
    RPS Digital P3 Intake ArchiveUpdated May 10, 2026TS

    RPS Digital P3 Intake Archive Api.Prompts source

    Imported TypeScript file from ../../app/app/routes/api.prompts.ts.

    Source file

    ../../app/app/routes/api.prompts.ts

    TypeScript87 lines
    1. import { json, type ActionFunctionArgs } from '@remix-run/node';
    2. import { randomUUID } from 'node:crypto';
    3. import path from 'node:path';
    4. import { getPromptProvider } from '../ai/provider.server';
    5. import { createJob, createPrompt, createProduct, createRelease, updateProductCurrentRelease } from '../db.server';
    6. import { buildObjectKeyPrefix } from '../../../shared/pipeline';
    7. import { requireInstalledShop } from '../authz.server';
    8. export async function action({ request }: ActionFunctionArgs) {
    9. if (request.method !== 'POST') {
    10. return json({ error: 'Method not allowed' }, { status: 405 });
    11. }
    12. const contentType = request.headers.get('content-type') || '';
    13. let body: Record<string, unknown> = {};
    14. try {
    15. body = contentType.includes('application/json')
    16. ? ((await request.json()) as Record<string, unknown>)
    17. : (Object.fromEntries(await request.formData()) as Record<string, unknown>);
    18. } catch {
    19. return json({ error: 'Invalid request body' }, { status: 400 });
    20. }
    21. const access = requireInstalledShop(request, body);
    22. if (access instanceof Response) return access;
    23. const prompt = String(body.prompt || '');
    24. const shopId = access.shopId;
    25. const sku = String(body.sku || `sku-${Date.now()}`);
    26. const release = String(body.release || 'v1');
    27. const prefixBase = String(body.prefixBase || (process.env.GCS_PREFIX || 'products'));
    28. if (!prompt.trim()) {
    29. return json({ error: 'Prompt is required' }, { status: 400 });
    30. }
    31. const provider = getPromptProvider();
    32. const outputDir = path.resolve(process.cwd(), 'tmp', `prompt-${randomUUID()}`);
    33. const generated = await provider.generateFromPrompt(prompt, outputDir);
    34. const promptId = createPrompt({
    35. shopId,
    36. rawPrompt: prompt,
    37. provider: generated.provider,
    38. model: generated.model,
    39. outputSummary: JSON.stringify(generated.metadata),
    40. });
    41. const productId = createProduct({ shopId, promptId });
    42. const releaseId = createRelease({ productId, version: release, status: 'draft' });
    43. updateProductCurrentRelease({ productId, releaseId });
    44. const objectKeyPrefix = buildObjectKeyPrefix(prefixBase, sku, release);
    45. let options = body.options || {};
    46. if (typeof options === 'string') {
    47. try {
    48. options = JSON.parse(options);
    49. } catch {
    50. options = {};
    51. }
    52. }
    53. const jobId = createJob({
    54. shopId,
    55. type: 'prompt',
    56. inputPayload: JSON.stringify({
    57. pipeline: {
    58. artPath: generated.imagePath,
    59. roomBgPath: body.roomBgPath || null,
    60. sku,
    61. release,
    62. outputDir,
    63. objectKeyPrefix,
    64. options,
    65. },
    66. metadata: generated.metadata,
    67. releaseId,
    68. productId,
    69. }),
    70. });
    71. return json({
    72. jobId,
    73. productId,
    74. releaseId,
    75. metadata: generated.metadata,
    76. });
    77. }