Ana içeriğe atla
Mantık işlevleri, Twenty platformunda çalışan sunucu tarafı TypeScript işlevleridir. HTTP istekleri, cron zamanlamaları veya veritabanı olayları tarafından tetiklenebilirler — ve ayrıca yapay zekâ ajanları için araçlar olarak sunulabilirler.
Her işlev dosyası, bir işleyici ve isteğe bağlı tetikleyiciler içeren bir yapılandırmayı dışa aktarmak için defineLogicFunction() kullanır.
src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk/define';
import type { RoutePayload } from 'twenty-sdk/logic-function';
import { CoreApiClient } from 'twenty-client-sdk/core';

const handler = async (params: RoutePayload) => {
  const client = new CoreApiClient();
  const body = (params.body ?? {}) as { name?: string };
  const name = body.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world';

  const result = await client.mutation({
    createPostCard: {
      __args: { data: { name } },
      id: true,
      name: true,
    },
  });
  return result;
};

export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'create-new-post-card',
  timeoutSeconds: 2,
  handler,
  httpRouteTriggerSettings: {
    path: '/post-card/create',
    httpMethod: 'POST',
    isAuthRequired: true,
  },
  /*databaseEventTriggerSettings: {
    eventName: 'people.created',
  },*/
  /*cronTriggerSettings: {
    pattern: '0 0 1 1 *',
  },*/
});
Kullanılabilir tetikleyici türleri:
  • httpRoute: İşlevinizi bir HTTP yolu ve yöntemiyle /s/ uç noktasının altında kullanıma sunar:
örn. path: '/post-card/create' https://your-twenty-server.com/s/post-card/create adresinden çağrılabilir
Arayüzsüz bir ön uç bileşeninden rota tarafından tetiklenen mantık fonksiyonunu çağırmak için bkz. Mantık fonksiyonu çağırma.
  • cron: Bir CRON ifadesi kullanarak işlevinizi bir zamanlamayla çalıştırır.
  • databaseEvent: Çalışma alanı nesnesi yaşam döngüsü olaylarında çalışır. Olay işlemi updated olduğunda, dinlenecek belirli alanlar updatedFields dizisinde belirtilebilir. Tanımsız veya boş bırakılırsa, herhangi bir güncelleme işlevi tetikler.
örn. person.updated, *.created, company.*
  • serverWebhook: Üçüncü taraf bir hizmetten (Stripe, GitHub, Svix, …) gelen webhook’ları alır tek bir kayıt kapsamlı uç noktadan ve hedef çalışma alanını payload’dan çözümler. Sunucu webhook tetikleyicisine bakın.
Bir işlevi CLI kullanarak manuel olarak da çalıştırabilirsiniz:
yarn twenty dev:function:exec -n create-new-post-card -p '{"key": "value"}'
yarn twenty dev:function:exec -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
Günlükleri şu şekilde izleyebilirsiniz:
yarn twenty dev:function:logs

Rota tetikleyicisi yükü

Bir rota tetikleyicisi mantık fonksiyonunuzu çağırdığında, AWS HTTP API v2 formatını izleyen bir RoutePayload nesnesi alır. RoutePayload türünü twenty-sdk/logic-function içinden içe aktarın:
import type { RoutePayload } from 'twenty-sdk/logic-function';

const handler = async (event: RoutePayload) => {
  const { headers, queryStringParameters, pathParameters, body } = event;
  const { method, path } = event.requestContext.http;

  return { message: 'Success' };
};
RoutePayload türünün yapısı şu şekildedir:
ÖzellikTürAçıklamaÖrnek
headersRecord\<string, string | undefined>HTTP başlıkları (forwardedRequestHeaders içinde listelenenlerle sınırlı)aşağıdaki bölüme bakın
queryStringParametersRecord\<string, string | undefined>Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir)/users?ids=1&ids=2&ids=3&name=Alice -> { ids: '1,2,3', name: 'Alice' }
pathParametersRecord\<string, string | undefined>Rota deseninden çıkarılan yol parametreleri/users/:id, /users/123 -> { id: '123' }
bodyobject | nullAyrıştırılmış istek gövdesi (JSON){ id: 1 } -> { id: 1 }
rawBodystring | undefinedJSON ayrıştırılmadan önceki özgün UTF-8 istek gövdesi. HMAC tarzı webhook imzalarını doğrulamak için kullanışlıdır (ör. GitHub’ın X-Hub-Signature-256, Stripe). Çalışma zamanı onu korumadığında undefined olur.
isBase64EncodedbooleanGövdenin base64 ile kodlanıp kodlanmadığı
requestContext.http.methodstringHTTP yöntemi (GET, POST, PUT, PATCH, DELETE)
requestContext.http.pathstringHam istek yolu

