Add callAppRoute to RestApiClient (#22863)
Adds a `callAppRoute` method to `RestApiClient` in `twenty-client-sdk/rest`. It calls one of the app's own HTTP routes using the injected `TWENTY_FUNCTIONS_URL`, resolved internally the same way the client already resolves `TWENTY_API_URL`, so app code no longer reads env vars or knows how function routes are hosted. Both app runtimes already go through `RestApiClient` for route calls (logic functions and front components), so both get this in one place; front components keep the existing 401 token-refresh flow. Pairs with #22825, which makes the injected `TWENTY_FUNCTIONS_URL` callable in every topology (app custom domain -> workspace isolated functions domain -> `SERVER_URL/s`). Once this ships in an SDK release, Call Recorder's own-route plumbing (logic-function and front-component utils) drops its URL resolution and calls `client.callAppRoute(path, body)`. --------- Co-authored-by: martmull <martmull@hotmail.fr> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
+9
-12
@@ -69,6 +69,7 @@ chapter.
|
||||
```tsx filename="src/front-components/generate-document-form.front-component.tsx"
|
||||
import { useEffect, useState } from 'react';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
import { RestApiClient } from 'twenty-client-sdk/rest';
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { enqueueSnackbar, useSelectedRecordIds } from 'twenty-sdk/front-component';
|
||||
|
||||
@@ -91,15 +92,10 @@ const GenerateDocumentForm = () => {
|
||||
}, []);
|
||||
|
||||
const generate = async () => {
|
||||
// Prefer the injected functions URL; fall back to the legacy /s prefix (self-hosted/local)
|
||||
const functionsBaseUrl =
|
||||
process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`;
|
||||
const token = process.env.TWENTY_APP_ACCESS_TOKEN ?? process.env.TWENTY_API_KEY;
|
||||
const res = await fetch(`${functionsBaseUrl}/documents/generate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ templateId, recordId }),
|
||||
}).then((r) => r.json());
|
||||
const res = await new RestApiClient().post<{ success: boolean }>(
|
||||
'/s/documents/generate',
|
||||
{ templateId, recordId },
|
||||
);
|
||||
await enqueueSnackbar({
|
||||
message: res.success ? 'Document generated.' : 'Generation failed.',
|
||||
variant: res.success ? 'success' : 'error',
|
||||
@@ -180,6 +176,7 @@ helper.
|
||||
|
||||
```tsx filename="src/front-components/document-viewer.front-component.tsx"
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
import { RestApiClient } from 'twenty-client-sdk/rest';
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { useFrontComponentExecutionContext } from 'twenty-sdk/front-component';
|
||||
import { Markdown } from 'src/utils/markdown-to-react';
|
||||
@@ -188,9 +185,9 @@ const DocumentViewer = () => {
|
||||
const recordId = useFrontComponentExecutionContext((c) => c.recordId ?? null);
|
||||
// ...load { content, file } for recordId, then derive the links:
|
||||
const pdfUrl = document.file?.[0]?.url;
|
||||
const functionsBaseUrl =
|
||||
process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL ?? ''}/s`;
|
||||
const webUrl = `${functionsBaseUrl}/documents/view?id=${recordId}`;
|
||||
const webUrl = new RestApiClient().resolveUrl('/s/documents/view', {
|
||||
query: { id: recordId },
|
||||
});
|
||||
|
||||
// Render the template body, plus quick links to the web page and the PDF.
|
||||
// Links open in a new tab so they don't navigate the embedded component.
|
||||
|
||||
+4
-9
@@ -9,15 +9,10 @@ The same handler can also answer HTTP requests. We'll add two routes:
|
||||
- a **POST** endpoint the UI calls to generate a document, and
|
||||
- a public **GET** endpoint that renders a document as a printable web page.
|
||||
|
||||
Both use `httpRouteTriggerSettings`. On the local dev server, app routes are
|
||||
served under the `/s` prefix (e.g. `http://localhost:2020/s/documents/generate`).
|
||||
|
||||
<Note>
|
||||
On Twenty Cloud, routes are served on the workspace's dedicated functions domain
|
||||
— the URL Twenty injects as `TWENTY_FUNCTIONS_URL`, with no `/s` prefix. The `/s`
|
||||
prefix is deprecated there and only remains for self-hosted and local instances.
|
||||
See [Calling a logic function](/developers/extend/apps/layout/front-components#calling-a-logic-function).
|
||||
</Note>
|
||||
Both use `httpRouteTriggerSettings`. App routes are addressed with an `/s/` path; on local
|
||||
and self-hosted instances, that path is served by your Twenty server
|
||||
(e.g. `http://localhost:2020/s/documents/generate`). On Twenty Cloud, `RestApiClient`
|
||||
resolves the path through the workspace's functions domain.
|
||||
|
||||
## POST route — generate on demand
|
||||
|
||||
|
||||
Reference in New Issue
Block a user