mcpField
E
enonic-content-management

enonic-content-management

github.com/webmaxruデータ・データベース0301 回インストール21 週間前に更新
リポジトリ

enonic-content-management について

Enonic XP プロジェクトでのコンテンツ一括操作や移行を支援する手順型スキルです。開発者が適切な API を選び、バッチ処理、ブランチと公開の管理、進捗報告を行えるようにします。

主な機能

  1. 01Enonic XP のプロジェクトとバージョンの特定
  2. 02コンテンツ API またはノード API の選択
  3. 03NoQL によるコンテンツ検索
  4. 04一括操作のバッチ処理
  5. 05draft と master の公開管理
  6. 06長時間タスクの進捗追跡

活用シーン

  1. 01JSON や CSV からのコンテンツ取り込み
  2. 02クエリ条件に合うコンテンツの更新や削除
  3. 03パスや環境間でのコンテンツ移行
  4. 04大規模操作の進捗レポート

インストール

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

$npx skills add https://github.com/webmaxru/enonic-agent-skills --skill enonic-content-management

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
bulk-update.template.ts
task-migration.template.ts
references/
compatibility.md
examples.md
migration-reference.md
troubleshooting.md
scripts/
find-enonic-targets.mjs

詳細

Enonic コンテンツ管理

手順

ステップ 1:Enonic XP プロジェクトと操作範囲を特定する

  1. ワークスペースで Enonic XP プロジェクトの目印を確認します。例:com.enonic.xp 依存関係を含む build.gradle、src/main/resources/ のディレクトリ構造、または xpVersion を含む gradle.properties。
  2. Node ランタイムが利用可能な場合は、node scripts/find-enonic-targets.mjs . を実行して、Enonic XP プロジェクトの目印と既存のコンテンツ操作ファイルをスキャンします。
  3. Enonic XP プロジェクトが見つからない場合は、ここで終了し、このスキルの対象は Enonic XP のコンテンツ操作のみであることを説明します。
  4. gradle.properties または build.gradle から対象の XP バージョンを確認し、適切な API を選択します。
  5. 依頼された操作を分類します。
    • 一括作成:外部ソース(JSON、CSV、API)からコンテンツをインポートします。
    • 一括更新:クエリ条件に一致する既存コンテンツを変更します。
    • 一括削除:クエリ条件に一致するコンテンツを削除します。
    • 移行:パス、サイト、または環境間でコンテンツを移動または変換します。
    • クエリ/集計:NoQL と集計を使用してコンテンツを取得、分析します。
    • 長時間実行タスク:進捗報告が必要な、約 100 件を超える項目を処理する操作です。

ステップ 2:API レイヤーとコンテキストを選択する

  1. クエリ DSL のパターン、バッチ処理の戦略、ブランチ処理のルールについては、references/migration-reference.md を読みます。
  2. CMS コンテンツを操作し、公開/非公開、コンテンツタイプの検証、コンテンツドメインの抽象化が必要な場合は、lib-content を選択します。
  3. 低レベルのノード操作、カスタムリポジトリ、または生データの移行におけるコンテンツタイプ検証の回避が必要な場合は、lib-node を選択します。
  4. 必要なコンテキストを特定します。
    • 変更操作は draft ブランチで、公開済みコンテンツの読み取りは master ブランチで実行するために、lib-context を使用します。
    • 高い権限が必要な操作では、role:system.admin プリンシパルを指定して lib-context を使用します。
  5. 操作で約 100 件を超える項目を処理する場合は、lib-task を使用したタスクコントローラーでラップします。パターンについては、references/migration-reference.md のタスクコントローラーに関するセクションを読みます。