forwardedRequestHeaders

Varsayılan olarak, güvenlik nedenleriyle gelen isteklerden HTTP başlıkları mantık fonksiyonunuza aktarılmaz. Belirli başlıklara erişmek için bunları forwardedRequestHeaders dizisinde listeleyin:
export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'webhook-handler',
  handler,
  httpRouteTriggerSettings: {
    path: '/webhook',
    httpMethod: 'POST',
    isAuthRequired: false,
    forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
  },
});
İşleyicinizde, iletilen başlıklara şu şekilde erişin:
const handler = async (event: RoutePayload) => {
  const signature = event.headers['x-webhook-signature'];
  const contentType = event.headers['content-type'];

  // Validate webhook signature...
  return { received: true };
};
Başlık adları küçük harfe normalize edilir. Onlara küçük harfli anahtarlarla erişin (örneğin, event.headers['content-type']).

Özel HTTP yanıtı

Varsayılan olarak, işleyicinizden düz bir değer döndürmek, onu 200 yanıtı olarak geri gönderir (nesneler için JSON, stringler için text/plain). Durum kodunu ve yanıt üstbilgilerini kontrol etmek için, twenty-sdk/logic-function içinden bir Response döndürün:
import { Response } from 'twenty-sdk/logic-function';

const handler = async (event: RoutePayload) => {
  return new Response('<h1>Hello</h1>', {
    status: 201,
    headers: { 'content-type': 'text/html' },
  });
};
Güvenlik nedenleriyle, yanıt üstbilgileri bir izin listesiyle sınırlandırılmıştır. Listede yer almayan herhangi bir üstbilgi (örneğin Set-Cookie, Access-Control-Allow-Origin gibi CORS üstbilgileri veya özel X-* üstbilgileri), yanıt gönderilmeden önce sessizce yok sayılır. İzin verilen yanıt üstbilgileri şunlardır:
  • content-type
  • content-language
  • content-disposition
  • cache-control
  • retry-after
Durum kodu geçerli bir HTTP durum kodu olmalıdır (100 ile 599 arasında). Yanıt üstbilgisi adları büyük/küçük harfe duyarsız olarak eşleştirilir.

Sunucu webhook tetikleyicisi

httpRouteTriggerSettings, /s/ altında bir fonksiyon sunar ve çalışma alanını istek ana bilgisayarından çözümler — bu da her çalışma alanının kendi alan adına sahip olduğu durumda işe yarar. Üçüncü taraf sağlayıcılar ise, her kiracının olaylarını tek webhook URL’sine iletir. Bu durum için serverWebhookTriggerSettings kullanın: fonksiyona kayıt kapsamlı bir uç noktadan erişilebilir ve çalışma alanı, payload’dan çözümlenir.
src/logic-functions/handle-provider-webhook.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk/define';
import type { RoutePayload } from 'twenty-sdk/logic-function';
import { Response } from 'twenty-sdk/logic-function';

const handler = async (event: RoutePayload) => {
  // Verify the signature yourself before doing anything (see below).
  // Return a non-2xx Response to make the provider retry.
  return { received: true };
};

