diff --git a/packages/twenty-docs/docs.json b/packages/twenty-docs/docs.json index c46f011fb8..939eff51cb 100644 --- a/packages/twenty-docs/docs.json +++ b/packages/twenty-docs/docs.json @@ -2161,7 +2161,7 @@ "pages": [ "l/de/developers/extend/apps/operations/overview", "l/de/developers/extend/apps/operations/cli", - "developers/extend/apps/operations/sync-and-recovery", + "l/de/developers/extend/apps/operations/sync-and-recovery", "l/de/developers/extend/apps/operations/testing", "l/de/developers/extend/apps/operations/publishing" ] @@ -4326,7 +4326,7 @@ "pages": [ "l/pt/developers/extend/apps/operations/overview", "l/pt/developers/extend/apps/operations/cli", - "developers/extend/apps/operations/sync-and-recovery", + "l/pt/developers/extend/apps/operations/sync-and-recovery", "l/pt/developers/extend/apps/operations/testing", "l/pt/developers/extend/apps/operations/publishing" ] @@ -4759,7 +4759,7 @@ "pages": [ "l/ro/developers/extend/apps/operations/overview", "l/ro/developers/extend/apps/operations/cli", - "developers/extend/apps/operations/sync-and-recovery", + "l/ro/developers/extend/apps/operations/sync-and-recovery", "l/ro/developers/extend/apps/operations/testing", "l/ro/developers/extend/apps/operations/publishing" ] @@ -5192,7 +5192,7 @@ "pages": [ "l/ru/developers/extend/apps/operations/overview", "l/ru/developers/extend/apps/operations/cli", - "developers/extend/apps/operations/sync-and-recovery", + "l/ru/developers/extend/apps/operations/sync-and-recovery", "l/ru/developers/extend/apps/operations/testing", "l/ru/developers/extend/apps/operations/publishing" ] @@ -5625,7 +5625,7 @@ "pages": [ "l/tr/developers/extend/apps/operations/overview", "l/tr/developers/extend/apps/operations/cli", - "developers/extend/apps/operations/sync-and-recovery", + "l/tr/developers/extend/apps/operations/sync-and-recovery", "l/tr/developers/extend/apps/operations/testing", "l/tr/developers/extend/apps/operations/publishing" ] @@ -6058,7 +6058,7 @@ "pages": [ "l/zh/developers/extend/apps/operations/overview", "l/zh/developers/extend/apps/operations/cli", - "developers/extend/apps/operations/sync-and-recovery", + "l/zh/developers/extend/apps/operations/sync-and-recovery", "l/zh/developers/extend/apps/operations/testing", "l/zh/developers/extend/apps/operations/publishing" ] diff --git a/packages/twenty-docs/l/de/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/l/de/developers/extend/apps/getting-started/quick-start.mdx index 247c73bfc7..75ec9ce377 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/getting-started/quick-start.mdx @@ -123,20 +123,22 @@ Verwenden Sie `--once`, um einen einzelnen Build + Sync auszuführen und zu been yarn twenty dev --once ``` -| Befehl | Verhalten | Wann verwenden | -| ------------------------ | ---------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| `yarn twenty dev` | Überwacht und synchronisiert bei jeder Änderung erneut. Läuft, bis Sie es stoppen. | Interaktive lokale Entwicklung. | -| `yarn twenty dev --once` | Einmaliger Build + Sync, beendet sich mit `0` bei Erfolg, mit `1` bei Fehler. | CI, Pre-Commit-Hooks, KI-Agenten, skriptgesteuerte Workflows. | +| Befehl | Verhalten | Wann verwenden | +| ---------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `yarn twenty dev` | Überwacht und synchronisiert bei jeder Änderung erneut. Läuft, bis Sie es stoppen. | Interaktive lokale Entwicklung. | +| `yarn twenty dev --once` | Einmaliger Build + Sync, beendet sich mit `0` bei Erfolg, mit `1` bei Fehler. | CI, Pre-Commit-Hooks, KI-Agenten, skriptgesteuerte Workflows. | +| `yarn twenty dev --once --dry-run` | Erstellt und gibt die Metadatenänderungen aus **ohne sie anzuwenden**. | Prüfen Sie, was eine Synchronisierung ändern würde, bevor Sie sie ausführen. | -Beide Modi benötigen ein authentifiziertes Remote-Repository. +Beide Modi benötigen ein authentifiziertes Remote-Repository. Weitere Informationen zu `--dry-run` finden Sie unter [Synchronisierung & Wiederherstellung](/l/de/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run). ### Dev-Modus-Optionen -| Flag | Beschreibung | -| ------------------------------------- | ----------------------------------------------------------------------------------- | -| `--once` | Einmal erstellen und synchronisieren, dann beenden. | -| `--debounceMs \` | Legt die Entprellzeit für Dateiänderungen in Millisekunden fest (Standard: `2000`). | -| `--verbose` / `--debug` | Zeigt ausführliche Build-Protokolle, Sync-Anfragen und Fehler-Traces an. | +| Flag | Beschreibung | +| ------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `--once` | Einmal erstellen und synchronisieren, dann beenden. | +| `--dry-run` | Mit `--once` können Sie die Metadatenänderungen anzeigen, ohne sie anzuwenden. Schreibt nichts. | +| `--debounceMs \` | Legt die Entprellzeit für Dateiänderungen in Millisekunden fest (Standard: `2000`). | +| `--verbose` / `--debug` | Zeigt ausführliche Build-Protokolle, Sync-Anfragen und Fehler-Traces an. | ## Was Sie erstellen können 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 fa53ea7e44..e5e5b59ce8 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 @@ -200,45 +200,22 @@ export default defineFrontComponent({ Front-Komponenten laufen browserseitig in einem isolierten Web Worker, während [Logikfunktionen](/l/de/developers/extend/apps/logic/logic-functions) serverseitig ausgeführt werden. Es gibt keinen direkten In-Process-Aufruf zwischen beiden – stattdessen ruft eine Front-Komponente eine Logikfunktion über HTTP auf. -Eine mit `httpRouteTriggerSettings` deklarierte Logikfunktion wird unter dem `/s/`-Endpunkt unter `${TWENTY_API_URL}/s\` bereitgestellt. Ihre Front-Komponente ruft diese Route mit `fetch` auf und authentifiziert sich dabei mit dem `TWENTY_APP_ACCESS_TOKEN`, das Twenty in den Worker injiziert. +Eine mit `httpRouteTriggerSettings` deklarierte Logikfunktion wird unter dem `/s/`-Endpunkt unter `${TWENTY_API_URL}/s\` bereitgestellt. Ihre Front-Komponente ruft diese Route mit dem `RestApiClient` aus `twenty-client-sdk/rest` auf, der sich mit dem `TWENTY_APP_ACCESS_TOKEN` authentifiziert, das Twenty in den Worker injiziert. -Ein kleiner wiederverwendbarer Helper hält die Aufrufstellen übersichtlich: - -```ts src/shared/call-app-route.ts -export async function callAppRoute( - path: string, - body: Record, -): Promise { - const apiUrl = process.env.TWENTY_API_URL ?? ''; - const token = process.env.TWENTY_APP_ACCESS_TOKEN; - - const res = await fetch(`${apiUrl}/s${path}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify(body), - }); - - if (!res.ok) { - throw new Error(`Logic function failed (${res.status})`); - } - - return res.json(); -} -``` +Der `RestApiClient` ist genau dafür gemacht. Er liest `TWENTY_API_URL` und `TWENTY_APP_ACCESS_TOKEN` aus der Worker-Umgebung, hängt den Header `Authorization: Bearer` an, serialisiert und parst JSON und löst einen `RestApiClientError` aus, wenn das Token oder die URL fehlt oder die Antwort kein 2xx-Status ist – sodass Sie diesen Boilerplate-Code nicht in jeder Komponente neu implementieren müssen. 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 { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; -import { callAppRoute } from 'src/shared/call-app-route'; +import { RestApiClient } from 'twenty-client-sdk/rest'; const SyncPrs = () => { const execute = async () => { - await callAppRoute('/github/fetch-prs', { + const client = new RestApiClient(); + + await client.post('/s/github/fetch-prs', { owner: 'twentyhq', repo: 'twenty', }); @@ -256,7 +233,7 @@ export default defineFrontComponent({ }); ``` -Der an `callAppRoute` übergebene `path` muss dem `httpRouteTriggerSettings.path` der Logikfunktion entsprechen (das `/s`-Präfix wird vom Helper hinzugefügt): +Der an den Client übergebene Pfad ist der öffentliche Pfad der Route – der `httpRouteTriggerSettings.path` der Logikfunktion, der mit `/s` präfixiert ist. Belasse `isAuthRequired: true`; der Client stellt das App-Zugriffstoken bereit, das Twenty für deine Komponente ausstellt: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -284,6 +261,48 @@ export default defineLogicFunction({ `TWENTY_API_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. +### RestApiClient-Referenz + +Importiere `RestApiClient` aus `twenty-client-sdk/rest`. Er gehört zur gleichen Client-Familie wie `CoreApiClient` und `MetadataApiClient`, zielt jedoch auf die HTTP-Routen deiner App statt auf die GraphQL-API. + +| 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 | + +`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. + +Die Basis-URL und das Token werden standardmäßig aus der Umgebung ermittelt. Gib bei Bedarf – zum Beispiel in Tests – Überschreibungen an den Konstruktor weiter: + +```ts +const client = new RestApiClient({ + baseUrl: 'https://api.example.com', + token: 'my-token', +}); +``` + +Fehlgeschlagene Anfragen lösen einen `RestApiClientError` aus, der `status`, `statusText`, `url` und den geparsten `body` bereitstellt: + +```tsx +import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest'; + +const client = new RestApiClient(); + +try { + const prs = await client.get('/s/github/fetch-prs', { + query: { state: 'open' }, + }); +} catch (error) { + if (error instanceof RestApiClientError) { + console.error(error.status, error.body); + } +} +``` + ## Zugriff auf den Laufzeitkontext Verwenden Sie innerhalb Ihrer Komponente SDK-Hooks, um auf den aktuellen Benutzer, den Datensatz und die Komponenteninstanz zuzugreifen: diff --git a/packages/twenty-docs/l/de/developers/extend/apps/operations/overview.mdx b/packages/twenty-docs/l/de/developers/extend/apps/operations/overview.mdx index 28d1fe8d50..4c75cd1ec3 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/operations/overview.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/operations/overview.mdx @@ -20,6 +20,9 @@ Die **Operationsschicht** umfasst alles, was Sie *an* Ihrer App tun, statt *mit* `yarn twenty`-Referenz – exec, logs, uninstall, remotes. + + Welcher Befehl wann, das Sync-Diff lesen sowie ein Stufenplan zur Wiederherstellung. + Vitest-Setup, Integrationstests, Typprüfung, CI-Workflow. diff --git a/packages/twenty-docs/l/de/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/l/de/developers/extend/apps/operations/sync-and-recovery.mdx new file mode 100644 index 0000000000..238d6454b2 --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/apps/operations/sync-and-recovery.mdx @@ -0,0 +1,111 @@ +--- +title: Synchronisierung & Wiederherstellung +description: Welchen Befehl Sie wann verwenden, wie Sie die Sync-Ausgabe lesen und eine Wiederherstellungsleiter, wenn lokale Metadaten abweichen – bevor es zu einem vollständigen Reset kommt. +icon: compass +--- + +Die lokale App-Entwicklung dreht sich um **Syncing**: Die CLI baut Ihr Manifest neu auf und der Server wendet nur die Differenz zwischen diesem und den Metadaten an, die sich bereits in Ihrem Workspace befinden. Diese Seite behandelt, zu welchem Befehl Sie greifen sollten, wie Sie lesen, was ein Sync geändert hat, und was Sie – der Reihe nach – tun sollten, wenn der lokale Zustand inkonsistent aussieht. + +## Welcher Befehl, wann + + +Für die tägliche lokale Iteration sollten Sie fast immer `yarn twenty dev` verwenden. Bereitstellen und Veröffentlichen sind zum Ausliefern von Releases gedacht, **nicht** für den lokalen Entwicklungszyklus. + + +| Sie möchten … | Befehl | Notizen | +| ------------------------------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Lokal mit Live-Sync iterieren | `yarn twenty dev` | Überwacht Ihre Dateien und synchronisiert bei jeder Änderung. | +| Einmal synchronisieren und beenden (CI, Skripte, Hooks) | `yarn twenty dev --once` | Führt einen Build und einen Sync aus und beendet sich anschließend. | +| Änderungen **anzeigen, ohne sie anzuwenden** | `yarn twenty dev --once --dry-run` | Berechnet und druckt das Diff; schreibt nichts. | +| Die App aus dem Workspace entfernen | `yarn twenty app:uninstall` | Fügen Sie `--yes` hinzu, um die Abfrage zu überspringen. | +| Einen Tarball an einen Server ausliefern | `yarn twenty app:publish --private` | Erfordert eine strikt höhere `package.json`-Version – siehe [Veröffentlichen](/l/de/developers/extend/apps/operations/publishing). | +| Im Marketplace (npm) veröffentlichen | `yarn twenty app:publish` | — | +| Eine bereitgestellte Version installieren/aktualisieren | `yarn twenty app:install` | Installiert die aktuell bereitgestellte Version. | +| Den lokalen Server zurücksetzen und sauber neu starten | `yarn twenty docker:reset` | Löscht **alle** lokalen Daten – letztes Mittel. | + +### Lokaler Sync benötigt keinen Versionssprung + +Die strikt steigende `version`-Regel (`VERSION_ALREADY_EXISTS` beim Deploy, `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION` bei der Installation) gilt für **`app:publish` / `app:install`** – den Release-Pfad. `yarn twenty dev` synchronisiert Ihr Manifest an Ort und Stelle und erfordert niemals eine Versionsänderung, sodass Sie `package.json` nicht anfassen müssen, um zu iterieren. Wenn Sie die Version erhöhen, um eine lokale Änderung zu testen, verwenden Sie den Release-Pfad, obwohl Sie den Entwicklungszyklus benötigen. + +## Die Sync-Ausgabe lesen + +Jeder Sync gibt die Metadatenänderungen aus, die er angewendet hat (oder anwenden würde, mit `--dry-run`): + +```text filename="Terminal" +Metadata changes: 2 created, 1 updated, 1 deleted + created objectMetadata rocket + created fieldMetadata timelineActivities + updated fieldMetadata launchedAt + deleted pageLayout legacyTab +✓ Synced +``` + +Dies ist Ihre erste Diagnose: Sie zeigt Ihnen genau, welche Objekte, Felder und Layouts sich geändert haben, sodass Sie bestätigen können, dass ein Sync das Erwartete getan hat, bevor Sie die UI prüfen. + +Wenn ein Sync bei einer einzelnen Entität fehlschlägt, nennt der Fehler die betreffende Entität und ihren `universalIdentifier`, zum Beispiel: + +```text +Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) failed +``` + +Verwenden Sie diesen Bezeichner, um die Entität in Ihrem Manifest (und bei Bedarf im Workspace) zu finden, anstatt zu raten, welche in Konflikt steht. + +## Änderungen vorab ansehen (Dry Run) + +`yarn twenty dev --once --dry-run` baut Ihr Manifest, fragt den Server nach dem Migrationsplan und gibt ihn aus – **ohne irgendetwas anzuwenden**. Dies ist der sichere Weg, um zu beantworten: "Was würde dieser Sync ändern?", bevor Sie sich darauf festlegen. + +```bash filename="Terminal" +yarn twenty dev --once --dry-run +``` + +```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 +``` + +Ein Dry Run: + +* **Schreibt nichts** – keine Metadatenmigration, kein Update von App-Einträgen, keine Änderungen an Standardrollen/-Tabs und keine API-Client-Generierung. +* Liefert dasselbe **Diff**, das ein echter Sync anwenden würde, sodass Sie erstellte/aktualisierte/gelöschte Entitäten im Voraus prüfen können. +* Ist nützlich vor einer riskanten Änderung, bei der Überprüfung einer KI-generierten Änderung oder in einem Skript, das fehlschlagen soll, wenn eine unerwartete Änderung kurz vor der Anwendung steht. + + +Ein Dry Run zeigt nur **Metadaten**-Änderungen an und erfordert, dass die App mindestens einmal synchronisiert wurde (damit der Workspace sie kennt). Wenn Sie ihn gegen eine App ausführen, die noch nie synchronisiert wurde, meldet der Server, dass die App nicht installiert ist – führen Sie zuerst einmal `yarn twenty dev` aus. + + +## Wiederherstellungsleiter + +Wenn lokale Metadaten falsch aussehen, eskalieren Sie in dieser Reihenfolge und stoppen Sie, sobald Sie nicht mehr blockiert sind. Jeder Schritt ist störender als der vorherige. + +1. **Erneut synchronisieren.** Führen Sie `yarn twenty dev --once` erneut aus. Syncs sind idempotent – das erneute Ausführen eines sauberen Manifests ist sicher und löst oft eine vorübergehende Störung. +2. **Plan ansehen.** Führen Sie `yarn twenty dev --once --dry-run` aus, um genau zu sehen, was der nächste Sync zu ändern beabsichtigt, ohne es anzuwenden. +3. **Benannten Fehler lesen.** Wenn ein Sync fehlschlägt, notieren Sie sich den Metadatentyp und den `universalIdentifier` in der Meldung (siehe oben) und lokalisieren Sie diese Entität in Ihrem Manifest. Ein Konflikt weist in der Regel auf einen doppelten oder wiederverwendeten Bezeichner hin. +4. **Deinstallieren und neu installieren.** `yarn twenty app:uninstall`, dann erneut synchronisieren (`yarn twenty dev`). Dies baut die Metadaten der App aus einem sauberen Zustand wieder auf, während der Rest Ihres Workspaces intakt bleibt. +5. **Vollständiger Reset (letztes Mittel).** `yarn twenty docker:reset`, dann erneut seeden und synchronisieren. + + +`yarn twenty docker:reset` löscht **alle** Daten in Ihrer lokalen Instanz – jeden Workspace, jeden Eintrag und jede App. Verwenden Sie ihn nur, wenn die vorherigen Schritte fehlgeschlagen sind. + + + +Auf einen Metadatenfehler gestoßen? Bitte [öffnen Sie ein Issue](https://github.com/twentyhq/twenty/issues/new/choose) und fügen Sie die fehlerhafte Migrationsmeldung (mit ihrem Metadatentyp und `universalIdentifier`), die `Metadata changes`-Ausgabe aus dem Sync sowie die von Ihnen ausgeführten Befehle bei. + + +## Gleichzeitige Syncs auf einem Workspace vermeiden + +Syncing wendet Metadatenmigrationen an. Mehrere Sync-, Deploy- oder Installationsvorgänge gleichzeitig gegen **denselben Workspace** auszuführen – zum Beispiel mehrere Terminals oder KI-Agenten, die parallel iterieren – kann diese Migrationen verschachteln und Metadaten in einem teilweise angewendeten Zustand zurücklassen. + +Der Server serialisiert Syncs pro Workspace, um dies zu verhindern, aber Sie sollten dennoch sensible Metadatenoperationen über einen **einzelnen** Prozess leiten, anstatt sie gleichzeitig auszulösen. Wenn Sie die Entwicklung mit mehreren Agenten orchestrieren, leiten Sie deren Sync-/Deploy-/Install-Aufrufe durch eine Queue, sodass immer nur einer gleichzeitig läuft. + +## Fehler voneinander unterscheiden + +Wenn etwas schiefläuft, ermöglichen Ihnen das Metadaten-Diff und benannte Fehler, den Fehler einzuordnen: + +* **Manifest-Build-Fehler** – die CLI schlägt vor dem Sync fehl (`MANIFEST_BUILD_FAILED`, `TYPECHECK_FAILED`); beheben Sie den Quellcode Ihrer App. +* **Sync-/Migrationsfehler** – der Build ist erfolgreich, aber das Anwenden des Diffs schlägt fehl und nennt die Entität und den `universalIdentifier`; beheben Sie die widersprüchlichen Metadaten. +* **App-Code-Laufzeitfehler** — die Synchronisierung ist erfolgreich, aber Ihre Logikfunktionen oder Komponenten verhalten sich zur Laufzeit unerwartet; überprüfen Sie die [Funktionsprotokolle](/l/de/developers/extend/apps/operations/cli). +* **Lokaler Instanzzustand** — nichts davon trifft zu und der Workspace sieht immer noch falsch aus; arbeiten Sie die Wiederherstellungsleiter nach unten ab. diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/getting-started/quick-start.mdx index b8cc35b6db..5a451c47a2 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/getting-started/quick-start.mdx @@ -123,18 +123,20 @@ Passe `--once` para executar uma única compilação + sincronização e sair yarn twenty dev --once ``` -| Comando | Comportamento | Quando usar | -| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -| `yarn twenty dev` | Monitora e ressincroniza a cada alteração. Fica em execução até você interrompê-lo. | Desenvolvimento local interativo. | -| `yarn twenty dev --once` | Executa uma única compilação + sincronização e, em seguida, encerra com o código `0` em caso de sucesso ou `1` em caso de falha. | Scripts, CI, hooks de pre-commit, agentes de IA e fluxos de trabalho com script. | +| Comando | Comportamento | Quando usar | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| `yarn twenty dev` | Monitora e ressincroniza a cada alteração. Fica em execução até você interrompê-lo. | Desenvolvimento local interativo. | +| `yarn twenty dev --once` | Executa uma única compilação + sincronização e, em seguida, encerra com o código `0` em caso de sucesso ou `1` em caso de falha. | Scripts, CI, hooks de pre-commit, agentes de IA e fluxos de trabalho com script. | +| `yarn twenty dev --once --dry-run` | Compila e imprime as alterações de metadados **sem aplicá-las**. | Inspecionar o que uma sincronização mudaria antes de confirmá-la. | -Ambos os modos precisam de um remoto autenticado. +Ambos os modos precisam de um remoto autenticado. Veja [Sincronização e recuperação](/l/pt/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run) para mais detalhes sobre `--dry-run`. ### Opções do modo de desenvolvimento | Opção | Descrição | | ------------------------------------- | ------------------------------------------------------------------------------------------------- | | `--once` | Compila e sincroniza uma vez e, em seguida, sai. | +| `--dry-run` | Com `--once`, visualize as alterações de metadados sem aplicá‑las. Não grava nada. | | `--debounceMs \` | Define o atraso de debounce para alterações de arquivo em milissegundos (padrão: `2000`). | | `--verbose` / `--debug` | Mostra registros detalhados de compilação, solicitações de sincronização e rastreamentos de erro. | 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 a649390984..6d19c0f09b 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 @@ -200,45 +200,22 @@ export default defineFrontComponent({ Os componentes de front são executados no navegador em um Web Worker isolado, 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` é exposta sob o endpoint `/s/` em `${TWENTY_API_URL}/s\`. Seu componente de front chama essa rota com `fetch`, autenticando com o `TWENTY_APP_ACCESS_TOKEN` que Twenty injeta no worker. +Uma função lógica declarada com `httpRouteTriggerSettings` é exposta sob o endpoint `/s/` em `${TWENTY_API_URL}/s\`. Seu componente de front chama essa rota com o `RestApiClient` de `twenty-client-sdk/rest`, que autentica com o `TWENTY_APP_ACCESS_TOKEN` que a Twenty injeta no worker. -Um pequeno helper reutilizável mantém os locais de chamada limpos: - -```ts src/shared/call-app-route.ts -export async function callAppRoute( - path: string, - body: Record, -): Promise { - const apiUrl = process.env.TWENTY_API_URL ?? ''; - const token = process.env.TWENTY_APP_ACCESS_TOKEN; - - const res = await fetch(`${apiUrl}/s${path}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify(body), - }); - - if (!res.ok) { - throw new Error(`Logic function failed (${res.status})`); - } - - return res.json(); -} -``` +O `RestApiClient` foi criado exatamente para isso. Ele lê `TWENTY_API_URL` e `TWENTY_APP_ACCESS_TOKEN` do ambiente do worker, adiciona o cabeçalho `Authorization: Bearer`, serializa e analisa JSON e lança um `RestApiClientError` quando o token ou a URL estão ausentes ou a resposta não é 2xx — para que você não precise reimplementar esse boilerplate em todos os componentes. 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 { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; -import { callAppRoute } from 'src/shared/call-app-route'; +import { RestApiClient } from 'twenty-client-sdk/rest'; const SyncPrs = () => { const execute = async () => { - await callAppRoute('/github/fetch-prs', { + const client = new RestApiClient(); + + await client.post('/s/github/fetch-prs', { owner: 'twentyhq', repo: 'twenty', }); @@ -256,7 +233,7 @@ export default defineFrontComponent({ }); ``` -O `path` passado para `callAppRoute` deve corresponder ao `httpRouteTriggerSettings.path` da função lógica (o prefixo `/s` é adicionado pelo helper): +O caminho passado para o cliente é o caminho público da rota — o `httpRouteTriggerSettings.path` da função de lógica, prefixado com `/s`. Mantenha `isAuthRequired: true`; o cliente fornece o token de acesso do app que o Twenty emite para o seu componente: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -284,6 +261,48 @@ export default defineLogicFunction({ `TWENTY_API_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. +### Referência do `RestApiClient` + +Importe `RestApiClient` de `twenty-client-sdk/rest`. Ele pertence à mesma família de clientes que `CoreApiClient` e `MetadataApiClient`, mas tem como alvo as rotas HTTP do seu app em vez da API GraphQL. + +| 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 | + +`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. + +A URL base e o token são resolvidos do ambiente por padrão. Passe substituições (overrides) para o construtor quando necessário — por exemplo, em testes: + +```ts +const client = new RestApiClient({ + baseUrl: 'https://api.example.com', + token: 'my-token', +}); +``` + +Requisições com falha geram um erro `RestApiClientError` que expõe `status`, `statusText`, `url` e o `body` analisado: + +```tsx +import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest'; + +const client = new RestApiClient(); + +try { + const prs = await client.get('/s/github/fetch-prs', { + query: { state: 'open' }, + }); +} catch (error) { + if (error instanceof RestApiClientError) { + console.error(error.status, error.body); + } +} +``` + ## Acessando o contexto de execução Dentro do seu componente, use hooks do SDK para acessar o usuário atual, o registro e a instância do componente: diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/operations/overview.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/operations/overview.mdx index ff201f68e8..9b6e4fa61c 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/operations/overview.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/operations/overview.mdx @@ -20,6 +20,9 @@ A **camada de operações** é tudo o que você faz *para* o seu app em vez de * Referência do `yarn twenty` — exec, logs, uninstall, remotes. + + Qual comando usar e quando, leitura do diff de sincronização e etapas de recuperação. + Configuração do Vitest, testes de integração, verificação de tipos, fluxo de trabalho de CI. diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/operations/sync-and-recovery.mdx new file mode 100644 index 0000000000..4223101ff4 --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/apps/operations/sync-and-recovery.mdx @@ -0,0 +1,111 @@ +--- +title: Sincronização e recuperação +description: Qual comando usar em cada caso, como ler a saída da sincronização e uma escada de recuperação para quando os metadados locais se desalinham — antes de chegar a um reset completo. +icon: bússola +--- + +O desenvolvimento local de apps gira em torno da **sincronização**: a CLI reconstrói seu manifesto e o servidor aplica apenas a diferença entre ele e os metadados que já estão no seu workspace. Esta página cobre qual comando usar, como ler o que uma sincronização mudou e o que fazer — em ordem — quando o estado local parece inconsistente. + +## Qual comando usar e quando + + +Para a iteração local do dia a dia, quase sempre você vai querer `yarn twenty dev`. Fazer deploy e publicar servem para entregar releases, **não** para o ciclo local. + + +| Você quer… | Comando | Notas | +| ------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| Iterar localmente com sincronização em tempo real | `yarn twenty dev` | Monitora seus arquivos e sincroniza a cada alteração. | +| Sincronizar uma vez e sair (CI, scripts, hooks) | `yarn twenty dev --once` | Um build + sincronização, depois encerra. | +| Prever mudanças **sem aplicá-las** | `yarn twenty dev --once --dry-run` | Calcula e imprime o diff; não grava nada. | +| Remover o app do workspace | `yarn twenty app:uninstall` | Adicione `--yes` para pular o prompt. | +| Enviar um tarball para um servidor | `yarn twenty app:publish --private` | Requer uma versão **estritamente maior** em `package.json` — veja [Publicação](/l/pt/developers/extend/apps/operations/publishing). | +| Publicar no marketplace (npm) | `yarn twenty app:publish` | — | +| Instalar / atualizar uma versão implantada | `yarn twenty app:install` | Instala a versão atualmente implantada. | +| Limpar o servidor local e começar do zero | `yarn twenty docker:reset` | Exclui **todos** os dados locais — último recurso. | + +### A sincronização local não precisa de incremento de versão + +A regra de `version` estritamente crescente (`VERSION_ALREADY_EXISTS` no deploy, `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION` na instalação) se aplica a **`app:publish` / `app:install`** — o caminho de release. `yarn twenty dev` sincroniza seu manifesto no lugar e nunca exige mudança de versão, então você não precisa mexer em `package.json` para iterar. Se você se pegar aumentando a versão para testar uma mudança local, está usando o caminho de release quando o que quer é o ciclo de desenvolvimento. + +## Lendo a saída da sincronização + +Cada sincronização imprime as mudanças de metadados que aplicou (ou aplicaria, com `--dry-run`): + +```text filename="Terminal" +Metadata changes: 2 created, 1 updated, 1 deleted + created objectMetadata rocket + created fieldMetadata timelineActivities + updated fieldMetadata launchedAt + deleted pageLayout legacyTab +✓ Synced +``` + +Este é seu primeiro diagnóstico: ele mostra exatamente quais objetos, campos e layouts mudaram, para que você possa confirmar que uma sincronização fez o que esperava antes de conferir na interface. + +Quando uma sincronização falha em uma única entidade, o erro nomeia a entidade com problema e seu `universalIdentifier`, por exemplo: + +```text +Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) failed +``` + +Use esse identificador para encontrar a entidade no seu manifesto (e, se necessário, no workspace), em vez de adivinhar qual está em conflito. + +## Visualizando mudanças (dry run) + +`yarn twenty dev --once --dry-run` compila seu manifesto, pede ao servidor o plano de migração e o imprime — **sem aplicar nada**. É a forma segura de responder "o que esta sincronização mudaria?" antes de se comprometer com ela. + +```bash filename="Terminal" +yarn twenty dev --once --dry-run +``` + +```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 +``` + +Um dry run: + +* **Não grava nada** — nenhuma migração de metadados, nenhuma atualização de registro de aplicativo, nenhuma mudança de função/aba padrão e nenhuma geração de cliente de API. +* Retorna o **mesmo diff** que uma sincronização real aplicaria, para que você possa revisar previamente as entidades criadas/atualizadas/excluídas. +* É útil antes de uma mudança arriscada, ao revisar uma mudança gerada por IA ou em um script que deve falhar se uma mudança inesperada estiver prestes a ser aplicada. + + +Um dry run só antevê mudanças de **metadados**, e exige que o app tenha sido sincronizado ao menos uma vez (para que o workspace o conheça). Se você rodar isso em um app que nunca foi sincronizado, o servidor informa que o app não está instalado — rode `yarn twenty dev` uma vez antes. + + +## Escada de recuperação + +Quando os metadados locais parecerem errados, aumente o nível nesta ordem e pare assim que estiver desbloqueado. Cada etapa é mais disruptiva que a anterior. + +1. **Ressincronizar.** Rode `yarn twenty dev --once` novamente. Sincronizações são idempotentes — rodar novamente um manifesto limpo é seguro e frequentemente resolve um problema transitório. +2. **Prever o plano.** Rode `yarn twenty dev --once --dry-run` para ver exatamente o que a próxima sincronização pretende mudar, sem aplicá-la. +3. **Leia o erro nomeado.** Se uma sincronização falhar, anote o tipo de metadado e o `universalIdentifier` na mensagem (veja acima) e localize essa entidade no seu manifesto. Um conflito geralmente aponta para um identificador duplicado ou reutilizado. +4. **Desinstalar e reinstalar.** `yarn twenty app:uninstall`, depois sincronize novamente (`yarn twenty dev`). Isso reconstrói os metadados do app a partir do zero, mantendo o restante do seu workspace intacto. +5. **Reset completo (último recurso).** `yarn twenty docker:reset`, depois faça o seeding e a sincronização novamente. + + +`yarn twenty docker:reset` exclui **todos** os dados da sua instância local — todos os workspaces, registros e apps. Use isso somente depois que as etapas anteriores tiverem falhado. + + + +Encontrou um erro de metadados? Por favor, [abra uma issue](https://github.com/twentyhq/twenty/issues/new/choose) e inclua a mensagem de migração que falhou (com seu tipo de metadado e `universalIdentifier`), a saída de `Metadata changes` da sincronização e os comandos que você rodou. + + +## Evite sincronizações concorrentes em um único workspace + +Sincronizar aplica migrações de metadados. Executar várias operações de sincronização, deploy ou instalação contra o **mesmo workspace ao mesmo tempo** — por exemplo, múltiplos terminais ou agentes de IA iterando em paralelo — pode intercalar essas migrações e deixar os metadados em um estado parcialmente aplicado. + +O servidor serializa sincronizações por workspace para evitar isso, mas você ainda deve direcionar operações sensíveis de metadados por um **único** processo em vez de dispará-las concorrentemente. Se você orquestra o desenvolvimento com múltiplos agentes, encaminhe as chamadas de sincronização/deploy/instalação deles por uma única fila, para que apenas uma rode por vez. + +## Diferenciando tipos de falha + +Quando algo dá errado, o diff de metadados e os erros nomeados permitem localizar a falha: + +* **Erro de build do manifesto** — a CLI falha antes de sincronizar (`MANIFEST_BUILD_FAILED`, `TYPECHECK_FAILED`); corrija o código-fonte do seu app. +* **Erro de sincronização / migração** — o build é bem-sucedido, mas aplicar o diff falha, nomeando a entidade e o `universalIdentifier`; corrija os metadados em conflito. +* **Erro de tempo de execução no código do app** — a sincronização é concluída com êxito, mas suas funções de lógica ou componentes se comportam de forma incorreta em tempo de execução; verifique os [logs de função](/l/pt/developers/extend/apps/operations/cli). +* **Estado da instância local** — nenhuma das opções acima e o espaço de trabalho ainda parece incorreto; prossiga descendo na escada de recuperação. diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/getting-started/quick-start.mdx index d81e03956f..7815182286 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/getting-started/quick-start.mdx @@ -123,18 +123,20 @@ Adăugați `--once` pentru a rula un singur build + sync și a ieși — acelaș yarn twenty dev --once ``` -| Comandă | Comportament | Când se folosește | -| ------------------------ | ------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -| `yarn twenty dev` | Monitorizează și resincronizează la fiecare modificare. Rulează până când îl opriți. | Dezvoltare locală interactivă. | -| `yarn twenty dev --once` | Un singur build + sync, iese cu `0` la succes, `1` la eșec. | CI, hook-uri pre-commit, agenți AI, fluxuri de lucru scriptate. | +| Comandă | Comportament | Când se folosește | +| ---------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | +| `yarn twenty dev` | Monitorizează și resincronizează la fiecare modificare. Rulează până când îl opriți. | Dezvoltare locală interactivă. | +| `yarn twenty dev --once` | Un singur build + sync, iese cu `0` la succes, `1` la eșec. | CI, hook-uri pre-commit, agenți AI, fluxuri de lucru scriptate. | +| `yarn twenty dev --once --dry-run` | Construiește și afișează modificările de metadate **fără a le aplica**. | Inspectarea modificărilor pe care le-ar face o sincronizare înainte de a le confirma. | -Ambele moduri necesită o conexiune la distanță autentificată. +Ambele moduri necesită o conexiune la distanță autentificată. Vezi [Sincronizare și recuperare](/l/ro/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run) pentru mai multe detalii despre `--dry-run`. ### Opțiuni pentru modul de dezvoltare | Opțiune | Descriere | | ------------------------------------- | ------------------------------------------------------------------------------------------------ | | `--once` | Construiește și sincronizează o singură dată, apoi iese. | +| `--dry-run` | Cu `--once`, poți previzualiza modificările de metadate fără a le aplica. Nu scrie nimic. | | `--debounceMs \` | Setează întârzierea de debounce pentru modificarea fișierului în milisecunde (implicit: `2000`). | | `--verbose` / `--debug` | Afișează jurnale detaliate de construire, cereri de sincronizare și urme ale erorilor. | 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 94673d0155..bfa3b1cceb 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 @@ -200,45 +200,22 @@ export default defineFrontComponent({ Componentele de front rulează în browser într-un Web Worker izolat, î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 expusă sub endpoint-ul `/s/` la `${TWENTY_API_URL}/s\`. Componenta ta de front apelează acea rută cu `fetch`, autentificându-se cu `TWENTY_APP_ACCESS_TOKEN` pe care Twenty îl injectează în worker. +O funcție logică declarată cu `httpRouteTriggerSettings` este expusă sub endpoint-ul `/s/` la `${TWENTY_API_URL}/s\`. Componenta ta de front apelează acea rută cu `RestApiClient` din `twenty-client-sdk/rest`, care se autentifică folosind `TWENTY_APP_ACCESS_TOKEN` pe care Twenty îl injectează în worker. -Un mic utilitar reutilizabil menține locurile de apel curate: - -```ts src/shared/call-app-route.ts -export async function callAppRoute( - path: string, - body: Record, -): Promise { - const apiUrl = process.env.TWENTY_API_URL ?? ''; - const token = process.env.TWENTY_APP_ACCESS_TOKEN; - - const res = await fetch(`${apiUrl}/s${path}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify(body), - }); - - if (!res.ok) { - throw new Error(`Logic function failed (${res.status})`); - } - - return res.json(); -} -``` +`RestApiClient` este creat exact pentru acest scop. Acesta citește `TWENTY_API_URL` și `TWENTY_APP_ACCESS_TOKEN` din mediul worker-ului, atașează antetul `Authorization: Bearer`, serializează și parsează JSON și aruncă un `RestApiClientError` atunci când token-ul sau URL-ul lipsesc sau când răspunsul nu este 2xx — astfel încât să nu trebuiască să reimplementezi acel boilerplate în fiecare componentă. 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 { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; -import { callAppRoute } from 'src/shared/call-app-route'; +import { RestApiClient } from 'twenty-client-sdk/rest'; const SyncPrs = () => { const execute = async () => { - await callAppRoute('/github/fetch-prs', { + const client = new RestApiClient(); + + await client.post('/s/github/fetch-prs', { owner: 'twentyhq', repo: 'twenty', }); @@ -256,7 +233,7 @@ export default defineFrontComponent({ }); ``` -`path` transmis către `callAppRoute` trebuie să corespundă cu `httpRouteTriggerSettings.path` al funcției logice (prefixul `/s` este adăugat de utilitar): +Calea transmisă către client este calea publică a rutei — proprietatea `httpRouteTriggerSettings.path` a funcției logice, cu prefixul `/s`. Păstrează `isAuthRequired: true`; clientul furnizează tokenul de acces al aplicației Twenty mints pentru componenta ta: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -284,6 +261,48 @@ export default defineLogicFunction({ `TWENTY_API_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. +### Referință `RestApiClient` + +Importă `RestApiClient` din `twenty-client-sdk/rest`. Face parte din aceeași familie de clienți ca `CoreApiClient` și `MetadataApiClient`, dar vizează rutele HTTP ale aplicației tale în locul API-ului GraphQL. + +| 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 | + +`options` acceptă `headers`, `query` (un „record” de parametri de query-string; valorile nule sau nealocate 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. + +URL-ul de bază și tokenul sunt rezolvate din mediu în mod implicit. Transmite suprascrieri către constructor atunci când este necesar — de exemplu, în teste: + +```ts +const client = new RestApiClient({ + baseUrl: 'https://api.example.com', + token: 'my-token', +}); +``` + +Cererile eșuate declanșează o eroare `RestApiClientError` care expune `status`, `statusText`, `url` și `body` analizat: + +```tsx +import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest'; + +const client = new RestApiClient(); + +try { + const prs = await client.get('/s/github/fetch-prs', { + query: { state: 'open' }, + }); +} catch (error) { + if (error instanceof RestApiClientError) { + console.error(error.status, error.body); + } +} +``` + ## Accesarea contextului de rulare În interiorul componentei, folosiți hook-urile SDK pentru a accesa utilizatorul curent, înregistrarea curentă și instanța componentei: diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/operations/overview.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/operations/overview.mdx index b46177b16f..4772d03062 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/operations/overview.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/operations/overview.mdx @@ -20,6 +20,9 @@ icon: rocket Referință pentru `yarn twenty` — exec, logs, uninstall, remotes. + + Ce comandă și când, citirea diferențelor de sincronizare și o schemă de recuperare. + Configurare Vitest, teste de integrare, verificare a tipurilor, flux de lucru CI. diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/operations/sync-and-recovery.mdx new file mode 100644 index 0000000000..d6070fb06e --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/apps/operations/sync-and-recovery.mdx @@ -0,0 +1,111 @@ +--- +title: Sincronizare și recuperare +description: Ce comandă să folosești și când, cum să citești rezultatul sincronizării și un plan în trepte de recuperare pentru situațiile în care metadatele locale deviază — înainte de a ajunge la o resetare completă. +icon: busolă +--- + +Dezvoltarea locală de aplicații se învârte în jurul **sincronizării**: CLI-ul reconstruiește manifestul și serverul aplică doar diferența dintre acesta și metadatele deja existente în spațiul tău de lucru. Această pagină explică ce comandă să folosești, cum să citești ce a modificat o sincronizare și ce să faci — în ordine — atunci când starea locală pare inconsistentă. + +## Ce comandă și când + + +Pentru iterațiile locale de zi cu zi vei dori aproape întotdeauna `yarn twenty dev`. Publicarea și deploy-ul sunt pentru lansarea de versiuni, **nu** pentru bucla locală. + + +| Vrei să… | Comandă | Notițe | +| -------------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| Iterează local cu sincronizare în timp real | `yarn twenty dev` | Monitorizează fișierele și sincronizează la fiecare modificare. | +| Sincronizează o singură dată și iese (CI, scripturi, hook-uri) | `yarn twenty dev --once` | O singură compilare + sincronizare, apoi iese. | +| Previzualizează modificările **fără a le aplica** | `yarn twenty dev --once --dry-run` | Calculează și afișează diff-ul; nu scrie nimic. | +| Elimină aplicația din spațiul de lucru | `yarn twenty app:uninstall` | Adaugă `--yes` pentru a sări peste prompt. | +| Trimite un tarball către un server | `yarn twenty app:publish --private` | Necesită o versiune `package.json` **strict mai mare** — vezi [Publicare](/l/ro/developers/extend/apps/operations/publishing). | +| Publică în marketplace (npm) | `yarn twenty app:publish` | — | +| Instalează / actualizează o versiune deja implementată | `yarn twenty app:install` | Instalează versiunea implementată în prezent. | +| Șterge serverul local și pornește de la zero | `yarn twenty docker:reset` | Șterge **toate** datele locale — ultimă soluție. | + +### Sincronizarea locală nu are nevoie de incrementarea versiunii + +Regula de `version` strict crescătoare (`VERSION_ALREADY_EXISTS` la deploy, `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION` la instalare) se aplică pentru **`app:publish` / `app:install`** — calea de release. `yarn twenty dev` sincronizează manifestul pe loc și nu necesită niciodată schimbarea versiunii, astfel încât nu trebuie să atingi `package.json` pentru a itera. Dacă ajungi să crești versiunea ca să testezi o modificare locală, folosești calea de release atunci când ai nevoie de bucla de dezvoltare. + +## Citirea rezultatului sincronizării + +Fiecare sincronizare afișează modificările de metadate pe care le-a aplicat (sau le-ar aplica, cu `--dry-run`): + +```text filename="Terminal" +Metadata changes: 2 created, 1 updated, 1 deleted + created objectMetadata rocket + created fieldMetadata timelineActivities + updated fieldMetadata launchedAt + deleted pageLayout legacyTab +✓ Synced +``` + +Acesta este primul tău instrument de diagnostic: îți spune exact ce obiecte, câmpuri și layout-uri s-au schimbat, astfel încât să poți confirma că o sincronizare a făcut ce te așteptai înainte să verifici interfața. + +Când o sincronizare eșuează pe o singură entitate, eroarea numește entitatea problematică și `universalIdentifier`-ul acesteia, de exemplu: + +```text +Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) failed +``` + +Folosește acel identificator pentru a găsi entitatea în manifest (și, dacă este nevoie, în spațiul de lucru) în loc să ghicești care intră în conflict. + +## Previzualizarea modificărilor (dry run) + +`yarn twenty dev --once --dry-run` construiește manifestul, cere serverului planul de migrare și îl afișează — **fără a aplica nimic**. Este modalitatea sigură de a răspunde la întrebarea „ce ar schimba această sincronizare?” înainte de a te angaja la ea. + +```bash filename="Terminal" +yarn twenty dev --once --dry-run +``` + +```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 +``` + +Un dry run: + +* **Nu scrie nimic** — fără migrare de metadate, fără actualizare a înregistrării aplicației, fără modificări ale rolului sau filei implicite și fără generare de client API. +* Returnează **același diff** pe care l-ar aplica o sincronizare reală, astfel încât poți revizui dinainte entitățile create/actualizate/șterse. +* Este util înaintea unei modificări riscante, când revizuiești o modificare generată de AI sau într-un script care ar trebui să eșueze dacă o modificare neașteptată este pe cale să fie aplicată. + + +Un dry run previzualizează doar modificările de **metadate** și necesită ca aplicația să fi fost sincronizată cel puțin o dată (astfel încât spațiul de lucru să știe de ea). Dacă îl rulezi pentru o aplicație care nu a fost niciodată sincronizată, serverul va raporta că aplicația nu este instalată — rulează mai întâi o dată `yarn twenty dev`. + + +## Plan de recuperare în trepte + +Când metadatele locale par greșite, escaladează în această ordine și oprește-te de îndată ce ești deblocat. Fiecare pas este mai disruptiv decât precedentul. + +1. **Resincronizează.** Rulează din nou `yarn twenty dev --once`. Sincronizările sunt idempotente — rularea din nou a unui manifest curat este sigură și rezolvă adesea o problemă temporară. +2. **Previzualizează planul.** Rulează `yarn twenty dev --once --dry-run` pentru a vedea exact ce intenționează să schimbe următoarea sincronizare, fără a o aplica. +3. **Citește eroarea nominalizată.** Dacă o sincronizare eșuează, notează tipul de metadate și `universalIdentifier`-ul din mesaj (vezi mai sus) și localizează acea entitate în manifest. Un conflict indică de obicei un identificator duplicat sau reutilizat. +4. **Dezinstalează și reinstalează.** `yarn twenty app:uninstall`, apoi sincronizează din nou (`yarn twenty dev`). Acest lucru reconstruiește metadatele aplicației de la zero, păstrând în același timp restul spațiului de lucru intact. +5. **Resetare completă (ultimă soluție).** `yarn twenty docker:reset`, apoi reinițializează datele și resincronizează. + + +`yarn twenty docker:reset` șterge **toate** datele din instanța ta locală — fiecare spațiu de lucru, înregistrare și aplicație. Folosește această comandă doar după ce pașii anteriori au eșuat. + + + +Ai întâlnit o eroare de metadate? Te rugăm să [deschizi un issue](https://github.com/twentyhq/twenty/issues/new/choose) și să incluzi mesajul de migrare eșuată (cu tipul de metadate și `universalIdentifier`-ul), rezultatul `Metadata changes` din sincronizare și comenzile pe care le-ai rulat. + + +## Evită sincronizările concurente pe același spațiu de lucru + +Sincronizarea aplică migrațiile de metadate. Rularea mai multor operațiuni de sincronizare, deploy sau instalare împotriva aceluiași spațiu de lucru în același timp — de exemplu, mai multe terminale sau agenți AI care iterează în paralel — poate intercala acele migrații și poate lăsa metadatele într-o stare aplicată parțial. + +Serverul serializează sincronizările per spațiu de lucru pentru a preveni acest lucru, dar ar trebui totuși să treci operațiunile sensibile de metadate printr-un proces **unic**, în loc să le declanșezi concurent. Dacă orchestrezi dezvoltarea cu mai mulți agenți, rutează apelurile lor de sync/deploy/install printr-o singură coadă, astfel încât să ruleze doar unul la un moment dat. + +## Deosebirea tipurilor de erori + +Când ceva nu merge bine, diff-ul de metadate și erorile nominalizate îți permit să localizezi eșecul: + +* **Eroare de construire a manifestului** — CLI-ul eșuează înainte de sincronizare (`MANIFEST_BUILD_FAILED`, `TYPECHECK_FAILED`); repară sursa aplicației. +* **Eroare de sincronizare / migrare** — build-ul reușește, dar aplicarea diff-ului eșuează, menționând entitatea și `universalIdentifier`-ul; repară metadatele care intră în conflict. +* **Eroare de execuție în codul aplicației** — sincronizarea reușește, dar funcțiile sau componentele tale logice se comportă incorect la execuție; verifică [jurnalele funcțiilor](/l/ro/developers/extend/apps/operations/cli). +* **Stare locală a instanței** — niciuna dintre cele de mai sus și spațiul de lucru tot arată greșit; coboară pe scara de recuperare. diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/getting-started/quick-start.mdx index 00dc83d9b3..151bab193f 100644 --- a/packages/twenty-docs/l/ru/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/apps/getting-started/quick-start.mdx @@ -123,20 +123,22 @@ yarn twenty dev yarn twenty dev --once ``` -| Команда | Поведение | Когда использовать | -| ------------------------ | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | -| `yarn twenty dev` | Отслеживает и повторно синхронизирует при каждом изменении. Продолжает работать, пока вы его не остановите. | Интерактивная локальная разработка. | -| `yarn twenty dev --once` | Одна сборка и синхронизация, завершает работу с кодом `0` при успехе и `1` при ошибке. | CI, хуки pre-commit, AI-агенты, скриптовые рабочие процессы. | +| Команда | Поведение | Когда использовать | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| `yarn twenty dev` | Отслеживает и повторно синхронизирует при каждом изменении. Продолжает работать, пока вы его не остановите. | Интерактивная локальная разработка. | +| `yarn twenty dev --once` | Одна сборка и синхронизация, завершает работу с кодом `0` при успехе и `1` при ошибке. | CI, хуки pre-commit, AI-агенты, скриптовые рабочие процессы. | +| `yarn twenty dev --once --dry-run` | Создает и выводит изменения метаданных **без их применения**. | Проверка того, какие изменения внесет синхронизация, прежде чем зафиксировать их. | -Оба режима требуют аутентифицированного удалённого репозитория. +Оба режима требуют аутентифицированного удалённого репозитория. Смотрите раздел [Syncing & recovery](/l/ru/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run) для получения дополнительной информации о `--dry-run`. ### Параметры режима разработки -| Флаг | Описание | -| ------------------------------------- | ------------------------------------------------------------------------------------- | -| `--once` | Выполнить сборку и синхронизацию один раз, затем завершить работу. | -| `--debounceMs \` | Установить задержку дебаунса изменений файлов в миллисекундах (по умолчанию: `2000`). | -| `--verbose` / `--debug` | Показывать подробные журналы сборки, запросы синхронизации и трассировки ошибок. | +| Флаг | Описание | +| ------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `--once` | Выполнить сборку и синхронизацию один раз, затем завершить работу. | +| `--dry-run` | С опцией `--once` можно просмотреть изменения метаданных, не применяя их. Ничего не записывает. | +| `--debounceMs \` | Установить задержку дебаунса изменений файлов в миллисекундах (по умолчанию: `2000`). | +| `--verbose` / `--debug` | Показывать подробные журналы сборки, запросы синхронизации и трассировки ошибок. | ## Что вы можете создать diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/layout/front-components.mdx index 377f5b9a55..5c368fb832 100644 --- a/packages/twenty-docs/l/ru/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/apps/layout/front-components.mdx @@ -200,45 +200,22 @@ export default defineFrontComponent({ Front-компоненты выполняются в браузере в изолированном Web Worker, в то время как [логические функции](/l/ru/developers/extend/apps/logic/logic-functions) выполняются на стороне сервера. Между ними нет прямого внутрипроцессного вызова — вместо этого front-компонент обращается к логической функции по HTTP. -Логическая функция, объявленная с `httpRouteTriggerSettings`, доступна по эндпоинту `/s/` по адресу `${TWENTY_API_URL}/s\`. Ваш front-компонент вызывает этот маршрут с помощью `fetch`, аутентифицируясь с использованием `TWENTY_APP_ACCESS_TOKEN`, который Twenty внедряет в worker. +Логическая функция, объявленная с `httpRouteTriggerSettings`, доступна по эндпоинту `/s/` по адресу `${TWENTY_API_URL}/s\`. Ваш front-компонент вызывает этот маршрут с помощью `RestApiClient` из `twenty-client-sdk/rest`, который аутентифицируется с использованием `TWENTY_APP_ACCESS_TOKEN`, который Twenty внедряет в worker. -Небольшой переиспользуемый хелпер делает места вызова чище: - -```ts src/shared/call-app-route.ts -export async function callAppRoute( - path: string, - body: Record, -): Promise { - const apiUrl = process.env.TWENTY_API_URL ?? ''; - const token = process.env.TWENTY_APP_ACCESS_TOKEN; - - const res = await fetch(`${apiUrl}/s${path}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify(body), - }); - - if (!res.ok) { - throw new Error(`Logic function failed (${res.status})`); - } - - return res.json(); -} -``` +`RestApiClient` создан именно для этого. Он считывает `TWENTY_API_URL` и `TWENTY_APP_ACCESS_TOKEN` из окружения worker, добавляет заголовок `Authorization: Bearer`, сериализует и парсит JSON и выбрасывает `RestApiClientError`, когда токен или URL отсутствуют или ответ не является 2xx — чтобы вам не приходилось реализовывать этот шаблонный код в каждом компоненте. Безголовый front-компонент может выполнить вызов при монтировании через компонент `Command`, а затем автоматически размонтироваться: ```tsx src/front-components/sync-prs.tsx import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; -import { callAppRoute } from 'src/shared/call-app-route'; +import { RestApiClient } from 'twenty-client-sdk/rest'; const SyncPrs = () => { const execute = async () => { - await callAppRoute('/github/fetch-prs', { + const client = new RestApiClient(); + + await client.post('/s/github/fetch-prs', { owner: 'twentyhq', repo: 'twenty', }); @@ -256,7 +233,7 @@ export default defineFrontComponent({ }); ``` -`path`, переданный в `callAppRoute`, должен совпадать с `httpRouteTriggerSettings.path` логической функции (префикс `/s` добавляется хелпером): +Путь, передаваемый клиенту, — это общедоступный путь маршрута: значение `httpRouteTriggerSettings.path` для логической функции с префиксом `/s`. Сохраните `isAuthRequired: true`; клиент передает токен доступа к приложению Twenty mints для вашего компонента: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -284,6 +261,48 @@ export default defineLogicFunction({ `TWENTY_API_URL` и `TWENTY_APP_ACCESS_TOKEN` внедряются автоматически — см. [переменные приложения](#application-variables). Поскольку секретные переменные приложения никогда не раскрываются front-компонентам, храните ключи API и другую конфиденциальную логику в логической функции, а не во front-компоненте. +### Справочник по RestApiClient + +Импортируйте `RestApiClient` из `twenty-client-sdk/rest`. Он принадлежит к тому же семейству клиентов, что и `CoreApiClient` и `MetadataApiClient`, но предназначен для HTTP-маршрутов вашего приложения вместо GraphQL API. + +| Метод | Описание | +| --------------------------------- | ----------------------------------------- | +| `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-методом | + +В `options` принимаются `headers`, `query` (объект с параметрами строки запроса; значения, равные null или undefined, пропускаются) и `AbortSignal` через `signal`. Объект `body`, не являющийся `FormData`, автоматически сериализуется в JSON. При получении `401` клиент один раз обновляет токен доступа через хост и повторяет запрос. + +Базовый URL и токен по умолчанию берутся из окружения. При необходимости передавайте переопределения в конструктор — например, в тестах: + +```ts +const client = new RestApiClient({ + baseUrl: 'https://api.example.com', + token: 'my-token', +}); +``` + +Неудачные запросы выбрасывают `RestApiClientError`, предоставляющую `status`, `statusText`, `url` и разобранное `body`: + +```tsx +import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest'; + +const client = new RestApiClient(); + +try { + const prs = await client.get('/s/github/fetch-prs', { + query: { state: 'open' }, + }); +} catch (error) { + if (error instanceof RestApiClientError) { + console.error(error.status, error.body); + } +} +``` + ## Доступ к контексту времени выполнения Внутри вашего компонента используйте хуки SDK для доступа к текущему пользователю, записи и экземпляру компонента: diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/operations/overview.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/operations/overview.mdx index 2ee009edee..dfc222f934 100644 --- a/packages/twenty-docs/l/ru/developers/extend/apps/operations/overview.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/apps/operations/overview.mdx @@ -20,6 +20,9 @@ icon: rocket Справочник по `yarn twenty` — exec, logs, uninstall, remotes. + + Какие команды когда использовать, как читать diff синхронизации и пошаговое восстановление. + Настройка Vitest, интеграционные тесты, проверка типов, рабочий процесс CI. diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/operations/sync-and-recovery.mdx new file mode 100644 index 0000000000..c44a46fe89 --- /dev/null +++ b/packages/twenty-docs/l/ru/developers/extend/apps/operations/sync-and-recovery.mdx @@ -0,0 +1,111 @@ +--- +title: Синхронизация и восстановление +description: Какую команду когда использовать, как читать вывод синхронизации и поэтапный план восстановления на случай расхождения локальных метаданных — до того, как дойдет до полного сброса. +icon: компас +--- + +Локальная разработка приложения строится вокруг **синхронизации**: CLI пересобирает ваш манифест, а сервер применяет только разницу между ним и метаданными, которые уже есть в вашем рабочем пространстве. На этой странице описано, какую команду выбрать, как читать, что изменила синхронизация, и что делать — по шагам — когда локальное состояние выглядит несогласованным. + +## Какую команду и когда использовать + + +Для повседневной локальной разработки вам почти всегда нужна команда `yarn twenty dev`. Развертывание и публикация предназначены для выпуска релизов, **а не** для локального цикла разработки. + + +| Вы хотите… | Команда | Заметки | +| ---------------------------------------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Выполнять локальные итерации с синхронизацией в реальном времени | `yarn twenty dev` | Отслеживает ваши файлы и синхронизирует при каждом изменении. | +| Выполнить одну синхронизацию и выйти (CI, скрипты, хуки) | `yarn twenty dev --once` | Одна сборка + синхронизация, затем завершение работы. | +| Предпросмотр изменений **без их применения** | `yarn twenty dev --once --dry-run` | Вычисляет и выводит diff; ничего не записывает. | +| Удалить приложение из рабочего пространства | `yarn twenty app:uninstall` | Добавьте `--yes`, чтобы пропустить запрос подтверждения. | +| Отправить на сервер tar-архив | `yarn twenty app:publish --private` | Требуется **строго более высокая** версия в `package.json` — см. [Публикация](/l/ru/developers/extend/apps/operations/publishing). | +| Опубликовать на маркетплейсе (npm) | `yarn twenty app:publish` | — | +| Установить / обновить развернутую версию | `yarn twenty app:install` | Устанавливает версию, которая сейчас развернута. | +| Очистить локальный сервер и начать с нуля | `yarn twenty docker:reset` | Удаляет **все** локальные данные — крайняя мера. | + +### Для локальной синхронизации не нужно повышать версию + +Правило строго возрастающей `version` (`VERSION_ALREADY_EXISTS` при deploy, `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION` при install) относится к **`app:publish` / `app:install`** — пути релизов. `yarn twenty dev` синхронизирует ваш манифест на месте и никогда не требует изменения версии, поэтому вам не нужно трогать `package.json`, чтобы делать итерации. Если вы ловите себя на том, что поднимаете версию, чтобы протестировать локальное изменение, значит вы используете релизный путь, когда вам нужен цикл разработки (dev loop). + +## Чтение вывода синхронизации + +Каждая синхронизация выводит изменения метаданных, которые она применила (или применила бы, с `--dry-run`): + +```text filename="Terminal" +Metadata changes: 2 created, 1 updated, 1 deleted + created objectMetadata rocket + created fieldMetadata timelineActivities + updated fieldMetadata launchedAt + deleted pageLayout legacyTab +✓ Synced +``` + +Это ваша первая диагностическая точка: она показывает, какие именно объекты, поля и макеты изменились, чтобы вы могли подтвердить, что синхронизация сделала то, что вы ожидали, до проверки в интерфейсе. + +Когда синхронизация завершается с ошибкой на одной сущности, в сообщении указываются проблемная сущность и её `universalIdentifier`, например: + +```text +Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) failed +``` + +Используйте этот идентификатор, чтобы найти сущность в своем манифесте (и, при необходимости, в рабочем пространстве), вместо того чтобы гадать, какая из них конфликтует. + +## Предпросмотр изменений (dry run) + +`yarn twenty dev --once --dry-run` собирает ваш манифест, запрашивает у сервера план миграции и выводит его — **без применения чего-либо**. Это безопасный способ ответить на вопрос «что изменит эта синхронизация?» до того, как вы на неё согласитесь. + +```bash filename="Terminal" +yarn twenty dev --once --dry-run +``` + +```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 +``` + +Пробный запуск (dry run): + +* **Ничего не записывает** — ни миграции метаданных, ни обновления записи приложения, ни изменений ролей/вкладок по умолчанию, ни генерации API‑клиента. +* Возвращает **тот же diff**, который применит реальная синхронизация, чтобы вы могли заранее просмотреть создаваемые/обновляемые/удаляемые сущности. +* Полезен перед рискованным изменением, при проверке изменения, сгенерированного ИИ, или в скрипте, который должен завершаться с ошибкой, если вот-вот будет применено неожиданное изменение. + + +Пробный запуск предварительно показывает только изменения **метаданных** и требует, чтобы приложение хотя бы один раз уже было синхронизировано (чтобы рабочее пространство знало о нём). Если вы запускаете его для приложения, которое никогда не синхронизировалось, сервер сообщит, что приложение не установлено — сначала один раз выполните `yarn twenty dev`. + + +## Лестница восстановления + +Когда локальные метаданные выглядят неверно, действуйте поэтапно в следующем порядке и останавливайтесь, как только проблема решена. Каждый следующий шаг более разрушителен, чем предыдущий. + +1. **Повторно синхронизируйте.** Снова выполните `yarn twenty dev --once`. Синхронизации идемпотентны — повторный запуск корректного манифеста безопасен и часто устраняет временный сбой. +2. **Просмотрите план.** Выполните `yarn twenty dev --once --dry-run`, чтобы увидеть, что именно намеревается изменить следующая синхронизация, не применяя эти изменения. +3. **Прочитайте сообщение об ошибке.** Если синхронизация завершается с ошибкой, обратите внимание на тип метаданных и `universalIdentifier` в сообщении (см. выше) и найдите эту сущность в своем манифесте. Конфликт обычно указывает на дублированный или повторно используемый идентификатор. +4. **Удалите и переустановите.** Выполните `yarn twenty app:uninstall`, затем синхронизируйте снова (`yarn twenty dev`). Это пересобирает метаданные приложения с нуля, сохраняя остальную часть вашего рабочего пространства нетронутой. +5. **Полный сброс (крайняя мера).** Выполните `yarn twenty docker:reset`, затем заново выполните начальное наполнение данными и синхронизацию. + + +`yarn twenty docker:reset` удаляет **все** данные в вашей локальной инсталляции — все рабочие пространства, записи и приложения. Используйте его только после того, как предыдущие шаги не помогли. + + + +Столкнулись с ошибкой метаданных? Пожалуйста, [создайте issue](https://github.com/twentyhq/twenty/issues/new/choose) и приложите сообщение о сбое миграции (с типом метаданных и `universalIdentifier`), вывод `Metadata changes` из синхронизации и команды, которые вы запускали. + + +## Избегайте одновременных синхронизаций в одном рабочем пространстве + +Синхронизация применяет миграции метаданных. Запуск нескольких операций sync, deploy или install по отношению к **одному и тому же рабочему пространству одновременно** — например, из нескольких терминалов или при параллельных итерациях агентов ИИ — может перемешать эти миграции и оставить метаданные в частично примененном состоянии. + +Сервер последовательно обрабатывает синхронизации для каждого рабочего пространства, чтобы предотвратить это, но вам всё равно следует пропускать чувствительные операции с метаданными через **один** процесс, а не запускать их параллельно. Если вы организуете разработку с несколькими агентами, направляйте их вызовы sync/deploy/install через одну очередь, чтобы в каждый момент времени выполнялась только одна операция. + +## Как различать типы сбоев + +Когда что‑то идёт не так, diff метаданных и именованные ошибки помогают определить, на каком этапе произошел сбой: + +* **Ошибка сборки манифеста** — CLI завершается с ошибкой до синхронизации (`MANIFEST_BUILD_FAILED`, `TYPECHECK_FAILED`); исправьте исходный код приложения. +* **Ошибка синхронизации / миграции** — сборка проходит успешно, но применение diff завершается сбоем с указанием сущности и `universalIdentifier`; исправьте конфликтующие метаданные. +* **Ошибка выполнения кода приложения** — синхронизация проходит успешно, но ваши логические функции или компоненты ведут себя неправильно во время выполнения; проверьте [журналы функций](/l/ru/developers/extend/apps/operations/cli). +* **Локальное состояние экземпляра** — ни один из вышеперечисленных пунктов не подходит, и рабочее пространство всё ещё выглядит неправильно; двигайтесь вниз по лестнице восстановления. diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/getting-started/quick-start.mdx index f2ff061075..56a649099a 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/getting-started/quick-start.mdx @@ -123,18 +123,20 @@ Tek bir derleme + eşitleme çalıştırıp çıkmak için `--once` parametresin yarn twenty dev --once ``` -| Komut | Davranış | Ne zaman kullanılmalı | -| ------------------------ | ----------------------------------------------------------------------- | --------------------------------------------------------------- | -| `yarn twenty dev` | Her değişiklikte izler ve yeniden eşitler. Siz durdurana kadar çalışır. | Etkileşimli yerel geliştirme. | -| `yarn twenty dev --once` | Tek derleme + eşitleme; başarıda `0`, başarısızlıkta `1` ile çıkar. | CI, pre-commit kancaları, AI ajanları, betiklenmiş iş akışları. | +| Komut | Davranış | Ne zaman kullanılmalı | +| ---------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| `yarn twenty dev` | Her değişiklikte izler ve yeniden eşitler. Siz durdurana kadar çalışır. | Etkileşimli yerel geliştirme. | +| `yarn twenty dev --once` | Tek derleme + eşitleme; başarıda `0`, başarısızlıkta `1` ile çıkar. | CI, pre-commit kancaları, AI ajanları, betiklenmiş iş akışları. | +| `yarn twenty dev --once --dry-run` | Meta veri değişikliklerini **uygulamadan oluşturur ve yazdırır**. | Bir senkronizasyonun, ona başlamadan önce neleri değiştireceğini incelemek. | -Her iki kipin de kimliği doğrulanmış bir uzak sunucuya ihtiyaç duyar. +Her iki kipin de kimliği doğrulanmış bir uzak sunucuya ihtiyaç duyar. `--dry-run` hakkında daha fazla bilgi için [Senkronizasyon ve kurtarma](/l/tr/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run) bölümüne bakın. ### Geliştirme kipi seçenekleri | Bayrak | Açıklama | | ------------------------------------- | ------------------------------------------------------------------------------------------ | | `--once` | Bir kez derleyip eşitleyin, ardından çıkın. | +| `--dry-run` | `--once` ile meta veri değişikliklerini uygulamadan önizleyin. Hiçbir şey yazmaz. | | `--debounceMs \` | Dosya değişikliği geciktirme süresini milisaniye cinsinden ayarlayın (varsayılan: `2000`). | | `--verbose` / `--debug` | Ayrıntılı derleme günlüklerini, eşitleme isteklerini ve hata izlerini gösterin. | 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 d61a881352..0a4ad0edd6 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 @@ -200,45 +200,22 @@ export default defineFrontComponent({ Ön bileşenler, tarayıcı tarafında izole 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, `${TWENTY_API_URL}/s\` altındaki `/s/` uç noktasında sunulur. Ön bileşeniniz bu rotayı, Twenty tarafından Worker'a enjekte edilen `TWENTY_APP_ACCESS_TOKEN` ile kimlik doğrulayarak `fetch` ile çağırır. +`httpRouteTriggerSettings` ile bildirilen bir mantık işlevi, `${TWENTY_API_URL}/s\` altındaki `/s/` uç noktasında sunulur. Ön bileşeniniz bu rotayı, Twenty tarafından Worker'a enjekte edilen `TWENTY_APP_ACCESS_TOKEN` ile kimlik doğrulayan `twenty-client-sdk/rest` içindeki `RestApiClient` ile çağırır. -Küçük, yeniden kullanılabilir bir yardımcı işlev çağrı noktalarını sade tutar: - -```ts src/shared/call-app-route.ts -export async function callAppRoute( - path: string, - body: Record, -): Promise { - const apiUrl = process.env.TWENTY_API_URL ?? ''; - const token = process.env.TWENTY_APP_ACCESS_TOKEN; - - const res = await fetch(`${apiUrl}/s${path}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify(body), - }); - - if (!res.ok) { - throw new Error(`Logic function failed (${res.status})`); - } - - return res.json(); -} -``` +`RestApiClient` tam da bunun için oluşturulmuştur. Worker ortamından `TWENTY_API_URL` ve `TWENTY_APP_ACCESS_TOKEN` değerlerini okur, `Authorization: Bearer` başlığını ekler, JSON'u serileştirip ayrıştırır ve belirteç veya URL eksik olduğunda ya da yanıt 2xx dışı olduğunda bir `RestApiClientError` fırlatır — böylece bu şablon kodunu her bileşende yeniden uygulamak zorunda kalmazsınız. 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 { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; -import { callAppRoute } from 'src/shared/call-app-route'; +import { RestApiClient } from 'twenty-client-sdk/rest'; const SyncPrs = () => { const execute = async () => { - await callAppRoute('/github/fetch-prs', { + const client = new RestApiClient(); + + await client.post('/s/github/fetch-prs', { owner: 'twentyhq', repo: 'twenty', }); @@ -256,7 +233,7 @@ export default defineFrontComponent({ }); ``` -`callAppRoute` fonksiyonuna geçirilen `path`, mantık işlevinin `httpRouteTriggerSettings.path` değeriyle eşleşmelidir (`/s` öneki yardımcı işlev tarafından eklenir): +İstemciye iletilen yol, rotanın herkese açık yoludur — mantık fonksiyonunun `httpRouteTriggerSettings.path` değeri, başına `/s` eklenmiş hâlidir. `isAuthRequired: true` değerini koruyun; istemci, bileşeniniz için uygulama erişim jetonunu (app access token) sağlar Twenty mints: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -284,6 +261,48 @@ export default defineLogicFunction({ `TWENTY_API_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. +### RestApiClient başvurusu + +`RestApiClient` öğesini `twenty-client-sdk/rest` içinden içe aktarın. `CoreApiClient` ve `MetadataApiClient` ile aynı istemci ailesine aittir, ancak GraphQL API yerine uygulamanızın HTTP rotalarını hedefler. + +| 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 | + +`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 nesne `body` otomatik olarak JSON’a serileştirilir. `401` durumunda, istemci erişim jetonunu bir kez ana makine (host) üzerinden yeniler ve isteği yeniden dener. + +Temel URL ve jeton varsayılan olarak ortamdan çözümlenir. Gerektiğinde — örneğin testlerde — kurucuya (constructor) geçersiz kılmalar (override) iletin: + +```ts +const client = new RestApiClient({ + baseUrl: 'https://api.example.com', + token: 'my-token', +}); +``` + +Başarısız istekler, `status`, `statusText`, `url` ve ayrıştırılmış `body` değerlerini açığa çıkaran bir `RestApiClientError` fırlatır: + +```tsx +import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest'; + +const client = new RestApiClient(); + +try { + const prs = await client.get('/s/github/fetch-prs', { + query: { state: 'open' }, + }); +} catch (error) { + if (error instanceof RestApiClientError) { + console.error(error.status, error.body); + } +} +``` + ## Çalışma zamanı bağlamına erişme Bileşeninizin içinde, geçerli kullanıcıya, kayda ve bileşen örneğine erişmek için SDK hook'larını kullanın: diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/operations/overview.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/operations/overview.mdx index fda032f71e..ae3c0abc7c 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/operations/overview.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/operations/overview.mdx @@ -20,6 +20,9 @@ icon: rocket `yarn twenty` referansı — exec, logs, uninstall, remotes. + + Hangi komut ne zaman, senkronizasyon diff'ini okuma ve kurtarma basamakları. + Vitest kurulumu, entegrasyon testleri, tür denetimi, CI iş akışı. diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/operations/sync-and-recovery.mdx new file mode 100644 index 0000000000..edf4da4c7a --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/apps/operations/sync-and-recovery.mdx @@ -0,0 +1,111 @@ +--- +title: Senkronizasyon ve kurtarma +description: Hangi komutu ne zaman kullanmanız gerektiği, senkronizasyon çıktısının nasıl okunacağı ve yerel üst veriler sapmaya başladığında — tam sıfırlamaya ulaşmadan önce — uygulanacak bir kurtarma merdiveni. +icon: compass +--- + +Yerel uygulama geliştirme **senkronizasyon** etrafında döner: CLI manifestinizi yeniden oluşturur ve sunucu, onu çalışma alanınızda hâlihazırda bulunan üst verilerle karşılaştırarak yalnızca aradaki farkı uygular. Bu sayfa, hangi komuta başvurmanız gerektiğini, bir senkronizasyonun neleri değiştirdiğini nasıl okuyacağınızı ve yerel durum tutarsız göründüğünde — sırayla — ne yapmanız gerektiğini açıklar. + +## Hangi komut, ne zaman + + +Günlük yerel yinelemelerde neredeyse her zaman `yarn twenty dev` kullanmak istersiniz. Dağıtım ve yayımlama, sürümleri göndermek içindir, yerel döngü için **değil**. + + +| Şunu yapmak istiyorsunuz… | Komut | Notlar | +| ---------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| Canlı senkronizasyonla yerelde yineleyin | `yarn twenty dev` | Dosyalarınızı izler ve her değişiklikte senkronize eder. | +| Bir kez senkronize et ve çık (CI, betikler, kancalar) | `yarn twenty dev --once` | Tek bir derleme + senkronizasyon yapar ve ardından çıkar. | +| Değişiklikleri **uygulamadan** önizleyin | `yarn twenty dev --once --dry-run` | Farkı hesaplar ve yazdırır; hiçbir şey yazmaz. | +| Uygulamayı çalışma alanından kaldırın | `yarn twenty app:uninstall` | İstemi atlamak için `--yes` ekleyin. | +| Bir tarball'ı sunucuya gönderin | `yarn twenty app:publish --private` | `package.json` içinde **kesin olarak daha yüksek** bir sürüm gerektirir — bkz. [Publishing](/l/tr/developers/extend/apps/operations/publishing). | +| Pazaryerine (npm) yayımlayın | `yarn twenty app:publish` | — | +| Dağıtılmış bir sürümü yükleyin / yükseltin | `yarn twenty app:install` | Şu anda dağıtılmış olan sürümü yükler. | +| Yerel sunucuyu silin ve temiz bir şekilde yeniden başlatın | `yarn twenty docker:reset` | Yerel verilerin **tamamını** siler — son çare. | + +### Yerel senkronizasyon için sürüm artırmaya gerek yoktur + +Sıkı artan `version` kuralı (dağıtımda `VERSION_ALREADY_EXISTS`, yüklemede `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION`) **`app:publish` / `app:install`** için — yani yayın yolu için — geçerlidir. `yarn twenty dev`, manifestinizi yerinde senkronize eder ve hiçbir zaman bir sürüm değişikliği gerektirmez, bu yüzden yineleme yapmak için `package.json` dosyasına dokunmanız gerekmez. Yerel bir değişikliği test etmek için kendinizi sürümü artırırken buluyorsanız, ihtiyacınız olan geliştirme döngüsü yerine yayın yolunu kullanıyorsunuz demektir. + +## Senkronizasyon çıktısını okuma + +Her senkronizasyon, uyguladığı (veya `--dry-run` ile uygulayacağı) üst veri değişikliklerini yazdırır: + +```text filename="Terminal" +Metadata changes: 2 created, 1 updated, 1 deleted + created objectMetadata rocket + created fieldMetadata timelineActivities + updated fieldMetadata launchedAt + deleted pageLayout legacyTab +✓ Synced +``` + +Bu, ilk tanı aracınızdır: tam olarak hangi nesnelerin, alanların ve düzenlerin değiştiğini size bildirir; böylece bir senkronizasyonun beklediğiniz gibi davranıp davranmadığını, arayüzü kontrol etmeden önce doğrulayabilirsiniz. + +Bir senkronizasyon tek bir varlıkta başarısız olduğunda, hata mesajı sorunlu varlığı ve onun `universalIdentifier` değerini adlandırır, örneğin: + +```text +Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) failed +``` + +Bu tanımlayıcıyı, çakışanın hangisi olduğunu tahmin etmek yerine, manifestinizdeki (ve gerekirse çalışma alanındaki) varlığı bulmak için kullanın. + +## Değişiklikleri önizleme (dry run) + +`yarn twenty dev --once --dry-run`, manifestinizi derler, sunucudan geçiş planını ister ve onu yazdırır — **hiçbir şeyi uygulamadan**. Bu, ona taahhüt etmeden önce "Bu senkronizasyon neyi değiştirir?" sorusunu yanıtlamanın güvenli yoludur. + +```bash filename="Terminal" +yarn twenty dev --once --dry-run +``` + +```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 +``` + +Bir dry run şunları yapar: + +* **Hiçbir şey yazmaz** — üst veri geçişi, uygulama kaydı güncellemesi, varsayılan rol/sekme değişiklikleri ve API istemcisi oluşturma işlemleri yapılmaz. +* Gerçek bir senkronizasyonun uygulayacağı **aynı farkı** döndürür; böylece oluşturulan/güncellenen/silinen varlıkları en baştan inceleyebilirsiniz. +* Riskli bir değişiklikten önce, bir yapay zekâ tarafından oluşturulan değişikliği gözden geçirirken veya beklenmedik bir değişiklik gerçekleşmek üzereyse betiğin başarısız olması gereken durumlarda kullanışlıdır. + + +Bir dry run yalnızca **üst veri** değişikliklerini önizler ve uygulamanın en az bir kez senkronize edilmiş olmasını gerektirir (böylece çalışma alanı ondan haberdar olur). Hiç senkronize edilmemiş bir uygulamaya karşı çalıştırırsanız, sunucu uygulamanın yüklü olmadığını bildirir — önce bir kez `yarn twenty dev` çalıştırın. + + +## Kurtarma merdiveni + +Yerel üst veriler hatalı görünüyorsa, bu adımları sırayla uygulayın ve engeliniz kalkar kalkmaz durun. Her adım bir öncekinden daha yıkıcıdır. + +1. **Yeniden senkronize edin.** `yarn twenty dev --once` komutunu tekrar çalıştırın. Senkronizasyonlar idempotenttir — temiz bir manifesti yeniden çalıştırmak güvenlidir ve çoğu zaman geçici bir aksaklığı giderir. +2. **Planı önizleyin.** Bir sonraki senkronizasyonun tam olarak neyi değiştirmeyi amaçladığını, uygulamadan görmek için `yarn twenty dev --once --dry-run` çalıştırın. +3. **Adlandırılmış hatayı okuyun.** Bir senkronizasyon başarısız olursa, iletideki üst veri türünü ve `universalIdentifier` değerini not alın (yukarıya bakın) ve manifestinizdeki o varlığı bulun. Bir çakışma genellikle yinelenen veya tekrar kullanılan bir tanımlayıcıya işaret eder. +4. **Kaldırın ve yeniden yükleyin.** `yarn twenty app:uninstall` komutunu çalıştırın, ardından yeniden senkronize edin (`yarn twenty dev`). Bu, uygulamanın üst verilerini temiz bir başlangıçtan yeniden oluşturur ve çalışma alanınızın geri kalanını olduğu gibi bırakır. +5. **Tam sıfırlama (son çare).** `yarn twenty docker:reset` komutunu çalıştırın, ardından yeniden tohumlayın ve yeniden senkronize edin. + + +`yarn twenty docker:reset`, yerel örneğinizdeki verilerin **tamamını** siler — tüm çalışma alanlarını, kayıtları ve uygulamaları. Yalnızca önceki adımlar başarısız olduktan sonra kullanın. + + + +Bir üst veri hatasıyla mı karşılaştınız? Lütfen [issue açın](https://github.com/twentyhq/twenty/issues/new/choose) ve başarısız olan geçiş iletisini (üst veri türü ve `universalIdentifier` ile birlikte), senkronizasyondan gelen `Metadata changes` çıktısını ve çalıştırdığınız komutları ekleyin. + + +## Tek bir çalışma alanında eşzamanlı senkronizasyonlardan kaçının + +Senkronizasyon, üst veri geçişlerini uygular. Aynı çalışma alanına karşı aynı anda birden çok senkronizasyon, dağıtım veya yükleme işlemi çalıştırmak — örneğin, birden çok terminal veya paralel yineleme yapan yapay zekâ ajanları — bu geçişlerin iç içe geçmesine ve üst verilerin kısmen uygulanmış bir durumda kalmasına neden olabilir. + +Sunucu, bunu önlemek için çalışma alanı başına senkronizasyonları sıralı hâle getirir, ancak yine de hassas üst veri işlemlerini aynı anda tetiklemek yerine **tek bir** süreç üzerinden geçirmeniz gerekir. Geliştirmeyi birden fazla ajanla orkestre ediyorsanız, onların senkronizasyon/dağıtım/yükleme çağrılarını tek bir kuyruğa yönlendirin ki aynı anda yalnızca biri çalışsın. + +## Hataları birbirinden ayırma + +Bir şeyler ters gittiğinde, üst veri farkı ve adlandırılmış hatalar, hatanın nerede oluştuğunu belirlemenizi sağlar: + +* **Manifest derleme hatası** — CLI, senkronizasyondan önce başarısız olur (`MANIFEST_BUILD_FAILED`, `TYPECHECK_FAILED`); uygulama kaynağınızı düzeltin. +* **Senkronizasyon / geçiş hatası** — derleme başarılı olur ancak farkı uygulama işlemi, varlığı ve `universalIdentifier` değerini adlandırarak başarısız olur; çakışan üst veriyi düzeltin. +* **Uygulama kodu çalışma zamanı hatası** — senkronizasyon başarılı olur ancak mantık fonksiyonlarınız veya bileşenleriniz çalışma zamanında beklenmedik şekilde davranır; [function logs](/l/tr/developers/extend/apps/operations/cli) bölümünü kontrol edin. +* **Yerel örnek durumu** — yukarıdakilerin hiçbiri geçerli değil ve çalışma alanı hâlâ hatalı görünüyorsa; kurtarma merdiveninde aşağı doğru ilerleyin. diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/getting-started/quick-start.mdx index 18779a3bf9..2f097adfce 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/getting-started/quick-start.mdx @@ -123,20 +123,22 @@ yarn twenty dev yarn twenty dev --once ``` -| 命令 | 行为 | 适用场景 | -| ------------------------ | -------------------------------- | ------------------------------- | -| `yarn twenty dev` | 监视并在每次更改时重新同步。 持续运行,直到你将其停止。 | 交互式本地开发。 | -| `yarn twenty dev --once` | 单次构建与同步,成功时以 `0` 退出,失败时以 `1` 退出。 | CI、pre-commit 钩子、AI 智能体、脚本化工作流。 | +| 命令 | 行为 | 适用场景 | +| ---------------------------------- | -------------------------------- | ------------------------------- | +| `yarn twenty dev` | 监视并在每次更改时重新同步。 持续运行,直到你将其停止。 | 交互式本地开发。 | +| `yarn twenty dev --once` | 单次构建与同步,成功时以 `0` 退出,失败时以 `1` 退出。 | CI、pre-commit 钩子、AI 智能体、脚本化工作流。 | +| `yarn twenty dev --once --dry-run` | 构建并打印元数据更改,**但不会应用这些更改**。 | 在提交同步之前检查它会更改哪些内容。 | -两种模式都需要经过身份验证的远程仓库。 +两种模式都需要经过身份验证的远程仓库。 有关 `--dry-run` 的更多信息,请参见 [同步与恢复](/l/zh/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run)。 ### 开发模式选项 -| 标志 | 描述 | -| ------------------------------------- | ------------------------------ | -| `--once` | 仅构建并同步一次,然后退出。 | -| `--debounceMs \` | 以毫秒为单位设置文件更改的防抖延迟(默认值:`2000`)。 | -| `--verbose` / `--debug` | 显示详细的构建日志、同步请求和错误跟踪。 | +| 标志 | 描述 | +| ------------------------------------- | -------------------------------------------- | +| `--once` | 仅构建并同步一次,然后退出。 | +| `--dry-run` | 使用 `--once` 时,可在不应用元数据更改的情况下预览这些更改。 不写入任何内容。 | +| `--debounceMs \` | 以毫秒为单位设置文件更改的防抖延迟(默认值:`2000`)。 | +| `--verbose` / `--debug` | 显示详细的构建日志、同步请求和错误跟踪。 | ## 你可以构建的内容 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 4da6c2392e..c3e37f9746 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 @@ -200,45 +200,22 @@ export default defineFrontComponent({ 前端组件在沙盒 Web Worker 中于浏览器端运行,而[逻辑函数](/l/zh/developers/extend/apps/logic/logic-functions)在服务器端运行。 二者之间没有直接的进程内调用——前端组件通过 HTTP 访问逻辑函数。 -使用 `httpRouteTriggerSettings` 声明的逻辑函数会通过 `/s/` 端点暴露在 `${TWENTY_API_URL}/s\` 下。 你的前端组件使用 `fetch` 调用该路由,并使用 Twenty 注入到 worker 中的 `TWENTY_APP_ACCESS_TOKEN` 进行身份验证。 +使用 `httpRouteTriggerSettings` 声明的逻辑函数会通过 `/s/` 端点暴露在 `${TWENTY_API_URL}/s\` 下。 你的前端组件使用来自 `twenty-client-sdk/rest` 的 `RestApiClient` 调用该路由,该客户端会使用 Twenty 注入到 worker 中的 `TWENTY_APP_ACCESS_TOKEN` 进行身份验证。 -一个小型可复用的辅助函数可以让调用端保持简洁: - -```ts src/shared/call-app-route.ts -export async function callAppRoute( - path: string, - body: Record, -): Promise { - const apiUrl = process.env.TWENTY_API_URL ?? ''; - const token = process.env.TWENTY_APP_ACCESS_TOKEN; - - const res = await fetch(`${apiUrl}/s${path}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify(body), - }); - - if (!res.ok) { - throw new Error(`Logic function failed (${res.status})`); - } - - return res.json(); -} -``` +`RestApiClient` 正是为这种场景而构建的。 它会从 worker 环境中读取 `TWENTY_API_URL` 和 `TWENTY_APP_ACCESS_TOKEN`,附加 `Authorization: Bearer` 请求头,对 JSON 进行序列化和解析,并在 token 或 URL 缺失或响应为非 2xx 时抛出 `RestApiClientError`——这样你就不必在每个组件中重复实现这些样板逻辑。 无头前端组件可以通过 `Command` 组件在挂载时执行调用,然后自动卸载: ```tsx src/front-components/sync-prs.tsx import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; -import { callAppRoute } from 'src/shared/call-app-route'; +import { RestApiClient } from 'twenty-client-sdk/rest'; const SyncPrs = () => { const execute = async () => { - await callAppRoute('/github/fetch-prs', { + const client = new RestApiClient(); + + await client.post('/s/github/fetch-prs', { owner: 'twentyhq', repo: 'twenty', }); @@ -256,7 +233,7 @@ export default defineFrontComponent({ }); ``` -传递给 `callAppRoute` 的 `path` 必须与逻辑函数的 `httpRouteTriggerSettings.path` 匹配(`/s` 前缀由辅助函数添加): +传递给客户端的路径是该路由的公共路径——逻辑函数的 `httpRouteTriggerSettings.path`,并以 `/s` 作为前缀。 保持 `isAuthRequired: true`;客户端会为你的组件提供由 Twenty 签发的应用访问令牌: ```ts src/logic-functions/fetch-prs.logic-function.ts import { defineLogicFunction } from 'twenty-sdk/define'; @@ -284,6 +261,48 @@ export default defineLogicFunction({ `TWENTY_API_URL` 和 `TWENTY_APP_ACCESS_TOKEN` 会被自动注入——参见 [应用变量](#application-variables)。 由于机密应用变量永远不会暴露给前端组件,请将 API 密钥和其他敏感逻辑保留在逻辑函数中,而不是前端组件中。 +### RestApiClient 参考 + +从 `twenty-client-sdk/rest` 中导入 `RestApiClient`。 它与 `CoreApiClient` 和 `MetadataApiClient` 属于同一客户端家族,但目标是你应用的 HTTP 路由,而不是 GraphQL API。 + +| 方法 | 描述 | +| --------------------------------- | ----------------- | +| `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 方法的通用请求 | + +`options` 接受 `headers`、`query`(查询字符串参数记录;空值会被跳过),以及通过 `signal` 传入的 `AbortSignal`。 非 `FormData` 类型的对象 `body` 会被自动进行 JSON 序列化。 在收到 `401` 时,客户端会通过宿主刷新一次访问令牌,然后重试该请求。 + +基础 URL 和令牌默认会从环境中解析得到。 在需要时将覆盖项传递给构造函数——例如在测试中: + +```ts +const client = new RestApiClient({ + baseUrl: 'https://api.example.com', + token: 'my-token', +}); +``` + +失败的请求会抛出 `RestApiClientError`,其中包含 `status`、`statusText`、`url` 和已解析的 `body`: + +```tsx +import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest'; + +const client = new RestApiClient(); + +try { + const prs = await client.get('/s/github/fetch-prs', { + query: { state: 'open' }, + }); +} catch (error) { + if (error instanceof RestApiClientError) { + console.error(error.status, error.body); + } +} +``` + ## 访问运行时上下文 在组件内部,使用 SDK 的 hooks 获取当前用户、记录和组件实例: diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/operations/overview.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/operations/overview.mdx index 6b94fd85ba..066b892f87 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/operations/overview.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/operations/overview.mdx @@ -20,6 +20,9 @@ icon: rocket `yarn twenty` 参考——exec、logs、uninstall、remotes。 + + 在阅读同步差异时应使用哪些命令,以及分步恢复流程。 + Vitest 配置、集成测试、类型检查、CI 工作流。 diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/operations/sync-and-recovery.mdx new file mode 100644 index 0000000000..f6d6644b32 --- /dev/null +++ b/packages/twenty-docs/l/zh/developers/extend/apps/operations/sync-and-recovery.mdx @@ -0,0 +1,111 @@ +--- +title: 同步与恢复 +description: 何时使用哪个命令、如何解读同步输出,以及在本地元数据发生漂移时的恢复阶梯——在不得不执行完全重置之前。 +icon: compass +--- + +本地应用开发围绕着**同步**展开:CLI 会重建你的 manifest,而服务器只会应用它与工作区中已存在元数据之间的差异。 本页介绍在不同情况下应使用哪个命令、如何阅读同步修改内容,以及当本地状态看起来不一致时——按顺序——应该怎么做。 + +## 在什么情况下用哪个命令 + + +在日常本地迭代中,你几乎总是需要 `yarn twenty dev`。 Deploy 和 publish 用于发布版本,**而不是**用于本地循环。 + + +| 如果你想要…… | 命令 | 备注 | +| ------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------ | +| 使用实时同步进行本地迭代 | `yarn twenty dev` | 监视你的文件,并在每次更改时执行同步。 | +| 同步一次后退出(CI、脚本、钩子) | `yarn twenty dev --once` | 执行一次构建和同步,然后退出。 | +| 在**不应用变更**的前提下预览更改 | `yarn twenty dev --once --dry-run` | 计算并打印 diff;不写入任何内容。 | +| 从工作区中移除该应用 | `yarn twenty app:uninstall` | 添加 `--yes` 以跳过提示。 | +| 将 tar 包发送到服务器 | `yarn twenty app:publish --private` | 需要一个**严格更高的** `package.json` 版本——参见 [Publishing](/l/zh/developers/extend/apps/operations/publishing)。 | +| 发布到应用市场(npm) | `yarn twenty app:publish` | — | +| 安装 / 升级已部署的版本 | `yarn twenty app:install` | 安装当前已部署的版本。 | +| 清空本地服务器并重新开始 | `yarn twenty docker:reset` | 删除**所有**本地数据——最后的手段。 | + +### 本地同步不需要提升版本号 + +严格递增的 `version` 规则(在 deploy 时为 `VERSION_ALREADY_EXISTS`,在 install 时为 `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION`)适用于 **`app:publish` / `app:install`**——即发布路径。 `yarn twenty dev` 就地同步你的 manifest,且从不要求修改版本,因此你无需为了迭代去改动 `package.json`。 如果你发现自己为了测试本地改动而不断提升版本号,说明你在想要使用开发循环时却走了发布路径。 + +## 阅读同步输出 + +每次同步都会打印它实际应用的(或在使用 `--dry-run` 时将要应用的)元数据更改: + +```text filename="Terminal" +Metadata changes: 2 created, 1 updated, 1 deleted + created objectMetadata rocket + created fieldMetadata timelineActivities + updated fieldMetadata launchedAt + deleted pageLayout legacyTab +✓ Synced +``` + +这是你的首要诊断工具:它会准确告诉你哪些对象、字段和布局发生了变化,这样你就可以在查看 UI 之前确认同步是否按预期进行。 + +当同步在某个实体上失败时,错误信息会给出有问题的实体及其 `universalIdentifier`,例如: + +```text +Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) failed +``` + +使用该标识符在 manifest 中(以及在需要时在工作区中)定位该实体,而不是猜测哪个实体发生了冲突。 + +## 预览更改(干跑 / dry run) + +`yarn twenty dev --once --dry-run` 会构建你的 manifest,向服务器请求迁移计划并打印出来——**不会实际应用任何内容**。 这是在真正执行前,以安全方式回答“这次同步会改动什么?”的办法。 + +```bash filename="Terminal" +yarn twenty dev --once --dry-run +``` + +```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 +``` + +一次 dry run: + +* **不会写入任何内容**——不会进行元数据迁移、不会更新应用记录、不会更改默认角色/标签,也不会生成 API 客户端。 +* 返回与真实同步将要应用的**相同 diff**,这样你可以预先审查将被创建 / 更新 / 删除的实体。 +* 在执行高风险改动之前、在审查 AI 生成的改动时,或在某些如果即将落地意外变更就应当失败的脚本中,dry run 都非常有用。 + + +dry run 只会预览**元数据**更改,并且要求应用至少已经同步过一次(这样工作区才知道它的存在)。 如果你在一个从未同步过的应用上运行它,服务器会报告该应用尚未安装——先运行一次 `yarn twenty dev`。 + + +## 恢复梯子 + +当本地元数据看起来不对时,按以下顺序逐步升级,并在问题解决后立即停止。 每一步都比前一步更具破坏性。 + +1. **重新同步。** 再次运行 `yarn twenty dev --once`。 同步是幂等的——在干净的 manifest 上重新运行是安全的,并且通常可以解决瞬时故障。 +2. **预览计划。** 运行 `yarn twenty dev --once --dry-run`,在不应用变更的前提下,准确查看下一次同步打算修改什么。 +3. **阅读具名错误。** 如果同步失败,记录消息中的元数据类型和 `universalIdentifier`(见上),并在 manifest 中定位该实体。 冲突通常指向重复或被重复使用的标识符。 +4. **卸载并重新安装。** 先执行 `yarn twenty app:uninstall`,然后再次同步(`yarn twenty dev`)。 这会在保留你工作区其余部分不变的情况下,从零重建该应用的元数据。 +5. **完全重置(最后手段)。** 执行 `yarn twenty docker:reset`,然后重新播种并重新同步。 + + +`yarn twenty docker:reset` 会删除本地实例中的**所有**数据——包括每个工作区、记录和应用。 只有在前面步骤全部无效时才使用它。 + + + +遇到元数据错误了吗? 请[提交 issue](https://github.com/twentyhq/twenty/issues/new/choose),并附上失败的迁移消息(包含其中的元数据类型和 `universalIdentifier`)、同步时的 `Metadata changes` 输出,以及你执行过的命令。 + + +## 避免在同一工作区上并发同步 + +同步会应用元数据迁移。 在**同一个工作区同时**运行多个同步、部署或安装操作——例如多个终端或多个 AI 代理并行迭代——会让这些迁移交错执行,从而让元数据处于部分应用的状态。 + +服务器会按工作区串行化同步以防止这种情况,但你仍然应当通过**单一**进程来处理敏感的元数据操作,而不要并发触发。 如果你使用多个代理来编排开发,请将它们的同步 / 部署 / 安装调用通过一个队列进行排队,这样任何时刻只有一个操作在运行。 + +## 区分不同类型的失败 + +当出现问题时,元数据 diff 和具名错误可以帮助你定位失败位置: + +* **Manifest 构建错误**——CLI 在同步前失败(`MANIFEST_BUILD_FAILED`、`TYPECHECK_FAILED`);请修复你的应用源代码。 +* **同步 / 迁移错误**——构建成功,但在应用 diff 时失败,并给出实体名称和 `universalIdentifier`;请修复冲突的元数据。 +* **应用代码运行时错误** — 同步成功,但你的逻辑函数或组件在运行时行为异常;请检查[函数日志](/l/zh/developers/extend/apps/operations/cli)。 +* **本地实例状态** — 不属于以上任何一种情况,但工作区仍然显示异常;请按照恢复步骤逐级排查。