ステップ 3:クエリを作成する

  1. 対象コンテンツに一致する NoQL クエリ文字列または DSL 式を作成します。
  2. コンテンツタイプで絞り込む場合は、contentLib.query() の contentTypes パラメーター、またはノードクエリの type プロパティ比較を使用します。
  3. 日付範囲クエリでは、instant() または dateTime() 関数と、range() クエリ関数を使用します。
  4. 全文検索では、適切なフィールドパスと演算子(AND/OR)を指定して fulltext() を使用します。
  5. パスを指定した操作では、子孫に一致させるために _path LIKE '/content/site-path/*' を使用します。注:NoQL クエリの _path プロパティには内部の /content/ プレフィックスが含まれますが、結果の hit._path はコンテンツドメインのパスを返し、このプレフィックスは含まれません。結果のパスからクエリを作成するときは、必ず /content/ を先頭に付けてください。
  6. exists、notExists、hasValue、または boolean の組み合わせを使用して、クエリ後の絞り込みを効率化する filters を追加します。
  7. グループ化した統計情報(用語の件数、日付ヒストグラム、数値範囲、統計値)が必要な操作には、aggregations を追加します。
  8. クエリと集計の完全なパターンについては、references/examples.md を読みます。 ステップ 4:バッチ処理を実装する
  9. start パラメーターと count パラメーターを使ってページネーションで取得し、すべての結果をメモリに読み込まないようにします。
  10. アイテムごとの処理の複雑さに応じて、count を 50~200 のバッチサイズに設定します。
  11. result.hits.length === 0 または start >= result.total になるまでループし、反復ごとに start をバッチサイズ分増やします。
  12. contentLib.create() を一括で実行する際は、アイテムごとのインデックス更新を避けるために refresh: false を設定し、バッチ完了後に手動で更新します。
  13. contentLib.modify() では、各コンテンツアイテムを安全に変換するためにエディターコールバックパターンを使用します。
  14. contentLib.publish() では、大規模な公開セットでタイムアウトしないよう、キーを 50~100 件ずつのグループに分けて処理します。
  15. レポート用に成功数と失敗数を記録します。
  16. 再利用可能なバッチ更新コントローラーテンプレートについては、assets/bulk-update.template.ts を確認します。注:テンプレートでは TypeScript/ESM 構文(import、const、アロー関数)が使われています。.js ファイルとして XP ランタイムにデプロイする際は、CommonJS JavaScript(require()、var、function())に適合させてください。

ステップ 5:ブランチ操作と公開を処理する

  1. コンテンツの変更は draft ブランチのコンテキストで実行します。
  2. 変更が完了したら、contentLib.publish() を使って変更したアイテムを master に公開します。XP < 7.12 の場合は、sourceBranch: 'draft' と targetBranch: 'master' を渡します。XP 7.12 以降では、これらのパラメーターは無視されます(常に draft から master に公開されます)。
  3. 一括更新したアイテムを公開する際は、依存関係が意図せず公開されるのを避けるため、includeDependencies: false を設定します。
  4. draft と master の状態を比較する操作には、lib-node の repo.diff() を使用し、target: 'master' と includeChildren: true を指定します。

ステップ 6:時間のかかる操作をタスクコントローラーでラップする

  1. インラインのタスク関数には taskLib.executeFunction() を、名前付きタスク記述子には taskLib.submitTask() を使用します。
  2. バッチ処理中は、一定の間隔で taskLib.progress({ info, current, total }) を使って進捗を報告します。
  3. 進捗報告に対応した再利用可能なタスクコントローラーテンプレートについては、assets/task-migration.template.ts を確認します。
  4. 重複した操作を開始する前に、taskLib.isRunning() で既存の実行中インスタンスを確認します。
  5. 操作による負荷が過剰な場合は、バッチ間のスロットリングに taskLib.sleep() を使用します。
  6. XP 7.13 以降の名前付きタスクでは、run 関数の第 2 引数として taskId が渡されます:exports.run = function(params, taskId) { ... }。

ステップ 7:結果を検証して報告する

  1. 操作の完了後、処理したアイテム数、作成・更新・削除したアイテム数、失敗したアイテム数、合計所要時間の概要をログに記録します。
  2. 移行操作では、移行先のパスをクエリして、移行先にコンテンツが存在することを確認します。
  3. 公開操作では、master ブランチをクエリして、公開状態を確認します。
  4. エラーが発生した場合は、エラーの詳細(コンテンツパス、エラーメッセージ)を構造化レポートにまとめます。

エラー処理

  • scripts/find-enonic-targets.mjs で Enonic XP プロジェクトが見つからない場合は、ワークスペースに Enonic XP アプリケーションが含まれていないことを説明します。
  • コンテンツ操作で contentAlreadyExists エラーが発生した場合は、対象が存在するか確認し、更新するかスキップするかを判断します。重複の処理パターンについては、references/troubleshooting.md を確認します。
  • クエリ結果が 0 件の場合は、クエリ構文、ブランチのコンテキスト、プロパティのパスを確認します。NoQL の文字列形式の不一致(たとえば、日付比較で instant() ラッパーがないこと)は、よくある原因です。
  • タスクが失敗またはタイムアウトした場合は、taskLib.get(taskId) で状態と進捗の詳細を確認します。タイムアウトや権限の問題については、references/troubleshooting.md を確認します。
  • 公開または変更時に AccessDeniedException が発生した場合は、lib-context を介してコンテキストに role:system.admin プリンシパルが含まれていることを確認します。

コメント