export default defineLogicFunction({
  universalIdentifier: 'b3c2f0a1-7d4e-4c9a-9f2b-2e1d6a4c8e10',
  name: 'handle-provider-webhook',
  handler,
  serverWebhookTriggerSettings: {
    workspaceIdResolver: { source: 'body', path: 'metadata.twentyWorkspaceId' },
    forwardedRequestHeaders: ['webhook-id', 'webhook-timestamp', 'webhook-signature'],
  },
});
Fonksiyona şu adresten erişilebilir:
POST https://your-twenty-server.com/webhooks/server/:applicationRegistrationUniversalIdentifier/:logicFunctionUniversalIdentifier
Her iki tanımlayıcı da manifest’inizdeki universalIdentifier değerleridir — uygulama kaydınınki ve bu mantık fonksiyonununki. Bu URL’yi sağlayıcıya kaydedin.Çalışma alanı çözümleme. Tek bir uç nokta her çalışma alanına hizmet verdiğinden, entegrasyonunuz hedef workspaceId değerini teslimatta bir yere koymalı ve workspaceIdResolver.{ source, path } platforma bunun nereden okunacağını söyler:
AlanDeğerlerNotlar
sourcebody | query | headerbody, ayrıştırılmış JSON’u okur. query en evrensel seçenektir — genellikle kaydettiğiniz callback URL’sini kontrol edersiniz, bu yüzden ?twentyWorkspaceId=… ekleyin.
pathnokta-yolu, örn. metadata.twentyWorkspaceIdAlfasayısal / _ / - segmentleriyle sınırlandırılmıştır; prototype anahtarları reddedilir.
Çözümlenen değer geçerli bir çalışma alanı UUID’si olmalı ve uygulamanızın o çalışma alanına yüklü olması gerekir, aksi halde istek, fonksiyon çalışmadan önce reddedilir.
İmza doğrulama sizin sorumluluğunuzdadır. Platform bu tetikleyici için webhook imzalarını doğrulamaz — yalnızca çalışma alanını çözümler ve fonksiyonunuzu çalıştırır. İşleyiciniz imzayı, event.rawBody ve forwardedRequestHeaders içinde listelediğiniz başlıkları kullanarak, sunucu/uygulama değişkeni olarak saklanan bir gizli anahtarla karşılaştırıp kendisi doğrulamalıdır. Her zaman herhangi bir yan etkiden önce doğrulayın ve sabit süreli bir karşılaştırma kullanın.
Çoğu sağlayıcı HMAC-SHA256 ile imzalar; farklı olan kısımlar başlık adı, özet kodlaması ve imzalanan payload dizesidir. Birkaç örnek:
Sağlayıcıİletilecek başlıklarİmzalanmış dizeÖzet
Svix (Recall, Resend, Clerk)webhook-id, webhook-timestamp, webhook-signature{id}.{timestamp}.{rawBody}base64 (gizli anahtar, whsec_ kaldırıldıktan sonra base64’tür)
Stripestripe-signature{timestamp}.{rawBody}hex
GitHubx-hub-signature-256{rawBody}hex (sha256= önekiyle)
Shopifyx-shopify-hmac-sha256{rawBody}base64
Slackx-slack-signature, x-slack-request-timestampv0:{timestamp}:{rawBody}hex (v0= önekiyle)
import { createHmac, timingSafeEqual } from 'crypto';

const handler = async (event: RoutePayload) => {
  const signature = event.headers['x-hub-signature-256'] ?? '';
  const expected =
    'sha256=' +
    createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET ?? '')
      .update(event.rawBody ?? '')
      .digest('hex');

  const a = Buffer.from(signature);
  const b = Buffer.from(expected);

  if (a.length !== b.length || !timingSafeEqual(a, b)) {
    return new Response({ error: 'invalid signature' }, { status: 401 });
  }

  // ...handle the verified event
  return { received: true };
};
Fonksiyon senkron olarak çalışır ve döndürdüğünüz değer HTTP yanıtı olur, bu nedenle sağlayıcılar durum kodunuzu görür ve 2xx olmayanlarda yeniden deneyebilir. İşleyicileri hızlı tutun — bazı sağlayıcılar (örn. Slack) birkaç saniye içinde zaman aşımına uğrar. Fonksiyon imza denetlenmeden önce çalıştığı için, bu uç noktayı edge’inizde hız sınırlamasıyla koruyun.

Veritabanı olay tetikleyicisi yükü

Bir veritabanı olay tetikleyicisi mantık fonksiyonunuzu çağırdığında, değişen her kayıt için bir DatabaseEventPayload alır. Yük, kaynak çalışma alanı ve nesne hakkındaki üstveriyi, kayıt düzeyindeki olayla birleştirir.
import type {
  DatabaseEventPayload,
  ObjectRecordCreateEvent,
  ObjectRecordDestroyEvent,
  ObjectRecordUpdateEvent,
} from 'twenty-sdk/logic-function';

