mcpField
W
widget-coherence

widget-coherence

github.com/serac-labs開発7761 回インストール9 週間前に更新
リポジトリ

widget-coherence について

ServiceNow Service Portal のウィジェット開発向けスキルで、サーバースクリプト、クライアントコントローラー、HTML テンプレートの整合性を扱います。データやアクションの流れを確認し、デプロイ前に不一致を見つけるための指針を提供します。

主な機能

  1. 01ウィジェット三者間の契約確認
  2. 02サーバーとクライアントのアクション照合
  3. 03データプロパティ初期化の指針
  4. 04Angular ディレクティブの一覧
  5. 05デプロイ前の検証チェックリスト

活用シーン

  1. 01ウィジェットのデータバインディング確認
  2. 02クライアントとサーバーのアクション不一致の発見
  3. 03クリックハンドラーとコントローラーメソッドの照合

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/serac-labs/serac --skill widget-coherence

インストール後、Claude Code で/widget-coherenceを入力して読み込まれたか確認します。

詳細

ServiceNow Service Portal のウィジェットの整合性

Service Portal のウィジェットでは、サーバースクリプト、クライアントコントローラー、HTML テンプレート間で完全に通信できる必要があります。これは必須です。これらのコンポーネントが正しく連携しないと、ウィジェットは動作しません。

3 者間の契約

すべてのウィジェットで、同期された通信が必要です。

1. サーバースクリプトの要件:
  • HTML が参照するすべての data.* プロパティを初期化する
  • クライアントが c.server.get() 経由で送信するすべての input.action を処理する
  • クライアントが期待する形式でデータを返す
2. クライアントコントローラーの要件:
  • HTML の ng-click から呼び出されるすべてのメソッドを実装する
  • サーバーとの通信には c.server.get({action: 'name'}) を使用する
  • サーバーから応答があったら c.data を更新する
3. HTML テンプレートの要件:
  • サーバーが提供する data.* プロパティのみを参照する
  • クライアントコントローラーで定義されているメソッドのみを呼び出す
  • 正しい Angular ディレクティブとバインディングを使用する

データフローのパターン

サーバー → クライアント → HTML
// SERVER SCRIPT
;(function () {
  data.incidents = []
  data.loading = true

  var gr = new GlideRecord("incident")
  gr.addQuery("active", true)
  gr.setLimit(10)
  gr.query()

  while (gr.next()) {
    data.incidents.push({
      sys_id: gr.getUniqueValue(),
      number: gr.getValue("number"),
      short_description: gr.getValue("short_description"),
    })
  }
  data.loading = false
})()
// CLIENT CONTROLLER
api.controller = function ($scope) {
  var c = this

  c.selectIncident = function (incident) {
    c.selectedIncident = incident
  }
}

<div ng-if="data.loading">Loading...</div>
<div ng-if="!data.loading">
  <div ng-repeat="incident in data.incidents" ng-click="c.selectIncident(incident)">
    {{incident.number}}: {{incident.short_description}}
  </div>
</div>
クライアント → サーバー(アクション)
// CLIENT CONTROLLER
c.saveIncident = function () {
  c.server
    .get({
      action: "save_incident",
      incident_data: c.formData,
    })
    .then(function (response) {
      if (response.data.success) {
        c.data.message = "Saved successfully"
      }
    })
}
// SERVER SCRIPT
if (input && input.action === "save_incident") {
  var gr = new GlideRecord("incident")
  gr.initialize()
  gr.setValue("short_description", input.incident_data.short_description)
  data.new_sys_id = gr.insert()
  data.success = !!data.new_sys_id
}

検証チェックリスト

ウィジェットをデプロイする前に、次の点を確認してください。

  • サーバーのすべての data.property が HTML またはクライアントで使用されている
  • すべての ng-click="c.method()" に、クライアント側の対応する c.method がある
  • すべての c.server.get({action: 'x'}) に、サーバー側の対応する if(input.action === 'x') がある
  • 対応する呼び出しがないメソッドや未使用のデータプロパティがない
  • すべての data.* プロパティがサーバーで初期化されている(空の場合も含む)

よくある失敗

アクション名の不一致
// CLIENT - sends 'saveIncident'
c.server.get({ action: "saveIncident" })

// SERVER - expects 'save_incident' (MISMATCH!)
if (input.action === "save_incident") {
}
メソッド名の不一致

<button ng-click="c.saveData()">Save</button>
// CLIENT - defines save() (MISMATCH!)
c.save = function () {}
未定義のデータプロパティ

<span>{{data.user.email}}</span>
// SERVER - only sets user.name (user.email is undefined!)
data.user = { name: userName }

Angular ディレクティブのリファレンス

ディレクティブ目的
ng-if条件に応じて要素をレンダリングする
ng-show/ng-hide表示を切り替える(要素は DOM に残ります)
ng-repeat配列を反復処理する
ng-clickクリックイベントを処理する
ng-model双方向のデータバインディング
ng-classCSS クラスを動的に設定する
ng-disabledフォーム要素を無効にする

コメント