i18n - docs translations (#22715)
Created by Github action <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22715?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
committed by
GitHub
parent
a0cf4cc9e1
commit
ebee7d71b9
@@ -4,9 +4,9 @@ description: Spouštějte logiku před instalací nebo po ní — naplňte data,
|
||||
icon: wrench
|
||||
---
|
||||
|
||||
Instalační hooky jsou speciální logické funkce, které se spouštějí během životního cyklu instalace nebo upgradu. Sdílí stejný runtime handleru jako běžné [logické funkce](/l/cs/developers/extend/apps/logic/logic-functions) a přijímají `InstallPayload`, ale deklarují se pomocí vlastních definičních funkcí — `definePostInstallLogicFunction()` a `definePreInstallLogicFunction()` — a fungují mimo běžný model triggerů (HTTP, cron, databázové události).
|
||||
Instalační hooky jsou speciální logické funkce, které se spouštějí během životního cyklu instalace nebo upgradu. Sdílí stejný runtime handleru jako běžné [logické funkce](/l/cs/developers/extend/apps/logic/logic-functions) a přijímají `InstallPayload` (`{ previousVersion?: string; newVersion: string }` — `previousVersion` je při čisté instalaci `undefined`), ale deklarují se pomocí vlastních definičních funkcí a fungují mimo běžný model triggerů (HTTP, cron, databázové události).
|
||||
|
||||
Každá aplikace může definovat **nanejvýš jednu pre-install** a **nanejvýš jednu post-install** funkci. Sestavení manifestu skončí chybou, pokud je zjištěno více než jedno.
|
||||
Každá aplikace může definovat **nanejvýš jednu pre-install** a **nanejvýš jednu post-install** funkci. Sestavení manifestu skončí chybou, pokud je zjištěno více než jedno z nich.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
@@ -19,111 +19,59 @@ Každá aplikace může definovat **nanejvýš jednu pre-install** a **nanejvý
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="definePostInstallLogicFunction" description="Spouští se po aplikování migrace metadat pracovního prostoru">
|
||||
## Na první pohled
|
||||
|
||||
Postinstalační funkce se spustí automaticky, jakmile je instalace vaší aplikace v pracovním prostoru dokončena. Server ji provede **poté**, co byla synchronizována metadata aplikace a vygenerován klient SDK, takže je pracovní prostor plně připraven k použití a nové schéma je zavedeno. Mezi typické případy použití patří naplnění výchozími daty, vytvoření počátečních záznamů, konfigurace nastavení pracovního prostoru nebo zřizování prostředků ve službách třetích stran.
|
||||
| | `definePreInstallLogicFunction` | `definePostInstallLogicFunction` |
|
||||
| --------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Běhy | Před migrací metadat — **předchozí** schéma a data jsou stále neporušené | Po migraci a vygenerování SDK — **nové** schéma je připravené |
|
||||
| Spuštění | Vždy synchronní; blokuje instalaci | Ve výchozím nastavení asynchronní (zařazeno do fronty, 3 pokusy); synchronní režim volitelný přes `shouldRunSynchronously: true` |
|
||||
| Při selhání | Instalace je **zrušena** před jakoukoli změnou schématu | Async: opakovaný pokus až 3krát. Sync: volající obdrží `POST_INSTALL_ERROR` (změny schématu se **ne**vracejí zpět) |
|
||||
| Typické použití | Zálohovat nebo opravit data, která by migrace ztratila; odmítnout rizikovou aktualizaci vyvoláním výjimky | Naplňte výchozí data, nakonfigurujte pracovní prostor, zaregistrujte externí prostředky |
|
||||
|
||||
```ts src/logic-functions/post-install.ts
|
||||
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
**Pravidlo:** výchozí volbou je post-install. Po pre-install sáhněte pouze tehdy, když je samotná migrace destruktivní a potřebujete zachytit předchozí stav, než zmizí.
|
||||
|
||||
const handler = async (payload: InstallPayload): Promise<void> => {
|
||||
console.log('Post install logic function executed successfully!', payload.previousVersion);
|
||||
};
|
||||
| Chcete... | Použít |
|
||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| Naplňte data, nakonfigurujte pracovní prostor, zaregistrujte externí prostředky | `post-install` |
|
||||
| Dlouho běžící práce, která by neměla blokovat odpověď instalace | `post-install` (výchozí asynchronní režim, s opakovanými pokusy workeru) |
|
||||
| Rychlé nastavení, na které volající spoléhá ihned po dokončení instalace | `post-install` s `shouldRunSynchronously: true` |
|
||||
| Čtěte nebo zálohujte data, která by nadcházející migrace ztratila | `pre-install` |
|
||||
| Odmítněte aktualizaci, která by poškodila existující data | `pre-install` (vyhoďte výjimku z obslužné funkce) |
|
||||
| Srovnání stavu při každé aktualizaci | Libovolný hook s `shouldRunOnVersionUpgrade: true` |
|
||||
|
||||
export default definePostInstallLogicFunction({
|
||||
universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
|
||||
name: 'post-install',
|
||||
description: 'Runs after installation to set up the application.',
|
||||
timeoutSeconds: 300,
|
||||
shouldRunOnVersionUpgrade: false,
|
||||
shouldRunSynchronously: false,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
## Chování sdílené oběma hooky
|
||||
|
||||
Postinstalační funkci můžete také kdykoli spustit ručně pomocí CLI:
|
||||
* Konfigurace je konfigurace `defineLogicFunction` bez nastavení triggeru, doplněná o `shouldRunOnVersionUpgrade`.
|
||||
* **Kdy se spouští**: ve výchozím nastavení pouze při čistých instalacích. Nastavte `shouldRunOnVersionUpgrade: true`, aby se spouštěl i při aktualizacích. Použijte `previousVersion` / `newVersion` k větvení podle cesty aktualizace.
|
||||
* **Idempotence je důležitá**: asynchronní post-install se může spouštět opakovaně a kterýkoli hook se znovu spouští při aktualizacích, když je `shouldRunOnVersionUpgrade` zapnuté.
|
||||
* Běžné prostředí logické funkce (`APPLICATION_ID`, `APP_ACCESS_TOKEN`, `API_URL`) je injektováno, takže můžete volat Twenty API s tokenem své aplikace.
|
||||
* Hook je při sestavení automaticky připojen k manifestu aplikace (`preInstallLogicFunction` / `postInstallLogicFunction`) — v [`defineApplication()`](/l/cs/developers/extend/apps/config/application) není potřeba na nic odkazovat.
|
||||
* Výchozí `timeoutSeconds` je 300, aby umožnil delší úlohy nastavení, jako je naplnění daty.
|
||||
* **Nespouští se v dev režimu**: `yarn twenty dev` přeskočí instalační flow a soubory synchronizuje přímo, takže se hooky v tomto režimu nikdy nespustí. Místo toho je spouštějte ručně:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev:function:exec --postInstall
|
||||
```
|
||||
|
||||
Hlavní body:
|
||||
* Postinstalační funkce používají `definePostInstallLogicFunction()` — specializovanou variantu, která vynechává nastavení spouštěčů (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `toolTriggerSettings`, `workflowActionTriggerSettings`).
|
||||
* Obslužná funkce obdrží `InstallPayload` s `{ previousVersion?: string; newVersion: string }` — `newVersion` je verze, která se instaluje, a `previousVersion` je verze, která byla nainstalována dříve (nebo `undefined` při čisté instalaci). Tyto hodnoty použijte k rozlišení čistých instalací od aktualizací a ke spuštění migrační logiky specifické pro verzi.
|
||||
* **Kdy se hook spouští**: ve výchozím nastavení pouze při čistých instalacích. Předejte `shouldRunOnVersionUpgrade: true`, pokud chcete, aby se spouštěl i při aktualizaci aplikace z předchozí verze. Pokud je vynechán, příznak má výchozí hodnotu `false` a při aktualizacích se hook přeskočí.
|
||||
* **Model provádění — ve výchozím nastavení asynchronní, synchronní volitelně**: příznak `shouldRunSynchronously` určuje *jak* se spouští post-install.
|
||||
* `shouldRunSynchronously: false` *(výchozí)* — hook je **zařazen do fronty zpráv** s `retryLimit: 3` a běží asynchronně ve workeru. Odezva instalace se vrátí hned po zařazení úlohy do fronty, takže pomalá nebo chybující obslužná funkce neblokuje volajícího. Worker se pokusí o opakování až třikrát. **Použijte pro dlouho běžící úlohy** — plnění velkých datových sad, volání pomalých externích API, zřizování externích prostředků, cokoli, co by mohlo přesáhnout rozumné časové okno HTTP odezvy.
|
||||
* `shouldRunSynchronously: true` — hook se provádí **inline během instalačního procesu** (stejný vykonavatel jako pre-install). Instalační požadavek blokuje, dokud obslužná funkce nedokončí, a pokud vyvolá výjimku, volající instalace obdrží `POST_INSTALL_ERROR`. Žádné automatické opakování. **Použijte pro rychlé úlohy, které se musí dokončit před odpovědí** — například vrácení validační chyby uživateli nebo rychlé nastavení, na kterém bude klient záviset ihned po návratu volání instalace. Mějte na paměti, že v době, kdy se spustí post-install, už byla migrace metadat aplikována, takže selhání v synchronním režimu změny schématu **ne**vrací zpět — pouze odhalí chybu.
|
||||
* Ujistěte se, že vaše obslužná funkce je idempotentní. V asynchronním režimu se může fronta pokusit až třikrát; v obou režimech se může hook znovu spustit při aktualizacích, pokud je `shouldRunOnVersionUpgrade: true`.
|
||||
* Proměnné prostředí `APPLICATION_ID`, `APP_ACCESS_TOKEN` a `API_URL` jsou dostupné uvnitř obslužné funkce (stejně jako u jakékoli jiné logické funkce), takže můžete volat Twenty API s aplikačním přístupovým tokenem omezeným na vaši aplikaci.
|
||||
* Na jednu aplikaci je povolena pouze jedna postinstalační funkce. Sestavení manifestu skončí chybou, pokud je zjištěna více než jedna.
|
||||
* Atributy funkce `universalIdentifier`, `shouldRunOnVersionUpgrade` a `shouldRunSynchronously` jsou během buildu automaticky připojeny k manifestu aplikace do pole `postInstallLogicFunction` — není potřeba je uvádět v [`defineApplication()`](/l/cs/developers/extend/apps/config/application).
|
||||
* Výchozí časový limit je nastaven na 300 sekund (5 minut), aby umožnil delší úlohy nastavení, jako je naplnění daty.
|
||||
* **Nespouští se v režimu dev**: když je aplikace registrována lokálně (pomocí `yarn twenty dev`), server zcela přeskočí instalační tok a synchronizuje soubory přímo prostřednictvím sledovače CLI — takže se post-install v režimu dev nikdy nespustí bez ohledu na `shouldRunSynchronously`. Použijte `yarn twenty dev:function:exec --postInstall` k ručnímu spuštění nad běžícím pracovním prostorem.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="definePreInstallLogicFunction" description="Spouští se před aplikováním migrace metadat pracovního prostoru">
|
||||
|
||||
Předinstalační funkce se během instalace spouští automaticky, **před aplikováním migrace metadat pracovního prostoru**. Má stejný tvar payloadu jako post-install (`InstallPayload`), ale je zařazena dříve v instalačním toku, aby mohla připravit stav, na němž nadcházející migrace závisí — typické použití zahrnuje zálohování dat, ověření kompatibility s novým schématem nebo archivaci záznamů, které se chystají přeuspořádat nebo odstranit.
|
||||
|
||||
```ts src/logic-functions/pre-install.ts
|
||||
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
|
||||
const handler = async (payload: InstallPayload): Promise<void> => {
|
||||
console.log('Pre install logic function executed successfully!', payload.previousVersion);
|
||||
};
|
||||
|
||||
export default definePreInstallLogicFunction({
|
||||
universalIdentifier: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
|
||||
name: 'pre-install',
|
||||
description: 'Runs before installation to prepare the application.',
|
||||
timeoutSeconds: 300,
|
||||
shouldRunOnVersionUpgrade: true,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
|
||||
Předinstalační funkci můžete také kdykoli spustit ručně pomocí CLI:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev:function:exec --preInstall
|
||||
```
|
||||
|
||||
Hlavní body:
|
||||
* Funkce pre-install používají `definePreInstallLogicFunction()` — stejné specializované nastavení jako u post-install, pouze připojené k jiné fázi životního cyklu.
|
||||
* Obě obslužné funkce pre- i post-install přijímají stejný typ `InstallPayload`: `{ previousVersion?: string; newVersion: string }`. Importujte jej jednou a znovu použijte pro oba hooky.
|
||||
* **Kdy se hook spouští**: umístěn těsně před migrací metadat pracovního prostoru (`synchronizeFromManifest`). Před spuštěním server provede čistě aditivní "zjednodušenou synchronizaci", která v metadatech pracovního prostoru zaregistruje pre-install funkci **nové** verze — ničeho dalšího se nedotkne — a poté ji spustí. Protože tato synchronizace je pouze aditivní, objekty, pole a data předchozí verze zůstávají při spuštění vaší obslužné funkce zachována: můžete bezpečně číst a zálohovat stav před migrací.
|
||||
* **Model provádění**: pre-install se provádí **synchronně** a **blokuje instalaci**. Pokud obslužná funkce vyvolá výjimku, instalace se přeruší ještě před aplikováním jakýchkoli změn schématu — pracovní prostor zůstane na předchozí verzi v konzistentním stavu. Je to záměrné: pre-install je vaše poslední šance odmítnout rizikovou aktualizaci.
|
||||
* Stejně jako u post-install je na jednu aplikaci povolena pouze jedna funkce pre-install. Během buildu je automaticky připojena k manifestu aplikace pod `preInstallLogicFunction`.
|
||||
* **Nespouští se v režimu dev**: stejně jako u post-install — u lokálně registrovaných aplikací je instalační tok zcela přeskočen, takže se pre-install pod `yarn twenty dev` nikdy nespustí. Použijte `yarn twenty dev:function:exec --preInstall` k ručnímu spuštění.
|
||||
<AccordionGroup>
|
||||
<Accordion title="definePostInstallLogicFunction" description="Spouští se po aplikování migrace metadat pracovního prostoru">
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Pre-install vs post-install: kdy použít který" description="Výběr správného instalačního hooku">
|
||||
|
||||
Oba hooky jsou součástí téhož instalačního toku a přijímají stejný `InstallPayload`. Rozdíl je v tom, **kdy** se spouštějí vzhledem k migraci metadat pracovního prostoru, a to určuje, jakých dat se mohou bezpečně dotýkat.
|
||||
|
||||
Pre-install je vždy **synchronní** (blokuje instalaci a může ji přerušit). Post-install je **ve výchozím nastavení asynchronní** — zařazen do workeru s automatickými pokusy o opakování — ale může přejít na synchronní provádění pomocí `shouldRunSynchronously: true`. Viz accordion `definePostInstallLogicFunction` výše, kdy použít jednotlivé režimy.
|
||||
|
||||
**Použijte `post-install` pro cokoli, co vyžaduje existenci nového schématu.** To je běžný případ:
|
||||
|
||||
* Plnění výchozími daty (vytváření počátečních záznamů, výchozích pohledů, demo obsahu) vůči nově přidaným objektům a polím.
|
||||
* Registrace webhooků u služeb třetích stran poté, co má aplikace své přihlašovací údaje.
|
||||
* Volání vlastního API k dokončení nastavení, které závisí na synchronizovaných metadatech.
|
||||
* Idempotentní logika "zajisti, že to existuje", která má při každé aktualizaci uvést stav do souladu — kombinujte s `shouldRunOnVersionUpgrade: true`.
|
||||
|
||||
Příklad — po instalaci naplňte výchozí záznam `PostCard`:
|
||||
Spouští se, jakmile vaše aplikace dokončí instalaci: metadata jsou synchronizovaná, klient SDK vygenerovaný a nové schéma je možné dotazovat. Příklad — při čisté instalaci naplňte výchozí záznam:
|
||||
|
||||
```ts src/logic-functions/post-install.ts
|
||||
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
import { createClient } from './generated/client';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
|
||||
if (previousVersion) return; // fresh installs only
|
||||
|
||||
const client = createClient();
|
||||
await client.postCard.create({
|
||||
data: { title: 'Welcome to Postcard', content: 'Your first card!' },
|
||||
const client = new CoreApiClient();
|
||||
await client.mutation({
|
||||
createPostCard: {
|
||||
__args: { data: { name: 'Welcome to Postcard', content: 'Your first card!' } },
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -133,22 +81,28 @@ export default definePostInstallLogicFunction({
|
||||
description: 'Seeds a welcome post card after install.',
|
||||
timeoutSeconds: 300,
|
||||
shouldRunOnVersionUpgrade: false,
|
||||
shouldRunSynchronously: false,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
|
||||
**Použijte `pre-install`, pokud by migrace jinak zničila nebo poškodila existující data.** Protože pre-install běží proti *předchozímu* schématu a jeho selhání vrací aktualizaci zpět, je to správné místo pro cokoli rizikového:
|
||||
Příznak `shouldRunSynchronously` řídí model spuštění:
|
||||
|
||||
* **Zálohování dat, která se chystají odstranit nebo přeuspořádat** — např. odstraňujete pole ve verzi v2 a potřebujete jeho hodnoty zkopírovat do jiného pole nebo je před spuštěním migrace exportovat do úložiště.
|
||||
* **Archivace záznamů, které by nové omezení zneplatnilo** — např. pole se stává `NOT NULL` a je třeba nejprve smazat nebo opravit řádky s hodnotami null.
|
||||
* **Ověření kompatibility a odmítnutí aktualizace, pokud nelze aktuální data čistě migrovat** — vyhoďte výjimku z obslužné funkce a instalace se ukončí bez provedených změn. Je to bezpečnější, než zjistit nekompatibilitu uprostřed migrace.
|
||||
* **Přejmenování nebo změna klíčů dat** před změnou schématu, která by ztratila vazby.
|
||||
* `false` *(výchozí)* — zařazeno do fronty zpráv (`retryLimit: 3`) a spuštěno workerem. Odezva instalace se vrátí, jakmile je úloha zařazena do fronty. **Používejte pro dlouho běžící práci** — naplňování velkých datových sad, pomalá API třetích stran.
|
||||
* `true` — spuštěno inline během instalačního flow. Instalační požadavek blokuje, dokud handler neskončí; vyvolaná chyba se projeví pro volajícího jako `POST_INSTALL_ERROR` (žádné opakované pokusy). **Používejte pro rychlou práci, která musí být dokončena před odpovědí.** Migrace už je v tomto bodě aplikovaná, takže selhání nevrací změny schématu zpět — pouze předá chybu dál.
|
||||
|
||||
Příklad — archivujte záznamy před destruktivní migrací:
|
||||
</Accordion>
|
||||
<Accordion title="definePreInstallLogicFunction" description="Spouští se před aplikováním migrace metadat pracovního prostoru">
|
||||
|
||||
Spouští se před migrací metadat, nad **předchozím** schématem — vhodné místo pro zálohování dat, která by migrace ztratila, nebo pro odmítnutí rizikové aktualizace. Před spuštěním server provede čistě aditivní „zjednodušenou synchronizaci“, která zaregistruje pouze pre-install funkci nové verze; vše ostatní — objekty, pole a data předchozí verze — zůstává při běhu vašeho handleru nedotčeno.
|
||||
|
||||
Pre-install je vždy **synchronní** a blokuje instalaci. Pokud obslužná funkce vyvolá výjimku, instalace se přeruší ještě před jakoukoli změnou schématu — pracovní prostor zůstane na předchozí verzi v konzistentním stavu. Je to záměrné: pre-install je vaše poslední šance odmítnout rizikovou aktualizaci.
|
||||
|
||||
Příklad — zkopírujte hodnoty staršího pole dříve, než ho migrace odstraní:
|
||||
|
||||
```ts src/logic-functions/pre-install.ts
|
||||
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
import { createClient } from './generated/client';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
|
||||
// Only the 1.x → 2.x upgrade drops the legacy `notes` field.
|
||||
@@ -156,24 +110,24 @@ const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise
|
||||
return;
|
||||
}
|
||||
|
||||
const client = createClient();
|
||||
const legacyRecords = await client.postCard.findMany({
|
||||
where: { notes: { isNotNull: true } },
|
||||
const client = new CoreApiClient();
|
||||
const { postCards } = await client.query({
|
||||
postCards: {
|
||||
__args: { filter: { notes: { isNot: null } } },
|
||||
edges: { node: { id: true, notes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
if (legacyRecords.length === 0) return;
|
||||
|
||||
// Copy legacy `notes` into the new `description` field before the migration
|
||||
// drops the `notes` column. If this fails, the upgrade is aborted and the
|
||||
// workspace stays on v1 with all data intact.
|
||||
await Promise.all(
|
||||
legacyRecords.map((record) =>
|
||||
client.postCard.update({
|
||||
where: { id: record.id },
|
||||
data: { description: record.notes },
|
||||
}),
|
||||
),
|
||||
);
|
||||
// Copy legacy `notes` into `description` before the migration drops the
|
||||
// column. If this fails, the upgrade aborts and the workspace stays on v1.
|
||||
for (const { node } of postCards.edges) {
|
||||
await client.mutation({
|
||||
updatePostCard: {
|
||||
__args: { id: node.id, data: { description: node.notes } },
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default definePreInstallLogicFunction({
|
||||
@@ -186,21 +140,5 @@ export default definePreInstallLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
**Zlaté pravidlo:**
|
||||
|
||||
| Chcete... | Použít |
|
||||
| ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| Naplňte výchozí data, nakonfigurujte pracovní prostor, zaregistrujte externí prostředky | `post-install` |
|
||||
| Spusťte dlouho běžící plnění nebo volání třetích stran, která by neměla blokovat odezvu instalace | `post-install` (výchozí — `shouldRunSynchronously: false`, s opakovanými pokusy workeru) |
|
||||
| Spusťte rychlé nastavení, na které bude volající spoléhat ihned po návratu volání instalace | `post-install` s `shouldRunSynchronously: true` |
|
||||
| Čtěte nebo zálohujte data, která by nadcházející migrace ztratila | `pre-install` |
|
||||
| Odmítněte aktualizaci, která by poškodila existující data | `pre-install` (vyhoďte výjimku z obslužné funkce) |
|
||||
| Spouštějte srovnání stavu při každé aktualizaci | `post-install` s `shouldRunOnVersionUpgrade: true` |
|
||||
| Proveďte jednorázové nastavení pouze při první instalaci | `post-install` s `shouldRunOnVersionUpgrade: false` (výchozí) |
|
||||
|
||||
<Note>
|
||||
Pokud si nejste jisti, výchozí volbou je **post-install**. Po pre-install sáhněte pouze tehdy, když je samotná migrace destruktivní a potřebujete zachytit předchozí stav, než zmizí.
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -86,6 +86,22 @@ export default defineObject({
|
||||
**Základní pole jsou přidána automaticky.** Když definujete vlastní objekt, Twenty pro vás vytvoří standardní pole jako `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` a `deletedAt`. Nemusíte je uvádět v poli `fields` — pouze svá vlastní pole. Výchozí pole můžete přepsat tak, že deklarujete pole se stejným názvem, ale jen zřídka je to dobrý nápad.
|
||||
</Note>
|
||||
|
||||
## Typy polí
|
||||
|
||||
Úplná sada hodnot `FieldType`, exportovaných z `twenty-sdk/define`:
|
||||
|
||||
| Kategorie | Typy |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Text | `TEXT`, `RICH_TEXT`, `ARRAY` (řetězců), `RAW_JSON` |
|
||||
| Číselné | `NUMBER` (`universalSettings.dataType`: `'float'` / `'int'` / `'bigint'`), `NUMERIC` (libovolná přesnost), `RATING`, `POSITION` |
|
||||
| Data | `DATE`, `DATE_TIME` |
|
||||
| Výběr | `BOOLEAN`, `SELECT`, `MULTI_SELECT` |
|
||||
| Složené | `FULL_NAME`, `ADDRESS`, `EMAILS`, `PHONES`, `LINKS`, `CURRENCY`, `ACTOR`, `FILES` |
|
||||
| Identifikátory a relace | `UUID`, `RELATION`, `MORPH_RELATION` (viz [Relations](/l/cs/developers/extend/apps/data/relations)) |
|
||||
| Systém | `TS_VECTOR` (vektor pro fulltextové vyhledávání, spravovaný serverem) |
|
||||
|
||||
Složené typy ukládají více podpolí (např. `FULL_NAME` = křestní + příjmení; `CURRENCY` = `amountMicros` + `currencyCode`). `SELECT` a `MULTI_SELECT` vyžadují pole `options`, jak je ukázáno v příkladu výše.
|
||||
|
||||
## Výchozí hodnoty
|
||||
|
||||
Výchozí textové hodnoty musí být uzavřené v jednoduchých uvozovkách **uvnitř** řetězce — `defaultValue: "'Draft'"`, ne `defaultValue: "Draft"`. Proto pole `status` výše používá `` `'${PostCardStatus.DRAFT}'` ``.
|
||||
|
||||
+32
-16
@@ -14,26 +14,39 @@ my-twenty-app/
|
||||
default-role.ts # Permissions for logic functions
|
||||
constants/
|
||||
universal-identifiers.ts # Auto-generated UUIDs and metadata
|
||||
front-components/
|
||||
main-page.tsx # Welcome page component
|
||||
navigation-menu-items/
|
||||
main-page.navigation-menu-item.ts # Sidebar entry for the welcome page
|
||||
page-layouts/
|
||||
main-page.page-layout.ts # Standalone page hosting the component
|
||||
__tests__/
|
||||
setup-test.ts
|
||||
app-install.integration-test.ts
|
||||
.github/workflows/ci.yml # GitHub Actions
|
||||
public/ # Static assets
|
||||
vitest.config.ts # Test runner config
|
||||
application-config.test.ts # Unit test
|
||||
global-setup.ts # Integration test setup (sync + uninstall)
|
||||
schema.integration-test.ts # Integration test against a live server
|
||||
.github/workflows/
|
||||
ci.yml # Lint, typecheck, unit + integration tests
|
||||
cd.yml # Deploy + install on push to main
|
||||
public/
|
||||
logo.svg # Static assets
|
||||
vitest.config.ts # Integration test runner config
|
||||
vitest.unit.config.ts # Unit test runner config
|
||||
tsconfig.json, tsconfig.spec.json
|
||||
.nvmrc, .yarnrc.yml, .oxlintrc.json
|
||||
README.md, LLMS.md
|
||||
README.md, AGENTS.md, CLAUDE.md
|
||||
```
|
||||
|
||||
## Klíčové soubory
|
||||
|
||||
| Soubor / Složka | Účel |
|
||||
| ---------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `src/application-config.ts` | **Povinné.** Hlavní konfigurační soubor vaší aplikace. |
|
||||
| `src/default-role.ts` | Výchozí role, která řídí, k čemu mohou vaše logické funkce přistupovat. |
|
||||
| `src/constants/universal-identifiers.ts` | Automaticky generovaná UUID a metadata (zobrazovaný název, popis). |
|
||||
| `src/__tests__/` | Integrační testy (nastavení + ukázkový test). |
|
||||
| `public/` | Statické soubory (obrázky, písma) doručované vaší aplikací. |
|
||||
| Soubor / Složka | Účel |
|
||||
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `src/application-config.ts` | **Povinné.** Hlavní konfigurační soubor vaší aplikace. |
|
||||
| `src/default-role.ts` | Výchozí role, která řídí, k čemu mohou vaše logické funkce přistupovat. |
|
||||
| `src/constants/universal-identifiers.ts` | Automaticky generovaná UUID a metadata (zobrazovaný název, popis). |
|
||||
| `src/front-components/`, `src/navigation-menu-items/`, `src/page-layouts/` | Úvodní uvítací stránka: front komponenta renderovaná samostatným rozložením stránky, dostupná z postranního panelu. |
|
||||
| `src/__tests__/` | Jednotkový test plus integrační test (s jeho globálním nastavením), který synchronizuje aplikaci proti skutečnému serveru. |
|
||||
| `public/` | Statické soubory (obrázky, písma) doručované vaší aplikací. |
|
||||
| `AGENTS.md` / `CLAUDE.md` | Pokyny pro agenty AI pro psaní kódu, kteří pracují na aplikaci. |
|
||||
|
||||
<Note>
|
||||
**Uspořádání souborů je na vás.** Výše uvedené složky jsou konvence — SDK detekuje entity pomocí analýzy AST u volání `export default defineEntity(...)` bez ohledu na to, kde se soubor nachází.
|
||||
@@ -47,15 +60,18 @@ Oba balíčky Twenty SDK patří pod `devDependencies`, ne pod `dependencies`:
|
||||
{
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"twenty-client-sdk": "^2.13.0",
|
||||
"twenty-sdk": "^2.13.0"
|
||||
"twenty-client-sdk": "2.20.0",
|
||||
"twenty-sdk": "2.20.0",
|
||||
"twenty-ui": "1.0.0-alpha.1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Nástroj pro scaffolding připne `twenty-sdk` a `twenty-client-sdk` ke své vlastní verzi — při aktualizaci udržujte tyto dva balíčky synchronizované.
|
||||
|
||||
* **`twenty-sdk`** dodává `twenty` CLI a nástroje pro sestavení/scaffolding. Běží pouze při vývoji a sestavování a nikdy není importován za běhu zveřejněné aplikace.
|
||||
* **`twenty-client-sdk`** je importován kódem vaší aplikace (`CoreApiClient`, `MetadataApiClient`, `RestApiClient`), ale Twenty ho poskytuje za běhu — logické funkce ho získávají z vygenerované SDK vrstvy a front-endové komponenty ho načítají z modulů poskytovaných serverem. Vaše nainstalovaná kopie se používá pouze pro kontrolu typů a build v době nasazení, takže ji nikdy není potřeba přibalit do nasazeného balíčku.
|
||||
|
||||
Ponechání kteréhokoli balíčku pod `dependencies` ho vtáhne do runtime balíčku nainstalované aplikace, kde je jen mrtvou vahou. `twenty build` vypíše varování, pokud je kterýkoli z nich stále uveden pod `dependencies`.
|
||||
Ponechání kteréhokoli balíčku pod `dependencies` ho vtáhne do runtime balíčku nainstalované aplikace, kde je jen mrtvou vahou. `twenty dev:build` vypíše varování, pokud je kterýkoli z nich stále uveden pod `dependencies`.
|
||||
|
||||
Vlastní runtime závislosti vaší aplikace (knihovny, které vaše logické funkce skutečně importují za běhu) přidejte jako obvykle pod `dependencies`.
|
||||
|
||||
@@ -6,17 +6,17 @@ description: Vytvořte svou první aplikaci Twenty během několika minut.
|
||||
|
||||
## Předpoklady
|
||||
|
||||
* **Node.js 24+** — [Stáhnout](https://nodejs.org/)
|
||||
* **Node.js 24.5+** — [Stáhnout](https://nodejs.org/)
|
||||
* **Yarn 4** — je součástí Node.js prostřednictvím Corepacku. Povolte jej: `corepack enable`
|
||||
* **Docker** — [Stáhnout](https://www.docker.com/products/docker-desktop/). Nutné pro spuštění lokálního serveru Twenty. Přeskočte, pokud už máte Twenty spuštěné jinde.
|
||||
|
||||
Vytváření aplikace Twenty má tři fáze. Generátor kostry je spojuje do jediného příkazu pro ideální scénář, ale každá fáze je samostatný koncept — když se něco nepovede, znalost aktuální fáze napoví, co opravit.
|
||||
|
||||
| Fáze | Co děláte | Nástroj | Výsledek |
|
||||
| ---------------------- | -------------------------------------------------------- | ----------------------------- | -------------------------------------------- |
|
||||
| **1. Vytvořit kostru** | Vygenerovat zdrojový kód aplikace | `npx create-twenty-app` | Projekt v TypeScriptu na disku |
|
||||
| **2. Spustit server** | Spustit server Twenty, do kterého se bude synchronizovat | Docker + `yarn twenty server` | Běžící instance Twenty |
|
||||
| **3. Synchronizovat** | Živě synchronizovat kód na server | `yarn twenty dev` | Vaše změny se objeví v uživatelském rozhraní |
|
||||
| Fáze | Co děláte | Nástroj | Výsledek |
|
||||
| ---------------------- | -------------------------------------------------------- | ----------------------------------- | -------------------------------------------- |
|
||||
| **1. Vytvořit kostru** | Vygenerovat zdrojový kód aplikace | `npx create-twenty-app` | Projekt v TypeScriptu na disku |
|
||||
| **2. Spustit server** | Spustit server Twenty, do kterého se bude synchronizovat | Docker + `yarn twenty docker:start` | Běžící instance Twenty |
|
||||
| **3. Synchronizovat** | Živě synchronizovat kód na server | `yarn twenty dev` | Vaše změny se objeví v uživatelském rozhraní |
|
||||
|
||||
---
|
||||
|
||||
@@ -28,7 +28,7 @@ Vytvořte novou aplikaci ze šablony:
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
```
|
||||
|
||||
Budete vyzváni k zadání názvu a popisu — výchozí hodnoty potvrdíte klávesou **Enter**. Tím se v `my-twenty-app/` vytvoří projekt v TypeScriptu se startovacím `application-config.ts`, výchozí rolí, CI workflow a integračním testem.
|
||||
Generátor kostry je neinteraktivní: název adresáře se stane názvem aplikace. Předejte `--display-name` a `--description` pro přizpůsobení vygenerovaných metadat (později je můžete také upravit v `src/constants/universal-identifiers.ts`). Tím se v `my-twenty-app/` vytvoří projekt v TypeScriptu se startovacím `application-config.ts`, výchozí rolí, pracovními postupy CI/CD a integračním testem.
|
||||
|
||||
**Po této fázi:** máte na svém počítači zdrojový kód aplikace. Zatím neběží — to je předmětem Fáze 2.
|
||||
|
||||
@@ -38,28 +38,14 @@ Budete vyzváni k zadání názvu a popisu — výchozí hodnoty potvrdíte klá
|
||||
|
||||
Vaše aplikace potřebuje server Twenty, do kterého se bude synchronizovat. Server je plnohodnotná instance Twenty — UI, GraphQL API, PostgreSQL — běžící lokálně v Dockeru. Váš lokální kód nahrává své definice na tento server, díky čemuž se objeví v UI.
|
||||
|
||||
Generátor kostry nabídne, že vám jej spustí:
|
||||
Nástroj pro vytváření projektů to spustí za vás: při spuštěném Dockeru stáhne image `twentycrm/twenty-app-dev`, spustí ji na portu `2020` a autentizuje CLI vůči předpřipravenému demo workspace (`tim@apple.dev`) — není vyžadováno žádné přihlášení.
|
||||
|
||||
> **Chcete nastavit lokální instanci Twenty?**
|
||||
|
||||
* **Ano (doporučeno)** — stáhne Docker image `twentycrm/twenty-app-dev` a spustí jej na portu `2020`. Nejprve se ujistěte, že Docker běží.
|
||||
* **Ne** — zvolte, pokud už máte server Twenty, ke kterému se chcete připojit. Můžete jej propojit později pomocí `yarn twenty remote:add`.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Spustit lokální instanci?" />
|
||||
</div>
|
||||
|
||||
Jakmile server běží, otevře se prohlížeč pro přihlášení. Použijte předpřipravený demo účet:
|
||||
|
||||
* **E-mail:** `tim@apple.dev`
|
||||
* **Heslo:** `tim@apple.dev`
|
||||
Chcete-li se místo toho připojit k existujícímu serveru Twenty, předejte `--url \<your-server-url>`. Vzdálené servery se ověřují pomocí OAuth: otevře se prohlížeč, abyste se mohli přihlásit a kliknout na **Authorize**, čímž udělíte nástroji CLI přístup k vašemu pracovnímu prostoru. (Můžete se také rozhodnout pro OAuth lokálně pomocí `--authentication-method oauth` — přihlaste se pomocí `tim@apple.dev` / `tim@apple.dev`.)
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Přihlašovací obrazovka Twenty" />
|
||||
</div>
|
||||
|
||||
Na další obrazovce klikněte na **Authorize** — tím udělíte nástroji CLI přístup k vašemu pracovnímu prostoru.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Autorizační obrazovka Twenty CLI" />
|
||||
</div>
|
||||
@@ -117,27 +103,31 @@ Klikněte na **View installed app**, abyste zobrazili instalaci v pracovním pro
|
||||
|
||||
### Jednorázová synchronizace pro CI a skripty
|
||||
|
||||
Předejte `--once` pro provedení jednoho sestavení + synchronizace a ukončení — stejný postup, bez sledování změn:
|
||||
Použijte `plan` a `apply` ke spuštění stejné pipeline jednorázově, bez watcheru:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
yarn twenty plan # preview the metadata changes without applying them
|
||||
yarn twenty apply # show the plan, then apply it
|
||||
```
|
||||
|
||||
| Příkaz | Chování | Kdy použít |
|
||||
| ---------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| `yarn twenty dev` | Sleduje změny a při každé změně znovu synchronizuje. Běží, dokud jej nezastavíte. | Interaktivní lokální vývoj. |
|
||||
| `yarn twenty dev --once` | Jedno sestavení + synchronizace, ukončí se s kódem `0` při úspěchu, `1` při chybě. | CI, pre-commit hooky, AI agenti, skriptované pracovní postupy. |
|
||||
| `yarn twenty dev --once --dry-run` | Sestaví a vypíše změny metadat **bez jejich použití**. | Kontrola toho, co by synchronizace změnila, ještě před jejím potvrzením. |
|
||||
| Příkaz | Chování | Kdy použít |
|
||||
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| `yarn twenty dev` | Sleduje změny a při každé změně znovu synchronizuje. Běží, dokud jej nezastavíte. | Interaktivní lokální vývoj. |
|
||||
| `yarn twenty apply` | Jedno sestavení + synchronizace, ukončí se s kódem `0` při úspěchu, `1` při chybě. Vyžádá si potvrzení destruktivních změn (předejte `--force`, abyste to přeskočili). | CI, pre-commit hooky, AI agenti, skriptované pracovní postupy. |
|
||||
| `yarn twenty plan` | Sestaví a vypíše změny metadat **bez jejich použití**. | Kontrola toho, co by synchronizace změnila, ještě před jejím potvrzením. |
|
||||
|
||||
Oba režimy vyžadují autentizovaný vzdálený server. Více informací o `--dry-run` najdete v části [Synchronizace a obnovení](/l/cs/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run).
|
||||
Všechny režimy vyžadují autentizovaný vzdálený server. Více informací o `plan` najdete v části [Synchronizace a obnovení](/l/cs/developers/extend/apps/operations/sync-and-recovery#previewing-changes-plan).
|
||||
|
||||
<Note>
|
||||
`yarn twenty dev --once` a `yarn twenty dev --once --dry-run` jsou zastaralé aliasy pro `yarn twenty apply` a `yarn twenty plan`.
|
||||
</Note>
|
||||
|
||||
### Možnosti vývojového režimu
|
||||
|
||||
| Přepínač | Popis |
|
||||
| ------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| `--once` | Jednou sestavit a synchronizovat, poté ukončit. |
|
||||
| `--dry-run` | Pomocí `--once` zobrazíte náhled změn metadat, aniž byste je použili. Nic nezapisuje. |
|
||||
| `--debounceMs \<ms>` | Nastaví prodlevu pro potlačení zákmitů při změnách souborů v milisekundách (výchozí: `2000`). |
|
||||
| `--force` | Aplikuje destruktivní změny (mazání) bez potvrzení. |
|
||||
| `--debounceMs \<ms>` | Nastaví prodlevu pro potlačení zákmitů při změnách souborů v milisekundách (výchozí: `1000`). |
|
||||
| `--verbose` / `--debug` | Zobrazí podrobné protokoly sestavení, požadavky synchronizace a trasování chyb. |
|
||||
|
||||
## Co můžete vytvořit
|
||||
|
||||
@@ -34,6 +34,10 @@ yarn twenty dev:add frontComponent
|
||||
| Zobrazení | `yarn twenty dev:add view` | `src/views/\<name>.ts` |
|
||||
| Položka navigační nabídky | `yarn twenty dev:add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
|
||||
| Rozvržení stránky | `yarn twenty dev:add pageLayout` | `src/page-layouts/\<name>.ts` |
|
||||
| Karta Rozložení stránky | `yarn twenty dev:add pageLayoutTab` | `src/page-layout-tabs/\<name>.ts` |
|
||||
| Položka menu příkazů | `yarn twenty dev:add commandMenuItem` | `src/command-menu-items/\<name>.ts` |
|
||||
| Pole zobrazení | `yarn twenty dev:add viewField` | `src/view-fields/\<name>.ts` |
|
||||
| Poskytovatel připojení | `yarn twenty dev:add connectionProvider` | `src/connection-providers/\<name>.ts` |
|
||||
|
||||
## Co generátor vytváří
|
||||
|
||||
|
||||
+2
-2
@@ -5,10 +5,10 @@ icon: wrench
|
||||
---
|
||||
|
||||
* **Chyby Dockeru** — Před spuštěním `yarn twenty docker:start` se ujistěte, že Docker Desktop (nebo démon) běží. Chybová zpráva ukáže správný příkaz pro spuštění pro váš operační systém.
|
||||
* **Nesprávná verze Node** — Je potřeba 24+. Ověřte pomocí `node -v`.
|
||||
* **Špatná verze Node** — Potřebujete verzi 24.5+ (`engines.node: ^24.5.0`). Ověřte pomocí `node -v`.
|
||||
* **Chybí Yarn 4** — Spusťte `corepack enable`.
|
||||
* **Rozbité závislosti** — `rm -rf node_modules && yarn install`.
|
||||
* **Chyby `twenty-sdk` po upgradu na v2.8.0** — V 2.8.0 byl přesunut z `dependencies` do `devDependencies`. Viz [Struktura projektu → Závislosti](/l/cs/developers/extend/apps/getting-started/project-structure#dependencies).
|
||||
* **`twenty build` upozorňuje na `twenty-client-sdk` v sekci `dependencies`** — je poskytován za běhu Twenty, takže by měl být přesunut do `devDependencies` vedle `twenty-sdk`. Viz [Struktura projektu → Závislosti](/l/cs/developers/extend/apps/getting-started/project-structure#dependencies).
|
||||
* **`twenty dev:build` upozorňuje na `twenty-client-sdk` v sekci `dependencies`** — je poskytován za běhu Twenty, takže by měl být přesunut do `devDependencies` vedle `twenty-sdk`. Viz [Struktura projektu → Závislosti](/l/cs/developers/extend/apps/getting-started/project-structure#dependencies).
|
||||
|
||||
Zasekli jste se? Zeptejte se na [Discordu Twenty](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
|
||||
@@ -13,7 +13,6 @@ export default defineCommandMenuItem({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
label: 'Open Dashboard',
|
||||
shortLabel: 'Dashboard',
|
||||
icon: 'IconLayoutDashboard',
|
||||
isPinned: true,
|
||||
availabilityType: 'GLOBAL',
|
||||
frontComponentUniversalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948',
|
||||
@@ -22,51 +21,23 @@ export default defineCommandMenuItem({
|
||||
|
||||
## Konfigurační pole
|
||||
|
||||
| Pole | Povinné | Popis |
|
||||
| --------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `universalIdentifier` | Ano | Stabilní jedinečné ID pro příkaz |
|
||||
| `label` | Ano | Plný popisek zobrazený v příkazovém menu (Cmd+K) |
|
||||
| `frontComponentUniversalIdentifier` | Ano | `universalIdentifier` frontendové komponenty, kterou tento příkaz otevírá |
|
||||
| `shortLabel` | Ne | Kratší popisek zobrazený na připnutém tlačítku rychlé akce |
|
||||
| `icon` | Ne | Název ikony zobrazený vedle popisku (např. `'IconBolt'`, `'IconSend'`) |
|
||||
| `isPinned` | Ne | Pokud je `true`, zobrazí příkaz jako tlačítko rychlé akce v pravém horním rohu stránky |
|
||||
| `availabilityType` | Ne | Určuje, kde se příkaz zobrazuje: `'GLOBAL'` (vždy dostupné), `'RECORD_SELECTION'` (pouze když jsou vybrány záznamy) nebo `'FALLBACK'` (zobrazeno, když neodpovídají žádné jiné příkazy) |
|
||||
| `availabilityObjectUniversalIdentifier` | Ne | Omezí příkaz na stránky konkrétního typu objektu (např. pouze u záznamů Company) |
|
||||
| `conditionalAvailabilityExpression` | Ne | Logický výraz, který dynamicky řídí viditelnost (viz níže) |
|
||||
| Pole | Povinné | Popis |
|
||||
| --------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `universalIdentifier` | Ano | Stabilní jedinečné ID pro příkaz |
|
||||
| `label` | Ano | Plný popisek zobrazený v příkazovém menu (Cmd+K) |
|
||||
| `frontComponentUniversalIdentifier` | Ano | `universalIdentifier` frontendové komponenty, kterou tento příkaz otevírá |
|
||||
| `shortLabel` | Ne | Kratší popisek zobrazený na připnutém tlačítku rychlé akce |
|
||||
| `icon` | Ne | **Zastaralé** — ignorováno ve prospěch ikony aplikace; při nastavení sestavení vypíše varování |
|
||||
| `isPinned` | Ne | Pokud je `true`, zobrazí příkaz jako tlačítko rychlé akce v pravém horním rohu stránky |
|
||||
| `availabilityType` | Ne | Určuje, kde se příkaz zobrazuje: `'GLOBAL'` (vždy dostupné), `'GLOBAL_OBJECT_CONTEXT'` (pouze na stránkách s kontextem objektu — indexové a záznamové stránky), `'RECORD_SELECTION'` (pouze když jsou vybrány záznamy) nebo `'FALLBACK'` (zobrazeno, když neodpovídají žádné jiné příkazy) |
|
||||
| `availabilityObjectUniversalIdentifier` | Ne | Omezí příkaz na stránky konkrétního typu objektu (např. pouze u záznamů Company) |
|
||||
| `conditionalAvailabilityExpression` | Ne | Logický výraz, který dynamicky řídí viditelnost (viz níže) |
|
||||
|
||||
## Příkazy bez rozhraní
|
||||
|
||||
Položka příkazového menu spárovaná s [front komponentou bez rozhraní](/l/cs/developers/extend/apps/layout/front-components#headless-vs-non-headless) je idiomatický způsob, jak dodat akci na jedno kliknutí — spustit kód, přejít na stránku nebo potvrdit a provést. Stránka Front Components popisuje [SDK Command komponenty](/l/cs/developers/extend/apps/layout/front-components#sdk-command-components) (`Command`, `CommandLink`, `CommandModal`, `CommandOpenSidePanelPage`), které obsluhují pattern akce-a-unmount.
|
||||
|
||||
Typický průběh:
|
||||
|
||||
```tsx src/front-components/run-action.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { Command } from 'twenty-sdk/command';
|
||||
import { CoreApiClient } from 'twenty-sdk/clients';
|
||||
|
||||
const RunAction = () => {
|
||||
const execute = async () => {
|
||||
const client = new CoreApiClient();
|
||||
await client.mutation({
|
||||
createTask: {
|
||||
__args: { data: { title: 'Created by my app' } },
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return <Command execute={execute} />;
|
||||
};
|
||||
|
||||
export default defineFrontComponent({
|
||||
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
|
||||
name: 'run-action',
|
||||
description: 'Creates a task from the command menu',
|
||||
component: RunAction,
|
||||
isHeadless: true,
|
||||
});
|
||||
```
|
||||
Typický průběh: bezhlavá komponenta vykreslí `<Command execute={...} />` (viz [úplný příklad](/l/cs/developers/extend/apps/layout/front-components#sdk-command-components)) a položka v nabídce příkazů na ni ukazuje:
|
||||
|
||||
```ts src/command-menu-items/run-action.command-menu-item.ts
|
||||
import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||||
@@ -74,7 +45,6 @@ import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||||
export default defineCommandMenuItem({
|
||||
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
|
||||
label: 'Run my action',
|
||||
icon: 'IconPlayerPlay',
|
||||
frontComponentUniversalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
|
||||
});
|
||||
```
|
||||
|
||||
@@ -49,14 +49,13 @@ export default defineCommandMenuItem({
|
||||
universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-456789012345',
|
||||
shortLabel: 'Hello',
|
||||
label: 'Hello World',
|
||||
icon: 'IconBolt',
|
||||
isPinned: true,
|
||||
availabilityType: 'GLOBAL',
|
||||
frontComponentUniversalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948',
|
||||
});
|
||||
```
|
||||
|
||||
Po synchronizaci pomocí `yarn twenty dev` (nebo po jednorázovém spuštění `yarn twenty dev --once`) se rychlá akce zobrazí v pravém horním rohu stránky:
|
||||
Po synchronizaci pomocí `yarn twenty dev` (nebo po jednorázovém spuštění `yarn twenty apply`) se rychlá akce zobrazí v pravém horním rohu stránky:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Tlačítko rychlé akce v pravém horním rohu" />
|
||||
@@ -88,11 +87,11 @@ Front-endové komponenty existují ve dvou režimech vykreslování řízených
|
||||
|
||||
```tsx src/front-components/sync-tracker.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
|
||||
import { useSelectedRecordIds, enqueueSnackbar } from 'twenty-sdk/front-component';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const SyncTracker = () => {
|
||||
const recordId = useRecordId();
|
||||
const [recordId] = useSelectedRecordIds();
|
||||
|
||||
useEffect(() => {
|
||||
enqueueSnackbar({ message: `Tracking record ${recordId}`, variant: 'info' });
|
||||
@@ -116,7 +115,7 @@ Protože komponenta vrací `null`, Twenty přeskočí vykreslení kontejneru —
|
||||
|
||||
Balíček `twenty-sdk` poskytuje čtyři pomocné komponenty Command navržené pro headless front-endové komponenty. Každá komponenta při připojení provede akci, chyby zpracuje zobrazením oznámení ve snackbaru a po dokončení automaticky odpojí front-endovou komponentu.
|
||||
|
||||
Importujte je z `twenty-sdk/command`:
|
||||
Importujte je z `twenty-sdk/front-component`:
|
||||
|
||||
* **`Command`** — Spustí asynchronní callback přes prop `execute`.
|
||||
* **`CommandLink`** — Naviguje na cestu v aplikaci. Props: `to`, `params`, `queryParams`, `options`.
|
||||
@@ -127,8 +126,8 @@ Zde je kompletní příklad headless front-endové komponenty, která pomocí `C
|
||||
|
||||
```tsx src/front-components/run-action.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { Command } from 'twenty-sdk/command';
|
||||
import { CoreApiClient } from 'twenty-sdk/clients';
|
||||
import { Command } from 'twenty-sdk/front-component';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const RunAction = () => {
|
||||
const execute = async () => {
|
||||
@@ -160,7 +159,6 @@ import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||||
export default defineCommandMenuItem({
|
||||
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
|
||||
label: 'Run my action',
|
||||
icon: 'IconPlayerPlay',
|
||||
frontComponentUniversalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
|
||||
});
|
||||
```
|
||||
@@ -169,7 +167,7 @@ A příklad s použitím `CommandModal` k vyžádání potvrzení před proveden
|
||||
|
||||
```tsx src/front-components/delete-draft.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { CommandModal } from 'twenty-sdk/command';
|
||||
import { CommandModal } from 'twenty-sdk/front-component';
|
||||
|
||||
const DeleteDraft = () => {
|
||||
const execute = async () => {
|
||||
@@ -202,7 +200,7 @@ Front komponenty běží v prohlížeči v izolovaném web workeru, zatímco [lo
|
||||
|
||||
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`:
|
||||
|
||||
> **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://\<your-workspace-subdomain>.twenty.com\<path>` — 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.
|
||||
> **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://\<your-workspace-subdomain>.withtwenty.com\<path>` — 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.
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
@@ -212,7 +210,7 @@ Headless front komponenta může volání spustit při mountu přes komponentu `
|
||||
|
||||
```tsx src/front-components/sync-prs.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { Command } from 'twenty-sdk/command';
|
||||
import { Command } from 'twenty-sdk/front-component';
|
||||
|
||||
const SyncPrs = () => {
|
||||
const execute = async () => {
|
||||
@@ -316,13 +314,13 @@ Uvnitř komponenty použijte hooky SDK pro přístup k aktuálnímu uživateli,
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import {
|
||||
useUserId,
|
||||
useRecordId,
|
||||
useSelectedRecordIds,
|
||||
useFrontComponentId,
|
||||
} from 'twenty-sdk/front-component';
|
||||
|
||||
const RecordInfo = () => {
|
||||
const userId = useUserId();
|
||||
const recordId = useRecordId();
|
||||
const [recordId] = useSelectedRecordIds();
|
||||
const componentId = useFrontComponentId();
|
||||
|
||||
return (
|
||||
@@ -405,12 +403,11 @@ Zde je příklad, který používá hostitelské API k zobrazení snackbaru a za
|
||||
|
||||
```tsx src/front-components/archive-record.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { useRecordId } from 'twenty-sdk/front-component';
|
||||
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
|
||||
import { CoreApiClient } from 'twenty-sdk/clients';
|
||||
import { enqueueSnackbar, closeSidePanel, useSelectedRecordIds } from 'twenty-sdk/front-component';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const ArchiveRecord = () => {
|
||||
const recordId = useRecordId();
|
||||
const [recordId] = useSelectedRecordIds();
|
||||
|
||||
const handleArchive = async () => {
|
||||
const client = new CoreApiClient();
|
||||
@@ -451,10 +448,10 @@ export default defineFrontComponent({
|
||||
Použijte `useSelectedRecordIds()` pro zpracování více vybraných záznamů. To je užitečné pro hromadné operace:
|
||||
|
||||
```tsx src/front-components/bulk-export.tsx
|
||||
import { defineFrontComponent, numberOfSelectedRecords } from 'twenty-sdk/define';
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
import { useSelectedRecordIds } from 'twenty-sdk/front-component';
|
||||
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
|
||||
import { CoreApiClient } from 'twenty-sdk/clients';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const BulkExport = () => {
|
||||
const selectedRecordIds = useSelectedRecordIds();
|
||||
@@ -492,12 +489,19 @@ export default defineFrontComponent({
|
||||
name: 'bulk-export',
|
||||
description: 'Export selected records',
|
||||
component: BulkExport,
|
||||
command: {
|
||||
universalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678902',
|
||||
label: 'Bulk Export',
|
||||
availabilityType: 'RECORD_SELECTION',
|
||||
conditionalAvailabilityExpression: numberOfSelectedRecords > 0,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Zobrazte ji pomocí [položky příkazové nabídky](/l/cs/developers/extend/apps/layout/command-menu-items) omezené na výběry záznamů:
|
||||
|
||||
```ts src/command-menu-items/bulk-export.command-menu-item.ts
|
||||
import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||||
|
||||
export default defineCommandMenuItem({
|
||||
universalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678902',
|
||||
label: 'Bulk Export',
|
||||
availabilityType: 'RECORD_SELECTION',
|
||||
frontComponentUniversalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678901',
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ export default defineNavigationMenuItem({
|
||||
|
||||
* `position` určuje pořadí v postranním panelu.
|
||||
|
||||
* Výčet také obsahuje `NavigationMenuItemType.RECORD`, používaný interně pro oblíbené záznamy vytvořené uživateli — nelze jej použít z manifestu aplikace (neexistuje žádné pole, které by odkazovalo na záznam).
|
||||
|
||||
* `icon` a `color` jsou volitelné a upravují, jak položka vypadá.
|
||||
|
||||
* `folderUniversalIdentifier` je k dispozici také na libovolné položce, aby ji bylo možné vložit do nadřazené položky typu `FOLDER`.
|
||||
|
||||
@@ -33,17 +33,32 @@ export default defineView({
|
||||
## Hlavní body
|
||||
|
||||
* `objectUniversalIdentifier` určuje, na který objekt se toto zobrazení vztahuje. Může to být vlastní objekt, který jste definovali, nebo standardní objekt Twenty.
|
||||
* `key` určuje typ zobrazení — `ViewKey.INDEX` je hlavní seznamové zobrazení pro daný objekt.
|
||||
* `key: ViewKey.INDEX` označuje zobrazení jako hlavní seznamové zobrazení objektu (to, které se otevře po kliknutí na navigační položku `OBJECT`).
|
||||
* `fields` určuje, které sloupce se zobrazí a v jakém pořadí. Každé pole odkazuje na `fieldMetadataUniversalIdentifier`.
|
||||
* Pro pokročilé konfigurace můžete také deklarovat `filters`, `filterGroups`, `groups` a `fieldGroups`.
|
||||
* Pro pokročilé konfigurace můžete také deklarovat `filters`, `filterGroups`, `sorts`, `groups` a `fieldGroups`.
|
||||
* `position` určuje pořadí, pokud pro stejný objekt existuje více zobrazení.
|
||||
|
||||
## Volitelné vlastnosti
|
||||
|
||||
| Vlastnost | Hodnoty | Popis |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `type` | `ViewType.TABLE` (výchozí), `ViewType.KANBAN`, `ViewType.CALENDAR` | Jak jsou záznamy uspořádány. (`FIELDS_WIDGET` / `TABLE_WIDGET` také existují, ale jsou používány interně widgety rozvržení stránky.) |
|
||||
| `visibility` | `ViewVisibility.WORKSPACE` (výchozí), `ViewVisibility.UNLISTED` | Zda je zobrazení uvedeno pro celý workspace nebo skryto ve výběrech. |
|
||||
| `openRecordIn` | `ViewOpenRecordIn.SIDE_PANEL` (výchozí), `ViewOpenRecordIn.RECORD_PAGE` | Kde se záznam otevře po kliknutí. |
|
||||
| `sorts` | `{ fieldMetadataUniversalIdentifier, direction: ViewSortDirection.ASC \| DESC }[]` | Výchozí pořadí řazení. |
|
||||
| `isCompact` | `boolean` | Kompaktní zobrazení řádků. |
|
||||
| `mainGroupByFieldMetadataUniversalIdentifier` + `shouldHideEmptyGroups` | — | Seskupení záznamů (např. sloupce kanbanu) podle pole. |
|
||||
| `kanbanAggregateOperation`, `kanbanAggregateOperationFieldMetadataUniversalIdentifier`, `kanbanColumnWidth` | `AggregateOperations.*` | Agregace a velikost sloupců v kanbanu. |
|
||||
| `calendarLayout`, `calendarFieldMetadataUniversalIdentifier` | `ViewCalendarLayout.DAY` / `WEEK` / `MONTH` | Zobrazení kalendáře: rozvržení a datumové pole, které určuje umístění záznamů. |
|
||||
|
||||
Všechny výše uvedené výčtové typy jsou exportovány z `twenty-sdk/define`.
|
||||
|
||||
## Filtry
|
||||
|
||||
Zobrazení může být dodáno s předem aplikovanými filtry. Každý filtr má tři souřadnice: **pole**, které se filtruje, **operand** (jak porovnávat) a **hodnotu** (proti čemu porovnávat). Všechny tři musí být v souladu — použití operandu, který se nehodí k typu pole, bude při synchronizaci odmítnuto.
|
||||
|
||||
```ts
|
||||
import { ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { ViewFilterOperand } from 'twenty-sdk/define';
|
||||
|
||||
filters: [
|
||||
{
|
||||
|
||||
@@ -51,8 +51,12 @@ export default defineLogicFunction({
|
||||
```
|
||||
|
||||
Dostupné typy spouštěčů:
|
||||
* **httpRoute**: Zpřístupní vaši funkci na HTTP cestě a metodě **pod koncovým bodem `/s/`**:
|
||||
> např. `path: '/post-card/create'` je volatelné na `https://your-twenty-server.com/s/post-card/create`
|
||||
* **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`
|
||||
|
||||
<Warning>
|
||||
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 `\<server-url>/s/\<path>` v opačném případě.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
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).
|
||||
|
||||
@@ -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 dorazí na váš koncový bod `/s/\<path>` | `httpRouteTriggerSettings` |
|
||||
| **HTTP route** | Požadavek zasáhne veřejnou adresu URL funkce | `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` |
|
||||
|
||||
@@ -4,7 +4,25 @@ description: příkazy `yarn twenty` pro spouštění funkcí, streamování log
|
||||
icon: terminal
|
||||
---
|
||||
|
||||
Kromě `dev`, `dev:build`, `dev:add` a `dev:typecheck` poskytuje `yarn twenty` CLI příkazy pro spouštění funkcí, zobrazení logů a správu instalací aplikací.
|
||||
CLI `yarn twenty` je vaše rozhraní ke všemu, co souvisí s aplikací. Úplný seznam příkazů:
|
||||
|
||||
| Příkaz | K čemu slouží | Zdokumentováno v |
|
||||
| ----------------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `dev` | Sleduje zdrojové soubory a živě synchronizuje změny | [Rychlý start](/l/cs/developers/extend/apps/getting-started/quick-start) |
|
||||
| `plán` | Náhled změn metadat bez jejich aplikování | [Synchronizace a obnovení](/l/cs/developers/extend/apps/operations/sync-and-recovery#previewing-changes-plan) |
|
||||
| `použít` | Aplikovat změny metadat po zobrazení plánu | [Synchronizace a obnovení](/l/cs/developers/extend/apps/operations/sync-and-recovery) |
|
||||
| `dev:build` | Zkompilovat aplikaci a vygenerovat API klienta (`--tarball` pro zabalení do `.tgz`) | [Publikování](/l/cs/developers/extend/apps/operations/publishing) |
|
||||
| `dev:typecheck` | Spustit kontrolu typů TypeScriptu | [Testování](/l/cs/developers/extend/apps/operations/testing) |
|
||||
| `dev:add` | Vytvořit základ nového objektu (scaffold) | [Scaffolding](/l/cs/developers/extend/apps/getting-started/scaffolding) |
|
||||
| `dev:generate-client` | Znovu vygenerovat typovaného API klienta | tato stránka |
|
||||
| `dev:function:exec` / `dev:function:logs` | Spustit funkce a streamovat jejich logy | tato stránka |
|
||||
| `dev:translations-extract` | Extrahovat přeložitelné řetězce do katalogů v `locales/` | [Překlady](/l/cs/developers/extend/apps/translations/overview) |
|
||||
| `dev:catalog-sync` | Spustit synchronizaci katalogu tržiště | [Publikování](/l/cs/developers/extend/apps/operations/publishing#how-marketplace-discovery-works) |
|
||||
| `app:publish` / `app:install` / `app:uninstall` | Životní cyklus vydání | [Publikování](/l/cs/developers/extend/apps/operations/publishing) a tato stránka |
|
||||
| `docker:*` | Spravovat kontejner lokálního serveru Twenty | [Lokální server](/l/cs/developers/extend/apps/getting-started/local-server) |
|
||||
| `remote:*` | Spravovat připojení k serveru | tato stránka |
|
||||
|
||||
Každý příkaz přijímá `-r, --remote \<name>` pro zacílení na konkrétní remote místo výchozího.
|
||||
|
||||
## Spouštění funkcí (`yarn twenty dev:function:exec`)
|
||||
|
||||
@@ -20,8 +38,9 @@ yarn twenty dev:function:exec -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
|
||||
# Pass a JSON payload
|
||||
yarn twenty dev:function:exec -n create-new-post-card -p '{"name": "Hello"}'
|
||||
|
||||
# Execute the post-install function
|
||||
# Execute the install hooks
|
||||
yarn twenty dev:function:exec --postInstall
|
||||
yarn twenty dev:function:exec --preInstall
|
||||
```
|
||||
|
||||
## Zobrazení logů funkcí (`yarn twenty dev:function:logs`)
|
||||
@@ -100,6 +119,12 @@ yarn twenty remote:list
|
||||
|
||||
# Set the active remote
|
||||
yarn twenty remote:use <name>
|
||||
|
||||
# Check that the active remote's authentication is still valid
|
||||
yarn twenty remote:status
|
||||
|
||||
# Remove a remote
|
||||
yarn twenty remote:remove <name>
|
||||
```
|
||||
|
||||
Vaše přihlašovací údaje jsou uloženy v `~/.twenty/config.json`.
|
||||
|
||||
@@ -229,7 +229,7 @@ yarn twenty dev:catalog-sync
|
||||
# yarn twenty dev:catalog-sync --remote production
|
||||
```
|
||||
|
||||
Metadata zobrazená v tržišti pocházejí z vaší konfigurace `defineApplication()` — z polí jako `displayName`, `description`, `author`, `category`, `logoUrl`, `screenshots`, `aboutDescription`, `websiteUrl` a `termsUrl`.
|
||||
Metadata zobrazená v marketplace pochází z vaší konfigurace `defineApplication()` — viz výše [Metadata marketplace](#marketplace-metadata).
|
||||
|
||||
<Note>
|
||||
Pokud vaše aplikace nedefinuje `aboutDescription` v `defineApplication()`, tržiště automaticky použije soubor `README.md` vašeho balíčku z npm jako obsah stránky O aplikaci. To znamená, že můžete spravovat jediný soubor README jak pro npm, tak pro tržiště Twenty. Pokud chcete v tržišti jiný popis, explicitně nastavte `aboutDescription`.
|
||||
|
||||
@@ -12,16 +12,20 @@ Lokální vývoj aplikací se točí kolem **synchronizace**: CLI znovu sestaví
|
||||
Pro každodenní lokální iteraci téměř vždy chcete `yarn twenty dev`. Nasazování a publikování slouží k vydávání verzí, **ne** pro lokální vývojovou smyčku.
|
||||
</Note>
|
||||
|
||||
| Chcete… | Příkaz | Poznámky |
|
||||
| --------------------------------------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| Iterujte lokálně s živou synchronizací | `yarn twenty dev` | Sleduje vaše soubory a při každé změně spustí synchronizaci. |
|
||||
| Jednorázová synchronizace a ukončení (CI, skripty, hooky) | `yarn twenty dev --once` | Provede jedno sestavení + synchronizaci a skončí. |
|
||||
| Náhled změn **bez jejich aplikování** | `yarn twenty dev --once --dry-run` | Spočítá a vypíše rozdíly; nic nezapisuje. |
|
||||
| Odebrat aplikaci z pracovního prostoru | `yarn twenty app:uninstall` | Přidejte `--yes` pro přeskočení výzvy. |
|
||||
| Odeslat tarball na server | `yarn twenty app:publish --private` | Vyžaduje **přísně vyšší** verzi v `package.json` — viz [Publikování](/l/cs/developers/extend/apps/operations/publishing). |
|
||||
| Publikovat na marketplace (npm) | `yarn twenty app:publish` | — |
|
||||
| Nainstalovat / aktualizovat nasazenou verzi | `yarn twenty app:install` | Nainstaluje aktuálně nasazenou verzi. |
|
||||
| Vymazat lokální server a začít znovu | `yarn twenty docker:reset` | Smaže **všechna** lokální data — krajní řešení. |
|
||||
| Chcete… | Příkaz | Poznámky |
|
||||
| --------------------------------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| Iterujte lokálně s živou synchronizací | `yarn twenty dev` | Sleduje vaše soubory a při každé změně spustí synchronizaci. |
|
||||
| Jednorázová synchronizace a ukončení (CI, skripty, hooky) | `yarn twenty apply` | Provede jedno sestavení + synchronizaci a skončí. Přidejte `--force`, abyste přeskočili potvrzení destruktivní změny. |
|
||||
| Náhled změn **bez jejich aplikování** | `yarn twenty plan` | Spočítá a vypíše rozdíly; nic nezapisuje. |
|
||||
| Odebrat aplikaci z pracovního prostoru | `yarn twenty app:uninstall` | Přidejte `--yes` pro přeskočení výzvy. |
|
||||
| Odeslat tarball na server | `yarn twenty app:publish --private` | Vyžaduje **přísně vyšší** verzi v `package.json` — viz [Publikování](/l/cs/developers/extend/apps/operations/publishing). |
|
||||
| Publikovat na marketplace (npm) | `yarn twenty app:publish` | — |
|
||||
| Nainstalovat / aktualizovat nasazenou verzi | `yarn twenty app:install` | Nainstaluje aktuálně nasazenou verzi. |
|
||||
| Vymazat lokální server a začít znovu | `yarn twenty docker:reset` | Smaže **všechna** lokální data — krajní řešení. |
|
||||
|
||||
<Note>
|
||||
`yarn twenty dev --once` a `yarn twenty dev --once --dry-run` stále fungují jako zastaralé aliasy pro `yarn twenty apply` a `yarn twenty plan`.
|
||||
</Note>
|
||||
|
||||
### Lokální synchronizace nevyžaduje zvýšení verze
|
||||
|
||||
@@ -29,19 +33,26 @@ Pravidlo striktně rostoucí `version` (`VERSION_ALREADY_EXISTS` při nasazení,
|
||||
|
||||
## Čtení výstupu synchronizace
|
||||
|
||||
Každá synchronizace vypíše změny metadat, které aplikovala (nebo by aplikovala s `--dry-run`):
|
||||
Každá synchronizace vypíše změny metadat, které aplikovala (nebo by aplikovala s `plan`), ve stylu Terraformu — jeden blok na entitu s jejími atributy a poté souhrnný řádek:
|
||||
|
||||
```text filename="Terminal"
|
||||
Metadata changes: 2 created, 1 updated, 1 deleted
|
||||
created objectMetadata rocket
|
||||
created fieldMetadata timelineActivities
|
||||
updated fieldMetadata launchedAt
|
||||
deleted pageLayout legacyTab
|
||||
✓ Synced
|
||||
# objectMetadata "rocket" will be created
|
||||
+ icon = "IconRocket"
|
||||
+ labelSingular = "Rocket"
|
||||
+ ...
|
||||
|
||||
# fieldMetadata "launchedAt" will be updated
|
||||
~ isNullable = false -> true
|
||||
|
||||
Plan: 2 to add, 1 to change, 1 to destroy.
|
||||
|
||||
✓ Synced My App (4 files)
|
||||
```
|
||||
|
||||
To je váš první diagnostický nástroj: přesně ukazuje, které objekty, pole a rozložení se změnily, takže si můžete ověřit, že synchronizace udělala to, co jste očekávali, ještě před kontrolou v UI.
|
||||
|
||||
Destruktivní změny (`to destroy`) jsou uvedeny s tím, co odstraňují (např. `objectMetadata "auditNote" — drops the table and all its rows`) a vyžadují interaktivní potvrzení, nebo `--force` ve skriptech.
|
||||
|
||||
Když synchronizace selže na jedné entitě, chyba uvede problematickou entitu a její `universalIdentifier`, například:
|
||||
|
||||
```text
|
||||
@@ -50,39 +61,42 @@ Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337)
|
||||
|
||||
Tento identifikátor použijte k nalezení entity ve vašem manifestu (a případně v pracovním prostoru) místo hádání, která je v konfliktu.
|
||||
|
||||
## Náhled změn (dry run)
|
||||
## Náhled změn (plan)
|
||||
|
||||
`yarn twenty dev --once --dry-run` sestaví váš manifest, požádá server o migrační plán a vypíše ho — aniž by cokoli aplikoval. Je to bezpečný způsob, jak si předem zodpovědět otázku „co by tato synchronizace změnila?“ ještě předtím, než se k ní zavážete.
|
||||
`yarn twenty plan` sestaví váš manifest, požádá server o migrační plán a vypíše ho — **aniž by cokoli aplikoval**. Je to bezpečný způsob, jak si předem zodpovědět otázku „co by tato synchronizace změnila?“ ještě předtím, než se k ní zavážete.
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once --dry-run
|
||||
yarn twenty plan
|
||||
```
|
||||
|
||||
```text filename="Terminal"
|
||||
Building manifest...
|
||||
Computing metadata diff (dry run, nothing will be applied)...
|
||||
Metadata changes: 1 created, 1 updated
|
||||
created fieldMetadata timelineActivities
|
||||
updated objectMetadata rocket
|
||||
✓ Dry run complete for My App — no changes were applied
|
||||
Computing metadata plan (read-only, nothing will be applied)...
|
||||
|
||||
# fieldMetadata "timelineActivities" will be created
|
||||
+ ...
|
||||
|
||||
Plan: 1 to add, 1 to change, 0 to destroy.
|
||||
|
||||
✓ Plan complete for My App — no changes were applied
|
||||
```
|
||||
|
||||
Spuštění nanečisto:
|
||||
Plán:
|
||||
|
||||
* **Nic nezapisuje** — žádná migrace metadat, žádná aktualizace záznamu aplikace, žádné změny výchozí role / karty a žádná generace API klienta.
|
||||
* Vrací **stejný diff**, jaký by aplikovala skutečná synchronizace, takže můžete předem zkontrolovat vytvořené / aktualizované / smazané entity.
|
||||
* Je užitečný před rizikovou změnou, při kontrole změny vygenerované pomocí AI nebo ve skriptu, který má selhat, pokud se má provést neočekávaná změna.
|
||||
|
||||
<Note>
|
||||
Režim dry run zobrazuje pouze náhled změn **metadat** a vyžaduje, aby byla aplikace alespoň jednou synchronizovaná (aby o ní pracovní prostor věděl). Pokud jej spustíte proti aplikaci, která nikdy nebyla synchronizovaná, server ohlásí, že aplikace není nainstalovaná — nejprve jednou spusťte `yarn twenty dev`.
|
||||
Plán zobrazuje pouze náhled změn **metadat** a vyžaduje, aby byla aplikace alespoň jednou synchronizovaná (aby o ní pracovní prostor věděl). Pokud jej spustíte proti aplikaci, která nikdy nebyla synchronizovaná, server ohlásí, že aplikace není nainstalovaná — nejprve jednou spusťte `yarn twenty dev`.
|
||||
</Note>
|
||||
|
||||
## Postup obnovy
|
||||
|
||||
Když lokální metadata vypadají špatně, postupujte v tomto pořadí a zastavte se, jakmile se problém vyřeší. Každý další krok je rušivější než ten předchozí.
|
||||
|
||||
1. **Znovu synchronizujte.** Znovu spusťte `yarn twenty dev --once`. Synchronizace jsou idempotentní — znovu spuštěný čistý manifest je bezpečný a často vyřeší přechodný problém.
|
||||
2. **Prohlédněte si plán.** Spusťte `yarn twenty dev --once --dry-run`, abyste přesně viděli, co chce další synchronizace změnit, aniž by to aplikovala.
|
||||
1. **Znovu synchronizujte.** Znovu spusťte `yarn twenty apply`. Synchronizace jsou idempotentní — znovu spuštěný čistý manifest je bezpečný a často vyřeší přechodný problém.
|
||||
2. **Prohlédněte si plán.** Spusťte `yarn twenty plan`, abyste přesně viděli, co chce další synchronizace změnit, aniž by to aplikovala.
|
||||
3. **Přečtěte si pojmenovanou chybu.** Pokud synchronizace selže, poznamenejte si typ metadat a `universalIdentifier` ve zprávě (viz výše) a tuto entitu najděte ve svém manifestu. Konflikt obvykle ukazuje na duplicitní nebo znovu použitý identifikátor.
|
||||
4. **Odinstalujte a znovu nainstalujte.** `yarn twenty app:uninstall`, poté znovu synchronizujte (`yarn twenty dev`). Tím znovu vybudujete metadata aplikace z čistého stavu, zatímco zbytek vašeho pracovního prostoru zůstane nedotčený.
|
||||
5. **Úplný reset (krajní řešení).** `yarn twenty docker:reset`, poté znovu naplňte data a synchronizujte.
|
||||
|
||||
@@ -78,6 +78,13 @@ Vytvořte `vitest.config.ts` v kořeni vaší aplikace:
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
|
||||
const TWENTY_API_KEY = process.env.TWENTY_API_KEY ?? '<the pre-seeded local dev key>';
|
||||
|
||||
// Make env vars available to globalSetup (test.env only applies to workers)
|
||||
process.env.TWENTY_API_URL = TWENTY_API_URL;
|
||||
process.env.TWENTY_API_KEY = TWENTY_API_KEY;
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
tsconfigPaths({
|
||||
@@ -88,66 +95,74 @@ export default defineConfig({
|
||||
test: {
|
||||
testTimeout: 120_000,
|
||||
hookTimeout: 120_000,
|
||||
fileParallelism: false,
|
||||
include: ['src/**/*.integration-test.ts'],
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
globalSetup: ['src/__tests__/global-setup.ts'],
|
||||
env: {
|
||||
TWENTY_API_URL: 'http://localhost:2020',
|
||||
TWENTY_API_KEY: 'your-api-key',
|
||||
TWENTY_API_URL,
|
||||
TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Vytvořte soubor nastavení, který před spuštěním testů ověří dostupnost serveru:
|
||||
Vytvořte globální soubor pro nastavení, který ověří, že je server dosažitelný, zapíše testovací konfiguraci pro SDK (`~/.twenty/config.test.json`) a před spuštěním testů provede synchronizaci aplikace:
|
||||
|
||||
```ts src/__tests__/setup-test.ts
|
||||
```ts src/__tests__/global-setup.ts
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
import { appDevOnce, appUninstall } from 'twenty-sdk/cli';
|
||||
|
||||
const APP_PATH = process.cwd();
|
||||
const CONFIG_DIR = path.join(os.homedir(), '.twenty');
|
||||
|
||||
export async function setup() {
|
||||
const apiUrl = process.env.TWENTY_API_URL!;
|
||||
const apiKey = process.env.TWENTY_API_KEY!;
|
||||
|
||||
beforeAll(async () => {
|
||||
// Verify the server is running
|
||||
const response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
|
||||
const response = await fetch(`${apiUrl}/healthz`);
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
'Start the server before running integration tests.',
|
||||
);
|
||||
throw new Error(`Twenty server is not reachable at ${apiUrl}.`);
|
||||
}
|
||||
|
||||
// Write a temporary config for the SDK
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
// Write the SDK's test config (the CLI reads config.test.json when NODE_ENV=test)
|
||||
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(TEST_CONFIG_DIR, 'config.json'),
|
||||
path.join(CONFIG_DIR, 'config.test.json'),
|
||||
JSON.stringify({
|
||||
remotes: {
|
||||
local: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
remotes: { local: { apiUrl, apiKey } },
|
||||
defaultRemote: 'local',
|
||||
}, null, 2),
|
||||
);
|
||||
});
|
||||
|
||||
// Start from a clean slate, then sync the app
|
||||
await appUninstall({ appPath: APP_PATH }).catch(() => {});
|
||||
|
||||
const result = await appDevOnce({ appPath: APP_PATH });
|
||||
if (!result.success) {
|
||||
throw new Error(`Dev sync failed: ${result.error?.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function teardown() {
|
||||
await appUninstall({ appPath: APP_PATH });
|
||||
}
|
||||
```
|
||||
|
||||
## Programová rozhraní SDK
|
||||
|
||||
Subcesta `twenty-sdk/cli` exportuje funkce, které můžete volat přímo z testovacího kódu:
|
||||
|
||||
| Funkce | Popis |
|
||||
| -------------- | ----------------------------------------------------- |
|
||||
| `appBuild` | Sestaví aplikaci a volitelně zabalí tarball |
|
||||
| `appDeploy` | Nahraje tarball na server |
|
||||
| `appInstall` | Nainstaluje aplikaci do aktivního pracovního prostoru |
|
||||
| `appUninstall` | Odinstaluje aplikaci z aktivního pracovního prostoru |
|
||||
| Funkce | Popis |
|
||||
| -------------- | ------------------------------------------------------------------------------ |
|
||||
| `appBuild` | Sestaví aplikaci a volitelně zabalí tarball |
|
||||
| `appDeploy` | Nahraje tarball na server |
|
||||
| `appDevOnce` | Jednorázově sestaví a synchronizuje aplikaci (stejně jako `yarn twenty apply`) |
|
||||
| `appInstall` | Nainstaluje aplikaci do aktivního pracovního prostoru |
|
||||
| `appUninstall` | Odinstaluje aplikaci z aktivního pracovního prostoru |
|
||||
|
||||
Každá funkce vrací objekt výsledku se `success: boolean` a buď `data`, nebo `error`.
|
||||
|
||||
@@ -238,64 +253,10 @@ Kontrolu typů můžete spustit i na vaší aplikaci bez spuštění testů:
|
||||
yarn twenty dev:typecheck
|
||||
```
|
||||
|
||||
Spustí se `tsc --noEmit` a nahlásí se případné chyby typů.
|
||||
Spustí se `tsc --noEmit` proti souboru `tsconfig.json` vaší aplikace a nahlásí se případné chyby typů. Vygenerované aplikace také obsahují skript `yarn typecheck`, který pokrývá i testovací soubory (`tsconfig.spec.json`).
|
||||
|
||||
## CI s GitHub Actions
|
||||
|
||||
Generátor kostry vytvoří připravený k použití workflow GitHub Actions v `.github/workflows/ci.yml`. Automaticky spouští integrační testy při každém pushi do `main` a u pull requestů.
|
||||
Generátor kostry vytvoří připravený k použití workflow v `.github/workflows/ci.yml`. Při každém pushi do `main` a při každém pull requestu spustí efemérní server Twenty v runneru (pomocí akce `twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test`), poté spustí `yarn lint`, `yarn typecheck`, `yarn test:unit` a `yarn test` s `TWENTY_API_URL` / `TWENTY_API_KEY` směřujícími na tento server. Nejsou vyžadována žádná tajemství a verzi serveru můžete připnout pomocí proměnné prostředí `TWENTY_VERSION` na začátku workflow.
|
||||
|
||||
Workflow:
|
||||
|
||||
1. Načte váš kód (checkout).
|
||||
2. Spustí dočasný server Twenty pomocí akce `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
|
||||
3. Nainstaluje závislosti pomocí `yarn install --immutable`
|
||||
4. Spustí `yarn test` s proměnnými `TWENTY_API_URL` a `TWENTY_API_KEY` vloženými z výstupů akce
|
||||
|
||||
```yaml .github/workflows/ci.yml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
TWENTY_VERSION: latest
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spawn Twenty instance
|
||||
id: twenty
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
|
||||
with:
|
||||
twenty-version: ${{ env.TWENTY_VERSION }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Run integration tests
|
||||
run: yarn test
|
||||
env:
|
||||
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
```
|
||||
|
||||
Není potřeba konfigurovat žádné secrets — akce `spawn-twenty-docker-image` spustí dočasný server Twenty přímo v runneru a vypíše podrobnosti připojení. Secret `GITHUB_TOKEN` je poskytován GitHubem automaticky.
|
||||
|
||||
Chcete-li připnout konkrétní verzi Twenty místo `latest`, změňte proměnnou prostředí `TWENTY_VERSION` na začátku workflow.
|
||||
Úplný postup pro obě workflow generované kostrou (`ci.yml` a nasazovací pipeline `cd.yml`) najdete v části [Publishing → Automated CI/CD](/l/cs/developers/extend/apps/operations/publishing#automated-cicd-scaffolded-workflows).
|
||||
|
||||
+7
-3
@@ -91,9 +91,11 @@ const GenerateDocumentForm = () => {
|
||||
}, []);
|
||||
|
||||
const generate = async () => {
|
||||
const apiBaseUrl = process.env.TWENTY_API_URL;
|
||||
// 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(`${apiBaseUrl}/s/documents/generate`, {
|
||||
const res = await fetch(`${functionsBaseUrl}/documents/generate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ templateId, recordId }),
|
||||
@@ -186,7 +188,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 webUrl = `${process.env.TWENTY_API_URL ?? ''}/s/documents/view?id=${recordId}`;
|
||||
const functionsBaseUrl =
|
||||
process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL ?? ''}/s`;
|
||||
const webUrl = `${functionsBaseUrl}/documents/view?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.
|
||||
|
||||
+9
-2
@@ -9,8 +9,15 @@ 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`. Trasy aplikací jsou vedeny pod `/s` na vašem
|
||||
serveru (např. `http://localhost:2020/s/documents/generate`).
|
||||
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`).
|
||||
|
||||
<Note>
|
||||
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).
|
||||
</Note>
|
||||
|
||||
## POST trasa – generovat na požádání
|
||||
|
||||
|
||||
+3
-3
@@ -77,11 +77,11 @@ Spustit tytéž brány CI:
|
||||
yarn lint # oxlint
|
||||
yarn typecheck # tsgo
|
||||
yarn test:unit # unit tests
|
||||
yarn twenty dev --once --dry-run # preview the metadata diff
|
||||
yarn twenty plan # preview the metadata diff
|
||||
```
|
||||
|
||||
Suchý běh vypíše přesně to, co by se změnilo na serveru bez jeho použití –
|
||||
je dobrá závěrečná kontrola. Viz
|
||||
Plán vypíše přesně to, co by se na serveru změnilo, aniž by změny provedl —
|
||||
dobrá závěrečná kontrola. Viz
|
||||
[Testing](/l/cs/developers/extend/apps/operations/testing) a
|
||||
[Synchronizace a obnovy](/l/cs/developers/extend/apps/operations/sync-and-recovery).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user