type Person = {
  id: string;
  emails?: { primaryEmail?: string };
};
Yük, şunları içerir:
ÖzellikAçıklama
nameperson.updated gibi bir olay adı.
workspaceIdOlayın gerçekleştiği çalışma alanı.
objectMetadataDeğişen nesne için üstveri.
recordIdDeğişen kaydın kimliği.
userId, userWorkspaceId, workspaceMemberIdOlay bir çalışma alanı kullanıcısı tarafından tetiklendiğinde aktör alanları.
propertiesİşleme bağlı olarak before, after, diff ve updatedFields içeren olay için kayıt verileri.
EtkinlikKayıt verileri
person.createdevent.properties.after
person.updatedevent.properties.before, event.properties.after, event.properties.diff, event.properties.updatedFields
person.destroyedevent.properties.before
Yumuşak silmeler için, kayıt deletedAt alanı değiştiğinden .deleted, güncelleme tarzı yapıyı izler. Kalıcı silmeler için .destroyed kullanın.
databaseEventTriggerSettings.updatedFields, hangi güncelleme olaylarının fonksiyonu tetikleyeceğini filtreler. event.properties.updatedFields, mevcut olayda hangi alanların gerçekten değiştiğini size bildirir.
Oluşturma olayı örneği:
type PersonCreatedEvent = DatabaseEventPayload<
  ObjectRecordCreateEvent<Person>
>;

const handler = async (event: PersonCreatedEvent) => {
  const person = event.properties.after;

  return {
    personId: event.recordId,
    email: person.emails?.primaryEmail,
  };
};
Güncelleme olayı örneği:
type PersonUpdatedEvent = DatabaseEventPayload<
  ObjectRecordUpdateEvent<Person>
>;

const handler = async (event: PersonUpdatedEvent) => {
  const { before, after, diff, updatedFields } = event.properties;

  return {
    personId: event.recordId,
    updatedFields,
    previousEmail: before.emails?.primaryEmail,
    currentEmail: after.emails?.primaryEmail,
    emailDiff: diff.emails,
  };
};
Yalnızca e-posta güncellemelerinde tetikle:
export default defineLogicFunction({
  ...,
  databaseEventTriggerSettings: {
    eventName: 'person.updated',
    updatedFields: ['emails'],
  },
});
Yok etme olayı örneği:
type PersonDestroyedEvent = DatabaseEventPayload<
  ObjectRecordDestroyEvent<Person>
>;

const handler = async (event: PersonDestroyedEvent) => {
  const personBeforeDestroy = event.properties.before;

  return {
    personId: event.recordId,
    email: personBeforeDestroy.emails?.primaryEmail,
  };
};

Bir işlevi bir yapay zekâ aracı veya iş akışı eylemi olarak kullanıma sunma

Mantık işlevleri, her birinin kendi tetikleyicisi olacak şekilde iki yerde kullanılabilir hâle getirilebilir:
  • toolTriggerSettings — işlevi Twenty’nin yapay zekâ özellikleri (sohbet, MCP, işlev çağırma) tarafından bulunabilir hâle getirir. Standart JSON Şeması’nı kullanır; LLM’lerin doğal olarak anladığı biçimdir.
  • workflowActionTriggerSettings — işlevin görsel iş akışı oluşturucusunda bir adım olarak görünmesini sağlar. Oluşturucunun uygun alan düzenleyicilerini, değişken seçicilerini ve etiketleri oluşturabilmesi için Twenty’nin zengin InputSchema’sını kullanır.
Bir işlev bunlardan birini, diğerini veya her ikisini de tercih edebilir. Bunlar, cronTriggerSettings, databaseEventTriggerSettings ve httpRouteTriggerSettings ile birlikte yer alır — aynı desen, aynı biçim.
src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';

const handler = async (params: { companyName: string; domain?: string }) => {
  const client = new CoreApiClient();

  const result = await client.mutation({
    createTask: {
      __args: {
        data: {
          title: `Enrich data for ${params.companyName}`,
          body: `Domain: ${params.domain ?? 'unknown'}`,
        },
      },
      id: true,
    },
  });

  return { taskId: result.createTask.id };
};

export default defineLogicFunction({
  universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
  name: 'enrich-company',
  description: 'Enrich a company record with external data',
  timeoutSeconds: 10,
  handler,
  toolTriggerSettings: {},
});
Önemli noktalar:
  • Bir işlev yüzeyleri karıştırabilir — onu sohbette VE iş akışı oluşturucusunda kullanıma sunmak için hem toolTriggerSettings hem de workflowActionTriggerSettings bildirin.
  • toolTriggerSettings.inputSchema ve workflowActionTriggerSettings.inputSchema ikisi de isteğe bağlıdır. Atlandığında, manifest oluşturucu bunları işleyici kaynak kodundan çıkarır (yapay zekâ aracı için JSON Şeması, iş akışı eylemi için Twenty’nin InputSchema’sı). Daha zengin tipleme istediğinizde birini açıkça belirtin — örneğin, iş akışı oluşturucu için FieldMetadataType’ı bilen CURRENCY veya RELATION gibi alanlarla ya da yapay zekâ aracısının okuyabileceği description alanlarıyla:
