Heroku AppLinkの使い方 (クエリ)

Heroku AppLinkのサンプルコードがもう少し欲しいところ...で、まずはクエリのサンプルでも備忘録として残してみる
※サンプルコードは Node.js 版のSDKを使ったものに限定です。SDKのリポジトリは https://github.com/heroku/heroku-applink-nodejs を参照してください。

1. 1つのオブジェクトだけクエリする

import * as salesforcesdk from "@heroku/applink";

const sfdc_id = 'xxxxx';

async function sample () {
  const sdk = salesforcesdk.init();
  // ※Authorized Userを使います
  const org = await sdk.addons.applink.getAuthorization(process.env.HEROKU_APPLINK_CONNECTION_NAME);

  // 取引先を取得する
  const accountQueryResult: salesforcesdk.RecordQueryResult = await org.dataApi.query(
    `select id,name from account where id = '${sfdc_id}'`
  );
  // accountQueryResult:
  // {
  //   records: (レコードの配列)
  //   totalSize: (クエリした全レコード件数)
  //   done: (falseだと、次のページリンクがある)
  //   nextRecordsUrl: (次ページのリンク)
  // }
  
  const accountRecords: salesforcesdk.QueriedRecord[] = accountQueryResult.records;
  // accountRecords:
  // [
  //   {
  //     type: (オブジェクトAPI)
  //     fields: (レコード内の属性がオブジェクトとして格納)
  //     subQueryResults: (サブクエリがあれば)
  //   }
  // ]
  const accountRecord: salesforcesdk.QueriedRecord = accountRecords[0];
  const account: { [key: string]: unknown } = accountRecord.fields;
  console.log(account.id);
  console.log(account.name);
  
}

2. サブクエリも追加してみる

import * as salesforcesdk from "@heroku/applink";

const sfdc_id = 'xxxxx';

async function sample () {
  const sdk = salesforcesdk.init();
  const org = await sdk.addons.applink.getAuthorization(process.env.HEROKU_APPLINK_CONNECTION_NAME);

  // 取引先と、それに紐つく取引先責任者を取得する
  const accountQueryResult: salesforcesdk.RecordQueryResult = await org.dataApi.query(
    `select id,name,(select name from contacts) from account where id = '${sfdc_id}'`
  );
  
  const accountRecords: salesforcesdk.QueriedRecord[] = accountQueryResult.records;
  const accountRecord: salesforcesdk.QueriedRecord = accountRecords[0];

  // subQueryResults内に、子リレーション名をkeyにした RecordQueryResult があるのでそれを取得する
  const contactQueryResult: salesforcesdk.RecordQueryResult = accountRecord.subQueryResults.contacts;
  if (contactQueryResult.totalSize == 0) {
    console.log('取引先責任者なし');
  }
  const contactRecords: salesforcesdk.QueriedRecord[] = contactQueryResult.records;
  contactRecords.forEach((record) => {
    // 取引先責任者名
    console.log(record.fields.name);
  });
}

3. 親オブジェクトへのリレーションを追加してみる

import * as salesforcesdk from "@heroku/applink";

const sfdc_id = 'xxxxx';

async function sample () {
  const sdk = salesforcesdk.init();
  const org = await sdk.addons.applink.getAuthorization(process.env.HEROKU_APPLINK_CONNECTION_NAME);

  // 商談と、商談明細をクエリする
  // 商談明細には、商品の商品名もクエリする
  const opportunityQueryResult: salesforcesdk.RecordQueryResult = await org.dataApi.query(
    `select id,name,(select id,product2.name from opportunitylineitems) from opportunity where id = '${sfdc_id}'`
  );

  const opportunityRecords: salesforcesdk.QueriedRecord[] = opportunityQueryResult.records;
  const opportunityRecord: salesforcesdk.QueriedRecord = opportunityRecords[0];

  const opportunitylineitemQueryResult: salesforcesdk.RecordQueryResult = opportunityRecord.subQueryResult.opportunitylineitems;
  const opportunitylineitemRecord: salesforcesdk.QueriedRecord = opportunitylineitemQueryResult.records[0];
  // opportunitylineitemRecord: 
  // {
  //   type: 'opportunitylineitem',
  //   fields: {
  //     id: '00kA...',
  //     product2: {
  //       type: 'product2',
  //       fields: {
  //         name: 'xxxxx...'
  //       }
  //     }
  //   }
  // }

  // 商談明細が参照する商品レコードを取得する
  const productRecord: salesforcesdk.QueriedRecord = opportunitylineitemRecord.fields.product2;
  // productRecord:
  // {
  //   type: 'product2',
  //   fields: {
  //     name: 'xxxx'
  //   }
  // }
  console.log(productRecord.field.name);
  
}

Read more

Salesforce

Salesforce コアサービスでサービス中断が発生(2026-9-16 16:50発生 2026-9-17 04:00解決)

ここ最近発生していなった大規模障害が発生しました。ちょうど日本時間の夕刻で、当社のお客様にも影響が出ていたため、本ポストを作成しました。 * AWS障害ではなく、Salesforce側の障害と思われます。 * Sandboxは実は正常だったということで修正されました。当日の状況とも合致します。 https://status.salesforce.com/incidents/20004433 以下は、日本語話者向けの妙訳です。(生成AIを利用しています。) 更新(2026-09-18 2:16) その後、当社チームが本インシデントについてさらに調査を進めた結果、Sandbox 環境は影響を受けていなかったことが判明しました。 実際の影響範囲を正確に反映するため、本投稿を更新し、Sandbox インスタンスを影響対象から除外しました。 この変更により混乱を招いた可能性があることをお詫び申し上げます。 As our teams investigated the incident further, we discovered that sandboxes were not

By Hiroki Matsumoto

Salesforce

Multi-Frameworkが運用組織で利用可能に(実質的に2026/7/9から)

Mutlti-Frameworkは2026/6/3にGAするも、Data SDKとGraphQLがGAしたのは7/9なので、実質的に動かせるのは、2026/7/9からということだった。 When: This feature is available starting June 3, 2026. Develop React Apps with Salesforce Multi-Framework (Generally Available) When: This feature is generally available starting July 9, 2026. Get Record Data in Your React Apps with Data SDK and

By Hiroki Matsumoto

Agentforce

文字起こしエージェントアクションの追加(Summer'26)

エージェントアクションにWhisper V3 Turbo (Whisper Large V3 Turboと思われる)による文字起こし機能が追加。6/22週から利用可能。 * Whisperはセルフホストっぽい。 * 5MB未満 * 話者識別やタイムスタンプはない。 電話音声だと帯域狭いから、適切な前処理すれば50分ぐらいいけるかも。MP3 64Kbpsだと10分ほどの計算になる。 Choose a Transcription Model for the Speech to Text Agent Action Use the Transcription Model parameter on the Speech to Text action to control which model converts audio to text. Choose the model

By Hiroki Matsumoto

Salesforce

Multi-FrameworkでReactAppを(内部向けアプリ)

あれ、もうGAになったのかな? 前に外部向け(Experience Cloud)のReact Appを作成してみたので、今度は内部向けも試してみる。今回はSandbox環境にデプロイして動かせるのか試してみよう。 内部向けのsfdxプロジェクトを作成 今回は --template に reactinternalapp を指定する $ sf template generate project --name wkInReactApp --template reactinternalapp npmパッケージのインストール&ビルド READMEにある通りに、作成したプロジェクトのルートディレクトリで、以下を実行する $ npm install $ npm run sf-project-setup > @salesforce/ui-bundle-template-base-sfdx-project@1.135.0 sf-project-setup >

By Takahiro Yonei