From 5f8baa9761d658dd5de57059b10cbaab5510c936 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 21:00:23 +0200 Subject: [PATCH] i18n - docs translations (#22933) Created by Github action Co-authored-by: github-actions --- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 14 ++--- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 12 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 2 +- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 13 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 2 +- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 12 +--- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 2 +- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 13 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 14 ++--- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 13 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 2 +- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 13 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 14 ++--- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 9 +-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 14 ++--- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 7 +-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 14 ++--- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 13 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 2 +- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 13 ++-- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 2 +- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 10 ++- .../extend/apps/layout/front-components.mdx | 63 ++++++++++--------- .../extend/apps/logic/logic-functions.mdx | 7 +-- .../developers/extend/apps/logic/overview.mdx | 14 ++--- .../document-generator/building-the-ui.mdx | 21 +++---- .../document-generator/http-routes.mdx | 7 +-- 60 files changed, 614 insertions(+), 709 deletions(-) diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/layout/front-components.mdx index 3255f91a49..2ec38ce9b6 100644 --- a/packages/twenty-docs/l/ar/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ تعمل مكونات الواجهة الأمامية على جانب المتصفح داخل Web Worker مُعزَل داخل iframe ذو origin غير شفاف، بينما تعمل [الدوال المنطقية](/l/ar/developers/extend/apps/logic/logic-functions) على جانب الخادم. لا توجد استدعاءات مباشرة ضمن العملية بين الاثنين — بدلاً من ذلك، يصل مكون الواجهة الأمامية إلى الدالة المنطقية عبر HTTP. -يتم الوصول إلى الدالة المنطقية المُعلَنة باستخدام `httpRouteTriggerSettings` عبر HTTP عند مسار التوجيه الخاص بها. يقوم Twenty بحقن عنوان URL الأساسي الذي تُقدَّم منه الدوال الخاصة بك في عامل التشغيل على أنه `TWENTY_FUNCTIONS_URL`، إلى جانب `TWENTY_APP_ACCESS_TOKEN` الذي يُصادِّق الاستدعاء. لا يوجد عميل SDK مخصص لاستدعاء دوالك الخاصة بعد، لذا استدعِها باستخدام `fetch` عادي: +يتم الوصول إلى الدالة المنطقية المُعلَنة باستخدام `httpRouteTriggerSettings` عبر HTTP عند مسار التوجيه الخاص بها. يتعامل `RestApiClient` مع المسارات التي تبدأ بـ `/s/` باعتبارها مسارات للتطبيق، ويُحوِّلها إلى عنوان الـ URL الذي تُقدَّم منه الدوال الخاصة بك، ويُجري عملية المصادقة عليها باستخدام `TWENTY_APP_ACCESS_TOKEN`. -> **على Twenty Cloud، يتم تقديم الدوال المنطقية المُفعَّلة عبر HTTP على نطاق مخصص لكل مساحة عمل** عند `https://\.withtwenty.com\` — وهذا بالضبط ما تُشير إليه قيمة `TWENTY_FUNCTIONS_URL`. للمتصلين الخارجيين، انسخ عنوان URL الدقيق من إعدادات **HTTP trigger** الخاصة بالدالة أو من علامة تبويب **Settings** في التطبيق. - - - مسار الدالة القديم `/s/` **مهمَل (deprecated)** وسيتم **إيقاف تفعيله في 2026-07-24**. استخدم بدلًا من ذلك `TWENTY_FUNCTIONS_URL` (أعلاه)، ورحِّل أي عناوين URL ثابتة من نوع `/s/` قبل ذلك التاريخ. يبقى مسار `/s/` متاحًا للاستضافة الذاتية. - +> **على Twenty Cloud، يتم تقديم الدوال المنطقية المُفعَّلة عبر HTTP على نطاق مخصص لكل مساحة عمل** عند `https://\.withtwenty.com\`. للمتصلين الخارجيين، انسخ عنوان URL الدقيق من إعدادات **HTTP trigger** الخاصة بالدالة أو من علامة تبويب **Settings** في التطبيق. يمكن لمكون واجهة أمامية عديم الرأس تنفيذ الاستدعاء عند التركيب عبر مكون `Command`، ثم إلغاء التركيب تلقائيًا: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -المسار المُضاف إلى `TWENTY_FUNCTIONS_URL` هو قيمة `httpRouteTriggerSettings.path` الخاصة بدالة المنطق (logic function). أبقِ `isAuthRequired: true`؛ فرمز `TWENTY_APP_ACCESS_TOKEN` الذي تُنشئه Twenty لمكوِّنك هو ما يصادق على الطلب: +المسار المُمرَّر إلى `RestApiClient` هو قيمة `httpRouteTriggerSettings.path` الخاصة بدالة المنطق (logic function) مع إضافة البادئة `/s`. أبقِ `isAuthRequired: true`؛ فرمز `TWENTY_APP_ACCESS_TOKEN` الذي تُنشئه Twenty لمكوِّنك هو ما يصادق على الطلب: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -يتم حقن `TWENTY_FUNCTIONS_URL` و`TWENTY_APP_ACCESS_TOKEN` تلقائيًا — انظر [متغيرات التطبيق](#application-variables). نظرًا لأن متغيرات التطبيق السرية لا تُعرَض أبدًا على مكونات الواجهة الأمامية، احتفِظ بمفاتيح واجهة برمجة التطبيقات والمنطق الحساس الآخر داخل الدالة المنطقية، وليس في مكون الواجهة الأمامية. +يتم حقن `TWENTY_APP_ACCESS_TOKEN` تلقائيًا — انظر [متغيرات التطبيق](#application-variables). نظرًا لأن متغيرات التطبيق السرية لا تُعرَض أبدًا على مكونات الواجهة الأمامية، احتفِظ بمفاتيح واجهة برمجة التطبيقات والمنطق الحساس الآخر داخل الدالة المنطقية، وليس في مكون الواجهة الأمامية. ### استدعاء واجهة REST API الخاصة بـ Twenty -لقراءة سجلات Twenty أو كتابتها من مكوِّن واجهة أمامية، استخدم `RestApiClient` من `twenty-client-sdk/rest`. ينتمي إلى نفس عائلة العملاء مثل `CoreApiClient` و`MetadataApiClient`، لكنه يستهدف واجهة REST API الخاصة بـ Twenty (`/rest/...`) بدلًا من واجهة GraphQL API، ويقرأ عنوان URL الأساسي الخاص بها من `TWENTY_API_URL`. +لاستدعاء مسارات HTTP الخاصة بالتطبيق أو لقراءة سجلات Twenty وكتابتها من مكوِّن واجهة أمامية، استخدم `RestApiClient` من `twenty-client-sdk/rest`. يُرسل المسارات من نوع `/s/...` إلى عنوان URL الأساسي للدوال في مساحة العمل الخاصة بك، ويُرسل أي مسار آخر، بما في ذلك `/rest/...`، إلى `TWENTY_API_URL`. -| طريقة | الوصف | -| --------------------------------- | -------------------------- | -| `get(path, options?)` | يرسل طلبًا من نوع `GET` | -| `post(path, body?, options?)` | يرسل طلبًا من نوع `POST` | -| `put(path, body?, options?)` | يرسل طلبًا من نوع `PUT` | -| `patch(path, body?, options?)` | يرسل طلبًا من نوع `PATCH` | -| `delete(path, options?)` | يرسل طلبًا من نوع `DELETE` | -| `request(method, path, options?)` | طلب عام بأي طريقة HTTP | +| طريقة | الوصف | +| --------------------------------- | ----------------------------------------------------------------------- | +| `get(path, options?)` | يرسل طلبًا من نوع `GET` | +| `post(path, body?, options?)` | يرسل طلبًا من نوع `POST` | +| `put(path, body?, options?)` | يرسل طلبًا من نوع `PUT` | +| `patch(path, body?, options?)` | يرسل طلبًا من نوع `PATCH` | +| `delete(path, options?)` | يرسل طلبًا من نوع `DELETE` | +| `request(method, path, options?)` | طلب عام بأي طريقة HTTP | +| `resolveUrl(path, options?)` | يُحوِّل مسارًا إلى عنوان URL كامل بدون إرسال طلب (لاستخدامه في الروابط) | تدعم `options` كلًا من `headers` و`query` (سجل لمعاملات query-string؛ يتم تخطي القيم nullish) و`AbortSignal` عبر `signal`. يتم تسلسل كائن `body` غير من النوع `FormData` إلى JSON تلقائيًا. عند حدوث `401`، يقوم العميل بتحديث رمز الوصول مرة واحدة عبر المضيف ثم يعيد محاولة الطلب. @@ -417,11 +411,22 @@ export default defineFrontComponent({ متغيرات النظام التالية تكون متاحة دائمًا عبر `process.env`: -| المتغيّر | الوصف | -| ------------------------- | ---------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | عنوان URL الأساسي الذي تُقدَّم منه دوال منطق HTTP الخاصة بتطبيقك | -| `TWENTY_API_URL` | عنوان URL الأساسي لـ Twenty Core API | -| `TWENTY_APP_ACCESS_TOKEN` | رمز مميز قصير العمر مُقيَّد بدور تطبيقك | +| المتغيّر | الوصف | +| ------------------------- | --------------------------------------- | +| `TWENTY_API_URL` | عنوان URL الأساسي لـ Twenty Core API | +| `TWENTY_APP_ACCESS_TOKEN` | رمز مميز قصير العمر مُقيَّد بدور تطبيقك | + +### `TWENTY_FUNCTIONS_URL` + +يقوم Twenty أيضًا بحقن `TWENTY_FUNCTIONS_URL` في مكوِّنات الواجهة الأمامية والدوال المنطقية: وهو عنوان URL الأساسي الذي تُقدَّم منه الدوال المنطقية المُفعَّلة عبر HTTP في تطبيقك. + +وهو موجود لأن ذلك العنوان (URL) ليس دائمًا هو خادم Twenty نفسه. على Twenty Cloud، يتم تقديم مسارات التطبيق على نطاق مخصص لكل مساحة عمل (`https://\.withtwenty.com`، أو نطاق التطبيق العمومي الأساسي عندما يتم تكوينه) بحيث تعمل الاستجابات المنشأة من التطبيق على أصل (origin) معزول بدلاً من أصل تطبيق Twenty. تُقدِّم النسخ المستضافة ذاتيًا والمحلية مسارات التطبيق تحت البادئة `/s` على الخادم نفسه وقد لا تضبط المتغير إطلاقًا. نظرًا لاختلاف عنوان URL الأساسي حسب مساحة العمل وحسب كل نسخة، لا يمكن لشفرتك (code) أن تُضمِّنه بشكل ثابت (hard-code) — يقوم الخادم بحقن القيمة الصحيحة وقت التشغيل. + +نادرًا ما تحتاج إلى قراءته مباشرة. استدعِ مساراتك عبر `RestApiClient` باستخدام مسار يبدأ بالبادئة `/s/`، وسيقوم العميل بحل عنوان URL نيابةً عنك: يزيل بادئة `/s` ويستخدم `TWENTY_FUNCTIONS_URL` كهدف، مع الرجوع إلى `\/s` عندما لا يكون المتغير مضبوطًا. استخدم `resolveUrl('/s/\')` للحصول على عنوان URL مطلق بدون إرسال طلب، على سبيل المثال لاستخدامه في رابط. اقرأ المتغير مباشرةً فقط عند إنشاء عنوان URL يدويًا: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## واجهة الاتصال مع المضيف diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/logic/logic-functions.mdx index 1e7f4c6605..3e7ffd2eb2 100644 --- a/packages/twenty-docs/l/ar/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` أنواع المشغّلات المتاحة: -* **httpRoute**: يعرض الدالة الخاصة بك على مسار وطريقة HTTP في مساحة العمل الخاصة بك **URL الأساسي للوظائف** - القيمة العشرين حقن كـ `TWENTY_FUNCTIONS_URL` (على 20 Cloud, مجال مخصص لكل عمل: -> مثال: `path: '/post-card/create'` يمكن استدعاؤه عبر `https://your-workspace.withtwenty.com/post-card/create` - - -مسار البادئة القديم `/s/' (https://your-twenty-server.com/s/post-card/create`) **مهمل على 20 Cloud** وسيتم إبطاله على **2026-07-24**. يبقى متاحا للحالات التي تستضيف ذاتيا أو المحلية والتي لا تشكل نطاق وظائف معزولة - استخدم `TWENTY_FUNCTIONS_URL` عند تعيينه. والعودة إلى `\/s/\` خلاف ذلك. - +* **httpRoute**: يعرِض وظيفتك على مسار وطريقة HTTP. في شيفرة التطبيق، أضف البادئة `/s/` إلى مسار التوجيه عند استخدام `RestApiClient`؛ يستخدم عنوان URL المنشور قاعدة `TWENTY_FUNCTIONS_URL` المُحدَّدة (أو `\/s` إذا لم تُحدَّد). لاستدعاء دالة منطقية يتم تشغيلها بواسطة مسار من مكون واجهة (بدون واجهة رسومية)، راجع قسم [استدعاء دالة منطقية](/l/ar/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/logic/overview.mdx index eccf1927b0..767cef1f05 100644 --- a/packages/twenty-docs/l/ar/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/apps/logic/overview.mdx @@ -40,13 +40,13 @@ icon: bolt دالة المنطق تختار واحدًا أو أكثر من المشغلات — كل إدخال أدناه هو حقل منفصل في `defineLogicFunction()`: -| المشغّل | متى يعمل | الإعداد | -| ---------------------- | ---------------------------------------------- | ------------------------------- | -| **مسار HTTP** | طلب يضرب عنوان URL العام لوظيفتك | `httpRouteTriggerSettings` | -| **كرون** | عند تطابق تعبير CRON | `cronTriggerSettings` | -| **حدث قاعدة البيانات** | يتم إنشاء سجل في مساحة العمل أو تحديثه أو حذفه | `databaseEventTriggerSettings` | -| **أداة ذكاء اصطناعي** | ميزة ذكاء اصطناعي في Twenty تقرر استدعاء دالتك | `toolTriggerSettings` | -| **إجراء سير العمل** | تستدعي خطوة في سير العمل دالتك | `workflowActionTriggerSettings` | +| المشغّل | متى يعمل | الإعداد | +| ---------------------- | -------------------------------------------------------------- | ------------------------------- | +| **مسار HTTP** | طلب يصل إلى نقطة نهاية `/s/\` الخاصة بك | `httpRouteTriggerSettings` | +| **كرون** | عند تطابق تعبير CRON | `cronTriggerSettings` | +| **حدث قاعدة البيانات** | يتم إنشاء سجل في مساحة العمل أو تحديثه أو حذفه | `databaseEventTriggerSettings` | +| **أداة ذكاء اصطناعي** | ميزة ذكاء اصطناعي في Twenty تقرر استدعاء دالتك | `toolTriggerSettings` | +| **إجراء سير العمل** | تستدعي خطوة في سير العمل دالتك | `workflowActionTriggerSettings` | تعمل الدوال ضمن عمليات Node.js معزولة، وتصل إلى مساحة العمل عبر عميل واجهة برمجة تطبيقات مضبوط الأنواع ومحدّد النطاق بالدور المصرّح عنه في [`defineApplication()`](/l/ar/developers/extend/apps/config/application). diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index 720ae7876e..bf639f902b 100644 --- a/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -66,6 +66,7 @@ export default defineNavigationMenuItem({ ```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'; @@ -88,15 +89,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', @@ -173,6 +169,7 @@ Markdown كصفحة مصقولة قابلة للطباعة. ```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'; @@ -181,9 +178,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. diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 2447fd578b..0b0545a31b 100644 --- a/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,14 +9,10 @@ description: قم بتفعيل الوظيفة على HTTP وتقديم الوث * نقطة النهاية **POST** مكالمات واجهة المستخدم لإنشاء وثيقة، و * نقطة نهاية عامة **GET** تجعل الوثيقة صفحة ويب قابلة للطباعة. -وكلاهما يستخدم `httpRouteTriggerSettings`. على خادم dev المحلي، طرق التطبيق هي -تقدم تحت بادئة `/s` (على سبيل المثال 'http://localhost:2020/s/documents/generate\`). - - -على عشرين سحابة، يتم خدمة المسارات على نطاق وظائف مساحة العمل المخصصة- عنوان URL 20 حقن بـ 'TWENTY_FUNCTIONS_URL`، بدون بادئة '/s'. البادئة `/s\` - مهملة هناك ولا تبقى إلا للجهات المحلية والمحلية. - انظر [تسمية دالة منطقية](/l/ar/developers/extend/apps/layout/front-components#calling-a-logic-function). - +وكلاهما يستخدم `httpRouteTriggerSettings`. يتم الوصول إلى مسارات التطبيق باستخدام مسار `/s/`؛ على النسخ المحلية +والمستضافة ذاتيًا، يتم تقديم هذا المسار بواسطة خادم Twenty الخاص بك +(مثلًا: `http://localhost:2020/s/documents/generate`). على Twenty Cloud، يقوم `RestApiClient` +بمعالجة المسار عبر نطاق وظائف مساحة العمل. ## مسار POST - توليد حسب الطلب diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/layout/front-components.mdx index 1ea53571cc..0c7dfdc9b1 100644 --- a/packages/twenty-docs/l/cs/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/cs/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Front komponenty běží v prohlížeči v sandboxovaném Web Workeru uvnitř iframe s nejasným původem (opaque-origin), zatímco [logické funkce](/l/cs/developers/extend/apps/logic/logic-functions) běží na serveru. Neexistuje mezi nimi žádné přímé volání v rámci jednoho procesu — místo toho se front komponenta k logické funkci připojuje přes HTTP. -Logická funkce deklarovaná pomocí `httpRouteTriggerSettings` je přes HTTP dostupná na své cestě (route path). Twenty vloží do workeru základní URL, ze které jsou vaše funkce poskytovány, jako `TWENTY_FUNCTIONS_URL` spolu s `TWENTY_APP_ACCESS_TOKEN`, který volání autentizuje. Zatím neexistuje žádný specializovaný klient SDK pro volání vlastních funkcí, takže je volejte pomocí prostého `fetch`: +Logická funkce deklarovaná pomocí `httpRouteTriggerSettings` je přes HTTP dostupná na své cestě (route path). `RestApiClient` považuje cesty začínající na `/s/` za aplikační trasy, převede je na URL, ze které jsou vaše funkce poskytovány, a autentizuje je pomocí `TWENTY_APP_ACCESS_TOKEN`. -> **V Twenty Cloud jsou logické funkce spouštěné přes HTTP poskytovány na vyhrazené doméně pro každý workspace** na adrese `https://\.withtwenty.com\` — právě na tuto adresu `TWENTY_FUNCTIONS_URL` směřuje. Pro externí volající zkopírujte přesnou URL z nastavení funkce **HTTP trigger** nebo z karty **Settings** aplikace. - - - Původní funkční trasa `/s/` je **zastaralá** a bude **deaktivována dne 2026-07-24**. Místo toho použijte `TWENTY_FUNCTIONS_URL` (viz výše) a do tohoto data migrujte všechny pevně zakódované adresy URL `/s/`. Trasa `/s/` zůstává k dispozici pro self-hosting. - +> **V Twenty Cloud jsou logické funkce spouštěné přes HTTP poskytovány na vyhrazené doméně pro každý workspace** na adrese `https://\.withtwenty.com\`. Pro externí volající zkopírujte přesnou URL z nastavení funkce **HTTP trigger** nebo z karty **Settings** aplikace. Headless front komponenta může volání spustit při mountu přes komponentu `Command` a poté se automaticky odmountovat: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -Cesta připojená k `TWENTY_FUNCTIONS_URL` je `httpRouteTriggerSettings.path` logické funkce. Ponechte `isAuthRequired: true`; `TWENTY_APP_ACCESS_TOKEN`, který Twenty vygeneruje pro vaši komponentu, požadavek autentizuje: +Cesta předaná `RestApiClient` je `httpRouteTriggerSettings.path` logické funkce s předponou `/s`. Ponechte `isAuthRequired: true`; `TWENTY_APP_ACCESS_TOKEN`, který Twenty vygeneruje pro vaši komponentu, požadavek autentizuje: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` a `TWENTY_APP_ACCESS_TOKEN` jsou vloženy automaticky — viz [Proměnné aplikace](#application-variables). Protože tajné proměnné aplikace nejsou nikdy vystaveny front komponentám, ponechte API klíče a další citlivou logiku v logické funkci, ne ve front komponentě. +`TWENTY_APP_ACCESS_TOKEN` je vložen automaticky — viz [Proměnné aplikace](#application-variables). Protože tajné proměnné aplikace nejsou nikdy vystaveny front komponentám, ponechte API klíče a další citlivou logiku v logické funkci, ne ve front komponentě. ### Volání Twenty REST API -Pro čtení nebo zápis záznamů Twenty z front komponenty použijte `RestApiClient` z `twenty-client-sdk/rest`. Patří do stejné rodiny klientů jako `CoreApiClient` a `MetadataApiClient`, ale cílí na Twenty REST API (`/rest/...`) místo na GraphQL API a svou základní URL čte z `TWENTY_API_URL`. +Pro volání aplikačních HTTP tras nebo čtení a zápis záznamů Twenty z front komponenty použijte `RestApiClient` z `twenty-client-sdk/rest`. Odesílá cesty `/s/...` na základní URL funkcí vašeho workspace a všechny ostatní cesty, včetně `/rest/...`, na `TWENTY_API_URL`. -| Metoda | Popis | -| --------------------------------- | ------------------------------------------ | -| `get(path, options?)` | Odešle požadavek `GET` | -| `post(path, body?, options?)` | Odešle požadavek `POST` | -| `put(path, body?, options?)` | Odešle požadavek `PUT` | -| `patch(path, body?, options?)` | Odešle požadavek `PATCH` | -| `delete(path, options?)` | Odešle požadavek `DELETE` | -| `request(method, path, options?)` | Obecný požadavek s libovolnou metodou HTTP | +| Metoda | Popis | +| --------------------------------- | -------------------------------------------------------------------- | +| `get(path, options?)` | Odešle požadavek `GET` | +| `post(path, body?, options?)` | Odešle požadavek `POST` | +| `put(path, body?, options?)` | Odešle požadavek `PUT` | +| `patch(path, body?, options?)` | Odešle požadavek `PATCH` | +| `delete(path, options?)` | Odešle požadavek `DELETE` | +| `request(method, path, options?)` | Obecný požadavek s libovolnou metodou HTTP | +| `resolveUrl(path, options?)` | Převede cestu na její úplnou URL bez odeslání požadavku (pro odkazy) | `options` přijímá `headers`, `query` (záznam parametrů dotazovacího řetězce; hodnoty typu nullish jsou vynechány) a `AbortSignal` prostřednictvím `signal`. Objekt `body`, který není typu `FormData`, je automaticky serializován do JSON. Při `401` klient jednou obnoví přístupový token prostřednictvím hostitele a požadavek znovu odešle. @@ -417,11 +411,22 @@ Tajné proměnné (`isSecret: true`) **nejsou** zpřístupněny front-endovým k Následující systémové proměnné jsou vždy dostupné přes `process.env`: -| Proměnná | Popis | -| ------------------------- | ---------------------------------------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | Základní adresa URL, ze které jsou poskytovány funkce aplikační logiky vaší aplikace přes HTTP | -| `TWENTY_API_URL` | Základní URL Twenty core API | -| `TWENTY_APP_ACCESS_TOKEN` | Krátkodobý token s oprávněními omezenými na roli vaší aplikace | +| Proměnná | Popis | +| ------------------------- | -------------------------------------------------------------- | +| `TWENTY_API_URL` | Základní URL Twenty core API | +| `TWENTY_APP_ACCESS_TOKEN` | Krátkodobý token s oprávněními omezenými na roli vaší aplikace | + +### `TWENTY_FUNCTIONS_URL` + +Twenty také vkládá `TWENTY_FUNCTIONS_URL` do front komponent a logických funkcí: základní URL, ze které jsou poskytovány vaše logické funkce spouštěné přes HTTP. + +Existuje proto, že tato URL není vždy samotný server Twenty. V Twenty Cloud jsou aplikační trasy poskytovány na vyhrazené doméně pro každý workspace (`https://\.withtwenty.com`, nebo hlavní veřejná doména aplikace, pokud je nakonfigurována), aby odpovědi vytvořené aplikací běžely na odděleném původu, a nikoli na původu aplikace Twenty. Self-hostované a lokální instance poskytují aplikační trasy pod předponou `/s` přímo na serveru a proměnnou nemusí vůbec nastavovat. Protože se základní URL liší podle workspace a instance, váš kód ji nemůže napevno zakódovat — server správnou hodnotu vloží za běhu. + +Jen zřídka ji potřebujete číst přímo. Volání svých tras provádějte přes `RestApiClient` s cestou s předponou `/s/` a klient za vás URL vyřeší: odstraní předponu `/s` a zacílí na `TWENTY_FUNCTIONS_URL`, přičemž pokud proměnná není nastavena, použije jako zálohu `\/s`. Použijte `resolveUrl('/s/\')` pro získání absolutní URL bez odeslání požadavku, např. pro odkaz. Proměnnou čtěte přímo pouze při ručním sestavování URL: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## API komunikace s hostitelem diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/logic/logic-functions.mdx index 860a81afc3..ce89d9e432 100644 --- a/packages/twenty-docs/l/cs/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/cs/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Dostupné typy spouštěčů: -* **httpRoute**: Expose your function on the HTTP path and method at a **functions base URL** of your workspace — value Twenty injects as `TWENTY_FUNCTIONS_URL` (na dvaceti Cloudu), vyhrazená doména na pracovní plochu): -> např. `path: '/post-card/create'` je volatelné na `https://your-workspace.withtwenty.com/post-card/create` - - -Starší trasa `/s/` prefixu (`https://your-twenty-server.com/s/post-card/create`) je **zastaralá na dvacet Cloud** a bude deaktivována na **2026-07-24**. Zůstává k dispozici pro vlastní hostované a místní instance, které nenastavují izolovanou doménu funkcí – použijte při nastavení `TWENTY_FUNCTIONS_URL`, a přejděte zpět na `\/s/\` v opačném případě. - +* **httpRoute**: Zpřístupní vaši funkci na HTTP cestě a metodě. V kódu aplikace přidejte prefix `/s/` k cestě routy při použití `RestApiClient`; nasazená URL používá injektovanou základní adresu `TWENTY_FUNCTIONS_URL` (nebo `\/s`, pokud není nastavena). Chcete-li vyvolat logickou funkci spuštěnou trasou z (bezhlavé) front-endové komponenty, podívejte se na [Volání logické funkce](/l/cs/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/logic/overview.mdx index eef4f73ac2..6a58244f47 100644 --- a/packages/twenty-docs/l/cs/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/cs/developers/extend/apps/logic/overview.mdx @@ -42,7 +42,7 @@ Logická funkce volí jeden nebo více spouštěčů — každá z níže uveden | Spouštěč | Kdy se spouští | Nastavení | | --------------------------- | ----------------------------------------------------------------- | ------------------------------- | -| **HTTP route** | Požadavek zasáhne veřejnou adresu URL funkce | `httpRouteTriggerSettings` | +| **HTTP route** | Požadavek dorazí na váš koncový bod `/s/\` | `httpRouteTriggerSettings` | | **Cron** | CRON výraz se shoduje | `cronTriggerSettings` | | **Událost databáze** | Záznam v pracovním prostoru je vytvořen, aktualizován nebo smazán | `databaseEventTriggerSettings` | | **Nástroj AI** | Funkce Twenty AI se rozhodne zavolat vaši funkci | `toolTriggerSettings` | diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index cbaedfc639..085bd91b23 100644 --- a/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ boxovaná uvnitř dvaceti. Náš přečte vybraný záznam, načte ```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. diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 3c308757df..272f857c30 100644 --- a/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/cs/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,10 @@ Stejný handler může také odpovědět na HTTP požadavky. Přidáme dva trasy * **POST** koncový bod uživatelského rozhraní volá, aby vytvořilo dokument, a * veřejný **GET** koncový bod, který vykresluje dokument jako tiskovou webovou stránku. -Oba použijte `httpRouteTriggerSettings`. Na místním serveru vývojáře jsou trasy -provozovány pod předponou `/s` (např. `http://localhost:2020/s/documents/generate`). - - -Na dvaceti Cloudu jsou trasy vedeny na doméně funkcí vyhrazených v pracovním prostoru -— URL je dvacet vložena jako `TWENTY_FUNCTIONS_URL`, bez předpony `/s`. Prefix `/s` -je tam zastaralý a zůstává pouze pro samostatně hostované a místní instance. -Viz [Volání logické funkce](/l/cs/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Oba použijte `httpRouteTriggerSettings`. Trasy aplikace jsou dostupné pomocí cesty `/s/`; na lokálních +a self-hostovaných instancích tuto cestu obsluhuje váš server Twenty +(např. `http://localhost:2020/s/documents/generate`). Ve Twenty Cloudu `RestApiClient` +sestavuje cestu prostřednictvím domény funkcí pracovního prostoru. ## POST trasa – generovat na požádání diff --git a/packages/twenty-docs/l/de/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/de/developers/extend/apps/layout/front-components.mdx index b48de5f8da..cd5c6a8d0d 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Front-Komponenten laufen browserseitig in einem Web-Worker, der in einem sandboxed iframe mit opaker Origin ausgeführt wird, während [Logikfunktionen](/l/de/developers/extend/apps/logic/logic-functions) serverseitig laufen. Es gibt keinen direkten In-Process-Aufruf zwischen beiden – stattdessen ruft eine Front-Komponente eine Logikfunktion über HTTP auf. -Eine mit `httpRouteTriggerSettings` deklarierte Logikfunktion ist über HTTP unter ihrem Routenpfad erreichbar. Twenty injiziert die Basis-URL, unter der deine Funktionen bereitgestellt werden, als `TWENTY_FUNCTIONS_URL` in den Worker, zusammen mit dem `TWENTY_APP_ACCESS_TOKEN`, das den Aufruf authentifiziert. Es gibt noch keinen eigenen SDK-Client zum Aufrufen deiner eigenen Funktionen, daher rufe sie mit einem einfachen `fetch` auf: +Eine mit `httpRouteTriggerSettings` deklarierte Logikfunktion ist über HTTP unter ihrem Routenpfad erreichbar. `RestApiClient` behandelt Pfade, die mit `/s/` beginnen, als App-Routen, löst sie zur URL auf, unter der deine Funktionen bereitgestellt werden, und authentifiziert sie mit `TWENTY_APP_ACCESS_TOKEN`. -> **In Twenty Cloud werden HTTP-ausgelöste Logikfunktionen auf einer eigenen, arbeitsbereichsspezifischen Domain bereitgestellt** unter `https://\.withtwenty.com\` — genau darauf verweist `TWENTY_FUNCTIONS_URL`. Für externe Aufrufer kopiere die exakte URL aus den **HTTP trigger**-Einstellungen der Funktion oder aus dem **Settings**-Tab der Anwendung. - - - Die `/s/`-Funktionsroute ist **veraltet** und wird **am 2026-07-24 deaktiviert**. Verwende stattdessen `TWENTY_FUNCTIONS_URL` (oben) und migriere alle hart codierten `/s/`-URLs vor diesem Datum. Die `/s/`-Route bleibt für Self-Hosting verfügbar. - +> **In Twenty Cloud werden HTTP-ausgelöste Logikfunktionen auf einer eigenen, arbeitsbereichsspezifischen Domain bereitgestellt** unter `https://\.withtwenty.com\`. Für externe Aufrufer kopiere die exakte URL aus den **HTTP trigger**-Einstellungen der Funktion oder aus dem **Settings**-Tab der Anwendung. Eine headless Front-Komponente kann den Aufruf beim Mounten über die `Command`-Komponente ausführen und sich anschließend automatisch unmounten: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -Der an `TWENTY_FUNCTIONS_URL` angehängte Pfad ist das `httpRouteTriggerSettings.path` der Logikfunktion. Belasse `isAuthRequired: true`; das `TWENTY_APP_ACCESS_TOKEN`, das Twenty für deine Komponente ausstellt, authentifiziert die Anfrage: +Der an `RestApiClient` übergebene Pfad ist der `httpRouteTriggerSettings.path` der Logikfunktion, der mit `/s` präfixiert ist. Belasse `isAuthRequired: true`; das `TWENTY_APP_ACCESS_TOKEN`, das Twenty für deine Komponente ausstellt, authentifiziert die Anfrage: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` und `TWENTY_APP_ACCESS_TOKEN` werden automatisch injiziert – siehe [Anwendungsvariablen](#application-variables). Da geheime Anwendungsvariablen niemals in Front-Komponenten offengelegt werden, sollten API-Schlüssel und andere sensible Logik in der Logikfunktion verbleiben und nicht in der Front-Komponente. +`TWENTY_APP_ACCESS_TOKEN` wird automatisch injiziert – siehe [Anwendungsvariablen](#application-variables). Da geheime Anwendungsvariablen niemals in Front-Komponenten offengelegt werden, sollten API-Schlüssel und andere sensible Logik in der Logikfunktion verbleiben und nicht in der Front-Komponente. ### Aufrufen der Twenty-REST-API -Um Twenty-Datensätze aus einer Front-Komponente zu lesen oder zu schreiben, verwende `RestApiClient` aus `twenty-client-sdk/rest`. Er gehört zur gleichen Client-Familie wie `CoreApiClient` und `MetadataApiClient`, zielt jedoch auf die Twenty-REST-API (`/rest/...`) statt auf die GraphQL-API und liest deren Basis-URL aus `TWENTY_API_URL`. +Um App-HTTP-Routen aufzurufen oder Twenty-Datensätze aus einer Front-Komponente zu lesen und zu schreiben, verwende `RestApiClient` aus `twenty-client-sdk/rest`. Es sendet `/s/...`-Pfade an die Funktions-Basis-URL deines Arbeitsbereichs und alle anderen Pfade, einschließlich `/rest/...`, an `TWENTY_API_URL`. -| Methode | Beschreibung | -| --------------------------------- | ---------------------------------------------------- | -| `get(path, options?)` | Sendet eine `GET`-Anfrage | -| `post(path, body?, options?)` | Sendet eine `POST`-Anfrage | -| `put(path, body?, options?)` | Sendet eine `PUT`-Anfrage | -| `patch(path, body?, options?)` | Sendet eine `PATCH`-Anfrage | -| `delete(path, options?)` | Sendet eine `DELETE`-Anfrage | -| `request(method, path, options?)` | Generische Anfrage mit einer beliebigen HTTP-Methode | +| Methode | Beschreibung | +| --------------------------------- | ---------------------------------------------------------------------------------------- | +| `get(path, options?)` | Sendet eine `GET`-Anfrage | +| `post(path, body?, options?)` | Sendet eine `POST`-Anfrage | +| `put(path, body?, options?)` | Sendet eine `PUT`-Anfrage | +| `patch(path, body?, options?)` | Sendet eine `PATCH`-Anfrage | +| `delete(path, options?)` | Sendet eine `DELETE`-Anfrage | +| `request(method, path, options?)` | Generische Anfrage mit einer beliebigen HTTP-Methode | +| `resolveUrl(path, options?)` | Löst einen Pfad zu seiner vollständigen URL auf, ohne eine Anfrage zu senden (für Links) | `options` akzeptiert `headers`, `query` (ein Record von Query-String-Parametern; null- bzw. undefined-Werte werden übersprungen) sowie ein `AbortSignal` über `signal`. Ein `body`-Objekt, das kein `FormData` ist, wird automatisch als JSON serialisiert. Bei einem `401` aktualisiert der Client das Access-Token einmal über den Host und versucht die Anfrage erneut. @@ -417,11 +411,22 @@ Geheime Variablen (`isSecret: true`) werden **nicht** in Front-Komponenten offen Die folgenden Systemvariablen sind immer über `process.env` verfügbar: -| Variable | Beschreibung | -| ------------------------- | ---------------------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | Basis-URL, von der die HTTP-Logikfunktionen deiner App bereitgestellt werden | -| `TWENTY_API_URL` | Basis-URL der Twenty-Core-API | -| `TWENTY_APP_ACCESS_TOKEN` | Kurzlebiges Token mit dem Geltungsbereich der Rolle Ihrer App | +| Variable | Beschreibung | +| ------------------------- | ------------------------------------------------------------- | +| `TWENTY_API_URL` | Basis-URL der Twenty-Core-API | +| `TWENTY_APP_ACCESS_TOKEN` | Kurzlebiges Token mit dem Geltungsbereich der Rolle Ihrer App | + +### `TWENTY_FUNCTIONS_URL` + +Twenty injiziert außerdem `TWENTY_FUNCTIONS_URL` in Front-Komponenten und Logikfunktionen: die Basis-URL, unter der die HTTP-ausgelösten Logikfunktionen deiner App bereitgestellt werden. + +Sie existiert, weil diese URL nicht immer der Twenty-Server selbst ist. In Twenty Cloud werden App-Routen auf einer eigenen, arbeitsbereichsspezifischen Domain bereitgestellt (`https://\.withtwenty.com` oder die primäre öffentliche Domain der Anwendung, falls eine konfiguriert ist), damit von der App erzeugte Antworten in einem isolierten Origin und nicht im Origin der Twenty-App ausgeführt werden. Self-Hosted- und lokale Instanzen stellen App-Routen unter dem Präfix `/s` auf dem Server selbst bereit und setzen die Variable eventuell gar nicht. Da die Basis-URL je nach Arbeitsbereich und Instanz variiert, kann dein Code sie nicht hardcoden – der Server injiziert zur Laufzeit den richtigen Wert. + +Du musst sie nur selten direkt lesen. Rufe deine Routen über `RestApiClient` mit einem mit `/s/` präfixierten Pfad auf, und der Client löst die URL für dich auf: Er entfernt das Präfix `/s` und verwendet `TWENTY_FUNCTIONS_URL` als Ziel, mit Fallback auf `\/s`, wenn die Variable nicht gesetzt ist. Verwende `resolveUrl('/s/\')`, um die absolute URL ohne das Senden einer Anfrage zu erhalten, z. B. für einen Link. Lies die Variable nur direkt aus, wenn du eine URL manuell zusammenbaust: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## Host-Kommunikations-API diff --git a/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx index 97799810dc..0aa9c98b7d 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Verfügbare Trigger-Typen: -* **httpRoute**: Enthält deine Funktion auf einem HTTP-Pfad und -Methode an der **Funktions-Basis-URL deines Arbeitsbereichs** — der Wert 20 Injekte als `TWENTY_FUNCTIONS_URL` (auf 20 Cloud, eine dedizierte Domain pro Arbeitsbereich): -> z. B. `path: '/post-card/create'` ist unter `https://your-workspace.withtwenty.com/post-card/create` aufrufbar - - -Die alte `/s/` Präfix Route (`https://your-twenty-server.com/s/post-card/create`) ist **veraltet in 20 Cloud** und wird auf **2026-07-24** deaktiviert. Es bleibt für selbstgehostete und lokale Instanzen verfügbar, die keine isolierte Funktionsdomain konfigurieren — benutze `TWENTY_FUNCTIONS_URL` wenn diese gesetzt ist und zurück fallen auf `\/s/\` sonst nicht. - +* **httpRoute**: Stellt Ihre Funktion über einen HTTP-Pfad und eine Methode bereit. Im Anwendungscode den Routenpfad bei Verwendung von `RestApiClient` mit dem Präfix `/s/` versehen; die bereitgestellte URL verwendet als Basis die injizierte `TWENTY_FUNCTIONS_URL` (oder `\/s`, wenn diese nicht gesetzt ist). Um eine routenausgelöste Logikfunktion von einer (headless) Front-Komponente aus aufzurufen, siehe [Aufrufen einer Logikfunktion](/l/de/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/de/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/de/developers/extend/apps/logic/overview.mdx index 66b7ac8fac..bf8d8287d6 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/logic/overview.mdx @@ -42,7 +42,7 @@ Eine Logikfunktion wählt einen oder mehrere Auslöser – jeder Eintrag unten i | Auslöser | Wann sie ausgeführt wird | Einstellung | | --------------------- | ------------------------------------------------------------------ | ------------------------------- | -| **HTTP-Route** | Eine Anfrage trifft die öffentliche URL Ihrer Funktion | `httpRouteTriggerSettings` | +| **HTTP-Route** | Eine Anfrage erreicht Ihren `/s/\`-Endpunkt | `httpRouteTriggerSettings` | | **Cron** | Ein CRON-Ausdruck trifft zu | `cronTriggerSettings` | | **Datenbankereignis** | Ein Workspace-Datensatz wird erstellt, aktualisiert oder gelöscht | `databaseEventTriggerSettings` | | **KI-Tool** | Eine Twenty-KI-Funktion entscheidet sich, Ihre Funktion aufzurufen | `toolTriggerSettings` | diff --git a/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index e4b7789a27..672ef9ad99 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ Kapitel. ```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 @@ Helfer machen. ```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. diff --git a/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 1c8f3efc1c..f7d720d117 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,9 @@ Der gleiche Handler kann auch HTTP-Anfragen beantworten. Wir werden zwei Routen * ein **POST** Endpunkt der UI-Aufrufe, um ein Dokument zu generieren, und * ein öffentlicher **GET** Endpunkt, der ein Dokument als druckbare Webseite darstellt. -Beide verwenden `httpRouteTriggerSettings`. Auf dem lokalen Dev-Server werden App-Routen -unter dem Präfix `/s` bedient (z.B. `http://localhost:2020/s/documents/generate`). - - -Bei 20 Cloud werden Routen in der dedizierten Funktion des Arbeitsbereichs, der Domain -– die URL 20 injiziert als `TWENTY_FUNCTIONS_URL`, ohne `/s` Präfix. Das `/s` -Präfix ist dort veraltet und bleibt nur für selbstgehostete und lokale Instanzen übrig. -Siehe [Aufruf einer Logikfunktion](/l/de/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Beide verwenden `httpRouteTriggerSettings`. App-Routen werden über einen `/s/`-Pfad adressiert; auf lokalen +und selbstgehosteten Instanzen wird dieser Pfad von Ihrem Twenty-Server +bereitgestellt (z. B. `http://localhost:2020/s/documents/generate`). In Twenty Cloud löst `RestApiClient` den Pfad über die Funktionen-Domain des Workspaces auf. ## POST-Route — bei Bedarf generieren diff --git a/packages/twenty-docs/l/es/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/es/developers/extend/apps/layout/front-components.mdx index 00463feb56..3e319a4000 100644 --- a/packages/twenty-docs/l/es/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/es/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Los componentes de front se ejecutan en el navegador dentro de un Web Worker aislado (sandboxed) dentro de un iframe de origen opaco, mientras que las [funciones de lógica](/l/es/developers/extend/apps/logic/logic-functions) se ejecutan en el servidor. No hay una llamada directa en el mismo proceso entre ambos; en su lugar, un componente de front accede a una función de lógica a través de HTTP. -Una función de lógica declarada con `httpRouteTriggerSettings` es accesible por HTTP en su ruta. Twenty inyecta en el worker la URL base desde la que se sirven tus funciones como `TWENTY_FUNCTIONS_URL`, junto con el `TWENTY_APP_ACCESS_TOKEN` que autentica la llamada. Todavía no hay un cliente SDK dedicado para invocar tus propias funciones, así que llámalas con un simple `fetch`: +Una función de lógica declarada con `httpRouteTriggerSettings` es accesible por HTTP en su ruta. `RestApiClient` trata las rutas que comienzan con `/s/` como rutas de la aplicación, las resuelve a la URL desde la que se sirven tus funciones y las autentica con `TWENTY_APP_ACCESS_TOKEN`. -> **En Twenty Cloud, las funciones de lógica activadas por HTTP se sirven en un dominio dedicado por espacio de trabajo** en `https://\.withtwenty.com\` — esto es exactamente a lo que se resuelve `TWENTY_FUNCTIONS_URL`. Para clientes externos, copia la URL exacta desde la configuración de **HTTP trigger** de la función o desde la pestaña **Settings** de la aplicación. - - - La ruta heredada de la función `/s/` está **obsoleta** y será **desactivada el 2026-07-24**. En su lugar, utiliza `TWENTY_FUNCTIONS_URL` (arriba) y migra cualquier URL de `/s/` codificada de forma fija antes de esa fecha. La ruta `/s/` sigue disponible para autoalojamiento. - +> **En Twenty Cloud, las funciones de lógica activadas por HTTP se sirven en un dominio dedicado por espacio de trabajo** en `https://\.withtwenty.com\`. Para clientes externos, copia la URL exacta desde la configuración de **HTTP trigger** de la función o desde la pestaña **Settings** de la aplicación. Un componente de front sin interfaz (headless) puede ejecutar la llamada al montar mediante el componente `Command` y luego desmontarse automáticamente: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -La ruta añadida a `TWENTY_FUNCTIONS_URL` es el `httpRouteTriggerSettings.path` de la función lógica. Mantén `isAuthRequired: true`; el `TWENTY_APP_ACCESS_TOKEN` que Twenty crea para tu componente autentica la solicitud: +La ruta que se pasa a `RestApiClient` es el `httpRouteTriggerSettings.path` de la función lógica, con el prefijo `/s`. Mantén `isAuthRequired: true`; el `TWENTY_APP_ACCESS_TOKEN` que Twenty crea para tu componente autentica la solicitud: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` y `TWENTY_APP_ACCESS_TOKEN` se inyectan automáticamente; consulta [Variables de la aplicación](#application-variables). Dado que las variables de aplicación secretas nunca se exponen a los componentes de front, mantén las claves de API y otra lógica confidencial en la función de lógica, no en el componente de front. +`TWENTY_APP_ACCESS_TOKEN` se inyecta automáticamente; consulta [Variables de la aplicación](#application-variables). Dado que las variables de aplicación secretas nunca se exponen a los componentes de front, mantén las claves de API y otra lógica confidencial en la función de lógica, no en el componente de front. ### Llamar a la API REST de Twenty -Para leer o escribir registros de Twenty desde un componente de interfaz, utiliza `RestApiClient` de `twenty-client-sdk/rest`. Pertenece a la misma familia de clientes que `CoreApiClient` y `MetadataApiClient`, pero se dirige a la API REST de Twenty (`/rest/...`) en lugar de a la API de GraphQL, leyendo su URL base de `TWENTY_API_URL`. +Para llamar a rutas HTTP de la aplicación o leer y escribir registros de Twenty desde un componente de interfaz, utiliza `RestApiClient` de `twenty-client-sdk/rest`. Envía las rutas `/s/...` a la URL base de las funciones de tu espacio de trabajo y cualquier otra ruta, incluidas `/rest/...`, a `TWENTY_API_URL`. -| Método | Descripción | -| --------------------------------- | -------------------------------------------- | -| `get(path, options?)` | Envía una solicitud `GET` | -| `post(path, body?, options?)` | Envía una solicitud `POST` | -| `put(path, body?, options?)` | Envía una solicitud `PUT` | -| `patch(path, body?, options?)` | Envía una solicitud `PATCH` | -| `delete(path, options?)` | Envía una solicitud `DELETE` | -| `request(method, path, options?)` | Solicitud genérica con cualquier método HTTP | +| Método | Descripción | +| --------------------------------- | --------------------------------------------------------------------------- | +| `get(path, options?)` | Envía una solicitud `GET` | +| `post(path, body?, options?)` | Envía una solicitud `POST` | +| `put(path, body?, options?)` | Envía una solicitud `PUT` | +| `patch(path, body?, options?)` | Envía una solicitud `PATCH` | +| `delete(path, options?)` | Envía una solicitud `DELETE` | +| `request(method, path, options?)` | Solicitud genérica con cualquier método HTTP | +| `resolveUrl(path, options?)` | Resuelve una ruta a su URL completa sin enviar una solicitud (para enlaces) | `options` acepta `headers`, `query` (un registro de parámetros de cadena de consulta; los valores nulos o indefinidos se omiten) y un `AbortSignal` mediante `signal`. Un objeto `body` que no sea de tipo `FormData` se serializa automáticamente como JSON. Ante un `401`, el cliente actualiza el token de acceso una vez a través del host y vuelve a intentar la solicitud. @@ -417,11 +411,22 @@ Las variables secretas (`isSecret: true`) **no** se exponen a los componentes de Las siguientes variables de sistema siempre están disponibles a través de `process.env`: -| Variable | Descripción | -| ------------------------- | ----------------------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | URL base desde la que se sirven las funciones de lógica HTTP de tu aplicación | -| `TWENTY_API_URL` | URL base de la API principal de Twenty | -| `TWENTY_APP_ACCESS_TOKEN` | Token de corta duración limitado al rol de tu aplicación | +| Variable | Descripción | +| ------------------------- | -------------------------------------------------------- | +| `TWENTY_API_URL` | URL base de la API principal de Twenty | +| `TWENTY_APP_ACCESS_TOKEN` | Token de corta duración limitado al rol de tu aplicación | + +### `TWENTY_FUNCTIONS_URL` + +Twenty también inyecta `TWENTY_FUNCTIONS_URL` en los componentes de interfaz y en las funciones lógicas: la URL base desde la que se sirven las funciones de lógica activadas por HTTP de tu aplicación. + +Existe porque esa URL no siempre es el propio servidor de Twenty. En Twenty Cloud, las rutas de la aplicación se sirven en un dominio dedicado por espacio de trabajo (`https://\.withtwenty.com`, o el dominio público principal de la aplicación cuando se configure uno) para que las respuestas definidas por la aplicación se ejecuten en un origen aislado en lugar de en el origen de la aplicación de Twenty. Las instancias autoalojadas y locales sirven las rutas de la aplicación bajo el prefijo `/s` en el propio servidor y es posible que no establezcan la variable en absoluto. Dado que la URL base varía por espacio de trabajo y por instancia, tu código no puede codificarla de forma rígida: el servidor inyecta el valor correcto en tiempo de ejecución. + +Rara vez necesitas leerla directamente. Llama a tus rutas a través de `RestApiClient` con una ruta con el prefijo `/s/` y el cliente resuelve la URL por ti: elimina el prefijo `/s` y apunta a `TWENTY_FUNCTIONS_URL`, recurriendo a `\/s` cuando la variable no está establecida. Utiliza `resolveUrl('/s/\')` para obtener la URL absoluta sin enviar una solicitud, por ejemplo, para un enlace. Lee la variable directamente solo cuando construyas una URL manualmente: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## API de comunicación con el host diff --git a/packages/twenty-docs/l/es/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/es/developers/extend/apps/logic/logic-functions.mdx index 5af78c98b4..3312605f03 100644 --- a/packages/twenty-docs/l/es/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/es/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Tipos de desencadenadores disponibles: -* **httpRoute**: Expone tu función en una ruta HTTP y método en la **URL base de las funciones de tu espacio de trabajo** — el valor Veinte inyectos como `TWENTY_FUNCTIONS_URL` (en la nube veinte, un dominio dedicado por área de trabajo): -> p. ej., `path: '/post-card/create'` se puede invocar en `https://your-workspace.withtwenty.com/post-card/create` - - -El prefijo heredado `/s/` (`https://your-twenty-server.com/s/post-card/create`) está \*\*obsoleto en 20 nubes y será desactivado en **2026-07-24**. Sigue disponible para instancias locales y autosuficientes que no configuran un dominio de funciones aisladas — use `TWENTY_FUNCTIONS_URL` cuando está definido. y vuelve a `\/s/\` de lo contrario. - +* **httpRoute**: Expone tu función en una ruta y método HTTP. En el código de la aplicación, añade el prefijo `/s/` a la ruta cuando uses `RestApiClient`; la URL desplegada utiliza la base inyectada `TWENTY_FUNCTIONS_URL` (o `\/s` cuando no está configurada). Para invocar una función de lógica activada por una ruta desde un componente de frontend (headless), consulta [Llamar a una función de lógica](/l/es/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/es/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/es/developers/extend/apps/logic/overview.mdx index a52379f229..a7475eedf6 100644 --- a/packages/twenty-docs/l/es/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/es/developers/extend/apps/logic/overview.mdx @@ -42,7 +42,7 @@ Una función de lógica selecciona uno o más disparadores: cada entrada a conti | Disparador | Cuándo se ejecuta | Configuración | | ------------------------------- | --------------------------------------------------------------- | ------------------------------- | -| **Ruta HTTP** | Una solicitud llega a la URL pública de tu función | `httpRouteTriggerSettings` | +| **Ruta HTTP** | Una solicitud llega a tu endpoint `/s/\` | `httpRouteTriggerSettings` | | **Cron** | Coincide una expresión CRON | `cronTriggerSettings` | | **Evento de base de datos** | Se crea, actualiza o elimina un registro del espacio de trabajo | `databaseEventTriggerSettings` | | **Herramienta de IA** | Una funcionalidad de IA de Twenty decide llamar a tu función | `toolTriggerSettings` | diff --git a/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index bdf81e4cac..1af5263507 100644 --- a/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ persona a través de `CoreApiClient`, y POSTs a la ruta desde el último capítu ```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', @@ -179,6 +175,7 @@ inline mediante un pequeño helper [`Markdown`](https://github.com/twentyhq/twen ```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'; @@ -187,9 +184,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. diff --git a/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 1eb032df30..01abfdc1f0 100644 --- a/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/es/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,10 @@ El mismo manejador también puede responder a peticiones HTTP. Añadiremos dos r * un endpoint **POST** para generar un documento, y * un endpoint público **GET** que renderiza un documento como una página web imprimible. -Ambos usan `httpRouteTriggerSettings`. En el servidor dev local, las rutas de la aplicación son -servidas bajo el prefijo `/s` (por ejemplo, `http://localhost:2020/s/documents/generate`). - - -En 20 nubes las rutas se sirven en el dominio -de funciones dedicadas del espacio de trabajo — la URL Veinte inyectos como `TWENTY_FUNCTIONS_URL`, sin prefijo `/s`. El prefijo -`/s` está obsoleto allí y sólo permanece para instancias locales y autoalojadas. -Ver [Llamar a una función lógica](/l/es/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Ambos usan `httpRouteTriggerSettings`. Las rutas de la aplicación se encuentran bajo la ruta `/s/`; en las instancias locales +y autoalojadas, esa ruta la sirve tu servidor de Twenty +(p. ej., `http://localhost:2020/s/documents/generate`). En Twenty Cloud, `RestApiClient` +resuelve la ruta a través del dominio de funciones del espacio de trabajo. ## Ruta POST — generar bajo demanda diff --git a/packages/twenty-docs/l/fr/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/fr/developers/extend/apps/layout/front-components.mdx index f6a6a58f17..8dff90d0f9 100644 --- a/packages/twenty-docs/l/fr/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/fr/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Les composants front s'exécutent côté navigateur dans un Web Worker isolé (sandboxé) à l'intérieur d'un iframe à origine opaque, tandis que les [fonctions logiques](/l/fr/developers/extend/apps/logic/logic-functions) s'exécutent côté serveur. Il n’y a aucun appel intra-processus direct entre les deux — à la place, un composant front appelle une fonction logique via HTTP. -Une fonction logique déclarée avec `httpRouteTriggerSettings` est accessible via HTTP à son chemin de route. Twenty injecte dans le worker l’URL de base à partir de laquelle vos fonctions sont servies sous la forme de `TWENTY_FUNCTIONS_URL`, ainsi que le `TWENTY_APP_ACCESS_TOKEN` qui authentifie l’appel. Il n’existe pas encore de client SDK dédié pour invoquer vos propres fonctions, donc appelez-les avec un simple `fetch` : +Une fonction logique déclarée avec `httpRouteTriggerSettings` est accessible via HTTP à son chemin de route. `RestApiClient` traite les chemins commençant par `/s/` comme des routes d’application, les résout vers l’URL à partir de laquelle vos fonctions sont servies et les authentifie avec `TWENTY_APP_ACCESS_TOKEN`. -> **Sur Twenty Cloud, les fonctions logiques déclenchées par HTTP sont servies sur un domaine dédié par espace de travail** à l’adresse `https://\.withtwenty.com\` — c’est exactement ce à quoi `TWENTY_FUNCTIONS_URL` correspond. Pour les appelants externes, copiez l’URL exacte à partir des paramètres **HTTP trigger** de la fonction ou de l’onglet **Settings** de l’application. - - - L’ancienne route de fonction `/s/` est **obsolète** et sera **désactivée le 2026-07-24**. Utilisez plutôt `TWENTY_FUNCTIONS_URL` (ci-dessus), et migrez toutes les URL `/s/` en dur avant cette date. La route `/s/` reste disponible pour l’auto-hébergement. - +> **Sur Twenty Cloud, les fonctions logiques déclenchées par HTTP sont servies sur un domaine dédié par espace de travail** à l’adresse `https://\.withtwenty.com\`. Pour les appelants externes, copiez l’URL exacte à partir des paramètres **HTTP trigger** de la fonction ou de l’onglet **Settings** de l’application. Un composant front sans interface (headless) peut effectuer l’appel au montage via le composant `Command`, puis se démonter automatiquement : ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -Le chemin ajouté à `TWENTY_FUNCTIONS_URL` correspond au `httpRouteTriggerSettings.path` de la fonction logique. Conservez `isAuthRequired: true` ; le `TWENTY_APP_ACCESS_TOKEN` que Twenty génère pour votre composant authentifie la requête : +Le chemin transmis à `RestApiClient` est la propriété `httpRouteTriggerSettings.path` de la fonction logique, préfixée par `/s`. Conservez `isAuthRequired: true` ; le `TWENTY_APP_ACCESS_TOKEN` que Twenty génère pour votre composant authentifie la requête : ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` et `TWENTY_APP_ACCESS_TOKEN` sont injectés automatiquement — voir [Variables d’application](#application-variables). Comme les variables d’application secrètes ne sont jamais exposées aux composants front, conservez les clés d’API et les autres éléments sensibles dans la fonction logique, et non dans le composant front. +`TWENTY_APP_ACCESS_TOKEN` est injecté automatiquement — voir [Variables d’application](#application-variables). Comme les variables d’application secrètes ne sont jamais exposées aux composants front, conservez les clés d’API et les autres éléments sensibles dans la fonction logique, et non dans le composant front. ### Appeler l’API REST de Twenty -Pour lire ou écrire des enregistrements Twenty depuis un composant frontal, utilisez `RestApiClient` depuis `twenty-client-sdk/rest`. Il appartient à la même famille de clients que `CoreApiClient` et `MetadataApiClient`, mais cible l’API REST de Twenty (`/rest/...`) plutôt que l’API GraphQL, en lisant son URL de base depuis `TWENTY_API_URL`. +Pour appeler des routes HTTP d’application ou lire et écrire des enregistrements Twenty depuis un composant frontal, utilisez `RestApiClient` depuis `twenty-client-sdk/rest`. Il envoie les chemins `/s/...` vers l’URL de base des fonctions de votre espace de travail et tous les autres chemins, y compris `/rest/...`, vers `TWENTY_API_URL`. -| Méthode | Description | -| --------------------------------- | ---------------------------------------------------- | -| `get(path, options?)` | Envoie une requête `GET` | -| `post(path, body?, options?)` | Envoie une requête `POST` | -| `put(path, body?, options?)` | Envoie une requête `PUT` | -| `patch(path, body?, options?)` | Envoie une requête `PATCH` | -| `delete(path, options?)` | Envoie une requête `DELETE` | -| `request(method, path, options?)` | Requête générique avec n’importe quelle méthode HTTP | +| Méthode | Description | +| --------------------------------- | ------------------------------------------------------------------------------- | +| `get(path, options?)` | Envoie une requête `GET` | +| `post(path, body?, options?)` | Envoie une requête `POST` | +| `put(path, body?, options?)` | Envoie une requête `PUT` | +| `patch(path, body?, options?)` | Envoie une requête `PATCH` | +| `delete(path, options?)` | Envoie une requête `DELETE` | +| `request(method, path, options?)` | Requête générique avec n’importe quelle méthode HTTP | +| `resolveUrl(path, options?)` | Résout un chemin vers son URL complète sans envoyer de requête (pour les liens) | `options` accepte `headers`, `query` (un enregistrement de paramètres de chaîne de requête ; les valeurs nullish sont ignorées), et un `AbortSignal` via `signal`. Un objet `body` qui n’est pas de type `FormData` est automatiquement sérialisé en JSON. Sur un `401`, le client actualise une fois le jeton d’accès via l’hôte puis retente la requête. @@ -417,11 +411,22 @@ Les variables secrètes (`isSecret: true`) ne sont **pas** exposées aux composa Les variables système suivantes sont toujours disponibles via `process.env` : -| Variable | Description | -| ------------------------- | ------------------------------------------------------------------------------------------------ | -| `TWENTY_FUNCTIONS_URL` | URL de base à partir de laquelle les fonctions de logique HTTP de votre application sont servies | -| `TWENTY_API_URL` | URL de base de l’API principale de Twenty | -| `TWENTY_APP_ACCESS_TOKEN` | Jeton de courte durée limité au rôle de votre application | +| Variable | Description | +| ------------------------- | --------------------------------------------------------- | +| `TWENTY_API_URL` | URL de base de l’API principale de Twenty | +| `TWENTY_APP_ACCESS_TOKEN` | Jeton de courte durée limité au rôle de votre application | + +### `TWENTY_FUNCTIONS_URL` + +Twenty injecte également `TWENTY_FUNCTIONS_URL` dans les composants frontaux et les fonctions logiques : l’URL de base à partir de laquelle les fonctions logiques déclenchées par HTTP de votre application sont servies. + +Elle existe parce que cette URL n’est pas toujours le serveur Twenty lui-même. Sur Twenty Cloud, les routes d’application sont servies sur un domaine dédié par espace de travail (`https://\.withtwenty.com`, ou le domaine public principal de l’application lorsqu’il est configuré) afin que les réponses créées par l’application s’exécutent sur une origine isolée plutôt que sur l’origine de l’application Twenty. Les instances auto-hébergées et locales servent les routes d’application sous le préfixe `/s` sur le serveur lui-même et peuvent ne pas définir la variable du tout. Comme l’URL de base varie selon l’espace de travail et l’instance, votre code ne peut pas la coder en dur — le serveur injecte la bonne valeur à l’exécution. + +Vous avez rarement besoin de la lire directement. Appelez vos routes via `RestApiClient` avec un chemin préfixé par `/s/` et le client résout l’URL pour vous : il retire le préfixe `/s` et cible `TWENTY_FUNCTIONS_URL`, en revenant à `\/s` lorsque la variable n’est pas définie. Utilisez `resolveUrl('/s/\')` pour obtenir l’URL absolue sans envoyer de requête, par exemple pour un lien. Lisez la variable directement uniquement lorsque vous construisez une URL manuellement : + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## API de communication de l'hôte diff --git a/packages/twenty-docs/l/fr/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/fr/developers/extend/apps/logic/logic-functions.mdx index 19e0c723de..d2df710aab 100644 --- a/packages/twenty-docs/l/fr/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/fr/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Types de déclencheurs disponibles : -* **httpRoute** : Expose votre fonction sur un chemin HTTP et une méthode dans l'URL de **fonctions de base** de votre espace de travail — la valeur de 20 injects en tant que `TWENTY_FUNCTIONS_URL` (sur Twenty Cloud, un domaine dédié par espace de travail): -> p. ex. `path: '/post-card/create'` peut être appelé à l'adresse `https://your-workspace.withtwenty.com/post-card/create` - - -L'ancienne route de préfixe `/s/` (`https://your-twenty-server.com/s/post-card/create`) est **obsolète sur Twenty Cloud** et sera désactivée le **2026-07-24**. Il reste disponible pour les instances auto-hébergées et locales qui ne configurent pas un domaine de fonctions isolées — utilisez `TWENTY_FUNCTIONS_URL` quand il est défini, et revenez à `\/s/\` autrement. - +* **httpRoute** : Expose votre fonction sur un chemin et une méthode HTTP. Dans le code de l'application, préfixez le chemin de la route avec `/s/` lorsque vous utilisez `RestApiClient` ; l'URL déployée utilise la base injectée `TWENTY_FUNCTIONS_URL` (ou `\/s` lorsqu'elle n'est pas définie). Pour appeler une fonction logique déclenchée par une route depuis un composant frontal (sans interface), consultez [Appeler une fonction logique](/l/fr/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/fr/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/fr/developers/extend/apps/logic/overview.mdx index d5a12571b8..04b10d6f93 100644 --- a/packages/twenty-docs/l/fr/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/fr/developers/extend/apps/logic/overview.mdx @@ -40,13 +40,13 @@ La **couche logique** d’une application Twenty est le code qui *s’exécute* Une fonction logique choisit un ou plusieurs déclencheurs — chaque entrée ci-dessous est un champ distinct sur `defineLogicFunction()`: -| Déclencheur | Moment d’exécution | Paramètre | -| -------------------------------- | ------------------------------------------------------------------------- | ------------------------------- | -| **Route HTTP** | Une requête atteint l'URL publique de votre fonction | `httpRouteTriggerSettings` | -| **Cron** | Une expression CRON correspond | `cronTriggerSettings` | -| **Événement de base de données** | Un enregistrement de l’espace de travail est créé, mis à jour ou supprimé | `databaseEventTriggerSettings` | -| **Outil IA** | Une fonctionnalité IA de Twenty décide d’appeler votre fonction | `toolTriggerSettings` | -| **Action de flux de travail** | Une étape de flux de travail invoque votre fonction | `workflowActionTriggerSettings` | +| Déclencheur | Moment d’exécution | Paramètre | +| -------------------------------- | ---------------------------------------------------------------------------- | ------------------------------- | +| **Route HTTP** | Une requête atteint votre point de terminaison `/s/\` | `httpRouteTriggerSettings` | +| **Cron** | Une expression CRON correspond | `cronTriggerSettings` | +| **Événement de base de données** | Un enregistrement de l’espace de travail est créé, mis à jour ou supprimé | `databaseEventTriggerSettings` | +| **Outil IA** | Une fonctionnalité IA de Twenty décide d’appeler votre fonction | `toolTriggerSettings` | +| **Action de flux de travail** | Une étape de flux de travail invoque votre fonction | `workflowActionTriggerSettings` | Les fonctions s’exécutent dans un environnement isolé dans des processus Node.js sandboxés et accèdent à l’espace de travail via un client API typé, limité au rôle déclaré sur [`defineApplication()`](/l/fr/developers/extend/apps/config/application). diff --git a/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index 8028a5a515..98c7bf5606 100644 --- a/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ par l'intermédiaire de `CoreApiClient`, et POSTs vers la route à partir du der ```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', @@ -179,6 +175,7 @@ en ligne via un petit [`Markdown`](https://github.com/twentyhq/twenty/blob/main/ ```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'; @@ -187,9 +184,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. diff --git a/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 785b8cae46..978d7ce1fc 100644 --- a/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/fr/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,10 @@ Le même gestionnaire peut également répondre aux requêtes HTTP. Nous allons * un point de terminaison **POST** que l'interface utilisateur appelle pour générer un document, et * un point de terminaison public **GET** qui rend un document en tant que page web imprimable. -Les deux utilisent `httpRouteTriggerSettings`. Sur le serveur de développement local, les routes des applications sont -servies sous le préfixe `/s` (par exemple `http://localhost:2020/s/documents/generate`). - - -Sur Twenty Cloud, les routes sont servies sur le domaine de fonctions dédiées à l'espace de travail -— l'URL 20 injecte en tant que `TWENTY_FUNCTIONS_URL`, sans préfixe `/s`. Le préfixe `/s` -est déprécié là-bas et ne reste que pour les instances auto-hébergées et locales. -Voir [Appel à une fonction logique] (/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Les deux utilisent `httpRouteTriggerSettings`. Les routes de l'application sont accessibles via le chemin `/s/` ; sur les instances locales +et auto-hébergées, ce chemin est géré par votre serveur Twenty +(par exemple, `http://localhost:2020/s/documents/generate`). Sur Twenty Cloud, `RestApiClient` +résout le chemin via le domaine des fonctions de l'espace de travail. ## Itinéraire POST — générer à la demande diff --git a/packages/twenty-docs/l/it/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/it/developers/extend/apps/layout/front-components.mdx index 0cc82a3461..dd3c101997 100644 --- a/packages/twenty-docs/l/it/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/it/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ I componenti front vengono eseguiti lato browser in un Web Worker in sandbox all'interno di un iframe con origine opaca, mentre le [funzioni logiche](/l/it/developers/extend/apps/logic/logic-functions) vengono eseguite lato server. Non esiste una chiamata diretta in-process tra i due; invece, un front component chiama una funzione logica tramite HTTP. -Una funzione logica dichiarata con `httpRouteTriggerSettings` è raggiungibile tramite HTTP al relativo percorso della route. Twenty inietta nel worker l'URL di base da cui vengono servite le tue funzioni come `TWENTY_FUNCTIONS_URL`, insieme al `TWENTY_APP_ACCESS_TOKEN` che autentica la chiamata. Non esiste ancora un client SDK dedicato per invocare le proprie funzioni, quindi chiamale con un semplice `fetch`: +Una funzione logica dichiarata con `httpRouteTriggerSettings` è raggiungibile tramite HTTP al relativo percorso della route. `RestApiClient` tratta i percorsi che iniziano con `/s/` come route dell’app, li risolve nell’URL da cui vengono servite le tue funzioni e li autentica con `TWENTY_APP_ACCESS_TOKEN`. -> **Su Twenty Cloud, le funzioni logiche attivate tramite HTTP sono servite su un dominio dedicato per ogni workspace** in `https://\.withtwenty.com\` — questo è esattamente ciò in cui viene risolto `TWENTY_FUNCTIONS_URL`. Per i chiamanti esterni, copia l’URL esatto dalle impostazioni del **trigger HTTP** della funzione o dalla scheda **Settings** dell’applicazione. - - - La route legacy della funzione `/s/` è **deprecata** e sarà **disattivata il 2026-07-24**. Usa invece `TWENTY_FUNCTIONS_URL` (sopra) e migra tutti gli URL `/s/` hard-coded prima di quella data. La route `/s/` rimane disponibile per il self-hosting. - +> **Su Twenty Cloud, le funzioni logiche attivate tramite HTTP sono servite su un dominio dedicato per ogni workspace** in `https://\.withtwenty.com\`. Per i chiamanti esterni, copia l’URL esatto dalle impostazioni del **trigger HTTP** della funzione o dalla scheda **Settings** dell’applicazione. Un front component headless può eseguire la chiamata al mount tramite il componente `Command`, quindi smontarsi automaticamente: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -Il percorso aggiunto a `TWENTY_FUNCTIONS_URL` è il `httpRouteTriggerSettings.path` della funzione logica. Mantieni `isAuthRequired: true`; il `TWENTY_APP_ACCESS_TOKEN` che Twenty genera per il tuo componente autentica la richiesta: +Il percorso passato a `RestApiClient` è la proprietà `httpRouteTriggerSettings.path` della funzione di logica, con prefisso `/s`. Mantieni `isAuthRequired: true`; il `TWENTY_APP_ACCESS_TOKEN` che Twenty genera per il tuo componente autentica la richiesta: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` e `TWENTY_APP_ACCESS_TOKEN` vengono inseriti automaticamente — vedi [Variabili dell'applicazione](#application-variables). Poiché le variabili di applicazione segrete non vengono mai esposte ai front component, mantieni le chiavi API e altra logica sensibile all’interno della funzione logica, non nel front component. +`TWENTY_APP_ACCESS_TOKEN` viene inserito automaticamente — vedi [Variabili dell’applicazione](#application-variables). Poiché le variabili di applicazione segrete non vengono mai esposte ai front component, mantieni le chiavi API e altra logica sensibile all’interno della funzione logica, non nel front component. ### Chiamare le Twenty REST API -Per leggere o scrivere record di Twenty da un front component, usa `RestApiClient` da `twenty-client-sdk/rest`. Appartiene alla stessa famiglia di client di `CoreApiClient` e `MetadataApiClient`, ma si rivolge alle Twenty REST API (`/rest/...`) invece della GraphQL API, leggendo il suo URL di base da `TWENTY_API_URL`. +Per chiamare le route HTTP dell’app o leggere e scrivere record di Twenty da un front component, usa `RestApiClient` da `twenty-client-sdk/rest`. Invia i percorsi `/s/...` alla base URL delle funzioni del tuo workspace e tutti gli altri percorsi, inclusi `/rest/...`, a `TWENTY_API_URL`. -| Metodo | Descrizione | -| --------------------------------- | -------------------------------------------- | -| `get(path, options?)` | Invia una richiesta `GET` | -| `post(path, body?, options?)` | Invia una richiesta `POST` | -| `put(path, body?, options?)` | Invia una richiesta `PUT` | -| `patch(path, body?, options?)` | Invia una richiesta `PATCH` | -| `delete(path, options?)` | Invia una richiesta `DELETE` | -| `request(method, path, options?)` | Richiesta generica con qualsiasi metodo HTTP | +| Metodo | Descrizione | +| --------------------------------- | --------------------------------------------------------------------------------- | +| `get(path, options?)` | Invia una richiesta `GET` | +| `post(path, body?, options?)` | Invia una richiesta `POST` | +| `put(path, body?, options?)` | Invia una richiesta `PUT` | +| `patch(path, body?, options?)` | Invia una richiesta `PATCH` | +| `delete(path, options?)` | Invia una richiesta `DELETE` | +| `request(method, path, options?)` | Richiesta generica con qualsiasi metodo HTTP | +| `resolveUrl(path, options?)` | Risolve un percorso nel suo URL completo senza inviare una richiesta (per i link) | `options` accetta `headers`, `query` (un record di parametri della query string; i valori nullish vengono ignorati) e un `AbortSignal` tramite `signal`. Un oggetto `body` non-`FormData` viene serializzato automaticamente in JSON. In caso di `401`, il client aggiorna il token di accesso una volta tramite l'host e ritenta la richiesta. @@ -417,11 +411,22 @@ Le variabili segrete (`isSecret: true`) **non** sono esposte ai componenti front Le seguenti variabili di sistema sono sempre disponibili tramite `process.env`: -| Variabile | Descrizione | -| ------------------------- | --------------------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | URL di base da cui vengono servite le funzioni di logica HTTP della tua app | -| `TWENTY_API_URL` | URL di base dell'API Core di Twenty | -| `TWENTY_APP_ACCESS_TOKEN` | Token di breve durata con ambito limitato al ruolo della tua app | +| Variabile | Descrizione | +| ------------------------- | ---------------------------------------------------------------- | +| `TWENTY_API_URL` | URL di base dell'API Core di Twenty | +| `TWENTY_APP_ACCESS_TOKEN` | Token di breve durata con ambito limitato al ruolo della tua app | + +### `TWENTY_FUNCTIONS_URL` + +Twenty inserisce anche `TWENTY_FUNCTIONS_URL` nei front component e nelle funzioni di logica: la base URL da cui vengono servite le funzioni di logica attivate tramite HTTP della tua app. + +Esiste perché quell’URL non coincide sempre con il server di Twenty stesso. Su Twenty Cloud, le route dell’app sono servite su un dominio dedicato per ogni workspace (`https://\.withtwenty.com`, oppure il dominio pubblico primario dell’applicazione quando è configurato) in modo che le risposte create dall’app vengano eseguite in un’origine isolata invece che nell’origine dell’app Twenty. Le istanze self-hosted e locali servono le route dell’app con il prefisso `/s` direttamente sul server e potrebbero non impostare affatto la variabile. Dato che la base URL varia per workspace e per istanza, il tuo codice non può codificarla in modo statico — il server inserisce il valore corretto a runtime. + +Raramente devi leggerla direttamente. Chiama le tue route tramite `RestApiClient` con un percorso con prefisso `/s/` e il client risolve l’URL per te: rimuove il prefisso `/s` e punta a `TWENTY_FUNCTIONS_URL`, usando `\/s` come fallback quando la variabile non è impostata. Usa `resolveUrl('/s/\')` per ottenere l’URL assoluto senza inviare una richiesta, ad esempio per un link. Leggi direttamente la variabile solo quando costruisci manualmente un URL: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## API di comunicazione con l'host diff --git a/packages/twenty-docs/l/it/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/it/developers/extend/apps/logic/logic-functions.mdx index c2a2b214e3..1c695701b8 100644 --- a/packages/twenty-docs/l/it/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/it/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Tipi di trigger disponibili: -* **httpRoute**: Espone la tua funzione su un percorso HTTP e un metodo al **URL di base delle funzioni del tuo workspace** — il valore Twenty inietta come `TWENTY_FUNCTIONS_URL` (su Twenty Cloud, un dominio dedicato per workspace -> ad es. `path: '/post-card/create'` è invocabile su `https://your-workspace.withtwenty.com/post-card/create` - - -Il prefisso tradizionale `/s/` (`https://your-twenty-server.com/s/post-card/create`) è **deprecato su Twenty Cloud** e sarà disattivato il **2026-07-24**. Rimane disponibile per le istanze locali e self-hosted che non configurano un dominio di funzioni isolate — usa `TWENTY_FUNCTIONS_URL` quando è impostato, e torna a `\/s/\` altrimenti. - +* **httpRoute**: Espone la tua funzione su un percorso e metodo HTTP. Nel codice dell'app, anteponi al percorso della route `/s/` quando utilizzi `RestApiClient`; l'URL distribuito utilizza la base `TWENTY_FUNCTIONS_URL` iniettata (o `\/s` quando non è impostata). Per richiamare, da un componente front-end (headless), una funzione logica attivata da una rotta, vedi [Chiamare una funzione logica](/l/it/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/it/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/it/developers/extend/apps/logic/overview.mdx index 0c7083af25..2e98239c92 100644 --- a/packages/twenty-docs/l/it/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/it/developers/extend/apps/logic/overview.mdx @@ -42,7 +42,7 @@ Una funzione logica sceglie uno o più trigger — ogni voce qui sotto è un cam | Scatenante | Quando viene eseguito | Impostazione | | ----------------------- | --------------------------------------------------------------------- | ------------------------------- | -| **Route HTTP** | Una richiesta colpisce l'URL pubblico della tua funzione | `httpRouteTriggerSettings` | +| **Route HTTP** | Una richiesta raggiunge il tuo endpoint `/s/\` | `httpRouteTriggerSettings` | | **Cron** | Viene soddisfatta un'espressione CRON | `cronTriggerSettings` | | **Evento database** | Un record dello spazio di lavoro viene creato, aggiornato o eliminato | `databaseEventTriggerSettings` | | **Strumento AI** | Una funzionalità AI di Twenty decide di chiamare la tua funzione | `toolTriggerSettings` | diff --git a/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index c3e9956705..13a25b90c4 100644 --- a/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ tramite `CoreApiClient`, e POSTs sul percorso dall'ultimo capitolo ```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. diff --git a/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 53e3adddae..b3dc004d64 100644 --- a/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/it/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,10 @@ Lo stesso gestore può anche rispondere alle richieste HTTP. Aggiungeremo due pe * un endpoint **POST** per generare un documento, e * un endpoint pubblico **GET** che rende un documento come una pagina web stampabile. -Entrambi usano `httpRouteTriggerSettings`. Sul server dev locale, gli itinerari delle app sono -serviti sotto il prefisso `/s` (ad es. `http://localhost:2020/s/documents/generate`). - - -Su Twenty Cloud, i percorsi sono serviti sul dominio delle funzioni dedicate -dello spazio di lavoro — l'URL Twenty inietta come `TWENTY_FUNCTIONS_URL`, senza prefisso `/s`. Il prefisso `/s` -è deprecato e rimane solo per le istanze autosostenute e locali. -Vedi [Chiamare una funzione logica](/l/it/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Entrambi usano `httpRouteTriggerSettings`. Le route dell'app sono accessibili tramite il percorso `/s/`; nelle istanze locali +e self-hosted, tale percorso è gestito dal tuo server Twenty +(ad es. `http://localhost:2020/s/documents/generate`). Su Twenty Cloud, `RestApiClient` +risolve il percorso tramite il dominio delle funzioni dell'area di lavoro. ## Percorso POST — generare su richiesta diff --git a/packages/twenty-docs/l/ja/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/ja/developers/extend/apps/layout/front-components.mdx index e84b834a74..09da4164a0 100644 --- a/packages/twenty-docs/l/ja/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/ja/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ フロントコンポーネントは不透明なオリジンの iframe 内にサンドボックス化された Web Worker 内でブラウザーサイドで実行され、一方で[ロジック関数](/l/ja/developers/extend/apps/logic/logic-functions)はサーバーサイドで実行されます。 両者の間にプロセス内での直接呼び出しはありません。その代わり、フロントコンポーネントは HTTP 経由でロジック関数にアクセスします。 -`httpRouteTriggerSettings` で宣言されたロジック関数は、そのルートパスで HTTP 経由でアクセスできます。 Twenty は、関数が提供されるベース URL を `TWENTY_FUNCTIONS_URL` としてワーカーに注入し、呼び出しを認証する `TWENTY_APP_ACCESS_TOKEN` も併せて渡します。 独自の関数を呼び出すための専用 SDK クライアントはまだないため、シンプルな `fetch` を使って呼び出してください。 +`httpRouteTriggerSettings` で宣言されたロジック関数は、そのルートパスで HTTP 経由でアクセスできます。 `RestApiClient` は、`/s/` で始まるパスをアプリのルートとして扱い、それらをあなたの関数が提供されている URL に解決し、`TWENTY_APP_ACCESS_TOKEN` で認証します。 -> **Twenty Cloud では、HTTP トリガーのロジック関数はワークスペースごとの専用ドメインで提供されます**。`https://\.withtwenty.com\` がそのドメインであり、これが `TWENTY_FUNCTIONS_URL` が解決される先とまったく同じです。 外部から呼び出す場合は、関数の **HTTP trigger** 設定、もしくはアプリケーションの **Settings** タブから、正確な URL をコピーしてください。 - - - レガシーな `/s/` 関数ルートは**非推奨**となっており、**2026-07-24 に無効化されます**。 代わりに(上記の)`TWENTY_FUNCTIONS_URL` を使用し、その日までにハードコードされた `/s/` URL をすべて移行してください。 `/s/` ルートはセルフホスティング向けには引き続き利用可能です。 - +> **Twenty Cloud では、HTTP トリガーのロジック関数はワークスペースごとの専用ドメインで提供されます**。`https://\.withtwenty.com\` で提供されます。 外部から呼び出す場合は、関数の **HTTP trigger** 設定、もしくはアプリケーションの **Settings** タブから、正確な URL をコピーしてください。 ヘッドレスフロントコンポーネントは、`Command` コンポーネント経由でマウント時に呼び出しを実行し、その後自動的にアンマウントできます。 ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -`TWENTY_FUNCTIONS_URL` に付加されるパスは、ロジック関数の `httpRouteTriggerSettings.path` です。 `isAuthRequired: true` のままにしておいてください。コンポーネント用に Twenty が発行する `TWENTY_APP_ACCESS_TOKEN` によってリクエストが認証されます。 +`RestApiClient` に渡されるパスは、ロジック関数の `httpRouteTriggerSettings.path` に `/s` を付加したものです。 `isAuthRequired: true` のままにしておいてください。コンポーネント用に Twenty が発行する `TWENTY_APP_ACCESS_TOKEN` によってリクエストが認証されます。 ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` と `TWENTY_APP_ACCESS_TOKEN` は自動的に挿入されます。詳しくは [Application variables](#application-variables) を参照してください。 秘匿アプリケーション変数はフロントコンポーネントに公開されることがないため、API キーやその他の機密性の高いロジックはフロントコンポーネントではなく、ロジック関数側に保持してください。 +`TWENTY_APP_ACCESS_TOKEN` は自動的に挿入されます。詳しくは [Application variables](#application-variables) を参照してください。 秘匿アプリケーション変数はフロントコンポーネントに公開されることがないため、API キーやその他の機密性の高いロジックはフロントコンポーネントではなく、ロジック関数側に保持してください。 ### Twenty REST API の呼び出し -フロントコンポーネントから Twenty のレコードを読み書きするには、`twenty-client-sdk/rest` の `RestApiClient` を使用します。 これは `CoreApiClient` や `MetadataApiClient` と同じクライアントファミリーに属しますが、GraphQL API ではなく Twenty REST API(`/rest/...`)を対象とし、そのベース URL を `TWENTY_API_URL` から取得します。 +アプリの HTTP ルートを呼び出したり、フロントコンポーネントから Twenty のレコードを読み書きしたりするには、`twenty-client-sdk/rest` の `RestApiClient` を使用します。 これは、`/s/...` のパスをワークスペースの関数のベース URL に送り、`/rest/...` を含むそれ以外のすべてのパスを `TWENTY_API_URL` に送信します。 -| メソッド | 説明 | -| --------------------------------- | ------------------------- | -| `get(path, options?)` | `GET` リクエストを送信します | -| `post(path, body?, options?)` | `POST` リクエストを送信します | -| `put(path, body?, options?)` | `PUT` リクエストを送信します | -| `patch(path, body?, options?)` | `PATCH` リクエストを送信します | -| `delete(path, options?)` | `DELETE` リクエストを送信します | -| `request(method, path, options?)` | 任意の HTTP メソッドによる汎用的なリクエスト | +| メソッド | 説明 | +| --------------------------------- | ------------------------------------ | +| `get(path, options?)` | `GET` リクエストを送信します | +| `post(path, body?, options?)` | `POST` リクエストを送信します | +| `put(path, body?, options?)` | `PUT` リクエストを送信します | +| `patch(path, body?, options?)` | `PATCH` リクエストを送信します | +| `delete(path, options?)` | `DELETE` リクエストを送信します | +| `request(method, path, options?)` | 任意の HTTP メソッドによる汎用的なリクエスト | +| `resolveUrl(path, options?)` | リクエストを送信せずに、パスを完全な URL に解決します(リンク向け) | `options` には、`headers`、`query`(クエリ文字列パラメーターのレコード。null 相当の値はスキップされます)、および `signal` 経由の `AbortSignal` を指定できます。 `FormData` ではないオブジェクト `body` は、自動的に JSON シリアル化されます。 `401` が発生した場合、クライアントはホスト経由で一度だけアクセス トークンを更新し、そのリクエストを再試行します。 @@ -417,11 +411,22 @@ export default defineFrontComponent({ 次のシステム変数は、常に `process.env` 経由で利用できます。 -| 変数 | 説明 | -| ------------------------- | ----------------------------- | -| `TWENTY_FUNCTIONS_URL` | アプリの HTTP ロジック関数が提供されるベース URL | -| `TWENTY_API_URL` | Twenty コア API のベース URL | -| `TWENTY_APP_ACCESS_TOKEN` | アプリのロールにスコープされた有効期間の短いトークン | +| 変数 | 説明 | +| ------------------------- | -------------------------- | +| `TWENTY_API_URL` | Twenty コア API のベース URL | +| `TWENTY_APP_ACCESS_TOKEN` | アプリのロールにスコープされた有効期間の短いトークン | + +### `TWENTY_FUNCTIONS_URL` + +Twenty はまた、`TWENTY_FUNCTIONS_URL` をフロントコンポーネントとロジック関数に挿入します。これは、アプリの HTTP トリガーのロジック関数が提供されるベース URL です。 + +この変数が存在するのは、その URL が必ずしも Twenty サーバー自体とは限らないためです。 Twenty Cloud では、アプリのルートはワークスペースごとの専用ドメイン(`https://\.withtwenty.com`、または設定されている場合はアプリケーションのプライマリ公開ドメイン)で提供されます。これにより、アプリで作成されたレスポンスが Twenty アプリのオリジンではなく分離されたオリジン上で実行されます。 セルフホストおよびローカルインスタンスでは、アプリのルートはサーバー自体の `/s` プレフィックスの下で提供され、この変数がまったく設定されない場合もあります。 ベース URL はワークスペースやインスタンスごとに異なるため、コードでハードコードすることはできません。サーバーが実行時に正しい値を挿入します。 + +この変数を直接読む必要があることはほとんどありません。 `/s/` プレフィックス付きのパスで `RestApiClient` を通じてルートを呼び出すと、クライアントが URL を解決します。`/s` プレフィックスを取り除き、`TWENTY_FUNCTIONS_URL` をターゲットにし、この変数が設定されていない場合は `\/s` をフォールバックとして使用します。 リクエストを送信せずに絶対 URL を取得するには、`resolveUrl('/s/\')` を使用します(リンクなどの用途)。 URL を手作業で組み立てる場合にのみ、この変数を直接読み取ってください。 + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## ホスト通信 API diff --git a/packages/twenty-docs/l/ja/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/ja/developers/extend/apps/logic/logic-functions.mdx index 1959e260b1..cbfbc67018 100644 --- a/packages/twenty-docs/l/ja/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/ja/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` 利用可能なトリガーの種類: -* **httpRoute**: ワークスペースの **関数 ベース URL** の HTTP パスとメソッドにあなたの関数を公開します。値 Twenty_FUNCTIONS_URL\` (Twenty Cloud 上) ワークスペースごとの専用ドメイン: -> 例:`path: '/post-card/create'` は `https://your-workspace.withtwenty.com/post-card/create` で呼び出せます - - -レガシーの `/s/` prefix route (`https://your-20-server.com/s/post-card/create`)は\*\*Twenty Cloudで非推奨になっており、**2026-07-24**で無効になります。 分離された関数ドメインを設定しない自己ホストおよびローカルインスタンスでも使用できます — 設定時は `TWENTY_FUNCTIONS_URL` を使用してください。 そして、 `\/s/\` に戻ります。 - +* **httpRoute**:HTTP のパスとメソッドで関数を公開します。 アプリのコードでは、`RestApiClient` を使用する際、ルートパスの先頭に `/s/` を付けてください。デプロイ後の URL では、`TWENTY_FUNCTIONS_URL` で注入されたベース URL が使用され、未設定の場合は `\/s` が使用されます。 (ヘッドレスの)フロントコンポーネントからルートトリガー型ロジック関数を呼び出す方法については、[ロジック関数を呼び出す](/l/ja/developers/extend/apps/layout/front-components#calling-a-logic-function)を参照してください。 diff --git a/packages/twenty-docs/l/ja/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/ja/developers/extend/apps/logic/overview.mdx index c06491f9eb..11b4f2c6da 100644 --- a/packages/twenty-docs/l/ja/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/ja/developers/extend/apps/logic/overview.mdx @@ -40,13 +40,13 @@ Twenty アプリの **ロジックレイヤー** は、*実行される* コー ロジック関数は 1 つ以上のトリガーを選択します。以下の各項目は、`defineLogicFunction()` 上の個別のフィールドです。 -| トリガー | 実行タイミング | 設定 | -| --------------- | ------------------------------- | ------------------------------- | -| **HTTP ルート** | リクエストがあなたの関数の公開 URL に一致しました | `httpRouteTriggerSettings` | -| **クロン** | CRON 式が一致したとき | `cronTriggerSettings` | -| **データベースイベント** | ワークスペースのレコードが作成、更新、または削除されたとき | `databaseEventTriggerSettings` | -| **AI ツール** | Twenty の AI 機能が関数を呼び出すことを決定したとき | `toolTriggerSettings` | -| **ワークフローアクション** | ワークフローステップが関数を呼び出したとき | `workflowActionTriggerSettings` | +| トリガー | 実行タイミング | 設定 | +| --------------- | --------------------------------------------------- | ------------------------------- | +| **HTTP ルート** | リクエストが `/s/\` エンドポイントに到達したとき | `httpRouteTriggerSettings` | +| **クロン** | CRON 式が一致したとき | `cronTriggerSettings` | +| **データベースイベント** | ワークスペースのレコードが作成、更新、または削除されたとき | `databaseEventTriggerSettings` | +| **AI ツール** | Twenty の AI 機能が関数を呼び出すことを決定したとき | `toolTriggerSettings` | +| **ワークフローアクション** | ワークフローステップが関数を呼び出したとき | `workflowActionTriggerSettings` | 関数は分離された Node.js プロセス内でサンドボックス実行され、[`defineApplication()`](/l/ja/developers/extend/apps/config/application) で宣言されたロールにスコープされた型付き API クライアントを通じてワークスペースにアクセスします。 diff --git a/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index 431ebb3b11..666f664034 100644 --- a/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -66,6 +66,7 @@ person テンプレートを読み込み、最後の ```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'; @@ -88,15 +89,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', @@ -175,6 +171,7 @@ Markdown 本文を洗練された印刷可能なページとしてレンダリ ```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'; @@ -183,9 +180,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. diff --git a/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 37acb5e320..72fb32204d 100644 --- a/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/ja/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,14 +9,7 @@ description: HTTP 経由で関数をトリガーし、ドキュメントを Web * ドキュメントを生成するUI呼び出しの **POST** エンドポイントと * ドキュメントを印刷可能なウェブページとしてレンダリングするパブリック**GET** エンドポイント。 -どちらも `httpRouteTriggerSettings` を使用します。 ローカル開発サーバーでは、アプリのルートは `/s` プレフィックスの下で提供されます(例:`http://localhost:2020/s/documents/generate`)。 - - -Twenty Cloud では、ルートはワークスペースの専用関数ドメイン -で提供されます。URL Twenty は `TWENTY_FUNCTIONS_URL` として挿入され、`/s` プレフィックスはありません。 `/s` -プレフィックスは非推奨で、自己ホストおよびローカルインスタンスのみが使用できます。 -[ロジック関数の呼び出し](/l/ja/developers/extend/apps/layout/front-components#calling-a-logic-function)を参照してください。 - +どちらも `httpRouteTriggerSettings` を使用します。 アプリのルートは `/s/` パスで指定されます。ローカル環境やセルフホスト環境では、そのパスは Twenty サーバーによって提供されます(例: `http://localhost:2020/s/documents/generate`)。 Twenty Cloud では、`RestApiClient` はワークスペースの functions ドメインを通じてパスを解決します。 ## POST route — オンデマンドで生成 diff --git a/packages/twenty-docs/l/ko/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/ko/developers/extend/apps/layout/front-components.mdx index a3ef13e80f..9d8423b2af 100644 --- a/packages/twenty-docs/l/ko/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/ko/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Front 컴포넌트는 opaque-origin iframe 내부에 샌드박스된 Web Worker 안에서 브라우저 측에서 실행되고, [logic functions](/l/ko/developers/extend/apps/logic/logic-functions)는 서버 측에서 실행됩니다. 두 요소 사이에는 프로세스 내에서의 직접 호출이 없습니다. 대신, Front 컴포넌트는 HTTP를 통해 로직 함수에 접근합니다. -`httpRouteTriggerSettings`로 선언된 로직 함수는 HTTP를 통해 해당 라우트 경로에서 액세스할 수 있습니다. Twenty는 워커에 함수들이 제공되는 기본 URL을 `TWENTY_FUNCTIONS_URL`로 주입하고, 호출을 인증하는 `TWENTY_APP_ACCESS_TOKEN`도 함께 주입합니다. 아직 자체 함수를 호출하기 위한 전용 SDK 클라이언트는 없으므로, 일반 `fetch`로 호출하세요: +`httpRouteTriggerSettings`로 선언된 로직 함수는 HTTP를 통해 해당 라우트 경로에서 액세스할 수 있습니다. `RestApiClient`는 `/s/`로 시작하는 경로를 앱 라우트로 처리하고, 해당 경로를 함수가 제공되는 URL로 해석한 뒤 `TWENTY_APP_ACCESS_TOKEN`으로 인증합니다. -> **Twenty Cloud에서 HTTP로 트리거되는 로직 함수는 작업공간별 전용 도메인에서 제공됩니다**: `https://\.withtwenty.com\` — 이는 `TWENTY_FUNCTIONS_URL`이 정확히 가리키는 주소입니다. 외부 호출자의 경우, 함수의 **HTTP trigger** 설정 또는 애플리케이션의 **Settings** 탭에서 정확한 URL을 복사하세요. - - - 레거시 `/s/` 함수 라우트는 **사용 중단(deprecated)** 되었으며 **2026-07-24에 비활성화됩니다**. 대신 위의 `TWENTY_FUNCTIONS_URL`을 사용하고, 해당 날짜 이전에 하드 코딩된 모든 `/s/` URL을 마이그레이션하세요. `/s/` 라우트는 셀프 호스팅의 경우 계속 사용 가능합니다. - +> **Twenty Cloud에서 HTTP로 트리거되는 로직 함수는 작업공간별 전용 도메인에서 제공됩니다**: `https://\.withtwenty.com\`. 외부 호출자의 경우, 함수의 **HTTP trigger** 설정 또는 애플리케이션의 **Settings** 탭에서 정확한 URL을 복사하세요. 헤드리스 Front 컴포넌트는 `Command` 컴포넌트를 통해 마운트 시점에 호출을 실행한 뒤, 자동으로 언마운트될 수 있습니다: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -`TWENTY_FUNCTIONS_URL`에 추가되는 경로는 로직 함수의 `httpRouteTriggerSettings.path`입니다. `isAuthRequired: true`로 유지하세요. 컴포넌트를 위해 Twenty가 발급하는 `TWENTY_APP_ACCESS_TOKEN`이 요청을 인증합니다: +`RestApiClient`에 전달되는 경로는 로직 함수의 `httpRouteTriggerSettings.path` 앞에 `/s`가 접두사로 붙은 값입니다. `isAuthRequired: true`로 유지하세요. 컴포넌트를 위해 Twenty가 발급하는 `TWENTY_APP_ACCESS_TOKEN`이 요청을 인증합니다: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL`과 `TWENTY_APP_ACCESS_TOKEN`은 자동으로 주입됩니다. 자세한 내용은 [Application variables](#application-variables)을 참고하세요. 비밀 애플리케이션 변수는 Front 컴포넌트에 절대 노출되지 않으므로, API 키 및 기타 민감한 로직은 Front 컴포넌트가 아니라 로직 함수 안에 유지해야 합니다. +`TWENTY_APP_ACCESS_TOKEN`은 자동으로 주입됩니다. 자세한 내용은 [Application variables](#application-variables)을 참고하세요. 비밀 애플리케이션 변수는 Front 컴포넌트에 절대 노출되지 않으므로, API 키 및 기타 민감한 로직은 Front 컴포넌트가 아니라 로직 함수 안에 유지해야 합니다. ### Twenty REST API 호출하기 -프론트 컴포넌트에서 Twenty 레코드를 읽거나 쓰려면 `twenty-client-sdk/rest`의 `RestApiClient`를 사용하세요. 이는 `CoreApiClient` 및 `MetadataApiClient`와 동일한 클라이언트 패밀리에 속하지만, GraphQL API 대신 Twenty REST API(`/rest/...`)를 대상으로 하며, 기본 URL은 `TWENTY_API_URL`에서 읽어 옵니다. +앱 HTTP 라우트를 호출하거나 프론트 컴포넌트에서 Twenty 레코드를 읽고 쓰려면 `twenty-client-sdk/rest`의 `RestApiClient`를 사용하세요. 이 클라이언트는 `/s/...` 경로를 작업공간의 함수 base URL로 전송하고, `/rest/...`를 포함한 그 외 모든 경로는 `TWENTY_API_URL`로 전송합니다. -| 방법 | 설명 | -| --------------------------------- | ------------------------------ | -| `get(path, options?)` | `GET` 요청을 전송합니다. | -| `post(path, body?, options?)` | `POST` 요청을 전송합니다. | -| `put(path, body?, options?)` | `PUT` 요청을 전송합니다. | -| `patch(path, body?, options?)` | `PATCH` 요청을 전송합니다. | -| `delete(path, options?)` | `DELETE` 요청을 전송합니다. | -| `request(method, path, options?)` | 임의의 HTTP 메서드를 사용하는 일반적인 요청입니다. | +| 방법 | 설명 | +| --------------------------------- | ------------------------------------- | +| `get(path, options?)` | `GET` 요청을 전송합니다. | +| `post(path, body?, options?)` | `POST` 요청을 전송합니다. | +| `put(path, body?, options?)` | `PUT` 요청을 전송합니다. | +| `patch(path, body?, options?)` | `PATCH` 요청을 전송합니다. | +| `delete(path, options?)` | `DELETE` 요청을 전송합니다. | +| `request(method, path, options?)` | 임의의 HTTP 메서드를 사용하는 일반적인 요청입니다. | +| `resolveUrl(path, options?)` | 요청을 보내지 않고(예: 링크용) 경로를 전체 URL로 해석합니다. | `options`는 `headers`, `query`(쿼리 문자열 파라미터의 레코드이며, nullish 값은 건너뜁니다), 그리고 `signal`을 통한 `AbortSignal`을 받습니다. `FormData`가 아닌 객체 `body`는 자동으로 JSON 직렬화됩니다. `401`이 발생하면 클라이언트는 호스트를 통해 한 번 액세스 토큰을 갱신한 뒤 요청을 재시도합니다. @@ -417,11 +411,22 @@ export default defineFrontComponent({ 다음 시스템 변수는 항상 `process.env`를 통해 사용할 수 있습니다: -| 변수 | 설명 | -| ------------------------- | -------------------------- | -| `TWENTY_FUNCTIONS_URL` | 앱의 HTTP 로직 함수가 제공되는 기본 URL | -| `TWENTY_API_URL` | Twenty 코어 API의 기본 URL | -| `TWENTY_APP_ACCESS_TOKEN` | 앱의 역할 범위로 제한된 단기간 유효한 토큰 | +| 변수 | 설명 | +| ------------------------- | ------------------------ | +| `TWENTY_API_URL` | Twenty 코어 API의 기본 URL | +| `TWENTY_APP_ACCESS_TOKEN` | 앱의 역할 범위로 제한된 단기간 유효한 토큰 | + +### `TWENTY_FUNCTIONS_URL` + +Twenty는 또한 프론트 컴포넌트와 로직 함수에 `TWENTY_FUNCTIONS_URL`을 주입합니다. 이는 앱의 HTTP로 트리거되는 로직 함수가 제공되는 base URL입니다. + +이 URL이 항상 Twenty 서버 자체를 가리키는 것은 아니기 때문에 이 변수가 존재합니다. Twenty Cloud에서는 앱 라우트가 작업공간별 전용 도메인(`https://\.withtwenty.com`, 또는 구성된 경우 애플리케이션의 기본 public 도메인)에서 제공되므로, 앱이 작성한 응답이 Twenty 앱 origin이 아니라 분리된 origin에서 실행됩니다. 셀프 호스팅 및 로컬 인스턴스에서는 앱 라우트가 서버 자체의 `/s` 접두사 아래에서 제공되며, 이 변수가 전혀 설정되지 않을 수 있습니다. base URL은 작업공간과 인스턴스마다 다르므로 코드에서 이를 하드코딩할 수 없으며, 서버가 런타임에 올바른 값을 주입합니다. + +이 변수를 직접 읽어야 하는 경우는 드뭅니다. `RestApiClient`를 통해 `/s/` 접두사가 붙은 경로로 라우트를 호출하면, 클라이언트가 URL을 대신 해석합니다. `/s` 접두사를 제거하고 `TWENTY_FUNCTIONS_URL`을 대상으로 하며, 변수가 설정되어 있지 않은 경우 `\/s`를 사용합니다. 요청을 보내지 않고 절대 URL이 필요할 때(예: 링크용) `resolveUrl('/s/\')`를 사용하세요. 직접 URL을 구성해야 할 때만 이 변수를 직접 읽으세요: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## 호스트 통신 API diff --git a/packages/twenty-docs/l/ko/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/ko/developers/extend/apps/logic/logic-functions.mdx index b4b26a8398..12c6e8ef33 100644 --- a/packages/twenty-docs/l/ko/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/ko/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` 사용 가능한 트리거 유형: -* **httpRoute**: 워크스페이스의 **functions base URL**(Twenty가 `TWENTY_FUNCTIONS_URL`로 주입하는 값, Twenty Cloud에서는 워크스페이스별 전용 도메인임)에서 HTTP 경로와 메서드로 함수를 노출합니다. -> 예: `path: '/post-card/create'`는 `https://your-workspace.withtwenty.com/post-card/create`에서 호출할 수 있습니다 - - -레거시 `/s/` prefix 경로(`https://your-twenty-server.com/s/post-card/create`)는 **Twenty Cloud에서 사용 중단(deprecated)** 되었으며 **2026-07-24**에 비활성화됩니다. 격리된 functions 도메인을 구성하지 않는 셀프 호스팅 및 로컬 인스턴스에서는 계속 사용할 수 있습니다. `TWENTY_FUNCTIONS_URL`이 설정되어 있을 경우 해당 값을 사용하고, 그렇지 않은 경우에는 `\/s/\`를 대신 사용하십시오. - +* **httpRoute**: HTTP 경로와 메서드로 함수를 노출합니다. 앱 코드에서 `RestApiClient`를 사용할 때는 라우트 경로 앞에 `/s/`를 접두사로 붙이십시오. 배포된 URL은 주입된 `TWENTY_FUNCTIONS_URL` 기본 URL(설정되지 않은 경우 `\/s`)을 사용합니다. (헤드리스) 프런트 컴포넌트에서 라우트로 트리거되는 로직 함수를 호출하려면 [로직 함수 호출하기](/l/ko/developers/extend/apps/layout/front-components#calling-a-logic-function)를 참고하세요. diff --git a/packages/twenty-docs/l/ko/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/ko/developers/extend/apps/logic/overview.mdx index ae6fc85f6b..ff03921d96 100644 --- a/packages/twenty-docs/l/ko/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/ko/developers/extend/apps/logic/overview.mdx @@ -40,13 +40,13 @@ Twenty 앱의 **로직 계층**은 *실행되는* 코드로, HTTP 요청, 크론 로직 함수는 하나 이상의 트리거를 선택합니다. 아래의 각 항목은 `defineLogicFunction()`의 개별 필드입니다: -| 트리거 | 실행 시점 | 설정 | -| -------------- | ---------------------------------- | ------------------------------- | -| **HTTP 경로** | 요청이 함수의 공개 URL에 도달합니다. | `httpRouteTriggerSettings` | -| **크론** | CRON 표현식이 일치할 때 | `cronTriggerSettings` | -| **데이터베이스 이벤트** | 워크스페이스 레코드가 생성, 업데이트 또는 삭제될 때 | `databaseEventTriggerSettings` | -| **AI 도구** | Twenty AI 기능이 사용자의 함수를 호출하기로 결정할 때 | `toolTriggerSettings` | -| **워크플로우 액션** | 워크플로우 단계가 사용자의 함수를 호출할 때 | `workflowActionTriggerSettings` | +| 트리거 | 실행 시점 | 설정 | +| -------------- | ---------------------------------------------- | ------------------------------- | +| **HTTP 경로** | 요청이 `/s/\` 엔드포인트에 도달할 때 | `httpRouteTriggerSettings` | +| **크론** | CRON 표현식이 일치할 때 | `cronTriggerSettings` | +| **데이터베이스 이벤트** | 워크스페이스 레코드가 생성, 업데이트 또는 삭제될 때 | `databaseEventTriggerSettings` | +| **AI 도구** | Twenty AI 기능이 사용자의 함수를 호출하기로 결정할 때 | `toolTriggerSettings` | +| **워크플로우 액션** | 워크플로우 단계가 사용자의 함수를 호출할 때 | `workflowActionTriggerSettings` | 함수는 격리된 Node.js 프로세스의 샌드박스 환경에서 실행되며, [`defineApplication()`](/l/ko/developers/extend/apps/config/application)에 선언된 역할 범위에 맞춰 지정된 타입의 API 클라이언트를 통해 워크스페이스에 접근합니다. diff --git a/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index f4af4aa841..b876f2bf8f 100644 --- a/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -62,6 +62,7 @@ export default defineNavigationMenuItem({ ```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'; @@ -84,15 +85,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', @@ -161,6 +157,7 @@ export default defineCommandMenuItem({ ```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'; @@ -169,9 +166,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. diff --git a/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 76f2297f94..1fe166d63f 100644 --- a/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/ko/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,12 +9,7 @@ description: HTTP를 통해 함수를 트리거하고 문서를 웹 페이지로 * UI가 문서를 생성하기 위해 호출하는 **POST** 엔드포인트, 그리고 * 문서를 인쇄 가능한 웹 페이지로 렌더링하는 공개 **GET** 엔드포인트입니다. -둘 다 `httpRouteTriggerSettings`를 사용합니다. 로컬 개발 서버에서는 앱 라우트가 `/s` 프리픽스 아래에서 제공됩니다(예: `http://localhost:2020/s/documents/generate`). - - -Twenty Cloud에서는 워크스페이스 전용 Functions 도메인에서 라우트가 제공됩니다. 이 도메인은 Twenty가 `/s` 프리픽스 없이 `TWENTY_FUNCTIONS_URL`로 주입하는 URL입니다. 해당 환경에서 `/s` 프리픽스는 더 이상 사용되지(deprecated) 않으며, 셀프 호스팅 및 로컬 인스턴스에서만 유지됩니다. -[로직 함수 호출하기](/l/ko/developers/extend/apps/layout/front-components#calling-a-logic-function)를 참고하세요. - +둘 다 `httpRouteTriggerSettings`를 사용합니다. 앱 라우트는 `/s/` 경로로 접근합니다. 로컬 및 셀프 호스팅 인스턴스에서는 해당 경로가 Twenty 서버에서 제공됩니다(예: `http://localhost:2020/s/documents/generate`). Twenty Cloud에서는 `RestApiClient`가 워크스페이스의 functions 도메인을 통해 경로를 해석합니다. ## POST 경로 — 온디맨드로 생성하기 diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/layout/front-components.mdx index b6e9a1a35a..d1c68d5716 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Os componentes de front são executados no navegador em um Web Worker em sandbox dentro de um iframe de origem opaca, enquanto as [funções lógicas](/l/pt/developers/extend/apps/logic/logic-functions) são executadas no servidor. Não há chamada direta no mesmo processo entre os dois — em vez disso, um componente de front acessa uma função lógica via HTTP. -Uma função lógica declarada com `httpRouteTriggerSettings` é acessível por HTTP em seu caminho de rota. Twenty injeta no worker a URL base a partir da qual suas funções são servidas como `TWENTY_FUNCTIONS_URL`, juntamente com o `TWENTY_APP_ACCESS_TOKEN` que autentica a chamada. Ainda não há um cliente SDK dedicado para invocar suas próprias funções, portanto chame-as com um simples `fetch`: +Uma função lógica declarada com `httpRouteTriggerSettings` é acessível por HTTP em seu caminho de rota. `RestApiClient` trata caminhos que começam com `/s/` como rotas de aplicativo, resolve-os para a URL a partir da qual suas funções são servidas e os autentica com `TWENTY_APP_ACCESS_TOKEN`. -> **No Twenty Cloud, funções lógicas acionadas por HTTP são servidas em um domínio dedicado por workspace** em `https://\.withtwenty.com\` — que é exatamente para onde `TWENTY_FUNCTIONS_URL` aponta. Para chamadores externos, copie a URL exata das configurações de **HTTP trigger** da função ou da guia **Settings** do aplicativo. - - - A rota legada da função `/s/` está **obsoleta** e será **desativada em 2026-07-24**. Use `TWENTY_FUNCTIONS_URL` (acima) em vez disso e migre quaisquer URLs de `/s/` fixas no código antes dessa data. A rota `/s/` continua disponível para auto-hospedagem. - +> **No Twenty Cloud, funções lógicas acionadas por HTTP são servidas em um domínio dedicado por workspace** em `https://\.withtwenty.com\`. Para chamadores externos, copie a URL exata das configurações de **HTTP trigger** da função ou da guia **Settings** do aplicativo. Um componente de front headless pode executar a chamada ao montar via o componente `Command` e, em seguida, desmontar automaticamente: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -O caminho anexado a `TWENTY_FUNCTIONS_URL` é o `httpRouteTriggerSettings.path` da função lógica. Mantenha `isAuthRequired: true`; o `TWENTY_APP_ACCESS_TOKEN` que a Twenty gera para o seu componente autentica a solicitação: +O caminho passado para o `RestApiClient` é o `httpRouteTriggerSettings.path` da função de lógica, prefixado com `/s`. Mantenha `isAuthRequired: true`; o `TWENTY_APP_ACCESS_TOKEN` que a Twenty gera para o seu componente autentica a solicitação: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` e `TWENTY_APP_ACCESS_TOKEN` são injetados automaticamente — consulte [Variáveis de aplicação](#application-variables). Como as variáveis de aplicação secretas nunca são expostas aos componentes de front, mantenha as chaves de API e outra lógica sensível na função lógica, não no componente de front. +`TWENTY_APP_ACCESS_TOKEN` é injetado automaticamente — consulte [Variáveis de aplicação](#application-variables). Como as variáveis de aplicação secretas nunca são expostas aos componentes de front, mantenha as chaves de API e outra lógica sensível na função lógica, não no componente de front. ### Chamando a API REST da Twenty -Para ler ou gravar registros da Twenty a partir de um front component, use `RestApiClient` de `twenty-client-sdk/rest`. Ele pertence à mesma família de clientes que `CoreApiClient` e `MetadataApiClient`, mas tem como alvo a API REST da Twenty (`/rest/...`) em vez da API GraphQL, lendo sua URL base de `TWENTY_API_URL`. +Para chamar rotas HTTP do aplicativo ou ler e gravar registros da Twenty a partir de um front component, use `RestApiClient` de `twenty-client-sdk/rest`. Ele envia caminhos `/s/...` para a URL base das funções do seu workspace e qualquer outro caminho, incluindo `/rest/...`, para `TWENTY_API_URL`. -| Método | Descrição | -| --------------------------------- | -------------------------------------------- | -| `get(path, options?)` | Envia uma requisição `GET` | -| `post(path, body?, options?)` | Envia uma requisição `POST` | -| `put(path, body?, options?)` | Envia uma requisição `PUT` | -| `patch(path, body?, options?)` | Envia uma requisição `PATCH` | -| `delete(path, options?)` | Envia uma requisição `DELETE` | -| `request(method, path, options?)` | Requisição genérica com qualquer método HTTP | +| Método | Descrição | +| --------------------------------- | ------------------------------------------------------------------------------- | +| `get(path, options?)` | Envia uma requisição `GET` | +| `post(path, body?, options?)` | Envia uma requisição `POST` | +| `put(path, body?, options?)` | Envia uma requisição `PUT` | +| `patch(path, body?, options?)` | Envia uma requisição `PATCH` | +| `delete(path, options?)` | Envia uma requisição `DELETE` | +| `request(method, path, options?)` | Requisição genérica com qualquer método HTTP | +| `resolveUrl(path, options?)` | Resolve um caminho para sua URL completa sem enviar uma requisição (para links) | `options` aceita `headers`, `query` (um registro de parâmetros de query string; valores nulos ou indefinidos são ignorados) e um `AbortSignal` via `signal`. Um objeto `body` que não seja `FormData` é serializado em JSON automaticamente. Em um `401`, o cliente atualiza o access token uma vez por meio do host e tenta a requisição novamente. @@ -417,11 +411,22 @@ Variáveis secretas (`isSecret: true`) **não** são expostas aos componentes de As seguintes variáveis de sistema estão sempre disponíveis via `process.env`: -| Variável | Descrição | -| ------------------------- | --------------------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | URL base a partir da qual as funções de lógica HTTP do seu app são servidas | -| `TWENTY_API_URL` | URL base da API principal da Twenty | -| `TWENTY_APP_ACCESS_TOKEN` | Token de curta duração limitado ao escopo do papel do seu app | +| Variável | Descrição | +| ------------------------- | ------------------------------------------------------------- | +| `TWENTY_API_URL` | URL base da API principal da Twenty | +| `TWENTY_APP_ACCESS_TOKEN` | Token de curta duração limitado ao escopo do papel do seu app | + +### `TWENTY_FUNCTIONS_URL` + +A Twenty também injeta `TWENTY_FUNCTIONS_URL` em front components e funções de lógica: a URL base a partir da qual as funções de lógica acionadas por HTTP do seu aplicativo são servidas. + +Ela existe porque essa URL nem sempre é o próprio servidor da Twenty. No Twenty Cloud, as rotas do aplicativo são servidas em um domínio dedicado por workspace (`https://\.withtwenty.com`, ou o domínio público primário da aplicação quando um é configurado) para que respostas criadas pelo aplicativo sejam executadas em uma origem isolada, em vez de na origem do aplicativo Twenty. Instâncias self-hosted e locais servem rotas do aplicativo sob o prefixo `/s` no próprio servidor e podem não definir a variável. Como a URL base varia por workspace e por instância, seu código não pode defini-la de forma fixa — o servidor injeta o valor correto em tempo de execução. + +Você raramente precisa lê-la diretamente. Chame suas rotas por meio de `RestApiClient` com um caminho prefixado com `/s/` e o cliente resolverá a URL para você: ele remove o prefixo `/s` e direciona para `TWENTY_FUNCTIONS_URL`, recorrendo a `\/s` quando a variável não está definida. Use `resolveUrl('/s/\')` para obter a URL absoluta sem enviar uma requisição, por exemplo, para um link. Leia a variável diretamente apenas ao construir uma URL manualmente: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## API de comunicação do host diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx index 5dc1bed301..781b241223 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Tipos de gatilho disponíveis: -* **httpRoute**: expõe sua função em um caminho HTTP e método na **URL base do seu espaço de trabalho** — o valor de 20 injeções como `TWENTY_FUNCTIONS_URL` (em Vinte nuvens, um domínio dedicado por espaço de trabalho): -> por exemplo, `path: '/post-card/create'` é acessível em `https://your-workspace.withtwenty.com/post-card/create` - - -A rota de prefixo `/s/` do legado (`https://your-twenty-server.com/s/post-card/create`) está **obsoleta em 20 Cloud** e será desativada em **2026-07-24**. Persiste disponível para instâncias auto-hospedadas e locais que não configuram um domínio de funções isoladas — use `TWENTY_FUNCTIONS_URL` quando estiver definido, e cair de volta para `\/s/\` caso contrário. - +* **httpRoute**: Expõe sua função em um caminho e método HTTP. No código do app, prefixe o caminho da rota com `/s/` ao usar `RestApiClient`; a URL implantada usa a base injetada `TWENTY_FUNCTIONS_URL` (ou `\/s` quando ela não está definida). Para invocar uma função de lógica acionada por rota a partir de um componente de front-end (headless), consulte [Chamando uma função de lógica](/l/pt/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/logic/overview.mdx index 94842a0abb..cacdedbf33 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/logic/overview.mdx @@ -40,13 +40,13 @@ A **camada de lógica** de um app do Twenty é o código que *é executado* — Uma função de lógica escolhe um ou mais gatilhos — cada entrada abaixo é um campo separado em `defineLogicFunction()`: -| Disparador | Quando é executado | Configuração | -| ----------------------------- | --------------------------------------------------------- | ------------------------------- | -| **Rota HTTP** | Uma solicitação atinge a URL pública da sua função | `httpRouteTriggerSettings` | -| **Cron** | Uma expressão CRON corresponde | `cronTriggerSettings` | -| **Evento de banco de dados** | Um registro do workspace é criado, atualizado ou excluído | `databaseEventTriggerSettings` | -| **Ferramenta de IA** | Um recurso de IA do Twenty decide chamar sua função | `toolTriggerSettings` | -| **Ação de fluxo de trabalho** | Uma etapa de fluxo de trabalho invoca sua função | `workflowActionTriggerSettings` | +| Disparador | Quando é executado | Configuração | +| ----------------------------- | ----------------------------------------------------------------- | ------------------------------- | +| **Rota HTTP** | Uma solicitação atinge seu endpoint `/s/\` | `httpRouteTriggerSettings` | +| **Cron** | Uma expressão CRON corresponde | `cronTriggerSettings` | +| **Evento de banco de dados** | Um registro do workspace é criado, atualizado ou excluído | `databaseEventTriggerSettings` | +| **Ferramenta de IA** | Um recurso de IA do Twenty decide chamar sua função | `toolTriggerSettings` | +| **Ação de fluxo de trabalho** | Uma etapa de fluxo de trabalho invoca sua função | `workflowActionTriggerSettings` | As funções são executadas em sandbox, em processos Node.js isolados, e acessam o workspace por meio de um cliente de API tipado, com escopo definido pelo papel declarado em [`defineApplication()`](/l/pt/developers/extend/apps/config/application). diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index 39d2279065..41603cf6ad 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ via `CoreApiClient`, e POSTs até a rota do último capítulo ```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. diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/http-routes.mdx index f4eaefab57..496c2146af 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,10 @@ O mesmo manipulador também pode responder solicitações HTTP. Vamos adicionar * um terminal **POST** aponta as chamadas da UI para gerar um documento e * um endpoint de **GET** público que renderiza um documento como uma página web impressa. -Ambos usam `httpRouteTriggerSettings`. No servidor local de desenvolvimento, as rotas de aplicativos são -servidas sob o prefixo `/s` (por exemplo, `http://localhost:2020/s/documents/generate`). - - -Em Vinte nuvens, as rotas são servidas no domínio de funções dedicadas do espaço de trabalho -— a URL de 20 injeções como `TWENTY_FUNCTIONS_URL`, sem prefixo `/s`. O prefixo `/s` -está obsoleto e só permanece para instâncias auto-hospedadas e locais. -Ver [Chamando uma função lógica](/l/pt/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Ambos usam `httpRouteTriggerSettings`. As rotas do aplicativo são acessadas com um caminho `/s/`; em instâncias locais +e auto-hospedadas, esse caminho é servido pelo seu servidor Twenty +(por exemplo, `http://localhost:2020/s/documents/generate`). No Twenty Cloud, `RestApiClient` +resolve o caminho por meio do domínio de funções do espaço de trabalho. ## Rota POST - gerar sob demanda diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/layout/front-components.mdx index d896324999..437efad9a7 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Componentele de front rulează în browser, într-un Web Worker sandboxat în interiorul unui iframe cu origine opacă, în timp ce [funcțiile logice](/l/ro/developers/extend/apps/logic/logic-functions) rulează pe server. Nu există un apel direct în același proces între cele două — în schimb, o componentă de front apelează o funcție logică prin HTTP. -O funcție logică declarată cu `httpRouteTriggerSettings` este accesibilă prin HTTP la ruta sa. Twenty injectează în worker URL-ul de bază de la care sunt deservite funcțiile tale ca `TWENTY_FUNCTIONS_URL`, împreună cu `TWENTY_APP_ACCESS_TOKEN` care autentifică apelul. Nu există încă un client SDK dedicat pentru apelarea propriilor funcții, așa că apelează-le cu un simplu `fetch`: +O funcție logică declarată cu `httpRouteTriggerSettings` este accesibilă prin HTTP la ruta sa. `RestApiClient` tratează căile care încep cu `/s/` ca rute ale aplicației, le rezolvă către URL-ul de la care sunt deservite funcțiile tale și le autentifică folosind `TWENTY_APP_ACCESS_TOKEN`. -> **În Twenty Cloud, funcțiile logice declanșate prin HTTP sunt deservite pe un domeniu dedicat pentru fiecare spațiu de lucru** la `https://\.withtwenty.com\` — acesta este exact URL-ul la care indică `TWENTY_FUNCTIONS_URL`. Pentru apelanții externi, copiază URL-ul exact din setările **HTTP trigger** ale funcției sau din fila **Settings** a aplicației. - - - Ruta veche a funcției `/s/` este **depășită** și va fi **dezactivată la 2026-07-24**. Folosește în schimb `TWENTY_FUNCTIONS_URL` (mai sus) și migrează orice URL-uri `/s/` hard-codate înainte de acea dată. Ruta `/s/` rămâne disponibilă pentru self-hosting. - +> **În Twenty Cloud, funcțiile logice declanșate prin HTTP sunt deservite pe un domeniu dedicat pentru fiecare spațiu de lucru** la `https://\.withtwenty.com\`. Pentru apelanții externi, copiază URL-ul exact din setările **HTTP trigger** ale funcției sau din fila **Settings** a aplicației. O componentă de front headless poate efectua apelul la montare prin componenta `Command`, apoi se demontează automat: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -Calea adăugată la `TWENTY_FUNCTIONS_URL` este `httpRouteTriggerSettings.path` al funcției logice. Păstrează `isAuthRequired: true`; `TWENTY_APP_ACCESS_TOKEN` pe care Twenty îl generează pentru componenta ta autentifică cererea: +Calea transmisă către `RestApiClient` este proprietatea `httpRouteTriggerSettings.path` a funcției logice, cu prefixul `/s`. Păstrează `isAuthRequired: true`; `TWENTY_APP_ACCESS_TOKEN` pe care Twenty îl generează pentru componenta ta autentifică cererea: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` și `TWENTY_APP_ACCESS_TOKEN` sunt injectate automat — vezi [Application variables](#application-variables). Deoarece variabilele de aplicație secrete nu sunt niciodată expuse componentelor de front, păstrează cheile API și altă logică sensibilă în funcția logică, nu în componenta de front. +`TWENTY_APP_ACCESS_TOKEN` este injectat automat — vezi [Application variables](#application-variables). Deoarece variabilele de aplicație secrete nu sunt niciodată expuse componentelor de front, păstrează cheile API și altă logică sensibilă în funcția logică, nu în componenta de front. ### Apelarea API-ului REST Twenty -Pentru a citi sau scrie înregistrări Twenty dintr-un front component, folosește `RestApiClient` din `twenty-client-sdk/rest`. Face parte din aceeași familie de clienți ca `CoreApiClient` și `MetadataApiClient`, dar vizează Twenty REST API (`/rest/...`) în locul API-ului GraphQL, citindu-și URL-ul de bază din `TWENTY_API_URL`. +Pentru a apela rute HTTP ale aplicației sau pentru a citi și scrie înregistrări Twenty dintr-un front component, folosește `RestApiClient` din `twenty-client-sdk/rest`. Trimite căile de forma `/s/...` către URL-ul de bază al funcțiilor spațiului tău de lucru, iar orice altă cale, inclusiv `/rest/...`, către `TWENTY_API_URL`. -| Metodă | Descriere | -| --------------------------------- | ------------------------------------ | -| `get(path, options?)` | Trimite o cerere `GET` | -| `post(path, body?, options?)` | Trimite o cerere `POST` | -| `put(path, body?, options?)` | Trimite o cerere `PUT` | -| `patch(path, body?, options?)` | Trimite o cerere `PATCH` | -| `delete(path, options?)` | Trimite o cerere `DELETE` | -| `request(method, path, options?)` | Cerere generică cu orice metodă HTTP | +| Metodă | Descriere | +| --------------------------------- | ----------------------------------------------------------------------------- | +| `get(path, options?)` | Trimite o cerere `GET` | +| `post(path, body?, options?)` | Trimite o cerere `POST` | +| `put(path, body?, options?)` | Trimite o cerere `PUT` | +| `patch(path, body?, options?)` | Trimite o cerere `PATCH` | +| `delete(path, options?)` | Trimite o cerere `DELETE` | +| `request(method, path, options?)` | Cerere generică cu orice metodă HTTP | +| `resolveUrl(path, options?)` | Rezolvă o cale la URL-ul ei complet fără a trimite o cerere (pentru link-uri) | `options` acceptă `headers`, `query` (un „record” de parametri de query-string; valorile nule sau nedefinite sunt omise) și un `AbortSignal` prin `signal`. Un obiect `body` care nu este de tip `FormData` este serializat automat în JSON. La un `401`, clientul reîmprospătează o dată tokenul de acces prin gazdă și reîncearcă cererea. @@ -417,11 +411,22 @@ Variabilele secrete (`isSecret: true`) **nu** sunt expuse componentelor de inter Următoarele variabile de sistem sunt întotdeauna disponibile prin `process.env`: -| Variabilă | Descriere | -| ------------------------- | ------------------------------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | URL-ul de bază de la care sunt deservite funcțiile de logică HTTP ale aplicației tale | -| `TWENTY_API_URL` | URL-ul de bază al API-ului de bază Twenty | -| `TWENTY_APP_ACCESS_TOKEN` | Token cu durată scurtă, limitat la rolul aplicației dvs. | +| Variabilă | Descriere | +| ------------------------- | -------------------------------------------------------- | +| `TWENTY_API_URL` | URL-ul de bază al API-ului de bază Twenty | +| `TWENTY_APP_ACCESS_TOKEN` | Token cu durată scurtă, limitat la rolul aplicației dvs. | + +### `TWENTY_FUNCTIONS_URL` + +Twenty injectează, de asemenea, `TWENTY_FUNCTIONS_URL` în front components și în funcțiile logice: URL-ul de bază de la care sunt deservite funcțiile logice ale aplicației tale declanșate prin HTTP. + +Există deoarece acel URL nu este întotdeauna chiar serverul Twenty. În Twenty Cloud, rutele aplicației sunt deservite pe un domeniu dedicat pentru fiecare spațiu de lucru (`https://\.withtwenty.com` sau domeniul public principal al aplicației atunci când este configurat unul), astfel încât răspunsurile generate de aplicație să ruleze pe o origine izolată, nu pe originea aplicației Twenty. Instanțele self-hosted și locale deservesc rutele aplicației sub prefixul `/s` chiar pe server și este posibil să nu seteze deloc variabila. Deoarece URL-ul de bază variază în funcție de spațiul de lucru și de instanță, codul tău nu îl poate hardcoda — serverul injectează valoarea corectă la runtime. + +Rareori ai nevoie să o citești direct. Apelează-ți rutele prin `RestApiClient` folosind o cale prefixată cu `/s/`, iar clientul îți rezolvă URL-ul: elimină prefixul `/s` și țintește `TWENTY_FUNCTIONS_URL`, folosind `\/s` ca rezervă atunci când variabila nu este setată. Folosește `resolveUrl('/s/\')` pentru a obține URL-ul absolut fără a trimite o cerere, de exemplu pentru un link. Citește variabila direct doar atunci când construiești manual un URL: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## API-ul de comunicare cu gazda diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx index 7284b4e3c8..ae1cb0725d 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Tipuri de declanșatoare disponibile: -* **httpRoute**: Expune funcţia pe o cale HTTP şi pe o metodă în **funcţiunea URL-ul bazei de lucru** - valoarea de douăzeci de injectări ca `TWENTY_FUNCTIONS_URL` (pe douăzeci Cloud, un domeniu specializat pentru spațiul de lucru): -> de ex. `path: '/post-card/create'` poate fi apelat la `https://your-workspace.withtwenty.com/post-card/create` - - -Prefixul moștenirii `/s/` (`https://your-twenty-server.com/s/post-card/create`) este **învechit pe 20 de Cloud** și va fi dezactivat pe **2026-07-24**. Rămâne disponibil pentru instanțe auto-găzduite și locale care nu configurează un domeniu de funcții izolate - utilizați `TWENTY_FUNCTIONS_URL` când este setat, şi întoarceţi-vă la `\/s/\` altfel. - +* **httpRoute**: Expune funcția pe o cale și o metodă HTTP. În codul aplicației, prefixează calea rutei cu `/s/` când folosești `RestApiClient`; URL-ul implementat folosește baza injectată `TWENTY_FUNCTIONS_URL` (sau `\/s` atunci când nu este setată). Pentru a apela o funcție logică declanșată de o rută dintr-o componentă front-end (headless), consultă [Apelarea unei funcții logice](/l/ro/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/logic/overview.mdx index 0f2707527f..a02b7c1889 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/logic/overview.mdx @@ -42,7 +42,7 @@ O funcție de logică alege unul sau mai multe declanșatoare — fiecare intrar | Declanșator | Când rulează | Setare | | ----------------------------- | ----------------------------------------------------------------- | ------------------------------- | -| **Rută HTTP** | O solicitare accesează URL-ul public al funcției tale | `httpRouteTriggerSettings` | +| **Rută HTTP** | O cerere ajunge la endpointul tău `/s/\` | `httpRouteTriggerSettings` | | **Cron** | O expresie CRON se potrivește | `cronTriggerSettings` | | **Eveniment de bază de date** | O înregistrare din workspace este creată, actualizată sau ștearsă | `databaseEventTriggerSettings` | | **Instrument IA** | O funcționalitate IA din Twenty decide să apeleze funcția ta | `toolTriggerSettings` | diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index 0288f56f37..530e7ad6d5 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -69,6 +69,7 @@ prin `CoreApiClient`, şi POST-uri pe ruta de la ultimul capitol ```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 @@ hel. ```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. diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 3c136850c3..e6e102a389 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,15 +9,10 @@ Același gestionar poate răspunde și la solicitările HTTP. Vom adăuga două * a **POST** final apeluri interfață pentru a genera un document, și * un obiectiv public **GET** care face un document ca o pagină web printabilă. -Ambele folosesc `httpRouteTriggerSettings`. Pe server-ul local dev, rutele aplicației sunt servite -sub prefixul `/s` (ex. `http://localhost:2020/s/documents/generate`). - - -În 22 de Cloud, rutele sunt servite pe domeniul funcțiilor dedicate din spațiul de lucru -— URL-ul Douăzeci injectează ca `TWENTY_FUNCTIONS_URL`, fără prefixul `/s`. Prefixul -este învechit acolo şi rămâne doar pentru instanţele auto-găzduite şi locale. -Vedeți [Apelarea unei funcții logice](/l/ro/developers/extend/apps/layout/front-components#calling-a-logic-function). - +Ambele folosesc `httpRouteTriggerSettings`. Rutele aplicației sunt accesate prin calea `/s/`; pe instanțele locale +și auto-găzduite, această cale este servită de serverul tău Twenty +(de ex. `http://localhost:2020/s/documents/generate`). Pe Twenty Cloud, `RestApiClient` +rezolvă calea prin domeniul de funcții al spațiului de lucru. ## Ruta POST – generarea la cerere diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/layout/front-components.mdx index 872d8b6c03..4baa83637f 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ Ön bileşenler, tarayıcı tarafında, opak kaynaklı bir iframe içinde yer alan korumalı (sandbox) bir Web Worker içinde çalışırken, [mantık işlevleri](/l/tr/developers/extend/apps/logic/logic-functions) sunucu tarafında çalışır. İkisi arasında doğrudan, işlem içi bir çağrı yoktur — bunun yerine, bir ön bileşen bir mantık işlevine HTTP üzerinden erişir. -`httpRouteTriggerSettings` ile bildirilen bir mantık işlevi, rota yolunda HTTP üzerinden erişilebilir durumdadır. Twenty, işlevlerinizin sunulduğu temel URL’yi, çağrıyı kimlik doğrulayan `TWENTY_APP_ACCESS_TOKEN` ile birlikte, worker’a `TWENTY_FUNCTIONS_URL` olarak enjekte eder. Kendi işlevlerinizi çağırmak için henüz özel bir SDK istemcisi yoktur, bu yüzden onları basit bir `fetch` ile çağırın: +`httpRouteTriggerSettings` ile bildirilen bir mantık işlevi, rota yolunda HTTP üzerinden erişilebilir durumdadır. `RestApiClient`, `/s/` ile başlayan yolları uygulama rotaları olarak ele alır, bunları fonksiyonlarınızın sunulduğu URL'ye çözümler ve `TWENTY_APP_ACCESS_TOKEN` ile kimlik doğrulaması yapar. -> **Twenty Cloud üzerinde, HTTP ile tetiklenen mantık işlevleri, çalışma alanı başına ayrılmış özel bir etki alanında** `https://\.withtwenty.com\` adresinde sunulur — bu, `TWENTY_FUNCTIONS_URL`'ün tam olarak çözümlendiği değerdir. Harici çağrıcılar için, tam URL’yi işlevin **HTTP trigger** ayarlarından veya uygulamanın **Settings** sekmesinden kopyalayın. - - - Eski `/s/` fonksiyon rotası **kullanımdan kaldırılmıştır (deprecated)** ve **2026-07-24 tarihinde devre dışı bırakılacaktır**. Bunun yerine yukarıdaki `TWENTY_FUNCTIONS_URL` değerini kullanın ve o tarihten önce sabit (hard-coded) tüm `/s/` URL’lerini taşıyın. `/s/` rotası, self-hosting için kullanılabilir olmaya devam eder. - +> **Twenty Cloud üzerinde, HTTP ile tetiklenen mantık işlevleri, çalışma alanı başına ayrılmış özel bir etki alanında** `https://\.withtwenty.com\` adresinde sunulur. Harici çağrıcılar için, tam URL’yi işlevin **HTTP trigger** ayarlarından veya uygulamanın **Settings** sekmesinden kopyalayın. Başsız bir ön bileşen, çağrıyı `Command` bileşeni aracılığıyla mount sırasında çalıştırabilir ve ardından otomatik olarak unmount olabilir: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -`TWENTY_FUNCTIONS_URL` değerine eklenen yol (path), mantık fonksiyonunun `httpRouteTriggerSettings.path` değeridir. `isAuthRequired: true` ayarını koruyun; bileşeniniz için Twenty'nin oluşturduğu `TWENTY_APP_ACCESS_TOKEN` isteği kimlik doğrular: +`RestApiClient`'e iletilen yol, başına `/s` eklenmiş mantık işlevinin `httpRouteTriggerSettings.path` değeridir. `isAuthRequired: true` ayarını koruyun; bileşeniniz için Twenty'nin oluşturduğu `TWENTY_APP_ACCESS_TOKEN` isteği kimlik doğrular: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` ve `TWENTY_APP_ACCESS_TOKEN` otomatik olarak enjekte edilir — bkz. [Uygulama değişkenleri](#application-variables). Gizli uygulama değişkenleri asla ön bileşenlere açığa çıkarılmadığından, API anahtarlarını ve diğer hassas mantığı ön bileşende değil, mantık işlevinin içinde tutun. +`TWENTY_APP_ACCESS_TOKEN` otomatik olarak enjekte edilir — bkz. [Uygulama değişkenleri](#application-variables). Gizli uygulama değişkenleri asla ön bileşenlere açığa çıkarılmadığından, API anahtarlarını ve diğer hassas mantığı ön bileşende değil, mantık işlevinin içinde tutun. ### Twenty REST API'sini çağırma -Bir front bileşeninden Twenty kayıtlarını okumak veya yazmak için, `twenty-client-sdk/rest` paketinden `RestApiClient` kullanın. `CoreApiClient` ve `MetadataApiClient` ile aynı istemci ailesine aittir, ancak GraphQL API yerine Twenty REST API'sini (`/rest/...`) hedefler ve temel URL'sini `TWENTY_API_URL` değerinden okur. +Uygulama HTTP rotalarını çağırmak veya bir front bileşeninden Twenty kayıtlarını okumak ve yazmak için `twenty-client-sdk/rest` paketinden `RestApiClient` kullanın. `/s/...` yollarını çalışma alanınızdaki işlevlerin temel URL'sine, `/rest/...` dahil diğer tüm yolları ise `TWENTY_API_URL`'ye gönderir. -| Yöntem | Açıklama | -| --------------------------------- | ---------------------------------------- | -| `get(path, options?)` | Bir `GET` isteği gönderir | -| `post(path, body?, options?)` | Bir `POST` isteği gönderir | -| `put(path, body?, options?)` | Bir `PUT` isteği gönderir | -| `patch(path, body?, options?)` | Bir `PATCH` isteği gönderir | -| `delete(path, options?)` | Bir `DELETE` isteği gönderir | -| `request(method, path, options?)` | Herhangi bir HTTP yöntemiyle genel istek | +| Yöntem | Açıklama | +| --------------------------------- | ------------------------------------------------------------------------ | +| `get(path, options?)` | Bir `GET` isteği gönderir | +| `post(path, body?, options?)` | Bir `POST` isteği gönderir | +| `put(path, body?, options?)` | Bir `PUT` isteği gönderir | +| `patch(path, body?, options?)` | Bir `PATCH` isteği gönderir | +| `delete(path, options?)` | Bir `DELETE` isteği gönderir | +| `request(method, path, options?)` | Herhangi bir HTTP yöntemiyle genel istek | +| `resolveUrl(path, options?)` | Bir istekte bulunmadan (bağlantılar için) bir yolu tam URL'sine çözümler | `options`, `headers`, `query` (sorgu dizesi parametrelerinin kaydı; null benzeri değerler atlanır) ve `signal` aracılığıyla bir `AbortSignal` kabul eder. `FormData` olmayan bir `body` nesnesi otomatik olarak JSON’a serileştirilir. `401` durumunda, istemci erişim jetonunu bir kez ana makine (host) üzerinden yeniler ve isteği yeniden dener. @@ -417,11 +411,22 @@ Gizli değişkenler (`isSecret: true`) ön uç bileşenlere açıklanmaz. Bunlar Aşağıdaki sistem değişkenleri her zaman `process.env` aracılığıyla kullanılabilir: -| Değişken | Açıklama | -| ------------------------- | -------------------------------------------------------------- | -| `TWENTY_FUNCTIONS_URL` | Uygulamanızın HTTP mantık fonksiyonlarının sunulduğu temel URL | -| `TWENTY_API_URL` | Twenty çekirdek API'sinin temel URL'si | -| `TWENTY_APP_ACCESS_TOKEN` | Uygulamanızın rolüyle sınırlanan kısa ömürlü bir belirteç | +| Değişken | Açıklama | +| ------------------------- | --------------------------------------------------------- | +| `TWENTY_API_URL` | Twenty çekirdek API'sinin temel URL'si | +| `TWENTY_APP_ACCESS_TOKEN` | Uygulamanızın rolüyle sınırlanan kısa ömürlü bir belirteç | + +### `TWENTY_FUNCTIONS_URL` + +Twenty ayrıca `TWENTY_FUNCTIONS_URL` değişkenini front bileşenlerine ve mantık işlevlerine enjekte eder: bu, uygulamanızın HTTP ile tetiklenen mantık işlevlerinin sunulduğu temel URL'dir. + +Bu değişken, bu URL her zaman Twenty sunucusunun kendisi olmadığı için mevcuttur. Twenty Cloud üzerinde, uygulama rotaları, uygulama tarafından yazılmış yanıtların Twenty uygulamasının kaynağı yerine yalıtılmış bir kaynak üzerinde çalışması için, çalışma alanı başına ayrılmış özel bir etki alanında (`https://\.withtwenty.com` veya yapılandırıldığında uygulamanın birincil genel etki alanında) sunulur. Self-hosted ve yerel örnekler, uygulama rotalarını sunucunun kendisinde `/s` öneki altında sunar ve değişkeni hiç ayarlamayabilir. Temel URL, çalışma alanına ve örneğe göre değiştiğinden, kodunuz bunu sabit olarak yazamaz — sunucu, çalışma zamanında doğru değeri enjekte eder. + +Bu değişkeni doğrudan okumanız nadiren gerekir. Rotalarınızı, yolu `/s/` önekiyle birlikte vererek `RestApiClient` üzerinden çağırın; istemci URL'yi sizin için çözümler: `/s` önekini kaldırır ve `TWENTY_FUNCTIONS_URL`'yi hedefler, değişken ayarlı değilse `\/s` adresine geri döner. Mutlak URL'yi bir istek göndermeden elde etmek için, örneğin bir bağlantı için, `resolveUrl('/s/\')` kullanın. Değişkeni yalnızca bir URL'yi elle oluştururken doğrudan okuyun: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## Host iletişim API'si diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx index 42d406ce38..7de88bfcb3 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` Kullanılabilir tetikleyici türleri: -* **httpRoute**: İşlevinizi, çalışma alanınızın **işlevler için temel URL'sinde** bir HTTP yolu ve yöntemi üzerinden kullanıma açar — Twenty'nin `TWENTY_FUNCTIONS_URL` olarak sağladığı değer (Twenty Cloud'da, her çalışma alanına ayrılmış özel bir alan adı): -> örn. `path: '/post-card/create'` `https://your-workspace.withtwenty.com/post-card/create` adresinden çağrılabilir - - -Eski `/s/` önekli rota (`https://your-twenty-server.com/s/post-card/create`) **Twenty Cloud'da kullanımdan kaldırılmıştır** ve **2026-07-24** tarihinde devre dışı bırakılacaktır. Yalıtılmış bir işlevler alan adı yapılandırmayan kendi barındırmalı ve yerel örnekler için kullanılabilir olmaya devam eder — ayarlanmışsa `TWENTY_FUNCTIONS_URL` değerini kullanın, aksi takdirde `\/s/\` rotasına geri dönün. - +* **httpRoute**: İşlevinizi bir HTTP yolu ve yöntemiyle kullanıma sunar. Uygulama kodunda, `RestApiClient` kullanırken rota yolunun başına `/s/` önekini ekleyin; dağıtılan URL, enjekte edilen `TWENTY_FUNCTIONS_URL` temel URL'sini (veya bu ayarlı değilse `\/s`) kullanır. Arayüzsüz bir ön uç bileşeninden rota tarafından tetiklenen mantık fonksiyonunu çağırmak için bkz. [Mantık fonksiyonu çağırma](/l/tr/developers/extend/apps/layout/front-components#calling-a-logic-function). diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/logic/overview.mdx index 7e613a4227..04d855b7c0 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/logic/overview.mdx @@ -42,7 +42,7 @@ Bir mantık fonksiyonu bir veya daha fazla tetikleyici seçer — aşağıdaki h | Tetikleyici | Ne zaman çalışır | Ayar | | --------------------- | ---------------------------------------------------------------------------- | ------------------------------- | -| **HTTP rotası** | Bir istek, işlevinizin herkese açık URL'sine ulaşır | `httpRouteTriggerSettings` | +| **HTTP rotası** | Bir istek `/s/\` endpoint'inize ulaşır | `httpRouteTriggerSettings` | | **Cron** | Bir CRON ifadesi eşleştiğinde | `cronTriggerSettings` | | **Veritabanı olayı** | Bir çalışma alanı kaydı oluşturulduğunda, güncellendiğinde veya silindiğinde | `databaseEventTriggerSettings` | | **Yapay zeka aracı** | Bir Twenty yapay zeka özelliği, fonksiyonunuzu çağırmaya karar verdiğinde | `toolTriggerSettings` | diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index 5b79143243..cf6b8e445c 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -63,6 +63,7 @@ Bir [ön uç bileşeni](/l/tr/developers/extend/apps/layout/front-components), T ```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'; @@ -85,15 +86,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', @@ -162,6 +158,7 @@ Bileşen, çalışma bağlamından geçerli kayıt kimliğini okur, belgeyi yük ```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'; @@ -170,9 +167,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. diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 48d487fb0b..91352f155f 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,12 +9,10 @@ Aynı işleyici HTTP isteklerine de yanıt verebilir. İki rota ekleyeceğiz: * belge oluşturmak için arayüzün çağırdığı bir **POST** uç noktası ve * belgeyi yazdırılabilir bir web sayfası olarak oluşturan herkese açık bir **GET** uç noktası. -Her ikisi de `httpRouteTriggerSettings` kullanır. Yerel geliştirme sunucusunda, uygulama yönlendirmeleri `/s` öneki altında sunulur (örneğin, `http://localhost:2020/s/documents/generate`). - - -Twenty Cloud üzerinde yönlendirmeler, çalışma alanına ayrılmış fonksiyon alan adında sunulur — Twenty'nin `/s` öneki olmadan `TWENTY_FUNCTIONS_URL` olarak eklediği URL'de. `/s` öneki orada kullanım dışıdır ve yalnızca kendi barındırılan ve yerel örneklerde kalmıştır. -[Mantık fonksiyonunu çağırma](/l/tr/developers/extend/apps/layout/front-components#calling-a-logic-function) bölümüne bakın. - +Her ikisi de `httpRouteTriggerSettings` kullanır. Uygulama rotalarına `/s/` yolu ile erişilir; yerel +ve kendi sunucunuzda barındırılan örneklerde, bu yol Twenty sunucunuz +tarafından sunulur (örneğin `http://localhost:2020/s/documents/generate`). Twenty Cloud'da, `RestApiClient` +bu yolu çalışma alanının functions alan adı üzerinden çözümler. ## POST rotası — istek üzerine oluşturma diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/layout/front-components.mdx index 5b8f2c3ae3..832eff9525 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/layout/front-components.mdx @@ -236,29 +236,22 @@ export default defineFrontComponent({ 前端组件在浏览器端的 Web Worker 中运行,该 Web Worker 被沙盒化在不透明来源的 iframe 中,而[逻辑函数](/l/zh/developers/extend/apps/logic/logic-functions)在服务器端运行。 二者之间没有直接的进程内调用——前端组件通过 HTTP 访问逻辑函数。 -使用 `httpRouteTriggerSettings` 声明的逻辑函数,可以通过其路由路径在 HTTP 上进行访问。 Twenty 会将提供你函数服务的基础 URL 作为 `TWENTY_FUNCTIONS_URL` 注入到 worker 中,同时注入用于对调用进行身份验证的 `TWENTY_APP_ACCESS_TOKEN`。 目前还没有用于调用你自定义函数的专用 SDK 客户端,因此请使用普通的 `fetch` 来调用它们: +使用 `httpRouteTriggerSettings` 声明的逻辑函数,可以通过其路由路径在 HTTP 上进行访问。 `RestApiClient` 会将以 `/s/` 开头的路径视为应用路由,将其解析到你的函数提供服务的 URL,并使用 `TWENTY_APP_ACCESS_TOKEN` 对其进行认证。 -> **在 Twenty Cloud 上,HTTP 触发的逻辑函数通过每个工作区的专用域名提供服务**,域名为 `https://\.withtwenty.com\`——这正是 `TWENTY_FUNCTIONS_URL` 所解析到的地址。 对于外部调用方,请从函数的 **HTTP trigger** 设置或应用的 **Settings** 选项卡中复制准确的 URL。 - - - 旧版的 `/s/` 函数路由已被**弃用**,并将于 **2026-07-24 停用**。 请改用上面的 `TWENTY_FUNCTIONS_URL`,并在该日期之前迁移所有硬编码的 `/s/` URL。 `/s/` 路由在自托管场景下仍可用。 - +> **在 Twenty Cloud 上,HTTP 触发的逻辑函数通过每个工作区的专用域名提供服务**,域名为 `https://\.withtwenty.com\`。 对于外部调用方,请从函数的 **HTTP trigger** 设置或应用的 **Settings** 选项卡中复制准确的 URL。 无头前端组件可以通过 `Command` 组件在挂载时执行调用,然后自动卸载: ```tsx src/front-components/sync-prs.tsx +import { RestApiClient } from 'twenty-client-sdk/rest'; import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/front-component'; const SyncPrs = () => { const execute = async () => { - await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, { - method: 'POST', - headers: { - Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }), + await new RestApiClient().post('/s/github/fetch-prs', { + owner: 'twentyhq', + repo: 'twenty', }); }; @@ -274,7 +267,7 @@ export default defineFrontComponent({ }); ``` -附加到 `TWENTY_FUNCTIONS_URL` 的路径是逻辑函数的 `httpRouteTriggerSettings.path`。 保持 `isAuthRequired: true`;Twenty 为你的组件生成的 `TWENTY_APP_ACCESS_TOKEN` 会对请求进行认证: +传递给 `RestApiClient` 的路径是逻辑函数的 `httpRouteTriggerSettings.path`,并以 `/s` 作为前缀。 保持 `isAuthRequired: true`;Twenty 为你的组件生成的 `TWENTY_APP_ACCESS_TOKEN` 会对请求进行认证: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -299,21 +292,22 @@ export default defineLogicFunction({ ``` -`TWENTY_FUNCTIONS_URL` 和 `TWENTY_APP_ACCESS_TOKEN` 会被自动注入——参见 [应用变量](#application-variables)。 由于机密应用变量永远不会暴露给前端组件,请将 API 密钥和其他敏感逻辑保留在逻辑函数中,而不是前端组件中。 +`TWENTY_APP_ACCESS_TOKEN` 会被自动注入——参见 [应用变量](#application-variables)。 由于机密应用变量永远不会暴露给前端组件,请将 API 密钥和其他敏感逻辑保留在逻辑函数中,而不是前端组件中。 ### 调用 Twenty REST API -要在前端组件中读取或写入 Twenty 记录,请使用来自 `twenty-client-sdk/rest` 的 `RestApiClient`。 它与 `CoreApiClient` 和 `MetadataApiClient` 属于同一客户端家族,但目标是 Twenty REST API(`/rest/...`),而不是 GraphQL API,其基础 URL 来自 `TWENTY_API_URL`。 +要在前端组件中调用应用 HTTP 路由或读取、写入 Twenty 记录,请使用来自 `twenty-client-sdk/rest` 的 `RestApiClient`。 它会将 `/s/...` 路径发送到你工作区的函数基础 URL,而将包括 `/rest/...` 在内的其他所有路径发送到 `TWENTY_API_URL`。 -| 方法 | 描述 | -| --------------------------------- | ----------------- | -| `get(path, options?)` | 发送一个 `GET` 请求 | -| `post(path, body?, options?)` | 发送一个 `POST` 请求 | -| `put(path, body?, options?)` | 发送一个 `PUT` 请求 | -| `patch(path, body?, options?)` | 发送一个 `PATCH` 请求 | -| `delete(path, options?)` | 发送一个 `DELETE` 请求 | -| `request(method, path, options?)` | 使用任意 HTTP 方法的通用请求 | +| 方法 | 描述 | +| --------------------------------- | ----------------------------- | +| `get(path, options?)` | 发送一个 `GET` 请求 | +| `post(path, body?, options?)` | 发送一个 `POST` 请求 | +| `put(path, body?, options?)` | 发送一个 `PUT` 请求 | +| `patch(path, body?, options?)` | 发送一个 `PATCH` 请求 | +| `delete(path, options?)` | 发送一个 `DELETE` 请求 | +| `request(method, path, options?)` | 使用任意 HTTP 方法的通用请求 | +| `resolveUrl(path, options?)` | 在不发送请求的情况下将路径解析为其完整 URL(用于链接) | `options` 接受 `headers`、`query`(查询字符串参数记录;空值会被跳过),以及通过 `signal` 传入的 `AbortSignal`。 非 `FormData` 类型的对象 `body` 会被自动进行 JSON 序列化。 在收到 `401` 时,客户端会通过宿主刷新一次访问令牌,然后重试该请求。 @@ -417,11 +411,22 @@ export default defineFrontComponent({ 以下系统变量始终可以通过 `process.env` 获取: -| 变量 | 描述 | -| ------------------------- | ---------------------- | -| `TWENTY_FUNCTIONS_URL` | 提供你应用 HTTP 逻辑函数的基础 URL | -| `TWENTY_API_URL` | Twenty 核心 API 的基础 URL | -| `TWENTY_APP_ACCESS_TOKEN` | 限定在你的应用角色范围内的短期令牌 | +| 变量 | 描述 | +| ------------------------- | --------------------- | +| `TWENTY_API_URL` | Twenty 核心 API 的基础 URL | +| `TWENTY_APP_ACCESS_TOKEN` | 限定在你的应用角色范围内的短期令牌 | + +### `TWENTY_FUNCTIONS_URL` + +Twenty 还会将 `TWENTY_FUNCTIONS_URL` 注入到前端组件和逻辑函数中:也就是你的应用的 HTTP 触发逻辑函数所提供服务的基础 URL。 + +之所以存在这个变量,是因为该 URL 并不总是 Twenty 服务器本身。 在 Twenty Cloud 上,应用路由通过每个工作区的专用域名提供服务(`https://\.withtwenty.com`,或者在已配置时为应用的主公共域名),以便应用生成的响应运行在一个与 Twenty 应用源不同的隔离源上。 自托管和本地实例会在服务器本身的 `/s` 前缀下提供应用路由,并且可能完全不会设置该变量。 由于基础 URL 会因工作区和实例而异,你的代码不能将其硬编码——服务器会在运行时注入正确的值。 + +你很少需要直接读取它。 通过 `RestApiClient` 使用带有 `/s/` 前缀的路径来调用你的路由,客户端会为你解析 URL:它会去掉 `/s` 前缀并将请求发往 `TWENTY_FUNCTIONS_URL`,在该变量未设置时则回退到 `\/s`。 使用 `resolveUrl('/s/\')` 来在不发送请求的情况下获取绝对 URL,例如用于链接。 仅在手动构建 URL 时才直接读取该变量: + +```ts +const routeUrl = `${process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`}/documents/generate`; +``` ## 宿主通信 API diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx index 309a967904..b7eb35c700 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx @@ -51,12 +51,7 @@ export default defineLogicFunction({ ``` 可用的触发器类型: -* **httpRoute**:在你工作区的 HTTP 路径和方法上显示你的函数。**函数基础的 URL** ——`TWENTY_FUNCTIONS_URL` (在20个云上) a 专用工作区: -> 例如 `path: '/post-card/create'` 可在 `https://your-workspace.withtwenty.com/post-card/create` 调用 - - -旧的 `/s/` 前缀路由 (`https://your-twentserver.com/s/post-card/create`) **在 20 Cloud** 上被废弃,并将在 **2026-07-24**被停用。 它仍可用于不配置一个孤立函数域的自托管和本地实例——在设置时使用 `TWENTY_FUNCTIONS_URL` 。 然后回到\/s/\。 - +* **httpRoute**:通过 HTTP 路径和方法公开你的函数。 在应用代码中,使用 `RestApiClient` 时,在路由路径前加上 `/s/` 前缀;已部署的 URL 使用注入的 `TWENTY_FUNCTIONS_URL` 基础地址(如果未设置,则使用 `\/s`)。 要从(无头)前端组件调用由路由触发的逻辑函数,请参见[调用逻辑函数](/l/zh/developers/extend/apps/layout/front-components#calling-a-logic-function)。 diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/logic/overview.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/logic/overview.mdx index 7426812d3b..6148bc6292 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/logic/overview.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/logic/overview.mdx @@ -40,13 +40,13 @@ Twenty 应用的 **逻辑层** 是实际*运行*的代码——用于响应 HTTP 逻辑函数选择一个或多个触发器——下面的每一项都是 `defineLogicFunction()` 上的一个独立字段: -| 触发器 | 触发时机 | 设置 | -| ----------- | ------------------------ | ------------------------------- | -| **HTTP 路由** | 一个请求点击你的公開的 URL | `httpRouteTriggerSettings` | -| **Cron** | 匹配到一个 CRON 表达式时 | `cronTriggerSettings` | -| **数据库事件** | 当工作区记录被创建、更新或删除时 | `databaseEventTriggerSettings` | -| **AI 工具** | 某个 Twenty AI 功能决定调用你的函数时 | `toolTriggerSettings` | -| **工作流动作** | 当工作流步骤调用你的函数时 | `workflowActionTriggerSettings` | +| 触发器 | 触发时机 | 设置 | +| ----------- | --------------------------------------- | ------------------------------- | +| **HTTP 路由** | 请求命中你的 `/s/\` 端点 | `httpRouteTriggerSettings` | +| **Cron** | 匹配到一个 CRON 表达式时 | `cronTriggerSettings` | +| **数据库事件** | 当工作区记录被创建、更新或删除时 | `databaseEventTriggerSettings` | +| **AI 工具** | 某个 Twenty AI 功能决定调用你的函数时 | `toolTriggerSettings` | +| **工作流动作** | 当工作流步骤调用你的函数时 | `workflowActionTriggerSettings` | 函数在隔离的 Node.js 进程沙箱中运行,并通过限定在 [`defineApplication()`](/l/zh/developers/extend/apps/config/application) 上声明角色范围内的类型化 API 客户端访问工作区。 diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx index c68b2c1614..8330313238 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/building-the-ui.mdx @@ -65,6 +65,7 @@ export default defineNavigationMenuItem({ ```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'; @@ -87,15 +88,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', @@ -170,6 +166,7 @@ Markdown 物体作为一个可打印的打印页面。 ```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'; @@ -178,9 +175,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. diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/http-routes.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/http-routes.mdx index 3d740b6248..be8a9adffc 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/http-routes.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/tutorials/document-generator/http-routes.mdx @@ -9,12 +9,7 @@ description: 通过 HTTP 触发函数并将文档渲染为 web 页面。 * a **POST** 让UI 调用来生成文档的端点,和 * 一个公开的 **GET** 端点,将文档作为可打印的网页。 -两者都使用 `httpRouteTriggerSettings` 。 在本地开发服务器上,应用路由在带有 `/s` 前缀的路径下提供服务(例如 `http://localhost:2020/s/documents/generate`)。 - - -在 Twenty Cloud 上,路由通过工作区专用的函数域名提供服务——即 Twenty 注入的、作为 `TWENTY_FUNCTIONS_URL` 的 URL,且没有 `/s` 前缀。 在那里,`/s` 前缀已被弃用,仅保留用于自托管和本地实例。 -参见[调用逻辑函数](/l/zh/developers/extend/apps/layout/front-components#calling-a-logic-function)。 - +两者都使用 `httpRouteTriggerSettings` 。 应用路由使用 `/s/` 路径;在本地和自托管实例上,该路径由你的 Twenty 服务器提供服务(例如:`http://localhost:2020/s/documents/generate`)。 在 Twenty Cloud 上,`RestApiClient` 通过工作区的 functions 域名来解析该路径。 ## POST 路由 — 按需生成