export default defineLogicFunction({
  ...,
  toolTriggerSettings: {
    inputSchema: {
      type: 'object',
      properties: {
        companyName: {
          type: 'string',
          description: 'The name of the company to enrich',
        },
        domain: {
          type: 'string',
          description: 'The company website domain (optional)',
        },
      },
      required: ['companyName'],
    },
  },
});
Parametrelerinizi bir kez tanımlayıp her iki yüzeyde de kullanmak için tek bir JSON Şeması (InputJsonSchema) oluşturun ve bunu iş akışı eylemi için twenty-sdk/logic-function içindeki jsonSchemaToInputSchema ile dönüştürün. toolTriggerSettings.inputSchema, JSON Şemasını doğrudan alırken workflowActionTriggerSettings.inputSchema, Twenty’nin InputSchema tipini bekler:
import { defineLogicFunction } from 'twenty-sdk/define';
import { jsonSchemaToInputSchema, type InputJsonSchema } from 'twenty-sdk/logic-function';

const inputSchema: InputJsonSchema = {
  type: 'object',
  properties: {
    companyName: { type: 'string', label: 'Company name' },
    domain: { type: 'string', label: 'Domain' },
  },
  required: ['companyName'],
};

export default defineLogicFunction({
  ...,
  toolTriggerSettings: { inputSchema },
  workflowActionTriggerSettings: {
    label: 'Enrich Company',
    icon: 'IconBuilding',
    inputSchema: jsonSchemaToInputSchema(inputSchema),
  },
});
İyi bir description yazın. AI ajanları, aracı ne zaman kullanacaklarına karar vermek için işlevin description alanına güvenir. Aracın ne yaptığını ve ne zaman çağrılması gerektiğini açıkça belirtin.
Çalışma zamanı yardımcıları. twenty-sdk/utils, işleyicilerin doğrudan twenty-shared içinden içe aktarma yapmasına gerek kalmaması için küçük çalışma zamanı yardımcılarını yeniden dışa aktarır. Örneğin, isDefined(value) hem null hem de undefined için false döndürür — bunu, çalışma zamanında T | undefined olarak yazılmış olsa bile null olarak gelebilen isteğe bağlı işleyici girdilerini güvenli şekilde daraltmak için kullanın:
import { isDefined } from 'twenty-sdk/utils';

const handler = async (params: { parentMessageId?: string }) => {
  if (isDefined(params.parentMessageId)) {
    // params.parentMessageId is narrowed to string here
  }
};
Yükleme kancaları — ön yükleme ve yükleme sonrası işleyiciler — bu çalışma zamanını paylaşır ancak kendi tanımlama işlevleriyle bildirilir ve tetikleyici ayarlarını almaz. definePreInstallLogicFunction ve definePostInstallLogicFunction için Yükleme Kancaları bölümüne bakın.

Tipli API istemcileri (twenty-client-sdk)

twenty-client-sdk paketi, mantık fonksiyonlarınızdan ve ön uç bileşenlerinizden Twenty API ile etkileşim kurmak için tip tanımlı iki GraphQL istemcisi sağlar.
İstemciİçe AktarUç noktaOluşturuldu mu?
CoreApiClienttwenty-client-sdk/core/graphql — çalışma alanı verileri (kayıtlar, nesneler)Evet, geliştirme/derleme zamanında
MetadataApiClienttwenty-client-sdk/metadata/metadata — çalışma alanı yapılandırması, dosya yüklemeleriHayır, önceden hazırlanmış olarak gelir
CoreApiClient, çalışma alanı verilerini sorgulamak ve değiştirmek için ana istemcidir. yarn twenty dev veya yarn twenty dev:build sırasında çalışma alanı şemanızdan oluşturulur, bu nedenle nesnelerinize ve alanlarınıza uyacak şekilde tamamen tiplenmiştir.
import { CoreApiClient } from 'twenty-client-sdk/core';

const client = new CoreApiClient();

