sasjs-adapter について
ブラウザーや Node.js から SAS のサービスやジョブを呼び出す TypeScript ライブラリです。SAS9、SASVIYA、SASJS に共通する API を使い、JavaScript アプリへの SAS 実行機能の組み込みを支援します。
主な機能
- 013 種類の SAS サーバーへの共通呼び出し
- 02入力テーブルの CSV シリアライズ
- 03パラメーター送信とファイルアップロード
- 04認証とセッションの管理
- 05リクエスト履歴の保存とログ取得
活用シーン
- 01ブラウザーからテーブルを送って SAS ジョブを実行
- 02Node.js から Viya にジョブを送信
- 03リクエストをデバッグして SAS ログを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sasjs/ skills --skill sasjs-adapterインストール後、Claude Code で/sasjs-adapterを入力して読み込まれたか確認します。
詳細
@sasjs/adapter
@sasjs/adapter は、ブラウザーまたは Node から SAS サービス/ジョブを呼び出すための TypeScript ライブラリです。SAS9、SASVIYA、SASJS の 3 種類のサーバーで共通の API を提供します。
基本設定
import SASjs from '@sasjs/adapter'
const sasjs = new SASjs({
serverUrl: 'https://sas.example.com',
serverType: 'SASVIYA', // SAS9 | SASVIYA | SASJS
appLoc: '/Public/app/myapp', // root folder of deployed services
contextName: 'SAS Job Execution compute context', // Viya only
debug: false
})
request() - 入力(JS -> SAS)
シグネチャ
sasjs.request(
sasJob: string,
data: { [key: string]: any[] } | null,
config?: { [key: string]: any }, // merged over SASjsConfig
loginRequiredCallback?: () => any,
authConfig?: AuthConfig, // Viya tokens for Node usage
extraResponseAttributes?: ExtraResponseAttributes[] // ['log'] | ['file'] | ['data']
)
sasJob:appLocを基準に解決される相対パス(先頭にスラッシュは付けません)、または絶対パスです。SAS の_programパラメーターになります。data:キーが SAS の work データセットになるオブジェクトです。サービスに入力が不要な場合はnullにできます。config:この呼び出しに限り、コンストラクターの設定にマージして上書きする設定です。
data オブジェクト - 任意の JSON ではなくテーブル
data の各キーの値は、すべてプレーンオブジェクトの 配列 でなければなりません。各キーはその名前を持つ SAS work データセットになり、配列内の各オブジェクトは行、各プロパティは列になります。
const res = await sasjs.request('services/common/getdata', {
customers: [
{ id: 1, name: 'Acme', active: true },
{ id: 2, name: 'Globex', active: false }
],
config: [{ rootdir: '/tmp', retries: 3 }] // even a single-row "config" table
})
SAS 側では、これらは work.customers および work.config として受け取られます。
入力検証ルール
送信前に、アダプターは data を検証します(validateInput を参照)。違反があると、ErrorResponse を伴ってプロミスが拒否されます。
dataはnullまたはプレーンオブジェクトでなければなりません(配列やプリミティブ値は不可)。- テーブルキーはすべて、英字またはアンダースコアで始まる必要があります:
/^[a-zA-Z_][a-zA-Z0-9_]*$/。数字で始まる名前は拒否されます。 - テーブル名は 32 文字 を超えてはなりません(SAS の名前の上限)。
- キーの下にある値はすべてオブジェクトの配列でなければなりません。オブジェクト以外の行は拒否されます。
- いずれの行のプロパティも
undefinedであってはなりません(null、文字列、数値、またはブール値である必要があります)。
テーブルを CSV にシリアライズする方法
各テーブルは convertToCSV を使って CSV に変換されます。変換では型が考慮されます。
- 文字列列:カンマ、タブ、改行、または引用符を含む場合にのみ引用符で囲みます。内部の
"は""にエスケープされます。 - 数値列:引用符で囲まずに出力されます。
- 数値列の null/空値:
.(SAS の欠損値)になります。 - 列の型推論:アダプターは列ごとにすべての行をスキャンします。列に
null/数値と特殊欠損値を表す文字列(.a-.z、_)の両方がある場合、その列の型はbest.になります。それ以外の場合は、最初の空でない値によってcharsとnumberのどちらかが決まります。 - 列フォーマットヘッダー:最初の CSV 行は、スペース区切りのフォーマット指定です(例:
name:$char20. id:best.)。SAS 側ではこれを使ってインフォーマットを割り当てます。 - バイトサイズの長さチェック:文字列の値は UTF-8 のバイト数で計測されます。いずれかの値が 32765 バイト を超えると、リクエストは
The max length of a string value in SASjs is 32765 characters.をスローします。 - フォーマットテーブル:
$を先頭に付けたキー(例:$customers)は、customersテーブルのフォーマット定義として扱われ、個別のデータセットとしては送信されません。そのformatsプロパティで、列名と SAS フォーマットを対応付けます。
2 つの転送方式
アダプターは、ペイロードのサイズとサーバーの種類に応じて転送方式を選択します(WebJobExecutor を参照)。
- パラメーター方式(Viya Web/SASjs サーバーのデフォルト、小さなペイロードの場合):各テーブルの CSV は、
sasjs{N}data(N = 1, 2, ...)という名前のフォームフィールドとして追加されます。sasjs_tablesフィールドには、テーブル名がスペース区切りで列挙されます。単一の CSV が 16000 文字を超える場合はチャンクに分割されます。sasjs{N}data0にチャンク数が入り、sasjs{N}data1..Nに各チャンクが入ります。 - ファイルアップロード方式(常に SAS 9 で使用。
JSON.stringify(data)が 500000 文字を超える、または;を含む場合は Viya/SASjs でも使用):各テーブルは{tableName}.csvという CSV ファイルとして、マルチパートフォームデータに追加されます。
どちらの場合も、debug: true の場合、本文はデバッグパラメーター(_debug=131、_omittextlog=false、_omitSessionResults=false)を含む multipart/form-data です。
request() - 出力(SAS -> JS)
レスポンスの形式は extraResponseAttributes によって異なります
デフォルト(extraResponseAttributes なし):解決された値は、パース済みの webout オブジェクトそのものです。つまり、SAS サービスが _webout に書き込んだ JSON が返されます。
// SAS service wrote: {"mydata":[{"COL1":"x","COL2":1}]}
const res = await sasjs.request('services/getdata', { in: [{ a: 1 }] })
// res === { mydata: [{ COL1: 'x', COL2: 1 }] }
// res.mydata[0].COL1 // note UPPERCASE column names
extraResponseAttributes を指定した場合(例:['log']):結果はラップされます。
const res = await sasjs.request('services/getdata', { in: [{ a: 1 }] }, {}, undefined, undefined, ['log'])
// res === { result: { mydata: [...] }, log: '<sas log string>' }
ExtraResponseAttributes は 'file' | 'data' | 'log' です。現行リリースで完全に実装されているのは log のみです。
名前の大文字・小文字
- 応答内のテーブル名は小文字です。これはアダプターではなく、SAS 側の
%webout/mp_jsonoutマクロによって適用されます。アダプターは webout の JSON をそのまま渡します。 - 列名は大文字です。SAS データセットの変数名は SAS 自体によって大文字に変換され、アダプターでは大文字・小文字を変換しません。
SAS サービスが出力する必要があるもの
サービスは _webout に有効な JSON を書き込む必要があります。通常は %webout(@sasjs/core 提供)を使用し、これは mp_jsonout をラップします。JSON の形式は、キーがテーブル名で、それぞれの値が行オブジェクトの配列であるオブジェクトです。
%webout(OPEN)
%webout(OBJ, work.customers) /* -> {"customers":[{...}]} */
%webout(CLOSE)
デバッグモード
config.debug が true の場合:
- SAS 9:生の応答は、ログと webout を含む文字列で、
>>weboutBEGIN<<と>>weboutEND<<で区切られます。アダプターはマーカー間の JSON を抽出します。 - Viya(web/JES):デバッグ応答は
parseSasViyaDebugResponse/parseSasViyaLogDebugResponseで解析され、ログと webout JSON が分離されます。 - Viya(compute API):ログは compute セッションから個別に取得されます。
いずれの場合も、デバッグを有効にして extraResponseAttributes: ['log'] を指定すると、SAS ログを res.log で参照できます。
リクエスト履歴
実行されたすべてのリクエストは、メモリ内の履歴に追加されます(上限は requestHistoryLimit。既定値は 10 です)。
sasjs.getSasRequests()
// SASjsRequest[]: { serviceLink, timestamp, sourceCode, generatedCode, logFile, SASWORK }
sourceCode と generatedCode が設定されるのは、debug: true の場合のみです。履歴はリングバッファーで、上限を超えると最も古いエントリーが削除されます。
認証
- SAS 9:
sasjs.logIn(username, password)(Stored Process サーバーに対するフォームベースの認証)。セッション Cookie は自動的に管理されます。 - Viya:OAuth クライアント/シークレット(クライアントクレデンシャル付与)または認可コードフローを使用します。トークンは自動的に更新されます。Node での使用時は CLI(
sasjs add cred)で設定します。Node では、authConfig(クライアント/シークレット/アクセストークン/リフレッシュトークン)をrequest()に渡します。 - SASJS サーバー:sasjs/server API に対するトークンベースの認証です。
主なクラス/モジュール
SASjs- メインのファサード:request()、logIn()/logOut()、uploadFile()、executeScript()、startComputeJob()、deployServicePack()RequestClient- HTTP レイヤー。リクエスト履歴(getRequests())、CSRF トークン、認証ヘッダーを保持します。WebJobExecutor- SAS 9 STP、Viya web JES、SASjs サーバーの web(マルチパートフォーム POST)ComputeJobExecutor- Viya compute API(名前付きコンテキストへのコードの直接送信)JesJobExecutor- Viya JES API(web アプリではなく、jobs API を介したジョブ送信)SasjsJobExecutor- SASjs サーバーの web 実行SessionManager- Viya compute セッションのライフサイクルSASViyaApiClient/SAS9ApiClient/SASjsApiClient- プラットフォームごとの低レベルクライアント(直接使用することはほとんどありません)file/ユーティリティ - SAS へのファイルアップロード(バイナリーコンテンツの処理)
ヒント
- 開発中は
debug: trueを設定すると、応答に SAS ログが表示されます。 response.status/エラー応答は必ず処理してください。SAS 側のエラー(例:%mp_abortによるエラー)は JSON 内に返され、必ずしも HTTP エラーになるとは限りません。- 大きなペイロードには、JSON 入力テーブルよりも CSV アップロードまたはストリームファイルを使用してください。
- デプロイに使用した
sasjsconfig.jsonのappLocと一致するようにappLocを設定してください。 - SAS から返される列名は大文字です。フロントエンドで小文字が必要な場合は、SAS の大文字・小文字を無理に変更しようとせず、JS でマッピングしてください。
- 数値入力列の
nullは SAS の欠損値(.)になります。文字列列の空文字列は空文字列になります。undefinedは使用しないでください。検証で拒否されます。
バンドラーを使わずにアダプターを使用する(ゼロビルド/厳格な CSP のフロントエンド)
パッケージのルートにある index.js は、グローバル変数 SASjs を公開する UMD バンドルです。最小構成のシードアプリに基づく手順は次のとおりです。
- package.json に
"prepare": "cp node_modules/@sasjs/adapter/index.js src/sasjs.js"を記述します(npm iの実行時に処理されます)。 - アプリのスクリプトより前に
<script src="sasjs.js"></script>を配置します。 - 非表示のカスタム要素で設定します:
<sasjs serverType="SASJS" appLoc="/Public/app/myapp" debug="false"></sasjs>。属性はdocument.querySelector('sasjs')で読み取ります。SAS 自体がアプリをストリーミングする場合は、serverUrlを省略してください。同一オリジンへのリクエストはそのまま動作します(CSPdefault-src 'self'に対応)。
制限事項
このスキルは、@sasjs/adapter ライブラリの静的リファレンスです。API、リクエスト/レスポンスの形式、認証、CSV のシリアル化に関するガイダンスを提供します。コードの実行、シェルコマンドの実行、ファイルシステムへのアクセス、データベースへの接続、ネットワークリクエストの実行は行いません。すべてのコード例は説明用です。ユーザー自身がアプリケーションに統合する必要があります。認証トークンへの言及は、アダプターライブラリが実行時に管理する値について説明したものです。このスキル自体がその値を読み取り、書き込み、またはアクセスすることはありません。