Lingara 開發者文件
呢頁係由英文翻譯過嚟嘅。如果兩個版本有出入,以英文頁為準。 睇英文頁
一個連接由步驟組成,任何步驟都可以帶一個腳本。步驟嘅腳本係一個函式嘅主體。佢會收到兩個值:lingara,即係呢頁講嘅 API;同埋 input,即係嗰個步驟自己啲欄位,連埋佢嘅用戶端同埋喺佢之前連接咗嘅步驟。input 嘅型別取決於步驟嘅種類,所以 Webhook 步驟嘅腳本讀嘅係 Webhook 步驟嘅欄位。腳本只會傳返啱啱好一個物件,由下面其中一個輔助函式建立。
腳本永遠睇唔到密鑰。當步驟需要佢嘅用戶端,佢會攞到一個控制代碼,例如 input.client,而輔助函式會記錄低呢個控制代碼。你套用連接嗰陣,Lingara 會填返真正嘅值。
腳本唔可以做嘅嘢
腳本喺你自己個瀏覽器度行,喺一個冇網絡、冇儲存空間嘅 worker 入面。佢要守以下限制:
- 佢要喺 1 秒之內完成。
- 佢傳返嘅字串最多 2048 個字元。
- 佢傳返嘅清單最多 64 項。
- 佢成個結果最多 16 KiB。
超出限制、拋出例外,或者傳返嘅唔係某個輔助函式結果嘅腳本,會令佢個步驟失敗,「開始檢查」會顯示係邊個步驟同埋原因。
版本承諾
呢頁嘅所有嘢都屬於 lingara.v1。喺 v1 入面,API 只會擴充:可能會出現新嘅輔助函式、新嘅可選選項或者新嘅步驟種類,但係你今日用得到嘅嘢都唔會被移除、改名或者收窄。會整壞腳本嘅改動會成為同呢個版本並存嘅新版本,而 v1 會維持原樣。
宣告
下面每個宣告都係由腳本編輯器自動完成所根據嘅同一個檔案產生。
NodeHandle
另一個步驟嘅 id,例如 "n1"。依賴其他步驟嘅步驟會用控制代碼指定佢嘅用戶端。
export type NodeHandle = string;
Scope
API 用戶端可以擁有嘅一項權限。由伺服器判斷你個帳戶可以用邊啲。
export type Scope = 'vocab:generate' | 'lesson_plans:read' | 'lesson_plans:write' | 'tutor:converse' | 'usage:read' | 'events:read' | 'events:write' | 'embed:mint' | 'embed:play';
AppSlot
Lingara App 入面可以顯示應用程式卡片嘅位置。
export type AppSlot = 'plans.empty_detail' | 'home.side';
ContextSlice
應用程式可以要求收到嘅學習者情境嘅一部分。
export type ContextSlice = 'languages' | 'plan_summary' | 'review_due' | 'tutor_topic';
ClientOptions
lingara.client 嘅選項。
export interface ClientOptions {
name: string;
scopes: readonly Scope[];
redirectUris?: readonly string[];
}
name(string) — 用戶端嘅名稱,同開發者工具顯示嘅一樣。scopes(readonly Scope[]) — 用戶端要求嘅權限。redirectUris?(readonly string[]) — 授權碼流程可以將學習者送返去嘅地方。伺服器對伺服器嘅用戶端可以唔填。
WebhookOptions
lingara.webhook 嘅選項。
export interface WebhookOptions {
client: NodeHandle;
url: string;
events: readonly string[];
}
client(NodeHandle) — 呢個 Webhook 所屬嘅用戶端步驟:input.client。url(string) — Lingara 傳送事件去嘅 HTTPS 地址。events(readonly string[]) — 要傳送嘅事件類型,例如"lesson_plan.ready"。
ManifestOptions
lingara.manifest 嘅選項,用 camelCase;輔助函式會寫出資訊清單嘅傳輸格式。
export interface ManifestOptions {
name: string | Readonly<Record<string, string>>;
description: string | Readonly<Record<string, string>>;
renderUrl: string;
slots: readonly AppSlot[];
context?: readonly ContextSlice[];
scopes?: readonly Scope[];
tutorNote?: boolean;
defaultLocale?: string;
}
name(string | Readonly<Record<string, string>>) — 應用程式嘅名稱:一個字串,或者每個語言代碼一個字串。description(string | Readonly<Record<string, string>>) — 關於應用程式嘅一句說話:一個字串,或者每個語言代碼一個字串。renderUrl(string) — Lingara 要應用程式張卡嘅 HTTPS 地址。slots(readonly AppSlot[]) — 應用程式張卡可以出現嘅位置。context?(readonly ContextSlice[]) — 應用程式收到嘅情境片段。預設係冇。scopes?(readonly Scope[]) — 應用程式向學習者要求嘅權限。預設係冇。tutorNote?(boolean) — 應用程式可唔可以留低備註畀導師。預設係false。defaultLocale?(string) — 純字串名稱或者描述儲存所用嘅語言代碼。預設係"en"。
AppOptions
lingara.app 嘅選項。
export interface AppOptions {
client: NodeHandle;
manifest: Manifest;
}
client(NodeHandle) — 呢個應用程式所屬嘅用戶端步驟:input.client。manifest(Manifest) — 應用程式嘅資訊清單,用lingara.manifest建立。
ClientSpec
用戶端步驟建立嘅嘢:一個 API 用戶端。
export interface ClientSpec {
readonly kind: 'client';
readonly name: string;
readonly scopes: readonly Scope[];
readonly redirectUris?: readonly string[];
}
kind('client') — 永遠係"client"。name(string) — 用戶端嘅名稱。scopes(readonly Scope[]) — 用戶端要求嘅權限。redirectUris?(readonly string[]) — 用戶端嘅重新導向 URI(如果有嘅話)。
SecretSpec
密鑰步驟建立嘅嘢:為佢嘅用戶端產生嘅新密鑰。
export interface SecretSpec {
readonly kind: 'secret';
readonly client: NodeHandle;
}
kind('secret') — 永遠係"secret"。client(NodeHandle) — 密鑰所屬嘅用戶端步驟。
WebhookSpec
Webhook 步驟建立嘅嘢:一個 Webhook 端點。
export interface WebhookSpec {
readonly kind: 'webhook';
readonly client: NodeHandle;
readonly url: string;
readonly events: readonly string[];
}
kind('webhook') — 永遠係"webhook"。client(NodeHandle) — Webhook 所屬嘅用戶端步驟。url(string) — 事件傳送去嘅地址。events(readonly string[]) — 傳送嘅事件類型。
AppSpec
應用程式步驟建立嘅嘢:一個喺 Lingara 入面畫卡嘅應用程式。
export interface AppSpec {
readonly kind: 'app';
readonly client: NodeHandle;
readonly manifest: Manifest;
}
kind('app') — 永遠係"app"。client(NodeHandle) — 應用程式所屬嘅用戶端步驟。manifest(Manifest) — 應用程式嘅資訊清單。
Manifest
傳輸格式嘅應用程式資訊清單,同伺服器儲存嘅樣一樣。
export interface Manifest {
readonly manifest_version: 1;
readonly default_locale: string;
readonly name: Readonly<Record<string, string>>;
readonly description: Readonly<Record<string, string>>;
readonly render_url: string;
readonly slots: readonly AppSlot[];
readonly context: readonly ContextSlice[];
readonly scopes: readonly Scope[];
readonly tutor_note: boolean;
}
manifest_version(1) — 永遠係1。default_locale(string) — 學習者自己嘅語言冇項目嗰陣顯示嘅語言。name(Readonly<Record<string, string>>) — 應用程式嘅名稱,按語言代碼分。description(Readonly<Record<string, string>>) — 關於應用程式嘅一句說話,按語言代碼分。render_url(string) — Lingara 要應用程式張卡嘅 HTTPS 地址。slots(readonly AppSlot[]) — 應用程式張卡可以出現嘅位置。context(readonly ContextSlice[]) — 應用程式收到嘅情境片段。scopes(readonly Scope[]) — 應用程式向學習者要求嘅權限。tutor_note(boolean) — 應用程式可唔可以留低備註畀導師。
Spec
輔助函式傳返嘅任何 spec。腳本只會傳返啱啱好一個。
export type Spec = ClientSpec | SecretSpec | WebhookSpec | AppSpec;
Upstream
每個直接上游步驟嘅輸出,按控制代碼索引。
export type Upstream = Readonly<Record<NodeHandle, Spec & {
readonly handle: NodeHandle;
}>>;
ClientInput
用戶端步驟嘅輸入:佢啲欄位,即係 lingara.client 嘅選項。
export interface ClientInput {
readonly name: string;
readonly scopes: readonly Scope[];
readonly redirectUris?: readonly string[];
readonly upstream: Upstream;
}
name(string) — 用戶端嘅名稱。scopes(readonly Scope[]) — 用戶端要求嘅權限。redirectUris?(readonly string[]) — 用戶端嘅重新導向 URI(如果個步驟有嘅話)。upstream(Upstream) — 每個直接上游步驟嘅輸出。
SecretInput
密鑰步驟嘅輸入。client 係同呢個步驟連接咗嘅嗰一個用戶端步驟。
export interface SecretInput {
readonly client: NodeHandle;
readonly upstream: Upstream;
}
client(NodeHandle) — 同呢個步驟連接咗嘅用戶端步驟。upstream(Upstream) — 每個直接上游步驟嘅輸出。
WebhookInput
Webhook 步驟嘅輸入:佢啲欄位,加埋連接咗嘅用戶端。
export interface WebhookInput {
readonly client: NodeHandle;
readonly url: string;
readonly events: readonly string[];
readonly upstream: Upstream;
}
client(NodeHandle) — 同呢個步驟連接咗嘅用戶端步驟。url(string) — 個步驟啲欄位指定嘅地址。events(readonly string[]) — 個步驟啲欄位指定嘅事件類型。upstream(Upstream) — 每個直接上游步驟嘅輸出。
AppInput
應用程式步驟嘅輸入:佢嘅資訊清單欄位,加埋連接咗嘅用戶端。
export interface AppInput {
readonly client: NodeHandle;
readonly manifest: ManifestOptions;
readonly upstream: Upstream;
}
client(NodeHandle) — 同呢個步驟連接咗嘅用戶端步驟。manifest(ManifestOptions) — 個步驟啲欄位描述嘅資訊清單。upstream(Upstream) — 每個直接上游步驟嘅輸出。
InputFor
指定種類嘅步驟腳本會收到嘅輸入。
export type InputFor<K extends Spec['kind']> = K extends 'client' ? ClientInput : K extends 'secret' ? SecretInput : K extends 'webhook' ? WebhookInput : AppInput;
LingaraV1
腳本調用嘅輔助函式。每個都會傳返一個凍結咗嘅 spec,型別錯咗嘅選項會拋出一個講明係邊個選項嘅 TypeError。
export interface LingaraV1 {
readonly version: 'v1';
client(options: ClientOptions): ClientSpec;
secret(client: NodeHandle): SecretSpec;
webhook(options: WebhookOptions): WebhookSpec;
app(options: AppOptions): AppSpec;
manifest(options: ManifestOptions): Manifest;
}
version('v1') — 永遠係"v1"。client(options: ClientOptions): ClientSpec— 一個 API 用戶端。secret(client: NodeHandle): SecretSpec— 為用戶端步驟產生嘅新密鑰。webhook(options: WebhookOptions): WebhookSpec— 用戶端步驟上面嘅 Webhook 端點。app(options: AppOptions): AppSpec— 用戶端步驟上面嘅應用程式。manifest(options: ManifestOptions): Manifest— 傳輸格式嘅資訊清單,並填埋 v1 留做可選嘅嗰啲選項。
return lingara.client({ name: input.name, scopes: input.scopes })
return lingara.secret(input.client)
return lingara.webhook({ client: input.client, url: input.url, events: input.events })
return lingara.app({ client: input.client, manifest: lingara.manifest(input.manifest) })
NodeScript
步驟嘅腳本就係呢個函式嘅主體:return lingara.webhook({ client: input.client, url: input.url, events: input.events })。
export type NodeScript<K extends Spec['kind']> = (lingara: LingaraV1, input: InputFor<K>) => Spec;