// Query records
const { companies } = await client.query({
  companies: {
    edges: {
      node: {
        id: true,
        name: true,
        domainName: {
          primaryLinkLabel: true,
          primaryLinkUrl: true,
        },
      },
    },
  },
});

// Create a record
const { createCompany } = await client.mutation({
  createCompany: {
    __args: {
      data: {
        name: 'Acme Corp',
      },
    },
    id: true,
    name: true,
  },
});
İstemci bir seçim kümesi sözdizimi kullanır: Bir alanı dahil etmek için true geçin, bağımsız değişkenler için __args kullanın ve ilişkiler için nesneleri iç içe yerleştirin. Çalışma alanı şemanıza göre tam otomatik tamamlama ve tip denetimi elde edersiniz.
CoreApiClient geliştirme/derleme zamanında oluşturulur. Bunu önce yarn twenty dev veya yarn twenty dev:build çalıştırmadan kullanırsanız, bir hata verir. Oluşturma otomatik olarak gerçekleşir — CLI, çalışma alanınızın GraphQL şemasını inceler ve @genql/cli kullanarak tiplenmiş bir istemci üretir.

Tür açıklamaları için CoreSchema’yı kullanma

CoreSchema, çalışma alanı nesnelerinize uyan TypeScript türleri sağlar — bileşen durumunu veya işlev parametrelerini tiplemek için kullanışlıdır:
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
import { useState } from 'react';

const [company, setCompany] = useState<
  Pick<CoreSchema.Company, 'id' | 'name'> | undefined
>(undefined);

const client = new CoreApiClient();
const result = await client.query({
  company: {
    __args: { filter: { position: { eq: 1 } } },
    id: true,
    name: true,
  },
});
setCompany(result.company);
MetadataApiClient, SDK ile birlikte önceden hazırlanmış olarak gelir (oluşturma gerektirmez). Çalışma alanı yapılandırması, uygulamalar ve dosya yüklemeleri için /metadata uç noktasını sorgular.
import { MetadataApiClient } from 'twenty-client-sdk/metadata';

const metadataClient = new MetadataApiClient();

// List first 10 objects in the workspace
const { objects } = await metadataClient.query({
  objects: {
    edges: {
      node: {
        id: true,
        nameSingular: true,
        namePlural: true,
        labelSingular: true,
        isCustom: true,
      },
    },
    __args: {
      filter: {},
      paging: { first: 10 },
    },
  },
});

Dosya yükleme

MetadataApiClient, dosya türündeki alanlara dosya eklemek için bir uploadFile yöntemi içerir:
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
import * as fs from 'fs';

const metadataClient = new MetadataApiClient();

const fileBuffer = fs.readFileSync('./invoice.pdf');

const uploadedFile = await metadataClient.uploadFile(
  fileBuffer,                                         // file contents as a Buffer
  'invoice.pdf',                                      // filename
  'application/pdf',                                  // MIME type
  '58a0a314-d7ea-4865-9850-7fb84e72f30b',            // field universalIdentifier
);

console.log(uploadedFile);
// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' }
ParametreTürAçıklama
fileBufferBufferDosyanın ham içeriği
filenamestringDosyanın adı (depolama ve görüntüleme için kullanılır)
contentTypestringMIME türü (belirtilmezse varsayılan olarak application/octet-stream kullanılır)
fieldMetadataUniversalIdentifierstringNesnenizdeki dosya türü alanının universalIdentifier değeri
Önemli noktalar:
  • Alan için universalIdentifier kullanır (çalışma alanına özgü kimliği değil), böylece yükleme kodunuz uygulamanızın yüklü olduğu herhangi bir çalışma alanında çalışır.
  • Döndürülen url, yüklenen dosyaya erişmek için kullanabileceğiniz imzalı bir URL’dir.
Kodunuz Twenty üzerinde çalıştığında (mantık işlevleri veya ön uç bileşenleri), platform kimlik bilgilerini ortam değişkenleri olarak enjekte eder:
  • TWENTY_API_URL — Twenty API’nin temel URL’si
  • TWENTY_APP_ACCESS_TOKEN — Uygulamanızın varsayılan işlev rolü kapsamında kısa ömürlü bir anahtar
Bunları istemcilere iletmeniz gerekmez — otomatik olarak process.env’den okurlar. API anahtarının izinleri, defineApplicationRole() ile bildirilen role (veya application-config.ts içindeki defaultRoleUniversalIdentifier üzerinden referans verilen role) göre belirlenir.