> For the complete documentation index, see [llms.txt](https://docs-embed.anyflow.jp/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-embed.anyflow.jp/anyflow-sdk/docs.md).

# Anyflow SDK

## SDK をインストールする <a href="#install-sdk" id="install-sdk"></a>

npm を使用して SDK をインストールするには次のコマンドを実行します。

```sh
npm install @anyflowinc/embed-sdk
```

npm を使用していない場合は[こちらの Google ドライブ](https://drive.google.com/drive/folders/1g02qUQpPoStXvM5kYzMTVTuh6M9OJPi6)からダウンロードして JavaScript ファイルを直接使用することも出来ます。参考：[npm を使用していない場合の使用方法](/anyflow-sdk/docs/faq.md)

## SDK を初期化する <a href="#init-sdk" id="init-sdk"></a>

AnyflowSDK のインスタンスを取得する前に、 AnyflowSDK を `init` 関数で初期化する必要があります。

`init` 関数の引数には、 AnyflowSDK が JWT を取得するために使用する非同期関数を指定します。\
`./path/to/your/jwt/endpoint` には、自社プロダクトに実装したJWTエンドポイントを設定します。\
（参考： [JWTを生成する](/release/embed/generate-jwt.md)）

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const fetchJwt = async () => {
  const res = await fetch("./path/to/your/jwt/endpoint");
  const json = await res.json();
  return json["token"];
};

AnyflowSDK.init(fetchJwt);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const fetchJwt = async () => {
  const res = await fetch("./path/to/your/jwt/endpoint");
  const json = await res.json();
  return json["token"];
};

AnyflowSDK.init(fetchJwt);
```

{% endtab %}
{% endtabs %}

セキュリティ上の理由から、JWT生成関数は必ず**実行ごとに異なる JWT を返却する**必要があります。\
具体的には、JWTのPayloadの中のjti（ユニークID）が毎回異なるようにしてください。\
逆に、anyflow\_team\_idやanyflow\_user\_idなどの値は同一ユーザーの中では変わらないようにしてください。（参考：[サンプルコード](/release/embed/generate-jwt.md#sanpurukdo)）

{% hint style="success" %}

### 自動的なトークンリフレッシュ

SDKの内部では、JWTはアクセストークンに交換して使用されます。

アクセストークンが有効期限切れとなった場合等には、SDKはinit時に引数に与えられたJWT生成関数を自動で呼び出して**新しいJWTを取得**してから、再度アクセストークンを発行しリフレッシュを行います。

そのため、init時の引数にはJWTそのもの（固定値）を与えるのではなく**JWTの生成関数**を与えるようにしてください。
{% endhint %}

{% hint style="danger" %}

### 注意

SDK の初期化は、後述する `destroy` を呼び出すまで、2回実行することはできません。すでに初期化している状態でもう一度初期化しようとすると、 `sdk_already_initialized` エラーがスローされます。
{% endhint %}

### オプション <a href="#init-option" id="init-option"></a>

`init` 関数の第2引数にオプションを指定できます。全てのオプションの指定は任意です。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
AnyflowSDK.init(fetchJwt, {
  env: "staging"
});
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
AnyflowSDK.init(fetchJwt, {
  env: "staging"
});
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="128.0078125">オプション</th><th width="442.65234375">説明</th><th>デフォルト値</th></tr></thead><tbody><tr><td>env</td><td>デプロイ環境のユニーク名を指定します。指定しなければデフォルトデプロイ環境が使用されます。</td><td>undefined</td></tr></tbody></table>

## SDK インスタンスを取得する <a href="#get-sdk-instance" id="get-sdk-instance"></a>

AnyflowSDK では、有効なインスタンスは1つのみ存在します。 SDK を初期化すると、 `instance` プロパティから有効な AnyflowSDK のインスタンスを取得することができるようになります。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const sdk = AnyflowSDK.instance;
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const sdk = AnyflowSDK.instance;
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}

### 注意

SDK を初期化する前に `instance` プロパティにアクセスすると、 `sdk_not_initialized` エラーがスローされます。
{% endhint %}

## SDK インスタンスを破棄する <a href="#destroy-sdk-instance" id="destroy-sdk-instance"></a>

AnyflowSDK を初期化すると、ソリューションウィザードを表示するための iframe と通信するために window にメッセージハンドラが設定されます。

SDK インスタンスが不要になれば、これらのメッセージハンドラが残ったままにならないように、 SDK インスタンスを破棄することができます。

SDK インスタンスを破棄するには、 AnyflowSDK の `destroy` 関数を実行します。

{% hint style="danger" %}

### 注意

`destroy` を実行すると、それまでに使用していた SDK インスタンスはもう使用できなくなります。破棄した SDK インスタンスを使用しようとすると、 `sdk_already_destroyed` エラーがスローされます。 SDK インスタンスの `isDestroyed` プロパティによって、SDK インスタンスが破棄されているかどうかを確認できます。

もう一度 SDK インスタンスが必要になった場合は、改めて `init` 関数で AnyflowSDK を初期化してください。
{% endhint %}

## ソリューションを取得する <a href="#get-solutions" id="get-solutions"></a>

`getSolution` メソッドを使用して特定のソリューションの情報 (`Solution`) を取得するか、 `getSolutions` メソッドを使用して現在使用可能なすべてのソリューションをリストで取得することができます。デプロイされていないソリューションは使用可能ではないため取得できません。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
// 特定のソリューションの情報のみ取得する
const solution: Solution = await sdk.getSolution("solution_id");

// リストで取得する
const solutions: Solution[] = await sdk.getSolutions();
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
// 特定のソリューションの情報のみ取得する
const solution = await sdk.getSolution("solution_id");

// リストで取得する
const solutions = await sdk.getSolutions();
```

{% endtab %}
{% endtabs %}

取得した `Solution` オブジェクトは不変です。 SDK を使用してソリューションの有効状態を変更しても、すでに取得してあった `Solution` オブジェクトの値が変更されることはありません。最新の値を取得するには、もう一度 `getSolution` メソッドで取得し直してください。

### ソリューションの状態を確認する <a href="#get-solution-state" id="get-solution-state"></a>

ソリューションの状態を取得することで、エンドユーザーのソリューションの利用状況に応じて UI の表示を変更する等を実現できます。

ソリューションの状態は、取得した `Solution` オブジェクトの `state` プロパティからアクセスできます。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const state: SolutionState = solution.state;
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const state = solution.state;
```

{% endtab %}
{% endtabs %}

`SolutionState` の値は、次のいずれかです：

<table><thead><tr><th width="177.74609375">state</th><th>説明</th></tr></thead><tbody><tr><td>not_installed</td><td>まだソリューションがインストールされていません。</td></tr><tr><td>enabled</td><td>ソリューションが有効です。</td></tr><tr><td>disabled</td><td>ソリューションはインストールされていますが、有効にされていません。</td></tr></tbody></table>

## ソリューションをインストールする <a href="#install-solution" id="install-solution"></a>

ソリューションをインストールするには、ソリューションウィザードと呼ばれる画面を表示し、ユーザーに各種設定項目を入力してもらう必要があります。

### ソリューションウィザードを作成する <a href="#create-wizard" id="create-wizard"></a>

ソリューションウィザードの UI は Anyflow によって提供されるため、まずは `createWizard` メソッドを使用して `SolutionWizard` をインスタンス化します。 `createWizard` にはソリューションウィザードを表示させたい iframe を指定します。

{% tabs %}
{% tab title="TypeSctipt" %}

```typescript
const iframe = document.getElementById("solution_wizard");
const solutionWizard: SolutionWizard = sdk.createWizard(iframe);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const iframe = document.getElementById("solution_wizard");
const solutionWizard = sdk.createWizard(iframe);
```

{% endtab %}
{% endtabs %}

iframe や `SolutionWizard` のインスタンスはソリューションごとに別々のものを使用することも、複数のソリューションで一つのものを共有して使用することもできます。

### ウィザードを翻訳する <a href="#translate-wizard" id="translate-wizard"></a>

`createWizard` の第2引数にIETF言語タグを指定することで、ウィザードの内容を翻訳することができます。

```javascript
sdk.createWizard(iframe, "en");
```

現在対応しているIETF言語タグは次の通りです

* `en` : 英語
* `zh-Hans` : 簡体中文
* `zh-Hant` : 繁体中文
* `ja` : 日本語(デフォルト)

### ソリューションウィザードを iframe に読み込む <a href="#load-wizard" id="load-wizard"></a>

ソリューションウィザードを指定した iframe に表示させるには、 `SolutionWizard` オブジェクトの `load` メソッドを使用します。 `load` メソッドにはソリューションウィザードを表示したいソリューションの ID を指定します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
solutionWizard.load("your_solution_id");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
solutionWizard.load("your_solution_id");
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}

### ヒント

iframeのスタイルは自社プロダクト側で調整する必要があります。
{% endhint %}

#### ソリューションウィザードにデフォルト値を与える <a href="#unload-wizard" id="unload-wizard"></a>

ソリューションウィザードを iframe に読み込ませる際に、ウィザードで採用するデフォルト値を与えることができます。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
solutionWizard.load("solution_id", {
  defaultInputs: [
    {
      type: "value",
      key: "...",
      value: "...",
    },
  ],
});
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
solutionWizard.load("solution_id", {
  defaultInputs: [
    {
      type: "value",
      key: "...",
      value: "...",
    },
  ],
});
```

{% endtab %}
{% endtabs %}

### ソリューションウィザードを破棄する <a href="#unload-wizard" id="unload-wizard"></a>

iframe 内に表示したソリューションウィザードを破棄するには、 `unload` メソッドを実行します。ソリューションウィザードが完了またはキャンセルされたタイミングで `unload` することを推奨します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
solutionWizard.unload();
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
solutionWizard.unload();
```

{% endtab %}
{% endtabs %}

## ソリューションをアンインストールする <a href="#uninstall-wizard" id="uninstall-wizard"></a>

ソリューションをアンインストールにするには、 `sdk` の `uninstallSolution` メソッドを実行します。ソリューションは再度インストールされるまで実行できなくなります。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
await sdk.uninstallSolution("your_solution_id");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
await sdk.uninstallSolution("your_solution_id");
```

{% endtab %}
{% endtabs %}

## ソリューションウィザードの状態を監視する <a href="#add-listner-to-wizard" id="add-listner-to-wizard"></a>

ソリューションウィザードが完了したりユーザーによってキャンセルされた時に処理を実行するには、 `SolutionWizard` オブジェクトに対して `addListener` メソッドで `SolutionWizardListener` を設定します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const listener: SolutionWizardListener = (event: SolutionWizardEvent, solutionId: string, solutionInstanceId?: string) => {
  if (event === "loaded") {
    // ソリューションウィザードが読み込まれたとき
  }
  if (event === "completed") {
    // ソリューションウィザードが完了したとき（ソリューションがインストールされたとき）
    // 完了したときのみ、リスナの第三引数 solutionInstanceId が渡ってきます
  }
  if (event === "canceled") {
    // ソリューションウィザードがキャンセルされたとき
  }
}
solutionWizard.addListener(listener);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const listener = (event, solutionId, solutionInstanceId) => {
  if (event === "loaded") {
    // ソリューションウィザードが読み込まれたとき
  }
  if (event === "completed") {
    // ソリューションウィザードが完了したとき
    // 完了したときのみ、リスナの第三引数 solutionInstanceId が渡ってきます
  }
  if (event === "canceled") {
    // ソリューションウィザードがキャンセルされたとき
  }
}
solutionWizard.addListener(listener);
```

{% endtab %}
{% endtabs %}

リスナが不要になった場合は `removeListener` メソッドで削除できます。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
solutionWizard.removeListener(listener);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
solutionWizard.removeListener(listener);
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}

### ソリューションインスタンスIDについて

エンドユーザーがソリューションをインストールすると、completedのイベントが呼び出され、リスナの第三引数 solutionInstanceId が渡ってきます。\
solutionInstanceId は[ベンダーサーバーAPI](/anyflow-api/vender-server-api.md#gai-yao)でも取得できます。
{% endhint %}

## ソリューションの設定を変更する <a href="#reload-wizard" id="reload-wizard"></a>

インストールしたソリューションの設定を変更するには、ソリューションをインストールした時と同様、ソリューションウィザードを使用します。

インストール済みの状態でソリューションウィザードを表示すると、ユーザーが以前に設定した内容が入った状態のソリューションウィザードが表示されます。もう一度ウィザードを完了させることで、ソリューションの設定が変更できます。

ソリューションウィザードを iframe に読み込むには、インストール時と同じように、 `SolutionWizard` オブジェクトの `load` メソッドを実行します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
solutionWizard.load("your_solution_id");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
solutionWizard.load("your_solution_id");
```

{% endtab %}
{% endtabs %}

## ソリューションの有効状態を変更する <a href="#enable-solution" id="enable-solution"></a>

ソリューションを有効にするには `sdk` の `enableSolution` メソッドを、無効にするには `disableSolution` メソッドを実行します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
// 有効にする
await sdk.enableSolution("your_solution_id");

// 無効にする
await sdk.disableSolution("your_solution_id");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
// 有効にする
await sdk.enableSolution("your_solution_id");

// 無効にする
await sdk.disableSolution("your_solution_id");
```

{% endtab %}
{% endtabs %}

## ソリューションを手動実行する <a href="#run-solution" id="run-solution"></a>

ユーザーの操作に応じてソリューションを手動実行するには、 SDK の `runSolution` メソッドを実行します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const job = await sdk.runSolution("your_solution_id");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const job = await sdk.runSolution("your_solution_id");
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}

### ヒント

`runSolution` メソッドで実行することができるのは、Clickトリガー（手動実行トリガー）が指定されているソリューションのみです。手動実行できないソリューションで `runSolution` を実行すると、 `AnyflowError` がスローされます。 `Solution` オブジェクトの `runnable` プロパティによって、手動実行トリガーが指定されているかどうかを確認できます。
{% endhint %}

## ソリューションの実行状態を確認する <a href="#get-job" id="get-job"></a>

`runSolution` の戻り値として取得できる Promise を解決すると得られるのは、ソリューションの実行インスタンスを表す `Job` オブジェクトです。

`Job` オブジェクトも `Solution` オブジェクトと同じく不変で、実行状態が変更されてもすでに取得済みの `Job` オブジェクトの値が変更されることはありません。

{% hint style="success" %}

### ヒント

SDK の `getJob` メソッドを使用して、最新の `Job` オブジェクトを取得できます。
{% endhint %}

ソリューションの実行状態は `Job` オブジェクトの `state` プロパティを読み込むことで確認できます。

<table><thead><tr><th width="153.12109375">state</th><th>説明</th></tr></thead><tbody><tr><td>running</td><td>この Job はまだ実行中です。</td></tr><tr><td>succeeded</td><td>この Job の実行は正常に完了しました。</td></tr><tr><td>failed</td><td>この Job の実行は失敗しました。</td></tr></tbody></table>

### ソリューションの実行状態を監視する <a href="#observe-job" id="observe-job"></a>

`Job` オブジェクト自体は不変のため、実行状態が変更されてもそのオブジェクトは変更されません。

ソリューションの実行状態が変更された時に新しい `Job` オブジェクトを取得するには、 SDK の `observeJob` メソッドを実行してジョブの変更を監視する必要があります。

`observeJob` に指定する `JobCallback` はジョブが変更された時に呼び出されます。 `JobCallback` の第一引数は変更内容を表す `JobEvent` で、第二引数は変更後の値を持った `Job` オブジェクトです。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const callback: JobCallback = (event: JobEvent, job: Job) => {
  if (event === "state_changed") {
    // ここで実行状態が変更されたときの処理
  }
}
sdk.observeJob("your_job_id", callback);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const callback = (event, job) => {
  if (event === "state_changed") {
    // ここで実行状態が変更されたときの処理
  }
}
sdk.observeJob("your_job_id", callback);
```

{% endtab %}
{% endtabs %}

監視を終了するには、 SDK の `unobserveJob` メソッドを実行します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
sdk.unobserveJob("your_job_id", callback);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
sdk.unobserveJob("your_job_id", callback);
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}

### ヒント

`Job.state` が `succeeded` または `failed` になると、明示的に `unobserveJob` を実行しなくても、監視は自動的に終了されます。
{% endhint %}

## ソリューションの実行履歴を表示する <a href="#load-history" id="load-history"></a>

<figure><img src="https://files.readme.io/50ed952-jobhistory.png" alt="565"><figcaption><p>ソリューションの実行履歴画面</p></figcaption></figure>

ソリューションの実行履歴を表示するには、 `SolutionWizard` オブジェクトの `loadHistory` メソッドを使用します。 `loadHistory` メソッドには実行履歴を確認したいソリューションの ID を指定します。

`loadHistory` メソッドを実行すると、ソリューションウィザードを作成するときに指定した iframe にソリューションの実行履歴が読み込まれます。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
solutionWizard.loadHistory("your_solution_id");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
solutionWizard.loadHistory("your_solution_id");
```

{% endtab %}
{% endtabs %}

iframe 内に表示したソリューションの実行履歴を破棄するには、 `SolutionWizard` オブジェクトの `unload` メソッドを実行します。\
ソリューションの実行履歴を閉じると `canceled` イベントが発行されるので、そのタイミングで `unload` することを推奨します。

## ソリューションの実行履歴を取得する <a href="#get-jobs" id="get-jobs"></a>

SDK の `getJobs` メソッドを使用すると、ソリューションの実行履歴を iframe に表示するのではなく、データとして直接 SDK から取得することができます。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const jobs: Job[] = await sdk.getJobs("your_solution_id", { page: 1, perPage: 100 });
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const jobs = await sdk.getJobs("your_solution_id", { page: 1, perPage: 100 });
```

{% endtab %}
{% endtabs %}

第二引数には取得するページや件数を指定できます。\
1度に取得できる件数（perPageの最大件数）は100件です。

`getJobs` の戻り値の Promise が解決すると、ソリューションの実行インスタンスを表す `Job` オブジェクトの一覧と、ページネーション等に関するメタデータが得られます。

```json
{
  jobs: [Job, ...],
  meta: {
    total: number,
    page: number,
    perPage: number,
  }
}
```

{% hint style="danger" %}
SDKのバージョンが 0.14.1 以下の場合、ページネーションを行うことはできません。

**0.14.1 以下での仕様**

* getJobsの第二引数（page, perPage 等）を指定することはできません。
* 実行履歴は直近の20件のみ取得できます。
* Jobオブジェクトの一覧 `[Job, ...]`  のみが返却されます
  {% endhint %}

## My Event を送信する <a href="#send-my-event" id="send-my-event"></a>

フロントエンドから直接 [My Event](https://anyflow.readme.io/docs/my-event) を送信するには、`sendMyEvent` メソッドを使用します。

{% tabs %}
{% tab title="TypeScript" %}

```typescript
const payload: MyEventPayload = {
  "name": "taro",
  "is_admin": true
};
await sdk.sendMyEvent("user_created", payload);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const payload = {
  "name": "taro",
  "is_admin": true
};
await sdk.sendMyEvent("user_created", payload);
```

{% endtab %}
{% endtabs %}

この例では、`user_created` というキーを持つ My Event を、 `payload` 変数の値をペイロードとして送信しています。

`payload` には送信する My Event で設定済みのスキーマに合う構造のデータを指定してください。\
スキーマに合わないペイロードを指定しても、このメソッドはエラーを返しません。

My Event のスキーマが求める値がペイロードに含まれていない場合、ソリューション内ではその変数の値は `None` になります。\
たとえば、この例の My Event に `{ "email": "[email protected]" }` をペイロードとして送信すると、ソリューション内の `payload.name` や `payload.is_admin` という変数の値は `None` になります。

次の場合、このメソッドの返す Promise は `my_event_not_triggered` エラーで reject されます。

* 指定した My Event が見つからない場合
* 指定した My Event を使用するソリューションが存在しない場合
* 指定した My Event を使用するソリューションをエンドユーザーがインストールしていない場合
* 指定した My Event を使用するソリューションをエンドユーザーが無効にしている場合


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs-embed.anyflow.jp/anyflow-sdk/docs.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
