最近のCatyScriptコード
可読性に難ありだったCatyScriptもけっこう改善された。普通に読める。
最近書いたスクリプト。二百数十行、30行限界説を唱えていた頃に比べると……
// -*- coding: utf-8 -*- /** * * リソースマトリックス (Resource Matrices) の操作 * */ module resmat; /** リソースインスタンスのパス */ type instancePath = string(remark="リソースインスタンスのパス"); /** コロンドットパス */ type cdpath = string(remark="コロンドットパス"); /** アクションのエントリーポイント * public:Trigger と類似している。 * * inputDatatype --> inputType これはTriggerも変更する。 * paramsDatatype --> paramsType これはTriggerも変更する。 * */ type EntryPoint = { /** エントリーポイントのURI */ "href": uri, /** HTTPメソッド */ @[default("GET")] "method": httpMethod?, /** 動詞 */ @[default("")] "verb": string?, /** 入力(リクエストボディ)の型 */ @[default("void")] "inputType": typeName?, /** パラメータの型 */ @[default("EmptyObject")] "paramsType": typeName?, *: any? }; /** リソースマトリックス (Resource Matrix) */ type ResMat = { /** リソースのコロンドットパス * アプリケーション名は除き、モジュールパス:ローカル名 */ "resourceClassCdpath" : cdpath, "pathPattern": [string*], "instances": [instancePath*], "actions" : {* /*アクションのローカル名*/: ActionSummary?}, }; /** アクション情報のサマリー */ type ActionSummary = { "name": string, /** HTTPメソッド */ @[default("GET")] "method": httpMethod?, /** 動詞 */ @[default("")] "verb": string?, /** 入力(インレットの入力)の型 */ @[default("void")] "inputType": typeName?, /** パラメータ(オプション)の型 */ @[default("EmptyObject")] "paramsType": typeName?, }; /** リソースマトリックス・データの置き場所 */ @[hidden] const RES_MAT_DIR = "data@this:/res-matrices/"; /** サンプルのリソースマトリックス */ @[hidden] const SAMPLE = { "resourceClassCdpath" : "pkgFoo.modBar:CSVRes", "pathPattern": ["/csv/*.csv", "/a/*.csv"], "instances": ["/csv/file1.csv", "/a/file2.csv"], "actions" : { "get": { "name": "get", "method": "GET", "verb": "", "inputType": "void", "paramsType": "EmptyObject", }, "getRaw": { "name": "getRaw", "method": "GET", "verb": "raw", "inputType": "void", "paramsType": "EmptyObject", }, }, }; /** リソースマトリックスデータをセットアップする */ command setup :: void -> void { SAMPLE > sample | $.resourceClassCdpath > cdpath; %cdpath | res-name-to-file-path > path; %sample | json:pretty | file:write --mkdir %path }; /** エラー時の処理(例外生成)をする */ @[hidden] command error :: string -> never { pass > msg; @UnknownError {"message":%msg} | throw-if-can }; /** リソースのファイル名からCDパスに変換する */ @[hidden] command file-name-to-res-name :: string -> string { text:split "." | [list:slice -2 -1 > res-local, list:slice 0 -2 > mod]; [%mod | text:join "." , %res-local | item 0] | text:join ":" }; /** リソースのCDパスからファイルパスに変換する */ @[hidden] command res-name-to-file-path :: string -> string { text:split ":" | text:join "." > base; [RES_MAT_DIR, %base, ".xjson"] | text:concat }; /** リソースマトリックスをロードする */ @[hidden] command load-matrix [string res-name] :: void -> ResMat { %1 | res-name-to-file-path > path; xjson:read %path }; /** 現在のリソースマトリックス名(=リソース名)をリストする */ command list :: void -> [string*] { RES_MAT_DIR > dir; file:list %dir | each {pv name | file-name-to-res-name} }; /** リソースマトリックスのインスタンスセット(配列)を取り出す */ command instances [string res-name] :: void -> [instancePath*] { %1 > res-name; load-matrix %res-name | $.instances }; /** リソースマトリックスのアクションセット(オブジェクト)を取り出す */ command actions [string res-name] :: void -> {*: ActionSummary?} { %1 > res-name; load-matrix %res-name | $.actions }; /** リソースマトリックスの成分(エントリーポイント)を取り出す */ command entry-point [string res-name, (string|null)? action-name, (instancePath|null)? instance] :: void -> any/*EntryPoint | [EntryPoint*]*/ { %1 > res-name; %2? > action-name; %3? > instance; [%action-name?, %instance?] | cond { [string, string] => entry-point-one %res-name %action-name %instance, [null, string] => entry-point-actions %res-name %instance, [string, null?] => entry-point-instances %res-name %action-name, [null?, null?] => entry-point-all %res-name, * => "No Argument" | error, } }; /** エントリーポイントを作る */ @[hidden] command make-entry-point :: [ActionSummary, string] -> any/*EntryPoint*/ { [nth 1 > action, nth 2 > instance]; [%HOST_URL, %APP_PATH] | text:concat > url-base; { "href": [%url-base, %instance] | text:concat, "method": %action | $.method?, "verb": %action | $.verb?, "inputType": %action | $.inputType?, "paramsType": %action | $.paramsType?, } }; /** リソースマトリックスの1つの成分を取り出す */ command entry-point-one [string res-name, string action-name, instancePath instance] :: void -> any/*EntryPoint*/ { %1 > res-name; %2 > action-name; %3 > instance; load-matrix %res-name | [$.instances > instances, $.actions > actions]; [%instances, %instance] | list:contains | when { False => ["No Instance: ", %instance] | text:concat | error , True => %actions | pv --safe %action-name | when { undefined => ["No Action", %action-name] | text:concat | error , * => [(%actions | pv %action-name), %instance] | make-entry-point } , } }; /** 指定されたインスタンスに対して、リソースマトリックスの列ベクトルを取り出す */ command entry-point-actions [string res-name, instancePath instance] :: void -> any/*EntryPoint*/ { %1 > res-name; %2 > instance; load-matrix %res-name | [$.instances > instances, $.actions > actions]; %actions | each {[pass, %instance] | make-entry-point} }; /** 指定されたアクションに対して、リソースマトリックスの行ベクトルを取り出す */ command entry-point-instances [string res-name, string action-name] :: void -> any/*EntryPoint*/ { %1 > res-name; %2 > action-name; load-matrix %res-name | [$.instances > instances, $.actions > actions]; %actions | pv %action-name > action; %instances | each {[%action, pass] | make-entry-point} }; /** リソースマトリックスのすべての成分を取り出す */ command entry-point-all [string res-name] :: void -> any { %1 > res-name; load-matrix %res-name | [$.instances > instances, $.actions > actions]; %actions | each { pass > action; %instances | each { [%action, pass] | make-entry-point } } }; // End of Module