> 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

## ダウンロードとインストール <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 = new 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#record-type-info-command) コマンドをご参照ください。

**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` を指定します。

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

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

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

`requestLinks` を指定しなかった場合、またはリンクが存在しない場合は `record.links` は `null` または空です。各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):ByteArray
```

| パラメータ  | 型            | 必須 | デフォルト | 説明           |
| ------ | ------------ | -- | ----- | ------------ |
| `file` | `KeeperFile` | はい |       | ダウンロードするファイル |

**レスポンス**

型: `Promise<Uint8Array>`

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

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

```javascript
downloadThumbnail(file:KeeperFile):ByteArray
```

| パラメータ  | 型            | 必須 | デフォルト | 説明                  |
| ------ | ------------ | -- | ----- | ------------------- |
| `file` | `KeeperFile` | はい |       | ダウンロードするサムネイル付きファイル |

**レスポンス**

型: `Promise<Uint8Array>`

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

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

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

```javascript
uploadFile = async (options:SecretManagerOptions, ownerRecord:KeeperRecord, file:KeeperFileUpload):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></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);
```

<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>await deleteSecret(smOptions, ["EG6KdJaaLG7esRZbMnfbFA"]);
</strong></code></pre>

{% endtab %}
{% endtabs %}

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

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

`SecretManagerOptions` に `queryFunction: cachingPostFunction` を追加

使用例:

```javascript
const options:SecretManagerOptions = {    
    storage: kvs,
    queryFunction: cachingPostFunction // `cachingPostFunction` をインポートする
}
```

### ブラウザセキュアストレージ <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")
await deleteFolder({storage: storage}, ["[FOLDER_UID1]", "[FOLDER_UID2]"], true)
```

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

サーバーの公開鍵が SDK に同梱されていない分離環境やプライベート環境では、公開鍵を自分で指定できます。`getSecrets` に渡すオプションオブジェクトに `serverPublicKey` (および任意で `serverPublicKeyId`) を設定します。

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

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

カスタムサーバー公開鍵を設定している間はその鍵が使われ続け、サーバーからプッシュされる鍵ローテーションのヒントは無視されます。サーバーが設定された鍵を拒否した場合は、`getSecrets` からプレーンな `Error` がスローされます (`KeeperError` ではありません。詳しくは[エラーハンドリング](#error-handling)をご参照ください)。`e.message` に拒否理由が含まれます。呼び出し側でラップし、不一致を明示的に処理してください。

```javascript
try {
    const { records } = await getSecrets(options)
} catch (e) {
    // key was rejected by the server — update 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="#error-handling" id="error-handling"></a>

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

```javascript
const { getSecrets, localConfigStorage, KeeperError, KeeperThrottleError } = 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 KeeperError) {
        // base class for SDK-raised errors; check e.message for details
    } else {
        throw e
    }
}
```

v17.5.0 では、`KeeperThrottleError` が SDK が `KeeperError` 階層を通じてスローする唯一のエラーです。構成やセットアップのエラー (フィールド不足、無効なトークンなど) はプレーンな `Error` としてスローされます。上記の `else` ブランチでキャッチされ、`instanceof KeeperError` ではキャッチされません。

Keeper バックエンドがリクエストをスロットル (HTTP 403) した場合、最大 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 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.keeper.io/keeperpam/jp/secrets-manager/developer-sdk-library/javascript-sdk.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.
