コンテンツにスキップ

スクリプトを書く

スクリプトノードは、フローの処理を TypeScript で記述するノードです。コードはランナー上の Deno で実行されます。

スクリプトノードを選ぶと、右側にエディタが開きます。上部に 標準ライブラリ / 外部パッケージ / ファンクション / 環境変数 / 認証情報 のインポート欄、その下にコードエディタ、さらに セキュリティフラグ の設定があります。

スクリプトノードの編集画面

スクリプトは、Parameter を受け取り Result を返す関数を default export します。

import { Parameter, Result } from "./nodeType.ts";
export default async function (parameter: Parameter): Promise<Result> {
// ここに処理を書く
return {
// 次のノードに渡す値
};
}
  • Parameter — このノードへの入力です。
  • Result — このノードの出力です。

フローは複数のノードを順に実行します。あるノードが return した Result が、次のノードの Parameter になります。 フローの最初のノードの Parameter には、トリガーの出力(HTTPリクエストの内容やフォームの入力など)が渡されます。

トリガー → ノードA → ノードB → 終了
(Result) ↑
Parameter

各ノードの「型」エディタで Result の項目を定義すると、./nodeType.ts の Parameter / Result 型が自動生成され、エディタ上で型補完が効きます。型は GUI と JSON のどちらでも定義できます。

フローの最初のノードには、起動したトリガーの内容が渡されます。トリガーが複数ある場合は code で判別できる union になります。

トリガー Parameter
定期実行 { code: string; scheduledAt: Temporal.Instant }
HTTPリクエスト { code: string; request: { searchParams; headers; jsonBody; binaryBody } }
フォーム { code: string; form: <フォームの型> }

定期実行の scheduledAt は、この実行が受け持つ実行予定時刻です。サーバーが停止していた間に過ぎた分を補填した実行では、現在時刻より前の値になります。「どの時刻ぶんの実行なのか」で処理を変えたい場合(対象期間を決める、二重処理を避けるなど)はこの値を使ってください。→ スケジュールを確認する

import { Parameter, Result } from "./nodeType.ts";
export default async function (parameter: Parameter): Promise<Result> {
// 予定時刻が属する日を集計対象にする(遅れて実行されても対象日がずれない)
const targetDate = parameter.scheduledAt
.toZonedDateTimeISO("Asia/Tokyo")
.toPlainDate();
console.log(`${targetDate} 分を集計します`);
return {};
}

環境変数・認証情報・ファンクション・データベースを使う

Section titled “環境変数・認証情報・ファンクション・データベースを使う”

スクリプトからは、synqlet: で始まる特別なモジュールを import して、Synqlet のリソースを利用できます。これらは エディタ上部(または右の「ライブラリ」パネル)の「+」から追加 すると、import 文が自動で挿入されます(ID を手入力する必要はありません)。

ID とコードのどちらでも指定できる

Section titled “ID とコードのどちらでも指定できる”

import に書く参照は、ID(UUID) でも コード でも構いません。コードは環境変数・認証情報・テーブル・ファンクションの作成画面で設定できる、組織内で一意な短い名前です。

// どちらも同じ環境変数を指す
import url from "synqlet:environment-variables/019cd0a6-ea24-7677-87af-6f62f67553f0";
import url from "synqlet:environment-variables/API_BASE_URL";
  • コードに使えるのは 半角英数字と _ だけです(- は ID と区別するため使えません)。63 文字以内。
  • コードを設定していないリソースは ID でしか参照できません。
  • 同じスクリプトの中で ID 参照とコード参照を混ぜても構いません。

コードを付けたリソースは、「ライブラリ」パネルの「+」から追加したときも自動でコードで挿入されます。

import API_BASE_URL from "synqlet:environment-variables/{環境変数のID または コード}";
// API_BASE_URL に環境変数の値が入る

→ 環境変数

import credential from "synqlet:credentials/{認証情報のID または コード}";
// 外部サービスを呼ぶ直前に毎回 await credential() する
const response = await fetch(url, {
headers: { Authorization: `Bearer ${await credential()}` },
});

await credential() に復号済みの認証情報(アクセストークンなど)が入ります。

→ 認証情報(認証情報を扱うにはランナー側で秘密鍵ファイルが必要です)

ファンクション(共通ロジックの再利用)

Section titled “ファンクション(共通ロジックの再利用)”
import formatData from "synqlet:functions/{ファンクションのID または コード}";
const result = await formatData(/* ... */);

→ ファンクション

データベース(テーブルの行の読み書き)

