> For the complete documentation index, see [llms.txt](https://docs.keeper.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keeper.io/keeperpam/jp/secrets-manager/developer-sdk-library/javascript-sdk.md).

# JavaScript SDK

Keeperシークレットマネージャー用Javascript SDKの詳細

## ダウンロードとインストール <a href="#download-and-installation" id="download-and-installation"></a>

### **NPMによるインストール** <a href="#install-with-npm" id="install-with-npm"></a>

```bash
npm install @keeper-security/secrets-manager-core
```

詳細については、<https://www.npmjs.com/package/@keeper-security/secrets-manager-core>をご参照ください。

### **ソースコード** <a href="#source-code" id="source-code"></a>

JavaScriptのソースコードは、[GitHubリポジトリ](https://github.com/Keeper-Security/secrets-manager/tree/master/sdk/javascript)で入手できます。

## SDKの使用 <a href="#using-the-sdk" id="using-the-sdk"></a>

### ストレージの初期化 <a href="#initialize-storage" id="initialize-storage"></a>

{% hint style="info" %}
トークンのみを使用して新しい構成 (後で使用するため) を生成する場合、トークンをバインドして `config.json`を完全に生成するために、少なくとも1回の読み取り操作が必要です。
{% endhint %}

シークレットを取得するには、まずマシンのローカルストレージを初期化する必要があります。

```javascript
initializeStorage(storage:KeyValueStorage, clientKey:String? = null, hostName:String? = null)
```

| パラメータ       | 型                 | 必須    | デフォルト | 説明                                                             |
| ----------- | ----------------- | ----- | ----- | -------------------------------------------------------------- |
| `storage`   | `KeyValueStorage` | はい    |       | 保存場所                                                           |
| `clientKey` | string            | オプション | null  | Keeperシークレットマネージャーに接続するためのトークン                                 |
| `hostName`  | string            | オプション | null  | シークレットを取得するサーバーの場所。 何も指定しない場合は、keepersecurity.com (米国) が使用されます |

#### **使用例** <a href="#example-usage" id="example-usage"></a>

```javascript
const { getSecrets, initializeStorage, localConfigStorage } = require('@keeper-security/secrets-manager-core')

const getKeeperRecords = async () => {

    // ワンタイムトークンはストレージの初期化に一度だけ使用
    // 初回実行以降の呼び出しでは、ksm-config.jsonを使用
    const oneTimeToken = "<One Time Access Token>";
    
    const storage = localConfigStorage("ksm-config.json")
    
    await initializeStorage(storage, oneTimeToken)
    // トークンのみを使用して（後で使用するために）設定を生成するには
    // トークンをバインドするアクセス操作が少なくとも1回必要です
    // トークンをバインドするには、以下の呼び出しの行頭のコメントを外す
    // await getSecrets({storage: storage})
    
    const {records} = await getSecrets({storage: storage})
    console.log(records)

    const firstRecord = records[0]
    const firstRecordPassword = firstRecord.data.fields.find(x => x.type === 'password')
    console.log(firstRecordPassword.value[0])
}

getKeeperRecords().finally()
```

### バインディングライフサイクル <a href="#binding-lifecycle" id="binding-lifecycle"></a>

ワンタイムトークンは、クライアント作成時ではなく、最初の `getSecrets()` 呼び出し時に引き換えられます。構成を外部ストア (AWS Secrets Manager、Azure Key Vault など) に保存する場合は、バインド後に読み出してから永続化します。詳しくは、[バインディングライフサイクル](/keeperpam/jp/secrets-manager/about/secrets-manager-configuration.md#binding-lifecycle)をご参照ください。

```typescript
import { getSecrets, localConfigStorage } from '@keeper-security/secrets-manager-core';

// 初回実行: 構成ファイルにワンタイムトークンが含まれています (`ksm init` で生成)。
const storage = localConfigStorage('ksm-config.json');
const { records } = await getSecrets({ storage });
// この呼び出しでトークンが引き換えられ、ksm-config.json がバインド済み認証情報で更新されます。

// 以降の実行: 変更は不要です。ストレージにバインド済み認証情報が保存されています。
const { records: records2 } = await getSecrets({ storage });
```

### シークレットの取得 <a href="#retrieve-secrets" id="retrieve-secrets"></a>

```javascript
getSecrets(options:SecretsManagerOptions, recordsFilter:List<String> = emptyList()):KeeperSecrets
```

| パラメータ           | 型                 | 必須    | デフォルト | 説明           |
| --------------- | ----------------- | ----- | ----- | ------------ |
| `storage`       | `KeyValueStorage` | はい    |       | 保存場所         |
| `recordsFilter` | string\[]         | オプション | 空のリスト | 取得するレコードのUID |

**レスポンス**

型: `KeeperSecrets`

すべてのKeeperのレコード、または指定したフィルタ条件に一致するレコードを含むオブジェクト

**使用例**

すべてのシークレットを取得

```javascript
const storage = inMemoryStorage() // 初期化の例を参照
const secrets = await getSecrets({storage: storage})
```

### タイトルでシークレットを取得 <a href="#retrieve-secrets-by-title" id="retrieve-secrets-by-title"></a>

```javascript
// 一致するレコードをすべて取得
getSecretsByTitle = async (options:SecretManagerOptions, recordTitle: string):Promise<KeeperRecord[]>

// 最初に一致したレコードだけを取得
getSecretByTitle = async (options:SecretManagerOptions, recordTitle: string):Promise<KeeperRecord>
```

<table><thead><tr><th width="178.10385756676556">パラメータ</th><th width="150">型</th><th width="150">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>options</code></td><td>SecretsManagerOptions</td><td>はい</td><td>事前に設定されたオプション</td></tr><tr><td><code>recordTitle</code></td><td>string</td><td>はい</td><td>検索するレコードタイトル</td></tr></tbody></table>

**使用例**

```javascript
const {
    getSecretByTitle,
    localConfigStorage,
} = require('@keeper-security/secrets-manager-core')

const getKeeperRecord = async () => {
    const options = { storage: localConfigStorage("ksm-config.json") }
    const myCredential = await getSecretByTitle(options, "My Credential")
}

getKeeperRecord().finally()
```

### シークレットから値を取得 <a href="#retrieve-values-from-a-secret" id="retrieve-values-from-a-secret"></a>

**パスワードを取得**

{% tabs %}
{% tab title="パスワード取得" %}

```javascript
secret.data.fields.find(x => x.type === 'password')
```

{% endtab %}

{% tab title="用例" %}

```javascript
const { getSecrets, initializeStorage, localConfigStorage } = require('@keeper-security/secrets-manager-core')

const getKeeperRecords = async () => {
    const storage = localConfigStorage("ksm-config.json")
    // レコードを取得
    const {records} = await getSecrets({storage: storage})
    // 最初のレコードからパスワードを取得
    const firstRecord = records[0]
    const firstRecordPassword = firstRecord.data.fields.find(x => x.type === 'password')
}
```

{% endtab %}
{% endtabs %}

フィールドタイプはKeeper[レコードタイプ](/enterprise-guide/jp/record-types.md)に基づきます。利用可能なフィールドの詳細な一覧については、コマンダーで [`record-type-info`](/keeperpam/jp/commander-cli/command-reference/record-commands/record-type-commands.md) コマンドをご参照ください。

**Keeper表記法を使用して他のフィールドを取得**

{% tabs %}
{% tab title="値を取得" %}

```javascript
getValue(secrets:KeeperSecrets, query: string): any
```

{% endtab %}

{% tab title="用例" %}

```javascript
const {
    getSecrets,
    localConfigStorage,
    getValue
} = require('@keeper-security/secrets-manager-core')

const getKeeperRecords = async () => {
    const options = { storage: localConfigStorage("ksm-config.json") }
    
    // シークレットを取得
    const secrets = await getSecrets(options)

    // ドット記法でログインを取得
    const loginValue = getValue(secrets, 'RECORD_UID/field/login')
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Keeper表記法の形式と機能については、[Keeper表記法のページ](/keeperpam/jp/secrets-manager/about/keeper-notation.md)をご参照ください。
{% endhint %}

| パラメータ     | 型               | 必須 | デフォルト | 説明                |
| --------- | --------------- | -- | ----- | ----------------- |
| `secrets` | `KeeperSecrets` | はい |       | 照会するシークレット        |
| `query`   | `string`        | はい |       | Keeper表記法を使用したクエリ |

#### **戻り値** <a href="#returns" id="returns"></a>

型: `any`

ドット記法のクエリで指定した位置にフィールド値がある場合はその値。ない場合は `undefined`。

### **TOTPコードを取得** <a href="#retrieve-a-totp-code" id="retrieve-a-totp-code"></a>

{% tabs %}
{% tab title="TOTPコードを取得" %}

```javascript
getTotpCode(
    url: string,
    unixTimeSeconds?: number
): Promise<{
    code: string
    timeLeft: number
    period: number
} | null>
```

{% endtab %}

{% tab title="使用例" %}

```javascript
const {
    getSecrets,
    localConfigStorage,
    getTotpCode,
    getValue} = require('@keeper-security/secrets-manager-core')

const getKeeperRecords = async () => {
    const options = { storage: localConfigStorage("ksm-config.json") }

    // シークレットを取得
    const secrets = await getSecrets(options)

    // Keeper表記法でレコードからTOTPのURIを取得
    const totpUri = getValue(secrets, 'RECORD_UID/field/oneTimeCode')

    // TOTPコードを取得
    const totpResult = await getTotpCode(totpUri)

    if (totpResult) {
        console.log(`TOTP Code: ${totpResult.code}`)
        console.log(`Expires in: ${totpResult.timeLeft} seconds`)
        console.log(`Period: ${totpResult.period} seconds`)
    } else {
        console.log('Invalid TOTP URL')
    }
}

getKeeperRecords().finally()
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Keeper表記法の形式と機能については、[Keeper表記法のページ](/keeperpam/jp/secrets-manager/about/keeper-notation.md)をご参照ください。
{% endhint %}

| パラメータ | 型        | 必須 | デフォルト | 説明       |
| ----- | -------- | -- | ----- | -------- |
| `url` | `string` | はい |       | TOTP Url |

| パラメータ             | 型        | 必須    | デフォルト      | 説明                        |
| ----------------- | -------- | ----- | ---------- | ------------------------- |
| `url`             | `string` | はい    |            | TOTP URL                  |
| `unixTimeSeconds` | `number` | オプション | 現在のタイムスタンプ | 秒単位のUnixタイムスタンプ (テストや検証用) |

* 表記法のクエリで指定するレコードUIDは、`secrets` パラメーターに渡したシークレットに含まれる必要があります。含まれない場合、クエリでは見つかりません。

#### **戻り値** <a href="#returns-1" id="returns-1"></a>

型: `Promise<{code: string, timeLeft: number, period: number} | null>`

次のプロパティを持つオブジェクト。

* `code` - TOTPコード (6〜8桁)
* `timeLeft` - コードが失効するまでの残り秒数
* `period` - TOTPの周期 (秒)。通常は30

TOTP URLが無効な場合や処理できない場合は `null` を返します。

### PAMレコードタイプ <a href="#pam-record-types" id="pam-record-types"></a>

PAMレコードは `record.data.type` で識別できます。

```typescript
for (const record of records) {
    switch (record.data.type) {
        case 'pamMachine':
            // host フィールドが利用可能
            break;
        case 'pamUser':
            // login フィールドが利用可能
            break;
        case 'pamDatabase':
            // databaseType フィールドが利用可能
            break;
    }
}
```

全11種類のPAMレコードタイプのフィールド定義は、[PAMレコードタイプ](/keeperpam/jp/secrets-manager/about/pam-record-types.md)をご参照ください。

### リンク済み認証情報 <a href="#linked-credentials" id="linked-credentials"></a>

PAMリソースレコードとリンク済み `pamUser` レコードを含めて取得するには、`QueryOptions` で `requestLinks: true` を指定します。

権限・データ・設定用のアクセサーを備えた、型付きの `KeeperRecordLink` オブジェクトを取得するには `getLinks(record)` を使用します。生の `record.links` 配列も引き続き利用できます。

```typescript
import { getSecrets2, getLinks } from '@keeper-security/secrets-manager-core';

const { records } = await getSecrets2({ storage }, { requestLinks: true });

for (const record of records) {
    for (const link of getLinks(record)) {
        console.log(`linked UID: ${link.recordUid}, path: ${link.path ?? ''}`);

        // permission accessors (non-throwing booleans)
        if (link.allowsRotation() && link.allowsConnections()) {
            // ...
        }

        // settings accessors: returns null when not present or decryption fails
        const aiSettings = await link.getAiSettingsData();
        if (aiSettings !== null) {
            // use aiSettings
        }
    }
}
```

`getLinks(record)` は、リンクをリクエストしなかった場合、またはリンクが存在しない場合は空の配列を返します。各SDK共通の説明は、[リンク済み認証情報](/keeperpam/jp/secrets-manager/about/linked-credentials.md)をご参照ください。

### シークレットを更新 <a href="#update-a-secret" id="update-a-secret"></a>

{% hint style="warning" %}
レコードを更新するコマンドは、成功してもローカルのレコード情報 (特に更新後のレコードのリビジョン) が自動では更新されません。そのため、すでに更新済みのレコードに続けて更新を行うと、リビジョンの不一致で失敗します。各更新バッチの後に、更新したレコードをすべて再読み込みしてください。
{% endhint %}

{% tabs %}
{% tab title="シークレットの更新" %}

```javascript
updateSecret(options, record)
```

{% endtab %}

{% tab title="使用例" %}

<pre class="language-javascript"><code class="lang-javascript"><strong>const { 
</strong>    getSecrets, 
    localConfigStorage, 
    updateSecret} = require('@keeper-security/secrets-manager-core')

const storage = localConfigStorage("ksm-config.json")

// レコードを取得
const {records} = await getSecrets({storage: storage})

// 最初のレコードを取得
const recordToUpdate = records[0]

// 新しいレコードタイトルとメモを設定
recordToUpdate.data.title = 'New Title'
recordToUpdate.data.notes = "New Notes"

// レコードの変更を保存
await updateSecret(options, recordToUpdate)
</code></pre>

{% endtab %}

{% tab title="トランザクションによる更新" %}

<pre class="language-javascript"><code class="lang-javascript"><strong>const { 
</strong>    getSecrets, 
    localConfigStorage, 
    updateSecret,
    completeTransaction,
    UpdateTransactionType,
    SecretManagerOptions
} = require('@keeper-security/secrets-manager-core')

// レコードを取得
const options = { storage: localConfigStorage("ksm-config.json") }
const {records} = await getSecrets(options)

// 最初のレコードのパスワードをローテーション
const secret = records[0]
const password = secret.data.fields.find(x => x.type === "password")
password.value[0] = "MyNewPassword"

// ボールト内のレコードを更新するためにトランザクションを開始
await updateSecret(options, secret, UpdateTransactionType.Rotation)

// リモートホスト上のパスワードをローテーション
const success = rotateRemoteSshPassword("MyNewPassword");

// トランザクションを完了（コミットまたはロールバック）
const rollback = !success
await completeTransaction(options, secret.recordUid, rollback)
</code></pre>

{% endtab %}
{% endtabs %}

<table data-header-hidden><thead><tr><th width="150">パラメータ</th><th width="257">型</th><th width="150">必須</th><th>デフォルト</th><th>説明</th></tr></thead><tbody><tr><td>パラメータ</td><td>型</td><td>必須</td><td>デフォルト</td><td>説明</td></tr><tr><td><code>options</code></td><td><code>SecretManagerOptions</code></td><td>はい</td><td></td><td></td></tr><tr><td><code>record</code></td><td><code>KeeperRecord</code></td><td>はい</td><td></td><td></td></tr></tbody></table>

**戻り値**

**型:** `Promise<void>`

### ランダムなパスワードを生成 <a href="#generate-a-random-password" id="generate-a-random-password"></a>

{% tabs %}
{% tab title="パスワードを生成" %}

```javascript
generatePassword(length, lowercase, uppercase, digits, specialCharacters)
```

{% endtab %}

{% tab title="使用例" %}

```javascript
const { 
    getSecrets,
    localConfigStorage,
    updateSecret,
    generatePassword } = require('@keeper-security/secrets-manager-core')

// ランダムなパスワードを生成
let newRandomPwd = await generatePassword()

const storage = localConfigStorage("ksm-config.json")
const {records} = await getSecrets({storage: storage})

// 最初のレコードを取得
const recordToUpdate = records[0]

// タイプが「password」のフィールドを検索
const recordToUpdatePasswordField = recordToUpdate.data.fields.find(x => x.type === 'password')

// 「password」フィールドに新しい値を設定
recordToUpdatePasswordField.value[0] = newRandomPwd

await updateSecret({storage: storage}, recordToUpdate)
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="203.7142857142857">パラメータ</th><th width="150">型</th><th width="150">必須</th><th>デフォルト</th></tr></thead><tbody><tr><td>length</td><td><code>int</code></td><td>オプション</td><td>64</td></tr><tr><td>lowercase</td><td><code>int</code></td><td>オプション</td><td>0</td></tr><tr><td>uppercase</td><td><code>int</code></td><td>オプション</td><td>0</td></tr><tr><td>digits</td><td><code>int</code></td><td>オプション</td><td>0</td></tr><tr><td>specialCharacters</td><td><code>int</code></td><td>オプション</td><td>0</td></tr></tbody></table>

各パラメーターは、それぞれの文字タイプを最低何文字含めるかを指定します。たとえば、`uppercase` は「大文字を最低何文字含めるか」を示します。

#### 戻り値 <a href="#returns-2" id="returns-2"></a>

型: `String`

### ファイルのダウンロード <a href="#download-a-file" id="download-a-file"></a>

```javascript
downloadFile(file: KeeperFile, timeoutMs?: number, options?: SecretManagerOptions): ByteArray
```

| パラメータ       | 型                      | 必須    | デフォルト | 説明                                                                           |
| ----------- | ---------------------- | ----- | ----- | ---------------------------------------------------------------------------- |
| `file`      | `KeeperFile`           | はい    |       | ダウンロードするファイル                                                                 |
| `timeoutMs` | `number`               | オプション |       | このコールで `options.requestTimeoutMs` を上書き ([リクエストタイムアウト](#request-timeouts)を参照) |
| `options`   | `SecretManagerOptions` | オプション |       | `timeoutMs` を指定しない場合に `options.requestTimeoutMs` を使用                         |

**レスポンス**

型: `Promise<Uint8Array>`

ダウンロード用のファイルのバイト列

### **サムネイル**のダウンロード <a href="#download-a-thumbnail" id="download-a-thumbnail"></a>

```javascript
downloadThumbnail(file: KeeperFile, timeoutMs?: number, options?: SecretManagerOptions): ByteArray
```

| パラメータ       | 型                      | 必須    | デフォルト | 説明                                                                           |
| ----------- | ---------------------- | ----- | ----- | ---------------------------------------------------------------------------- |
| `file`      | `KeeperFile`           | はい    |       | ダウンロードするサムネイル付きファイル                                                          |
| `timeoutMs` | `number`               | オプション |       | このコールで `options.requestTimeoutMs` を上書き ([リクエストタイムアウト](#request-timeouts)を参照) |
| `options`   | `SecretManagerOptions` | オプション |       | `timeoutMs` を指定しない場合に `options.requestTimeoutMs` を使用                         |

**レスポンス**

型: `Promise<Uint8Array>`

ダウンロード用サムネイルのバイト列

### ファイルのアップロード <a href="#upload-a-file" id="upload-a-file"></a>

ファイルのアップロード:

```javascript
uploadFile = async (options: SecretManagerOptions, ownerRecord: KeeperRecord, file: KeeperFileUpload, timeoutMs?: number): Promise<string>
```

<table><thead><tr><th width="184.14763231197773">パラメータ</th><th width="246.99431983802478">型</th><th width="150">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>options</code></td><td>SecretsManagerOptions</td><td>はい</td><td>ストレージとクエリの設定</td></tr><tr><td><code>ownerRecord</code></td><td>KeeperRecord</td><td>はい</td><td>アップロードされたファイルを添付するレコード</td></tr><tr><td><code>file</code></td><td>KeeperFileUpload</td><td>はい</td><td>アップロードするファイル</td></tr><tr><td><code>timeoutMs</code></td><td>number</td><td>オプション</td><td>このコールで <code>options.requestTimeoutMs</code> を上書き</td></tr></tbody></table>

Keeperファイルアップロードオブジェクトを作成:

```javascript
type KeeperFileUpload = {
    name: string
    title: string
    type?: string
    data:Uint8Array
}
```

<table><thead><tr><th width="169">パラメータ</th><th width="150">型</th><th width="150">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>name</code></td><td>string</td><td>はい</td><td>アップロード後にKeeperに格納されるファイルの名前</td></tr><tr><td><code>title</code></td><td>string</td><td>はい</td><td>アップロード後にKeeperに格納されるファイルのタイトル</td></tr><tr><td><code>type</code></td><td>string</td><td>オプション</td><td>ファイルのデータのMIMEタイプ。何も指定しない場合は、「application/octet-stream」が使用されます</td></tr><tr><td><code>data</code></td><td>Uint8Array</td><td>はい</td><td>バイト型のファイルデータ</td></tr></tbody></table>

**使用例**

```javascript
// ファイルを添付するレコードを取得
const {records} = await getSecrets({storage: storage}, ['XXX'])
const ownerRecord = records[0]

// アップロードするファイルデータを取得
const fileData = fs.readFileSync('./assets/my-file.json')

// 選択したレコードにファイルをアップロード
await uploadFile(options, ownerRecord, {
    name: 'my-file.json',
    title:'Sample File',
    type: 'application/json',
    data: fileData
})
```

### シークレットの作成 <a href="#create-a-secret" id="create-a-secret"></a>

#### 要件 <a href="#prerequisites" id="prerequisites"></a>

* 共有フォルダのUID
  * 共有フォルダには、シークレットマネージャーアプリケーションからアクセスできること
  * ユーザーとシークレットマネージャーアプリケーションには編集権限が付与されていること
  * 共有フォルダには、少なくとも1つのレコードが存在すること
* 作成されたレコードとレコードのフィールドは正しい形式で設定されていること
  * 各レコードタイプのフィールド形式については、[こちらのページ](https://github.com/Keeper-Security/gitbook-jp-secrets-manager/tree/main/commander-cli/command-reference/record-commands/default-record-types.md#field-types)をご参照ください
* TOTPフィールドには、KSM SDK以外で生成されたURLのみを指定できます
* レコード作成後、添付ファイルは [uploadFile](#upload-a-file) でアップロードできます

{% tabs %}
{% tab title="レコードを作成" %}

<pre class="language-javascript"><code class="lang-javascript"><strong>createSecret(options, folderUid, record)
</strong></code></pre>

<table><thead><tr><th width="166">パラメータ</th><th width="226">型</th><th>必須</th><th>デフォルト</th></tr></thead><tbody><tr><td>options</td><td>SecretManagerOptions</td><td>はい</td><td></td></tr><tr><td>folderUid</td><td>string</td><td>はい</td><td></td></tr><tr><td>record</td><td>JSON Object</td><td>はい</td><td></td></tr></tbody></table>
{% endtab %}

{% tab title="サブフォルダでレコードを作成" %}

<pre class="language-javascript"><code class="lang-javascript"><strong>createSecret2(options, createOptions, record)
</strong></code></pre>

<table><thead><tr><th width="166">パラメータ</th><th width="226">型</th><th>必須</th><th>デフォルト</th></tr></thead><tbody><tr><td>options</td><td>SecretManagerOptions</td><td>はい</td><td></td></tr><tr><td>createOptions</td><td>CreateOptions</td><td>はい</td><td></td></tr><tr><td>record</td><td>JSON Object</td><td>はい</td><td></td></tr></tbody></table>
{% endtab %}

{% tab title="ログイン情報レコードの例" %}
この例では、ログイン値と生成されたパスワードを含むログイン情報タイプのレコードを作成します。

{% hint style="info" %}
例の `[FOLDER UID]` を、シークレットマネージャーアプリケーションがアクセスできる共有フォルダのUIDに置き換えます。
{% endhint %}

```javascript
let newRec = {
    "title": "Sample KSM Record: JavaScript",
    "type": "login",
    "fields": [
        { "type": "login",    "value": [ "username@email.com" ] },
        { "type": "password", "value": [ await generatePassword() ] }
    ],
    "notes": "This is a JavaScript record creation example"
}

let recordUid = await createSecret(options, folderUid, newRec)
```

{% endtab %}

{% tab title="カスタムタイプの例" %}
この例では、カスタムのレコードタイプのレコードを作成します。

{% hint style="info" %}
例の `[FOLDER UID]` を、シークレットマネージャーアプリケーションがアクセスできる共有フォルダのUIDに置き換えます。
{% endhint %}

```javascript
let newRec = {
    "title": "Sample Custom Type KSM Record: JavaScript",
    "type": "Custom Login",
    "fields": [
        {
            "type": "host",
            "label":"My Custom Host lbl",
            "value": [ {"hostName":"127.0.0.1", "port":"8080"} ],
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "login",
            "label":"My Custom Login lbl",
            "value": [ "login@email.com" ],
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "password",
            "label":"My Custom Password lbl",
            "value": [ await generatePassword() ],
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "url",
            "label":"My Login Page",
            "value": [ "http://localhost:8080/login" ],
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "securityQuestion",
            "label":"My Question 1",
            "value": [ {
                "question":"What is one plus one (write just a number)",
                "answer":"2"
            } ],
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "phone",
            "value": [{
                "region":"US",
                "number":"510-444-3333",
                "ext":"2345",
                "type":"Mobile"
            }],
            "label":"My Phone Number"
        },
        {
            "type": "date",
            "value": [ 1641934793000 ],
            "label":"My Date Lbl",
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "name",
            "value": [{
                "first":"John",
                "middle":"Patrick",
                "last":"Smith"
            }],
            "label":"My Custom Name lbl",
            "required": true,
            "privacyScreen": false
        },
        {
            "type": "oneTimeCode",
            "label":"My TOTP",
            "value": ["otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example"],
            "required": true,
            "privacyScreen": false
        }
    ],
    "custom": [
        {
            "type": "phone",
            "value": [{
                "region":"US",
                "number": "(510) 123-3456"
            }],
            "label":"My Custom Phone Lbl 1"
        },
        {
            "type": "phone",
            "value": [ {
                "region":"US",
                "number":"510-111-3333",
                "ext":"45674",
                "type":"Mobile" } ],
            "label":"My Custom Phone Lbl 2"
        }
    ],
    "notes": "\tThis custom type record was created\n\tvia KSM Katacoda JavaScript Example"
}

let recordUid = await createSecret(options, "[FOLDER UID]", newRec)
```

{% endtab %}
{% endtabs %}

### シークレットの削除 <a href="#delete-a-secret" id="delete-a-secret"></a>

JavaScript KSM SDKでKeeperボルトのレコードを削除できます。

{% tabs %}
{% tab title="シークレットの削除" %}

```javascript
deleteSecret(smOptions, recordUids): Promise<SecretsManagerDeleteResponse>;
```

<table><thead><tr><th>パラメータ</th><th width="250.66666666666666">型</th><th align="center">必須</th></tr></thead><tbody><tr><td><code>smOptions</code></td><td><code>SecretManagerOptions</code></td><td align="center">はい</td></tr><tr><td><code>recordUids</code></td><td><code>string[]</code></td><td align="center">はい</td></tr></tbody></table>
{% endtab %}

{% tab title="使用例" %}

<pre class="language-javascript"><code class="lang-javascript">// シークレットマネージャーを設定
const smOptions = { storage: localConfigStorage("ksm-config.json") 

// レコードUIDで特定のシークレットを削除
<strong>const response = await deleteSecret(smOptions, ["EG6KdJaaLG7esRZbMnfbFA"]);
</strong></code></pre>

{% endtab %}
{% endtabs %}

**レスポンス**

型: `SecretsManagerDeleteResponse`

```javascript
type SecretsManagerDeleteResponse = {
    records: { recordUid: string, responseCode: string, errorMessage: string }[]
    folders: { folderUid: string, responseCode: string, errorMessage: string }[]
}
```

このコールは、サーバーが要求されたUIDの一部を拒否した場合でも解決されます。各項目の `responseCode` を確認してください。`'ok'` 以外の値は、そのレコードが削除されなかったことを示し、理由は `errorMessage` に含まれます。SDKは失敗した項目ごとに `console.error` の行もログへ出力しますが、一部の失敗によってエラーがスローされることはありません。[フォルダの削除](#delete-folders) も、`folders` 配列内に同じ形式のレスポンスを返します。

### キャッシュ <a href="#caching" id="caching"></a>

ネットワークへのアクセスが失われた際にシークレットへのアクセスも失うという事態を避けるため、JavaScript SDKでは、シークレットを暗号化されたファイルとしてローカルマシンにキャッシュすることができます。

{% hint style="warning" %}
17.6.0以降、単体の `cachingPostFunction` (Node) は `createCachingFunction(storage, options?)` に置き換えられました。旧関数は、保護対象のデータと同じ場所に、プロセスの作業ディレクトリからの固定パスでキャッシュキーを平文のまま保存し、復元時の整合性チェックもありませんでした。`cachingPostFunction` を直接呼び出していた場合は、アップグレード後に作業ディレクトリ内の古いキャッシュファイルを削除してください。このファイルは自動的には削除されません。
{% endhint %}

`SecretManagerOptions` に `queryFunction: createCachingFunction(storage)` を追加します。キャッシュの読み取りには、SDKが既に使用している構成情報が必要です (キャッシュキーはアプリキーから導出されます)。そのため、キャッシュファイルを盗まれただけではシークレットを読み取ることはできません。キャッシュは認証済みであり、改ざんや破損があったファイルはそのまま信頼されず拒否されます。

**Node (オプションオブジェクト):**

```javascript
const { createCachingFunction, localConfigStorage } = require('@keeper-security/secrets-manager-core')

const storage = localConfigStorage("ksm-config.json")
const options = {
    storage,
    queryFunction: createCachingFunction(storage, {
        cachePath: '/custom/path/ksm-cache.dat', // オプション。デフォルトは ~/.keeper/ksm-cache.dat
        maxCacheAgeMs: 12 * 60 * 60 * 1000        // オプション。デフォルトは24時間
    })
}
```

**ブラウザ (位置引数の `maxCacheAgeMs`):**

```javascript
import { createCachingFunction, localConfigStorage } from '@keeper-security/secrets-manager-core'

const storage = localConfigStorage("ksm-config.json")
const options = {
    storage,
    queryFunction: createCachingFunction(storage, 12 * 60 * 60 * 1000) // オプション。デフォルトは24時間
}
```

{% hint style="info" %}
Nodeとブラウザでは、この第2引数の扱いが異なります。Nodeではオプションオブジェクトを、ブラウザでは単純な数値の `maxCacheAgeMs` を渡します。ブラウザには `cachePath` オプションはなく、キャッシュにはIndexedDBを使用します。
{% endhint %}

ネットワーク障害が発生した場合、キャッシュされたレスポンスが存在し、まだ有効期限内であれば、そのレスポンスが返され、内容が古い可能性があることを示す警告がログに出力されます。クライアント側で意図的に設定したタイムアウト ([リクエストタイムアウト](#request-timeouts)を参照) では、キャッシュからのレスポンスは返されません。見かけ上成功したかのような古いレスポンスの代わりに、実際のエラーとして呼び出し元に伝播します。最初の (バインド) コールは、バインドコール自体がキャッシュに必要なアプリキーを確立するため、キャッシュされません。

### ブラウザセキュアストレージ <a href="#browser-secure-storage" id="browser-secure-storage"></a>

ブラウザでは、`secureStorage(dbName)` により、非抽出可能な AES-256-GCM キーで IndexedDB 内の KSM 認証情報を暗号化したストレージバックエンドが利用できます。キーはブラウザ内で生成され、エクスポートできないため、保存された認証情報は抽出可能な形式では保持されません。

`secureStorage` は非同期のため、ストレージインスタンスの取得には `await` が必要です。ブラウザビルドでのみ利用できます。ブラウザバンドル外 (Node.js、SSR) でインポートすると `undefined` になります。node エントリーポイントには含まれません。

```javascript
import { secureStorage, getSecrets, initializeStorage } from '@keeper-security/secrets-manager-core'

const storage = await secureStorage('ksm-secure')

await initializeStorage(storage, '<One Time Access Token>')
const { records } = await getSecrets({ storage })
```

### フォルダ <a href="#folders" id="folders"></a>

フォルダは完全なCRUD (作成、読み取り、更新、削除操作) に対応しています。

### フォルダの読み取り <a href="#read-folders" id="read-folders"></a>

フォルダの完全な階層構造をダウンロードします。

```javascript
getFolders = async (options:SecretManagerOptions):Promise<KeeperFolder[]>
```

**レスポンス**

型: `KeeperFolder[]`

**使用例**

```javascript
const storage = localConfigStorage("ksm-config.json")
const folders = await getFolders({storage: storage})
```

### フォルダの作成 <a href="#create-a-folder" id="create-a-folder"></a>

作成には `CreateOptions` とフォルダ名の指定が必要です。`CreateOptions` に含まれる `folder UID` パラメータは必須で、これは共有フォルダのUIDを指定します。`sub-folder UID` は任意で、省略された場合は、指定された共有フォルダの直下に通常のフォルダが新規作成されます。なお、`sub-folder UID` は必ずしも親の共有フォルダの直下である必要はなく、何階層も深い位置を指定することも可能です。

```javascript
createFolder = async (options:SecretManagerOptions, createOptions:CreateOptions, folderName: string):Promise<string>
```

<table><thead><tr><th width="181.85161529417937">パラメータ</th><th width="242.99431983802478">型</th><th width="102">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>options</code></td><td><code>SecretsManagerOptions</code></td><td>はい</td><td>事前に設定されたオプション</td></tr><tr><td><code>createOptions</code></td><td><code>CreateOptions</code></td><td>はい</td><td>親およびサブフォルダのUID</td></tr><tr><td><code>folderName</code></td><td><code>string</code></td><td>はい</td><td>フォルダ名</td></tr></tbody></table>

```javascript
type CreateOptions = {
    folderUid: string
    subFolderUid?: string
}
```

**使用例**

```javascript
const storage = localConfigStorage("ksm-config.json")
const folderUid = await createFolder({storage: storage}, {folderUid: "[PARENT_SHARED_FOLDER_UID]"}, "new_folder")
```

### フォルダの更新 <a href="#update-a-folder" id="update-a-folder"></a>

フォルダのメタデータ (現在はフォルダ名のみ) を更新します。

```javascript
updateFolder = async (options:SecretManagerOptions, folderUid: string, folderName: string):Promise<void>
```

<table><thead><tr><th width="154.85161529417937">パラメータ</th><th width="243.99431983802478">型</th><th width="100">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>options</code></td><td><code>SecretsManagerOptions</code></td><td>はい</td><td>事前に設定されたオプション</td></tr><tr><td><code>folderUid</code></td><td><code>string</code></td><td>はい</td><td>フォルダのUID</td></tr><tr><td><code>folderName</code></td><td><code>string</code></td><td>はい</td><td>新しいフォルダ名</td></tr></tbody></table>

**使用例**

```javascript
const storage = localConfigStorage("ksm-config.json")
await updateFolder({storage: storage}, "[FOLDER_UID]", "new_folder_name")
```

### フォルダの削除 <a href="#delete-folders" id="delete-folders"></a>

フォルダのリストを削除します。空でないフォルダを削除するには、`forceDeletion`フラグを使用します。

{% hint style="info" %}
`forceDeletion` を使用する際は、親フォルダとその子フォルダのUIDを同時に送信しないように注意してください。削除の順序によっては、エラーが発生する可能性があります (例: 親が先に削除され、その後で子フォルダを削除しようとした場合など)。UIDのリストが常にFIFO (先入れ先出し) 順に処理される保証はありません。
{% endhint %}

{% hint style="info" %}
ボルトに存在しないフォルダのUIDやKSMアプリケーションで共有されていないフォルダのUIDはエラーになりません。
{% endhint %}

```javascript
deleteFolder = async (options:SecretManagerOptions, folderUids: string[], forceDeletion?: boolean):Promise<SecretsManagerDeleteResponse>
```

<table><thead><tr><th width="180.85161529417937">パラメータ</th><th width="242.99431983802478">型</th><th width="100">必須</th><th width="89">デフォルト</th><th>説明</th></tr></thead><tbody><tr><td><code>options</code></td><td><code>SecretsManagerOptions</code></td><td>はい</td><td></td><td>事前に設定されたオプション</td></tr><tr><td><code>folderUids</code></td><td><code>string[]</code></td><td>はい</td><td></td><td>フォルダUIDリスト</td></tr><tr><td><code>forceDeletion</code></td><td><code>bool</code></td><td>いいえ</td><td><code>false</code></td><td>空でないフォルダを強制的に削除</td></tr></tbody></table>

**使用例**

```javascript
const storage = localConfigStorage("ksm-config.json")
const response = await deleteFolder({storage: storage}, ["[FOLDER_UID1]", "[FOLDER_UID2]"], true)
```

**レスポンス**

[シークレットの削除](#delete-a-secret)のレスポンスと同じ形式で、`folders` 配列に格納されます。このコールは、サーバーが一部のUIDを拒否した場合でも解決されるため、成功したものと決めつけず、各項目の `responseCode` を確認してください。

### カスタムサーバー公開鍵 <a href="#custom-server-public-key" id="custom-server-public-key"></a>

サーバーの公開鍵が SDK に同梱されていない分離環境やプライベート環境では、公開鍵を自分で指定できます。`getSecrets` に渡すオプションオブジェクトに `serverPublicKey` と `serverPublicKeyId` をあわせて設定します。`serverPublicKey` を設定する場合、`serverPublicKeyId` も必須で、正の整数を指定する必要があります。

```javascript
const options = {
    storage: localConfigStorage("ksm-config.json"),
    serverPublicKey: "<base64-encoded server public key>",
    serverPublicKeyId: "<key id>"
}

const { records } = await getSecrets(options)
```

`serverPublicKey` / `serverPublicKeyId` の値は、代わりに構成のフィールドとして保存することもできます。カスタムサーバー公開鍵を設定している間はその鍵が使われ続け、サーバーからプッシュされる鍵ローテーションのヒントは無視されます。17.6.0以降、鍵を固定した後にどちらか一方だけを変更することはできず、変更する際は両方のフィールドをあわせて指定する必要があります。`serverPublicKeyId` だけを指定しても、固定済みのカスタム鍵のIDは変更されません。サーバーが設定された鍵を拒否した場合、または `serverPublicKey` / `serverPublicKeyId` の設定に誤りがある場合 (片方のみの指定、IDが整数でない、サポートされていない同梱IDなど) は、`getSecrets` から `KeeperError` がスローされ (詳しくは[エラーハンドリング](#error-handling)をご参照ください)、`e.message` に理由が含まれます。呼び出し側でラップし、不一致を明示的に処理してください。

```javascript
try {
    const { records } = await getSecrets(options)
} catch (e) {
    // 鍵がサーバーに拒否された、または serverPublicKey / serverPublicKeyId の設定に誤りがある
    throw e
}
```

### プロキシ対応 <a href="#proxy-support" id="proxy-support"></a>

プロキシを使用するには、`@keeper-security/secrets-manager-core` に含まれる\
`setCustomProxyAgent` を使用して、プロキシエージェントをインストールおよび設定する必要があります。

**使用例**

```javascript
const {
    getSecrets,
    initializeStorage,
    localConfigStorage,
    setCustomProxyAgent
} = require('@keeper-security/secrets-manager-core')
const { HttpsProxyAgent } = require('https-proxy-agent')

const getKeeperRecords = async () => {
    // プロキシのURLを設定
    setCustomProxyAgent(new HttpsProxyAgent('http://user:password@127.0.0.1:3128'))

    const storage = localConfigStorage("config.json")
    
    await initializeStorage(storage, 'US:EXAMPLE_ONE_TIME_TOKEN', 'keepersecurity.com')
    const {records} = await getSecrets({storage: storage})

    console.log(records)
}
```

{% hint style="danger" %}
`setCustomProxyAgent` は Node.js 環境でのみ動作し、ブラウザでは使用できません。
{% endhint %}

### リクエストタイムアウト <a href="#request-timeouts" id="request-timeouts"></a>

SDKが1回のネットワーク通信を待機する時間の上限は、`SecretManagerOptions` の `requestTimeoutMs` で設定します。デフォルトは30秒です。`getSecrets`、`updateSecret`、その他メインのリクエスト経路を通るすべての呼び出しに加え、[キャッシュ](#caching)へのフォールバックにも適用されます。

```javascript
const options = {
    storage: localConfigStorage("ksm-config.json"),
    requestTimeoutMs: 10000 // 10秒
}
```

`downloadFile`、`downloadThumbnail`、`uploadFile` はそれぞれ独自のオプションの `timeoutMs` も受け付け、その呼び出しについては `requestTimeoutMs` より優先されます。

```javascript
await downloadFile(file, 60000, options) // options.requestTimeoutMs に関わらず、このダウンロードには60秒が適用される
```

タイムアウトが発生すると、実際に適用されたタイムアウト値を含む `KeeperError` でコールが拒否されます。`requestTimeoutMs` は個々の試行1回ごとの上限であり、コール全体の上限ではありません。サーバー側のスロットリングでリトライされるリクエストは、リトライ間の待機時間が別枠で `requestTimeoutMs` に含まれないため、合計では設定値を超えて長くかかることがあります。ただし、すべてのリトライを通した合計時間には上限があります (バックオフのスケジュールは後述のエラーハンドリングを参照)。

{% hint style="info" %}
`0`、負の数、`NaN`、`Infinity` を指定した場合は、リクエストを送信する前に即座にプレーンな `Error` (`KeeperError` ではありません) がスローされます。
{% endhint %}

### エラーハンドリング <a href="#error-handling" id="error-handling"></a>

SDK からエクスポートされる `KeeperError` は、SDK 由来のエラーの基底クラスです。これをキャッチすることで、SDK 由来のエラーと予期しないランタイム障害を区別できます。`KeeperError` は組み込みの `Error` を継承するため、既存の `instanceof Error` による処理はそのまま動作します。

```javascript
const { getSecrets, localConfigStorage, KeeperError, KeeperThrottleError, KeeperStorageError, KeeperCryptoError } = require('@keeper-security/secrets-manager-core')

try {
    const { records } = await getSecrets({ storage: localConfigStorage("ksm-config.json") })
} catch (e) {
    if (e instanceof KeeperThrottleError) {
        // request was throttled and automatic retries were exhausted
    } else if (e instanceof KeeperStorageError) {
        // failure reading or writing the local config/cache file; e.code carries the fs errno (EACCES, ENOSPC, ...) when one exists
    } else if (e instanceof KeeperCryptoError) {
        // a specific folder could not be decrypted; e.failure classifies why, e.uid identifies the item
    } else if (e instanceof KeeperError) {
        // base class for SDK-raised errors; check e.message for details
    } else {
        throw e
    }
}
```

17.6.0以降、SDKは `KeeperError` 階層を通じて4種類のエラーをスローします。具体的には `KeeperThrottleError`、`KeeperStorageError`、`KeeperCryptoError`、そしてその他のSDK起因の失敗を表す `KeeperError` 自体です (誤って設定された `serverPublicKey` / `serverPublicKeyId` も含みます。詳しくは[カスタムサーバー公開鍵](#custom-server-public-key)をご参照ください)。リクエストを送信する前に失敗する呼び出し側の入力ミス (使用できない `requestTimeoutMs` など。[リクエストタイムアウト](#request-timeouts)を参照) は、Keeperのバックエンドとのやり取りの失敗ではなく不正な引数であるため、依然としてプレーンな `Error` としてスローされ、`KeeperError` にはなりません。`KeeperStorageError` はNode専用です。ブラウザでのストレージ障害 (`localConfigStorage` と `secureStorage` はいずれもIndexedDBを使用) は、このサブタイプではなくプレーンな `KeeperError` で拒否されます。両方のプラットフォームで同じハンドラーでストレージ障害をキャッチする必要がある場合は、`instanceof KeeperStorageError` ではなく `instanceof KeeperError` を確認してください。

復号に失敗したフォルダが結果から省かれるだけで済ませず、その失敗に個別に対応したい場合は、`getFolders()` を呼び出す際に `SecretManagerOptions` へ `onDecryptionError` を渡します。

```javascript
const options = {
    storage: localConfigStorage("ksm-config.json"),
    onDecryptionError: (info) => {
        console.error(`Failed to decrypt ${info.uid}: ${info.failure} — ${info.message}`)
        // 部分的な結果を返す代わりにコールを中断する場合は、ここでスローする
    }
}
```

Keeper バックエンドがリクエストをスロットル (HTTP 403またはHTTP 429) した場合、最大5回まで自動リトライされます。サーバーが `retry_after` 値を含む場合はその遅延が使われ、含まれない場合は指数バックオフ (\~11、22、44、88、176 秒、それぞれジッター付き) にフォールバックします。すべてのリトライが使い果たされた場合は `KeeperThrottleError` がスローされます。自動リトライは呼び出し側の変更なしで動作します。


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.keeper.io/keeperpam/jp/secrets-manager/developer-sdk-library/javascript-sdk.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
