sasjs-framework について
sasjs-framework は、Web フロントエンドと SAS バックエンドを組み合わせる SASjs アプリの構成を説明する静的リファレンススキルです。SAS 9、Viya、SASjs server 向けのレイアウト、設定、サービス契約、品質管理を扱います。
主な機能
- 01標準的なアプリ構成
- 02ターゲット別の設定
- 03フロントエンドと SAS のサービス契約
- 04入力検証の指針
- 05複数ターゲットのコード構成
- 06テストと lint の実践
活用シーン
- 01SASjs アプリ構成の計画
- 02複数ターゲットへのデプロイ設定
- 03フロントエンドと SAS サービス間のデータ設計
- 04入力安全性とテスト手法の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sasjs/ skills --skill sasjs-frameworkインストール後、Claude Code で/sasjs-frameworkを入力して読み込まれたか確認します。
同梱ファイルsasjsconfig-schema.json
詳細
SASjs Framework - SASjs アプリケーションの構築
SASjs アプリは、Web フロントエンド(Angular、React、バニラなど、任意のフレームワーク)と、標準的なレイアウトに整理された SAS バックエンドコードを組み合わせたものです。@sasjs/cli によってコンパイルされ、SAS 9、Viya、または SASjs サーバーにデプロイされます。フロントエンドは @sasjs/adapter を介して SAS と通信し、バックエンドサービスは _webout 経由で JSON を返します。
標準的なプロジェクトレイアウト
sasjs/
sasjsconfig.json # project + target configuration
macros/ # project-specific macros (macroFolders)
services/ # web services called from the frontend
jobs/ # jobs (scheduled / flow / long-running)
programs/ # plain programs (initProgram, termProgram, utilities)
db/ # DDL + static data per library (sasjs db)
tests/ # tests run by `sasjs test`
mocks/ # mock responses for offline frontend dev (syncFolder)
doxy/ # extra doxygen content for `sasjs doc`
sasjsconfig.json
ルート設定にはデフォルト値を保持し、targets[] の各エントリーでこれらを上書きできます。主なセクションは次のとおりです。
macroFolders、binaryFolders- CLI がマクロやバイナリを検索する場所serviceConfig.serviceFolders- サービスのソースフォルダー。initProgramは各サービスの前に実行されます(ライブラリ名やオプションを設定します)jobConfig.jobFolders- ジョブのソースフォルダーprogramFolders- アプリとともにコンパイルおよびデプロイされるプログラムstreamConfig-streamWeb: trueにすると、ビルド済みフロントエンドが SAS にストリーミングされ、プラットフォーム自体によって配信されます(別の Web サーバーは不要です)。webSourcePathはフロントエンドのビルド出力先を指定しますsyncFolder- サーバーと同期されるフォルダー(例:モック)testConfig-sasjs test用の初期化/終了プログラムtargets[]- 環境ごとの上書き設定:serverUrl、serverType(SAS9/SASVIYA/SASJS)、appLoc(デプロイ先のルート。例:/Public/app/myapp)、ターゲット固有のmacroFolders(プラットフォーム用シムのtargets/viya/macros_viyaなど)、httpsAgentOptions、deployConfig
完全な JSON スキーマは、このファイルの隣にある sasjsconfig-schema.json に含まれています。設定の変更は、このスキーマに照らして検証してください。"$schema": "https://cli.sasjs.io/sasjsconfig-schema.json" を指定して参照します。
Viya のストリーミングされたフロントエンドファイル(MIME タイプ)
streamWeb: true の場合、CLI はフロントエンド(index.html は streamServiceName に応じて名前を変更し、CSS/JS とともに)を %mv_createfile マクロを使って Viya Files サービスにアップロードします。このマクロは、正しくストリーミングされるよう、特定の方法でファイルを作成します。
- 拡張子から判定したコンテンツタイプ(
%mf_mimetype)を指定して/files/filesに POST します typeDefName=file_html(%mv_getViyaFileExtParms経由)を設定し、ファイルを HTML として認識させます- HTML/SVG では
Content-Dispositionにattachmentを付けずに送信するため、ブラウザーで表示されます
filename filesrvc のファイル参照名とデータステップによる書き換えを使って、ストリーミングされたフロントエンドファイルをその場で更新しないでください。その場合、Files サービスがファイルを汎用の BLOB として扱い、MIME タイプが失われるため、アプリがストリーミングされなくなります(ブラウザーがファイルをダウンロードするか、生のテキストを表示します)。実行時にストリーミングされたファイルを変更するには(例:HTML 内の compute contextname の修正)、ファイルを読み込み(読み込みには filesrvc のファイル参照名を使用できます)、変更した内容を一時的なファイル参照名に書き込み、%mv_createfile(path=..., name=..., inref=...) でファイルを再作成してください(古いファイルを削除し、正しい MIME タイプで再度 POST します)。
サービスコントラクト(フロントエンド <-> SAS)
- アダプターは入力テーブル(オブジェクトの配列)を指定して
services/<folder>/<name>に POST し、JS キーにちなんだ名前のワークデータセットを作成します。 - サービスの SAS コードは
initProgramの後に実行されます。入力を読み取り、処理を行い、出力 JSON を_weboutに書き込みます。 - @sasjs/core マクロを使用する一般的なパターン:
/**
@file
@brief Example service returning data
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@li mp_abort.sas
**/
/* validation / logic here */
%mp_jsonout(OPEN)
%mp_jsonout(OBJ,results,dslabel=results)
%mp_jsonout(CLOSE)
-
ヘッダー内の
<h4> SAS Macros </h4>の@liエントリーはドキュメントではなく、コンパイラーの依存関係マニフェストです。サービスが呼び出すすべてのマクロをここに記載しないと、ビルドにインライン化されず、デプロイされたジョブはApparent invocation of macro X not resolvedというエラーで実行時に失敗します。宣言されていない呼び出しは、宣言済みマクロの@liチェーンによってたまたまインライン化されると(推移的な解決)、テストに通ることがありますが、そのマクロの依存関係が変更されると動作しなくなります。既存のサービスを編集する際は、本文内の%macro()呼び出しをヘッダーのエントリーと照合して再確認し、mf_getuser.sasのような小さなヘルパーも含め、不足しているものを宣言してください。 -
エラー時は
%mp_abort(...)(mf_abortは非推奨)を使用して適切に中断し、アダプターが不完全なレスポンスではなく、JSON 内の構造化エラーを受け取るようにしてください。%if/%elseブロック内で%mp_abortを呼び出してはいけません。マクロプロセッサーが中断後も実行を続ける場合があります。代わりに、たとえば次のように条件付きのiftrue=パラメーターを使用します。
%mp_abort(iftrue= (%mf_existds(work.results)=0)
,mac=&_program
,msg=%str(No results found)
)
中断が %include ブロック内で発生すると、SAS は _webout に適切に戻れません。インクルードの後に(マクロラッパーの外で)%mp_abort(mode=INCLUDE) を呼び出してください。これは work.mp_abort_errds に中断ステータスがあるかどうかを確認します。
サービス入力のサニタイズ(SAS マクロインジェクション)
Web リクエストから届くすべての値(入力テーブル、URL パラメーター)は、攻撃者が制御できるものとして扱ってください。生成コード内でマクロ変数として解決される場合(libname パス、set/from 文、where 句、%include など)、スペース、引用符、セミコロン、&/% のマクロトリガーが、典型的な SAS インジェクションの攻撃経路になります。
ルール:
%mp_validatecol(incol,RULE,outcol)(@sasjs/core)を使って、call symputxの前にデータステップで入力を検証してください。合格した場合のみ symput を実行し、それ以外の場合は中断します(%mp_abort(iftrue=...))。ルールにはISLIB(有効な libref)、ISNAME(有効な SAS 名、例:メンバー/テーブル名)、LIBDS(LIBREF.DATASET)、FORMAT、ISINT、ISNUMがあります。- ホワイトリストがある場合は使用してください。構文検証の後、その値がパスやコードの生成に使われる前に、コントロールテーブル(例:主キーのルックアップ)に存在することを確認してください。
- コントロールテーブルから読み戻した値も改ざんされている可能性があります。コード生成マクロに渡す前に、それらも検証してください。
- コードに埋め込む必要がある自由記述値(例:ユーザーメッセージ)は、マクロトリガーを除去してください。
compress(value,'&%;')を使うか、危険な各文字をtranwrdで置き換えてください。ただし、自由記述をコードに含めないことを優先してください。
%let libds=0;
data _null_;
set work.sascontroltable;
%mp_validatecol(libds,LIBDS,is_libds)
if is_libds=1 then call symputx('libds',libds);
else putlog 'ERR' 'OR: invalid libds: ' libds;
run;
%mp_abort(iftrue= ("&libds"="0")
,mac=&_program
,msg=%str(Invalid libds provided)
)
複数ターゲットの方針
- 共有フォルダー内のバックエンドコードはプラットフォーム中立に保ち、プラットフォーム固有のシムは
targets/<name>/macros_*フォルダーに配置して、そのターゲットでのみ登録してください。 - プラットフォーム機能マクロは @sasjs/core にあります(
mm_*はメタデータ、mv_*は Viya、ms_*はサーバー)。サーバーの種類を手動で判定する分岐は使用しないでください。
品質ゲート(Data Controller のような成熟したアプリの規約に従ってください)
.sasファイルを編集した後はsasjs lintを実行し、編集したファイルの警告をすべて修正してください。- リンターは、
/* ... */ブロックコメント内の継続行も含め、すべての場所で2スペースのインデントを適用します。コメントのテキストを3つ以上のスペースで揃えないでください。 - バックエンドロジックを変更する場合はテストを追加し、
sasjs testを実行してください。マクロをテストするときは、マクロ変数のスコープ漏れを検出するため、必ずテスト対象のマクロを%mp_assertscope(SNAPSHOT)/%mp_assertscope(COMPARE, ...)で囲んでください。また、プラットフォームに応じて分岐するコードはすべて%macroラッパーで囲んでください(テストプログラムでマクロの条件分岐を開いたままにしないでください)。 - ライブの SAS サーバーがなくてもフロントエンドを開発できるように、
sasjs/mocksにモックを用意してください。 - 自動コミットやバージョンの更新は行わないでください。リリースはパイプライン主導です(Conventional Commits)。
- Markdown ファイルでは、行を途中で折り返さないでください。段落ごとに1行にしてください。
- アプリはオフライン/オンプレミス環境で動作する必要があります。フロントエンドのバンドルに外部 CDN アセットを含めないでください。
テストは冪等である必要があります
テストファイルは繰り返し実行しても(途中で失敗した実行の後も)パスする必要があります。
- ファイルの先頭に
%let syscc=0;を記述してください。多くの DC マクロは&syscc>0の場合、開始時に異常終了します。また、前のテストでWARNINGが発生するとsysccは4になります。 - 準備処理は防御的にしてください。設定レコードは削除してから挿入し(異常終了後に残ったデータに対応します)、既存の物理テーブルがないことを前提とせず、再作成してください。
参照実装
フォルダーレイアウト、sasjsconfig.json の複数ターゲット設定、サービス構造、ストリーミングビルド、テスト/モックの規約などのパターンについては、既存のアプリを参照してください。例:
- https://git.datacontroller.io/dc/dc
- https://github.com/sasjs/react-seed-app
- https://github.com/sasjs/macro-dash
制限事項
このスキルは、SASjs アプリケーション構築のための静的なリファレンスです。プロジェクト構造、設定、サービス契約に関するガイダンスを提供します。コードの実行、シェルコマンドの実行、ファイルシステムへのアクセス、データベースへの接続、ネットワークリクエストの送信は行いません。ファイルパス、ビルド出力、デプロイ先への言及は、SASjs プロジェクトの構造を説明するものです。このスキルがそれらのパスを作成、変更、またはアクセスすることはありません。