Section titled “データベース(テーブルの行の読み書き)”
import * as customers from "synqlet:database/{テーブルのID または テーブルコード}";
// 一覧取得(ページングは自動)
for await (const row of customers.list({
filter: { values: { status: { _eq: "active" } } },
})) {
console.log(row.values.name);
}
// 作成・更新・削除
const created = await customers.insertOne({
values: { name: "株式会社サンプル" },
});
await customers.updateOne({ id: created.id, values: { status: "active" } });
await customers.deleteOne(created.id);

テーブルのフィールド定義から型が自動生成されるため、フィールド名・値の型がエディタで補完されます。

→ スクリプトからデータベースを操作する

HTTPリクエストトリガーへの応答

Section titled “HTTPリクエストトリガーへの応答”

HTTPリクエストトリガーで「レスポンスをカスタマイズする」を有効にした場合、sendResponse で応答を返せます。

import { sendResponse } from "synqlet:http-request-trigger";
await sendResponse(new Response("OK", { status: 200 }));

処理は続けたいけれど人に気づいてほしいことは、addWarning で警告として記録できます。console.warn は標準エラー出力に出るだけで警告にはならないので、区別してください。

import { addWarning } from "synqlet:warning";
await addWarning("在庫が不足しています");
  • 記録した警告はジョブの「ログ」とランナージョブ詳細のログに残ります。ログの中では必ず行が分かれて表示されるので、メッセージの末尾に改行を入れる必要はありません(結果メールに載るログでも同じです)。
  • フロージョブの一覧の「警告」列、詳細画面のノードの警告アイコン、ランナージョブ詳細の「警告」欄にも、記録時刻付きで表示されます。
  • 画面右に開く実行結果のパネル(プレイグラウンドやファンクションのテスト実行、実行中のフロージョブ)でも、ログの上に「警告」の欄が現れます。実行中は数秒ごとに自動更新されます。
  • 送信し終わるまで待つ必要があるので、必ず await してください。
  • 記録に失敗してもスクリプトは止まりません(警告は本処理に付随する記録なので、記録できなかっただけで処理を失敗させません)。失敗したときは理由が標準エラー出力に残ります。

実行中のフロージョブ・ランナージョブのIDと、その詳細画面のURLを取得できます。通知やチケットに実行ログへのリンクを添えたいときに使います。

import { flowJobUrl, runnerJobUrl } from "synqlet:job";
await notify(`処理が終わりました: ${flowJobUrl}`);
名前 内容
flowJobId フロージョブのID
flowJobUrl フロージョブ詳細画面のURL
runnerJobId ランナージョブのID
runnerJobUrl ランナージョブ詳細画面のURL
  • ファンクションやスクリプトノードのテスト実行にはフロージョブが無いため、flowJobId と flowJobUrl は空文字になります。使う前に空でないか確かめてください。
  • URLは組織を含む形(.../o/{組織ID}/flow-jobs/{ID})なので、そのまま開けます。

標準ライブラリ・外部パッケージ

Section titled “標準ライブラリ・外部パッケージ”
  • 標準ライブラリ — Deno Namespace APIs(Deno.*)と Web Platform APIs(fetch など)が使えます。
  • 外部パッケージ — npm / jsr のパッケージを import できます。「外部パッケージ」の「+」から追加します。
import { z } from "npm:zod";
import { delay } from "jsr:@std/async";

スクリプトは Deno 上で実行され、既定ではすべての権限が「すべて拒否」 になっています。必要な操作だけを明示的に許可することで、安全に実行できます。

セキュリティフラグ(Deno 権限)の設定

設定できる権限は次のとおりです(それぞれ「許可」と「拒否」を指定でき、拒否が許可より優先 されます)。

権限 内容
ファイルの読み取り ファイルシステムの読み取り
ファイルの書き込み ファイルシステムの書き込み
ネットワークアクセス 外部への通信(fetch など)
環境変数 OS の環境変数へのアクセス
システム情報 システム情報の取得
サブプロセス 外部コマンドの実行
FFI 外部ライブラリの呼び出し

スクリプト内の console.log / console.error などの出力は、実行時の ジョブのログ に記録されます。処理の途中経過の確認やデバッグに使えます。

console.log("処理を開始します", parameter);

実行後、ジョブ(フロージョブ / ランナージョブ)の詳細からログを確認できます。

スクリプトノードには 最大試行回数 を設定できます。処理が失敗したときに、設定した回数まで自動で再試行します。一時的な外部エラーに備えたいときに利用します。

プレイグラウンドで動作確認する

Section titled “プレイグラウンドで動作確認する”

公開する前に、フローエディタの「プレイグラウンド」タブから動作を確認できます。実行するランナーを選び、試し実行用のスクリプトを実行して、結果やログを確認します。問題がなければリビジョンを作成して公開します。